summaryrefslogtreecommitdiff
path: root/as/macro.c
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>2002-07-27 09:23:57 +0200
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:16:11 +0200
commita7aba15e8efffb1c5d3097656f1a93955a64f01f (patch)
tree4bb9d6d1d1528bc5647670d510aca6cc5fb300a8 /as/macro.c
downloaddev86-a7aba15e8efffb1c5d3097656f1a93955a64f01f.tar.gz
Import origs.tar.gzorigs
Diffstat (limited to 'as/macro.c')
-rw-r--r--as/macro.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/as/macro.c b/as/macro.c
new file mode 100644
index 0000000..9363947
--- /dev/null
+++ b/as/macro.c
@@ -0,0 +1,175 @@
+/* macro.c - expand macros for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "macro.h"
+
+#ifdef STDC_HEADERS_MISSING
+int strncmp P((const char *s1, const char *s2, unsigned n));
+#else
+#undef NULL
+#include <string.h>
+#endif
+
+/*
+ Enter macro: stack macro and get its parameters.
+ Parameters form a linked list of null-terminated strings of form
+ next:string. The first string is the macro number in 4 bytes.
+*/
+
+PUBLIC void entermac(symptr)
+struct sym_s *symptr;
+{
+ if (maclevel >= MAXMAC)
+ error(MACOV);
+ else if (macpar + 2 > macptop)
+ error(PAROV); /* no room for 0th param */
+ /* (2 structs to fit it!) */
+ else
+ {
+ char ch;
+ struct schain_s *param1;
+ register char *reglineptr;
+ register char *stringptr;
+
+ ++maclevel;
+ (--macstak)->text = (char *) symptr->value_reg_or_op.value;
+ macstak->parameters = param1 = macpar;
+ param1->next = NULL;
+ *(stringptr = build_number(++macnum, 3, param1->string)) = 0;
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* TODO: alignment */
+ getsym();
+ if (sym != LPAREN)
+ return; /* no other params */
+ reglineptr = lineptr;
+ stringptr = macpar->string;
+ while (TRUE)
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV);
+ return;
+ }
+ ch = *reglineptr++;
+ if (ch == '/')
+ /* escaped means no special meaning for slash, comma, paren */
+ ch = *reglineptr++;
+ else if (ch == ',' || ch == ')')
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV); /* no room for null */
+ return;
+ }
+ *stringptr = 0;
+ param1->next = macpar; /* ptr from previous */
+ (param1 = macpar)->next = NULL;
+ /* this goes nowhere */
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* but is finished OK - TODO align */
+ stringptr = macpar->string;
+ if (ch == ')')
+ return;
+ continue;
+ }
+ if ((*stringptr++ = ch) == 0)
+ {
+ symname = reglineptr;
+ error(RPEXP);
+ return;
+ }
+ }
+ }
+}
+
+/* MACRO pseudo-op */
+
+PUBLIC void pmacro()
+{
+ bool_t saving;
+ bool_t savingc;
+ struct sym_s *symptr;
+
+ saving = /* prepare for bad macro */
+ savingc = FALSE; /* normally don't save comments */
+ macload = TRUE; /* show loading */
+ if (label != NULL)
+ error(ILLAB);
+ else if (sym != IDENT)
+ error(LABEXP);
+ else
+ {
+ symptr = gsymptr;
+ if (symptr->type & MNREGBIT)
+ error(LABEXP);
+ else if (symptr->type & LABIT || symptr->data & FORBIT)
+ error(RELAB);
+ else if (pass == 0 || symptr->type & REDBIT)
+ /* copy on pass 0, also pass 1 if redefined */
+ {
+ saving = TRUE;
+ if (symptr->type & MACBIT)
+ symptr->type |= REDBIT;
+ else
+ symptr->type |= MACBIT;
+ symptr->data = UNDBIT; /* undefined till end */
+ symptr->value_reg_or_op.value = (unsigned) heapptr;
+ /* beginning of store for macro */
+ /* value s.b. (char *) */
+ getsym_nolookup(); /* test for "C" */
+ if (sym == IDENT && lineptr == symname + 1 && *symname == 'C')
+ savingc = TRUE;
+ }
+ }
+ while (TRUE)
+ {
+ skipline();
+ listline();
+ readline();
+ if (!macload)
+ break; /* macload cleared to show eof */
+ getsym_nolookup();
+ if (sym == IDENT)
+ {
+ if (lineptr == symname + 4 && strncmp(symname, "MEND", 4) == 0)
+ break;
+ }
+ else if (sym != MACROARG)
+ {
+ if (!savingc)
+ continue; /* don't save comment */
+ }
+ if (!saving)
+ continue;
+ {
+ register char *reglineptr;
+ register char *regheapptr;
+
+ reglineptr = linebuf;
+ regheapptr = heapptr;
+ do
+ {
+ if (regheapptr >= heapend)
+ {
+ heapptr = regheapptr;
+ fatalerror(SYMOV); /* won't fit */
+ }
+ }
+ while ((*regheapptr++ = *reglineptr++) != EOLCHAR);
+ heapptr = regheapptr;
+ }
+ }
+ macload = FALSE;
+ if (saving)
+ {
+ *heapptr++ = ETB;
+ symptr->data = 0;
+ }
+}