diff options
author | Robert de Bath <rdebath@poboxes.com> | 2002-07-27 09:23:57 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:16:11 +0200 |
commit | a7aba15e8efffb1c5d3097656f1a93955a64f01f (patch) | |
tree | 4bb9d6d1d1528bc5647670d510aca6cc5fb300a8 /as/macro.c | |
download | dev86-a7aba15e8efffb1c5d3097656f1a93955a64f01f.tar.gz |
Import origs.tar.gzorigs
Diffstat (limited to 'as/macro.c')
-rw-r--r-- | as/macro.c | 175 |
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; + } +} |