/* * Definition received via -D or -U */ void doadefine(Tokenrow *trp, int type) { Nlist *np; static Token onetoken[1] = {{ NUMBER, 0, 0, 0, 1, (uchar*)"1" }}; static Tokenrow onetr = { onetoken, onetoken, onetoken+1, 1 }; trp->tp = trp->bp; if (type=='U') { if (trp->lp-trp->tp != 2 || trp->tp->type!=NAME) goto syntax; if ((np = lookup(trp->tp, 0)) == NULL) return; np->flag &= ~ISDEFINED; return; } if (trp->tp >= trp->lp || trp->tp->type!=NAME) goto syntax; np = lookup(trp->tp, 1); np->flag |= ISDEFINED; trp->tp += 1; if (trp->tp >= trp->lp || trp->tp->type==END) { np->vp = &onetr; return; } if (trp->tp->type!=ASGN) goto syntax; trp->tp += 1; if ((trp->lp-1)->type == END) trp->lp -= 1; np->vp = normtokenrow(trp); return; syntax: error(FATAL, "Illegal -D or -U argument %r", trp); }
/* * Gather an arglist, starting in trp with tp pointing at the macro name. * Return total number of tokens passed, stash number of args found. * trp->tp is not changed relative to the tokenrow. */ int gatherargs(Tokenrow *trp, Tokenrow **atr, int *narg) { int parens = 1; int ntok = 0; Token *bp, *lp; Tokenrow ttr; int ntokp; int needspace; *narg = -1; /* means that there is no macro call */ /* look for the ( */ for (;;) { trp->tp++; ntok++; if (trp->tp >= trp->lp) { gettokens(trp, 0); if ((trp->lp-1)->type==END) { trp->lp -= 1; trp->tp -= ntok; return ntok; } } if (trp->tp->type==LP) break; if (trp->tp->type!=NL) return ntok; } *narg = 0; ntok++; ntokp = ntok; trp->tp++; /* search for the terminating ), possibly extending the row */ needspace = 0; while (parens>0) { if (trp->tp >= trp->lp) gettokens(trp, 0); if (needspace) { needspace = 0; makespace(trp); } if (trp->tp->type==END) { trp->lp -= 1; trp->tp -= ntok; error(ERROR, "EOF in macro arglist"); return ntok; } if (trp->tp->type==NL) { trp->tp += 1; adjustrow(trp, -1); trp->tp -= 1; makespace(trp); needspace = 1; continue; } if (trp->tp->type==LP) parens++; else if (trp->tp->type==RP) parens--; trp->tp++; ntok++; } trp->tp -= ntok; /* Now trp->tp won't move underneath us */ lp = bp = trp->tp+ntokp; for (; parens>=0; lp++) { if (lp->type == LP) { parens++; continue; } if (lp->type==RP) parens--; if (lp->type==DSHARP) lp->type = DSHARP1; /* ## not special in arg */ if (lp->type==COMMA && parens==0 || parens<0 && (lp-1)->type!=LP) { if (*narg>=NARG-1) error(FATAL, "Sorry, too many macro arguments"); ttr.bp = ttr.tp = bp; ttr.lp = lp; atr[(*narg)++] = normtokenrow(&ttr); bp = lp+1; } } return ntok; }
/* * do a macro definition. tp points to the name being defined in the line */ void dodefine(Tokenrow *trp) { Token *tp; Nlist *np; Tokenrow *def, *args; tp = trp->tp+1; if (tp>=trp->lp || tp->type!=NAME) { error(ERROR, "#defined token is not a name"); return; } np = lookup(tp, 1); if (np->flag&ISUNCHANGE) { error(ERROR, "#defined token %t can't be redefined", tp); return; } /* collect arguments */ tp += 1; args = NULL; if (tp<trp->lp && tp->type==LP && tp->wslen==0) { /* macro with args */ int narg = 0; tp += 1; args = new(Tokenrow); maketokenrow(2, args); if (tp->type!=RP) { int err = 0; for (;;) { Token *atp; if (tp->type!=NAME) { err++; break; } if (narg>=args->max) growtokenrow(args); for (atp=args->bp; atp<args->lp; atp++) if (atp->len==tp->len && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0) error(ERROR, "Duplicate macro argument"); *args->lp++ = *tp; narg++; tp += 1; if (tp->type==RP) break; if (tp->type!=COMMA) { err++; break; } tp += 1; } if (err) { error(ERROR, "Syntax error in macro parameters"); return; } } tp += 1; } trp->tp = tp; if (((trp->lp)-1)->type==NL) trp->lp -= 1; def = normtokenrow(trp); if (np->flag&ISDEFINED) { if (comparetokens(def, np->vp) || (np->ap==NULL) != (args==NULL) || np->ap && comparetokens(args, np->ap)) error(ERROR, "Macro redefinition of %t", trp->bp+2); } if (args) { Tokenrow *tap; tap = normtokenrow(args); dofree(args->bp); args = tap; } np->ap = args; np->vp = def; np->flag |= ISDEFINED; }
/* * do a macro definition. tp points to the name being defined in the line */ void dodefine(Tokenrow * trp) { Token *tp; Nlist *np; Source *s; Tokenrow *def, *args; static uchar location[(PATH_MAX + 8) * NINC], *cp; tp = trp->tp + 1; if (tp >= trp->lp || tp->type != NAME) { error(ERROR, "#defined token is not a name"); return; } np = lookup(tp, 1); if (np->flag & ISUNCHANGE) { error(ERROR, "#defined token %t can't be redefined", tp); return; } /* collect arguments */ tp += 1; args = NULL; if (tp < trp->lp && tp->type == LP && tp->wslen == 0) { tp += 1; args = new(Tokenrow); maketokenrow(2, args); if (tp->type != RP) { /* macro with args */ size_t narg = 0; int err = 0; for (;;) { Token *atp; if (tp->type != NAME) { err++; break; } if (narg >= args->max) growtokenrow(args); for (atp = args->bp; atp < args->lp; atp++) if (atp->len == tp->len && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0) error(ERROR, "Duplicate macro argument"); *args->lp++ = *tp; narg++; tp += 1; if (tp->type == RP) break; if (tp->type != COMMA) { err++; break; } tp += 1; } if (err) { error(ERROR, "Syntax error in macro parameters"); return; } } tp += 1; } trp->tp = tp; if (((trp->lp) - 1)->type == NL) trp->lp -= 1; def = normtokenrow(trp); if (np->flag & ISDEFINED) { if (comparetokens(def, np->vp) || (np->ap == NULL) != (args == NULL) || (np->ap && comparetokens(args, np->ap))) { if ( np->loc ) error(ERROR, "Macro redefinition of %t (already defined at %s)", trp->bp + 2, np->loc); else error(ERROR, "Macro redefinition of %t (already defined at %s)", trp->bp + 2, "commandline" ); } } if (args) { Tokenrow *tap; tap = normtokenrow(args); dofree(args->bp); dofree(args); args = tap; } np->ap = args; np->vp = def; np->flag |= ISDEFINED; /* build location string of macro definition */ for (cp = location, s = cursource; s; s = s->next) if (*s->filename) { if (cp != location) *cp++ = ' '; sprintf((char *)cp, "%s:%d", s->filename, s->line); cp += strlen((char *)cp); } np->loc = newstring(location, strlen((char *)location), 0); if (Mflag) { if (np->ap) error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp); else error(INFO, "Macro definition of %s [%r]", np->name, np->vp); } }