/* macro.c - expand macros for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "scan.h" #undef EXTERN #define EXTERN #include "macro.h" /* 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 = NUL_PTR; *(stringptr = build_number(++macnum, 3, param1->string)) = 0; macpar = (struct schain_s *) (stringptr + 1); /* TODO: alignment */ getsym(); if (sym == EOLSYM) return; /* no other params */ if (sym != LPAREN) reglineptr = symname; else 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 == ')' || ch == '!' || ch == ';' || ch == '\n' || ch == 0) { if (stringptr >= (char *) macptop) { symname = reglineptr; error(PAROV); /* no room for null */ return; } *stringptr = 0; param1->next = macpar; /* ptr from previous */ (param1 = macpar)->next = NUL_PTR; /* 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=0; int maclen = 8; int macoff = 0; char * macbuf = asalloc(8); saving = /* prepare for bad macro */ savingc = FALSE; /* normally don't save comments */ macload = TRUE; /* show loading */ if (label != NUL_PTR) 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 != last_pass || 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 = (offset_t) macbuf; 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 || strncmp(symname, "mend", 4) == 0) ) { getsym(); break; } } else if (sym != MACROARG) { if (!savingc) continue; /* don't save comment */ } if (!saving) continue; { char * p = strchr(linebuf, EOLCHAR); int len = (p-linebuf+1); if ( macoff + len > maclen-4 ) { maclen = maclen * 2 + len; macbuf = asrealloc(macbuf, maclen); } memcpy(macbuf+macoff, linebuf, len); macoff += len; } } macload = FALSE; if (saving) { macbuf[macoff] = ETB; symptr->value_reg_or_op.value = (offset_t) macbuf; symptr->data = 0; } }