/* * build an input token.. * consider only those starting with _ or A-Za-z. This is a * combo with lookup to speed things up. */ static ndptr inspect(int c, char *tp) { char *name = tp; char *etp = tp+MAXTOK; ndptr p; unsigned int h; h = *tp++ = c; while ((isalnum(c = gpbc()) || c == '_') && tp < etp) h = (h << 5) + h + (*tp++ = c); if (c != EOF) PUTBACK(c); *tp = EOS; /* token is too long, it won't match anything, but it can still * be output. */ if (tp == ep) { outputstr(name); while (isalnum(c = gpbc()) || c == '_') { if (sp < 0) putc(c, active); else CHRSAVE(c); } *name = EOS; return nil; } for (p = hashtab[h % HASHSIZE]; p != nil; p = p->nxtptr) if (h == p->hv && STREQ(name, p->name)) break; return p; }
/* * build an input token.. * consider only those starting with _ or A-Za-z. */ static ndptr inspect(int c, char *tp) { char *name = tp; char *etp = tp+MAXTOK; ndptr p; *tp++ = c; while ((isalnum(c = gpbc()) || c == '_') && tp < etp) *tp++ = c; if (c != EOF) PUSHBACK(c); *tp = EOS; /* token is too long, it won't match anything, but it can still * be output. */ if (tp == ep) { outputstr(name); while (isalnum(c = gpbc()) || c == '_') { if (sp < 0) reallyputchar(c); else CHRSAVE(c); } *name = EOS; return NULL; } p = ohash_find(¯os, ohash_qlookupi(¯os, name, (const char **)&tp)); if (p == NULL) return NULL; if (macro_getdef(p) == NULL) return NULL; return p; }
/* * output string directly, without pushing it for reparses. */ void outputstr(const char *s) { if (sp < 0) reallyoutputstr(s); else while (*s) CHRSAVE(*s++); }
/* * output string directly, without pushing it for reparses. */ void outputstr(const char *s) { if (sp < 0) while (*s) putc(*s++, active); else while (*s) CHRSAVE(*s++); }
/* * macro - the work horse.. */ static void macro(void) { char token[MAXTOK+1]; int t, l; ndptr p; int nlpar; cycle { t = gpbc(); if (t == '_' || isalpha(t)) { p = inspect(t, token); if (p != nil) putback(l = gpbc()); if (p == nil || (l != LPAREN && (p->type & NEEDARGS) != 0)) outputstr(token); else { /* * real thing.. First build a call frame: */ pushf(fp); /* previous call frm */ pushf(p->type); /* type of the call */ pushf(0); /* parenthesis level */ fp = sp; /* new frame pointer */ /* * now push the string arguments: */ pushs1(p->defn); /* defn string */ pushs1(p->name); /* macro name */ pushs(ep); /* start next..*/ if (l != LPAREN && PARLEV == 0) { /* no bracks */ chrsave(EOS); if ((uintptr_t)sp == STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, 2, CALTYP); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ fp = PREVFP; /* rewind stack...*/ } } } else if (t == EOF) { if (sp > -1) { warnx( "unexpected end of input, unclosed parenthesis:"); dump_stack(paren, PARLEV); exit(1); } if (ilevel <= 0) break; /* all done thanks.. */ release_input(infile+ilevel--); free(inname[ilevel+1]); bufbase = bbase[ilevel]; emitline(); continue; } /* * non-alpha token possibly seen.. * [the order of else if .. stmts is important.] */ else if (LOOK_AHEAD(t,lquote)) { /* strip quotes */ nlpar = 0; record(quotes, nlpar++); /* * Opening quote: scan forward until matching * closing quote has been found. */ do { l = gpbc(); if (LOOK_AHEAD(l,rquote)) { if (--nlpar > 0) outputstr(rquote); } else if (LOOK_AHEAD(l,lquote)) { record(quotes, nlpar++); outputstr(lquote); } else if (l == EOF) { if (nlpar == 1) warnx("unclosed quote:"); else warnx("%d unclosed quotes:", nlpar); dump_stack(quotes, nlpar); exit(1); } else { if (nlpar > 0) { if (sp < 0) putc(l, active); else CHRSAVE(l); } } } while (nlpar != 0); } else if (sp < 0 && LOOK_AHEAD(t, scommt)) { fputs(scommt, active); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { fputs(ecommt, active); break; } if (t == EOF) break; putc(t, active); } } else if (sp < 0) { /* not in a macro at all */ putc(t, active); /* output directly.. */ } else switch(t) { case LPAREN: if (PARLEV > 0) chrsave(t); while (isspace(l = gpbc())) ; /* skip blank, tab, nl.. */ putback(l); record(paren, PARLEV++); break; case RPAREN: if (--PARLEV > 0) chrsave(t); else { /* end of argument list */ chrsave(EOS); if ((uintptr_t)sp == STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, sp-fp, CALTYP); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ fp = PREVFP; /* rewind stack...*/ } break; case COMMA: if (PARLEV == 1) { chrsave(EOS); /* new argument */ while (isspace(l = gpbc())) ; putback(l); pushs(ep); } else chrsave(t); break; default: if (LOOK_AHEAD(t, scommt)) { char *pc; for (pc = scommt; *pc; pc++) chrsave(*pc); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { for (pc = ecommt; *pc; pc++) chrsave(*pc); break; } if (t == EOF) break; CHRSAVE(t); } } else CHRSAVE(t); /* stack the char */ break; } } }
/* * macro - the work horse.. */ static void macro(void) { char token[MAXTOK+1]; int t, l; ndptr p; int nlpar; cycle { t = gpbc(); if (LOOK_AHEAD(t,lquote)) { /* strip quotes */ nlpar = 0; record(quotes, nlpar++); /* * Opening quote: scan forward until matching * closing quote has been found. */ do { l = gpbc(); if (LOOK_AHEAD(l,rquote)) { if (--nlpar > 0) outputstr(rquote); } else if (LOOK_AHEAD(l,lquote)) { record(quotes, nlpar++); outputstr(lquote); } else if (l == EOF) { if (nlpar == 1) warnx("unclosed quote:"); else warnx("%d unclosed quotes:", nlpar); dump_stack(quotes, nlpar); exit(1); } else { if (nlpar > 0) { if (sp < 0) reallyputchar(l); else CHRSAVE(l); } } } while (nlpar != 0); } else if (sp < 0 && LOOK_AHEAD(t, scommt)) { reallyoutputstr(scommt); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { reallyoutputstr(ecommt); break; } if (t == EOF) break; reallyputchar(t); } } else if (t == '_' || isalpha(t)) { p = inspect(t, token); if (p != NULL) pushback(l = gpbc()); if (p == NULL || (l != LPAREN && (macro_getdef(p)->type & NEEDARGS) != 0)) outputstr(token); else { /* * real thing.. First build a call frame: */ pushf(fp); /* previous call frm */ pushf(macro_getdef(p)->type); /* type of the call */ pushf(is_traced(p)); pushf(0); /* parenthesis level */ fp = sp; /* new frame pointer */ /* * now push the string arguments: */ pushs1(macro_getdef(p)->defn); /* defn string */ pushs1((char *)macro_name(p)); /* macro name */ pushs(ep); /* start next..*/ if (l != LPAREN && PARLEV == 0) { /* no bracks */ chrsave(EOS); if (sp == (int)STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, 2, CALTYP, TRACESTATUS); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ fp = PREVFP; /* rewind stack...*/ } } } else if (t == EOF) { if (!mimic_gnu /* you can puke right there */ && sp > -1 && ilevel <= 0) { warnx( "unexpected end of input, unclosed parenthesis:"); dump_stack(paren, PARLEV); exit(1); } if (ilevel <= 0) break; /* all done thanks.. */ release_input(infile+ilevel--); emit_synchline(); bufbase = bbase[ilevel]; continue; } else if (sp < 0) { /* not in a macro at all */ reallyputchar(t); /* output directly.. */ } else switch(t) { case LPAREN: if (PARLEV > 0) chrsave(t); while (isspace(l = gpbc())) /* skip blank, tab, nl.. */ if (PARLEV > 0) chrsave(l); pushback(l); record(paren, PARLEV++); break; case RPAREN: if (--PARLEV > 0) chrsave(t); else { /* end of argument list */ chrsave(EOS); if (sp == (int)STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, sp-fp, CALTYP, TRACESTATUS); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ fp = PREVFP; /* rewind stack...*/ } break; case COMMA: if (PARLEV == 1) { chrsave(EOS); /* new argument */ while (isspace(l = gpbc())) ; pushback(l); pushs(ep); } else chrsave(t); break; default: if (LOOK_AHEAD(t, scommt)) { char *cp; for (cp = scommt; *cp; cp++) chrsave(*cp); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { for (cp = ecommt; *cp; cp++) chrsave(*cp); break; } if (t == EOF) break; CHRSAVE(t); } } else CHRSAVE(t); /* stack the char */ break; } } }