1*da2e3ebdSchin /*********************************************************************** 2*da2e3ebdSchin * * 3*da2e3ebdSchin * This software is part of the ast package * 4*da2e3ebdSchin * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5*da2e3ebdSchin * and is licensed under the * 6*da2e3ebdSchin * Common Public License, Version 1.0 * 7*da2e3ebdSchin * by AT&T Knowledge Ventures * 8*da2e3ebdSchin * * 9*da2e3ebdSchin * A copy of the License is available at * 10*da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11*da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*da2e3ebdSchin * * 13*da2e3ebdSchin * Information and Software Systems Research * 14*da2e3ebdSchin * AT&T Research * 15*da2e3ebdSchin * Florham Park NJ * 16*da2e3ebdSchin * * 17*da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18*da2e3ebdSchin * * 19*da2e3ebdSchin ***********************************************************************/ 20*da2e3ebdSchin #pragma prototyped 21*da2e3ebdSchin /* 22*da2e3ebdSchin * Glenn Fowler 23*da2e3ebdSchin * AT&T Research 24*da2e3ebdSchin * 25*da2e3ebdSchin * preprocessor control directive support 26*da2e3ebdSchin */ 27*da2e3ebdSchin 28*da2e3ebdSchin #include "pplib.h" 29*da2e3ebdSchin 30*da2e3ebdSchin #include <regex.h> 31*da2e3ebdSchin 32*da2e3ebdSchin #define TOKOP_DUP (1<<0) 33*da2e3ebdSchin #define TOKOP_STRING (1<<1) 34*da2e3ebdSchin #define TOKOP_UNSET (1<<2) 35*da2e3ebdSchin 36*da2e3ebdSchin struct edit 37*da2e3ebdSchin { 38*da2e3ebdSchin struct edit* next; 39*da2e3ebdSchin regex_t re; 40*da2e3ebdSchin }; 41*da2e3ebdSchin 42*da2e3ebdSchin struct map 43*da2e3ebdSchin { 44*da2e3ebdSchin struct map* next; 45*da2e3ebdSchin regex_t re; 46*da2e3ebdSchin struct edit* edit; 47*da2e3ebdSchin }; 48*da2e3ebdSchin 49*da2e3ebdSchin #define RESTORE (COLLECTING|CONDITIONAL|DEFINITION|DIRECTIVE|DISABLE|EOF2NL|HEADER|NOSPACE|NOVERTICAL|PASSEOF|STRIP) 50*da2e3ebdSchin 51*da2e3ebdSchin /* 52*da2e3ebdSchin * common predicate assertion operations 53*da2e3ebdSchin * op is DEFINE or UNDEF 54*da2e3ebdSchin */ 55*da2e3ebdSchin 56*da2e3ebdSchin static void 57*da2e3ebdSchin assert(int op, char* pred, char* args) 58*da2e3ebdSchin { 59*da2e3ebdSchin register struct pplist* a; 60*da2e3ebdSchin register struct ppsymbol* sym; 61*da2e3ebdSchin register struct pplist* p; 62*da2e3ebdSchin register struct pplist* q; 63*da2e3ebdSchin 64*da2e3ebdSchin if (!args) switch (op) 65*da2e3ebdSchin { 66*da2e3ebdSchin case DEFINE: 67*da2e3ebdSchin goto mark; 68*da2e3ebdSchin case UNDEF: 69*da2e3ebdSchin a = 0; 70*da2e3ebdSchin goto unmark; 71*da2e3ebdSchin } 72*da2e3ebdSchin if (a = (struct pplist*)hashget(pp.prdtab, pred)) 73*da2e3ebdSchin { 74*da2e3ebdSchin p = 0; 75*da2e3ebdSchin q = a; 76*da2e3ebdSchin while (q) 77*da2e3ebdSchin { 78*da2e3ebdSchin if (streq(q->value, args)) 79*da2e3ebdSchin { 80*da2e3ebdSchin if (op == DEFINE) return; 81*da2e3ebdSchin q = q->next; 82*da2e3ebdSchin if (p) p->next = q; 83*da2e3ebdSchin else a = q; 84*da2e3ebdSchin } 85*da2e3ebdSchin else 86*da2e3ebdSchin { 87*da2e3ebdSchin p = q; 88*da2e3ebdSchin q = q->next; 89*da2e3ebdSchin } 90*da2e3ebdSchin } 91*da2e3ebdSchin if (op == UNDEF) 92*da2e3ebdSchin { 93*da2e3ebdSchin unmark: 94*da2e3ebdSchin hashput(pp.prdtab, pred, a); 95*da2e3ebdSchin if (sym = ppsymref(pp.symtab, pred)) 96*da2e3ebdSchin sym->flags &= ~SYM_PREDICATE; 97*da2e3ebdSchin return; 98*da2e3ebdSchin } 99*da2e3ebdSchin } 100*da2e3ebdSchin if (op == DEFINE) 101*da2e3ebdSchin { 102*da2e3ebdSchin p = newof(0, struct pplist, 1, 0); 103*da2e3ebdSchin p->next = a; 104*da2e3ebdSchin p->value = strdup(args); 105*da2e3ebdSchin hashput(pp.prdtab, NiL, p); 106*da2e3ebdSchin mark: 107*da2e3ebdSchin if ((pp.state & COMPILE) && pp.truncate) return; 108*da2e3ebdSchin if (sym = ppsymset(pp.symtab, pred)) 109*da2e3ebdSchin sym->flags |= SYM_PREDICATE; 110*da2e3ebdSchin } 111*da2e3ebdSchin } 112*da2e3ebdSchin 113*da2e3ebdSchin /* 114*da2e3ebdSchin * tokenize string ppop() 115*da2e3ebdSchin * 116*da2e3ebdSchin * op PP_* op 117*da2e3ebdSchin * name option name 118*da2e3ebdSchin * s string of option values 119*da2e3ebdSchin * n option sense 120*da2e3ebdSchin * flags TOKOP_* flags 121*da2e3ebdSchin */ 122*da2e3ebdSchin 123*da2e3ebdSchin static void 124*da2e3ebdSchin tokop(int op, char* name, register char* s, register int n, int flags) 125*da2e3ebdSchin { 126*da2e3ebdSchin register int c; 127*da2e3ebdSchin register char* t; 128*da2e3ebdSchin 129*da2e3ebdSchin if (!(flags & TOKOP_UNSET) && !n) error(2, "%s: option cannot be unset", name); 130*da2e3ebdSchin else if (!s) ppop(op, s, n); 131*da2e3ebdSchin else if (flags & TOKOP_STRING) 132*da2e3ebdSchin { 133*da2e3ebdSchin PUSH_LINE(s); 134*da2e3ebdSchin for (;;) 135*da2e3ebdSchin { 136*da2e3ebdSchin pp.state &= ~NOSPACE; 137*da2e3ebdSchin c = pplex(); 138*da2e3ebdSchin pp.state |= NOSPACE; 139*da2e3ebdSchin if (!c) break; 140*da2e3ebdSchin if (c != ' ') 141*da2e3ebdSchin ppop(op, (flags & TOKOP_DUP) ? strdup(pp.token) : pp.token, n); 142*da2e3ebdSchin } 143*da2e3ebdSchin POP_LINE(); 144*da2e3ebdSchin } 145*da2e3ebdSchin else do 146*da2e3ebdSchin { 147*da2e3ebdSchin while (*s == ' ') s++; 148*da2e3ebdSchin for (t = s; *t && *t != ' '; t++); 149*da2e3ebdSchin if (*t) *t++ = 0; 150*da2e3ebdSchin else t = 0; 151*da2e3ebdSchin if (*s) ppop(op, (flags & TOKOP_DUP) ? strdup(s) : s, n); 152*da2e3ebdSchin } while (s = t); 153*da2e3ebdSchin } 154*da2e3ebdSchin 155*da2e3ebdSchin /* 156*da2e3ebdSchin * return symbol pointer for next token macro (re)definition 157*da2e3ebdSchin */ 158*da2e3ebdSchin 159*da2e3ebdSchin static struct ppsymbol* 160*da2e3ebdSchin macsym(int tok) 161*da2e3ebdSchin { 162*da2e3ebdSchin register struct ppsymbol* sym; 163*da2e3ebdSchin 164*da2e3ebdSchin if (tok != T_ID) 165*da2e3ebdSchin { 166*da2e3ebdSchin error(2, "%s: invalid macro name", pptokstr(pp.token, 0)); 167*da2e3ebdSchin return 0; 168*da2e3ebdSchin } 169*da2e3ebdSchin sym = pprefmac(pp.token, REF_CREATE); 170*da2e3ebdSchin if ((sym->flags & SYM_FINAL) && (pp.mode & HOSTED)) return 0; 171*da2e3ebdSchin if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 172*da2e3ebdSchin { 173*da2e3ebdSchin if (!(pp.option & ALLPOSSIBLE)) 174*da2e3ebdSchin error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 175*da2e3ebdSchin return 0; 176*da2e3ebdSchin } 177*da2e3ebdSchin if (!sym->macro) sym->macro = newof(0, struct ppmacro, 1, 0); 178*da2e3ebdSchin return sym; 179*da2e3ebdSchin } 180*da2e3ebdSchin 181*da2e3ebdSchin /* 182*da2e3ebdSchin * get one space canonical pplex() line, sans '\n', and place in p 183*da2e3ebdSchin * x is max+1 pos in p 184*da2e3ebdSchin * 0 returned if line too large 185*da2e3ebdSchin * otherwise end of p ('\0') returned 186*da2e3ebdSchin */ 187*da2e3ebdSchin 188*da2e3ebdSchin static char* 189*da2e3ebdSchin getline(register char* p, char* x, int disable) 190*da2e3ebdSchin { 191*da2e3ebdSchin register int c; 192*da2e3ebdSchin register char* s; 193*da2e3ebdSchin char* b; 194*da2e3ebdSchin long restore; 195*da2e3ebdSchin 196*da2e3ebdSchin restore = pp.state & (NOSPACE|STRIP); 197*da2e3ebdSchin pp.state &= ~(NEWLINE|NOSPACE|STRIP); 198*da2e3ebdSchin pp.state |= EOF2NL; 199*da2e3ebdSchin b = p; 200*da2e3ebdSchin while ((c = pplex()) != '\n') 201*da2e3ebdSchin { 202*da2e3ebdSchin if (disable) 203*da2e3ebdSchin { 204*da2e3ebdSchin if (c == ' ') 205*da2e3ebdSchin /*ignore*/; 206*da2e3ebdSchin else if (disable == 1) 207*da2e3ebdSchin disable = (c == T_ID && streq(pp.token, pp.pass)) ? 2 : 0; 208*da2e3ebdSchin else 209*da2e3ebdSchin { 210*da2e3ebdSchin disable = 0; 211*da2e3ebdSchin if (c == ':') 212*da2e3ebdSchin pp.state |= DISABLE; 213*da2e3ebdSchin } 214*da2e3ebdSchin } 215*da2e3ebdSchin s = pp.token; 216*da2e3ebdSchin while (*p = *s++) 217*da2e3ebdSchin if (++p >= x) 218*da2e3ebdSchin { 219*da2e3ebdSchin p = 0; 220*da2e3ebdSchin goto done; 221*da2e3ebdSchin } 222*da2e3ebdSchin } 223*da2e3ebdSchin if (p > b && *(p - 1) == ' ') 224*da2e3ebdSchin p--; 225*da2e3ebdSchin if (p >= x) 226*da2e3ebdSchin p = 0; 227*da2e3ebdSchin else 228*da2e3ebdSchin *p = 0; 229*da2e3ebdSchin done: 230*da2e3ebdSchin pp.state &= ~(NOSPACE|STRIP); 231*da2e3ebdSchin pp.state |= restore; 232*da2e3ebdSchin return p; 233*da2e3ebdSchin } 234*da2e3ebdSchin 235*da2e3ebdSchin /* 236*da2e3ebdSchin * regex error handler 237*da2e3ebdSchin */ 238*da2e3ebdSchin 239*da2e3ebdSchin void 240*da2e3ebdSchin regfatal(regex_t* p, int level, int code) 241*da2e3ebdSchin { 242*da2e3ebdSchin char buf[128]; 243*da2e3ebdSchin 244*da2e3ebdSchin regerror(code, p, buf, sizeof(buf)); 245*da2e3ebdSchin regfree(p); 246*da2e3ebdSchin error(level, "regular expression: %s", buf); 247*da2e3ebdSchin } 248*da2e3ebdSchin 249*da2e3ebdSchin /* 250*da2e3ebdSchin * process a single directive line 251*da2e3ebdSchin */ 252*da2e3ebdSchin 253*da2e3ebdSchin int 254*da2e3ebdSchin ppcontrol(void) 255*da2e3ebdSchin { 256*da2e3ebdSchin register char* p; 257*da2e3ebdSchin register int c; 258*da2e3ebdSchin register int n; 259*da2e3ebdSchin register char* s; 260*da2e3ebdSchin register struct ppmacro* mac; 261*da2e3ebdSchin register struct ppsymbol* sym; 262*da2e3ebdSchin struct edit* edit; 263*da2e3ebdSchin struct map* map; 264*da2e3ebdSchin struct ppfile* fp; 265*da2e3ebdSchin int o; 266*da2e3ebdSchin int directive; 267*da2e3ebdSchin long restore; 268*da2e3ebdSchin struct pptuple* rp; 269*da2e3ebdSchin struct pptuple* tp; 270*da2e3ebdSchin char* v; 271*da2e3ebdSchin int emitted; 272*da2e3ebdSchin 273*da2e3ebdSchin union 274*da2e3ebdSchin { 275*da2e3ebdSchin struct map* best; 276*da2e3ebdSchin struct ppinstk* inp; 277*da2e3ebdSchin struct pplist* list; 278*da2e3ebdSchin char* string; 279*da2e3ebdSchin struct ppsymbol* symbol; 280*da2e3ebdSchin int type; 281*da2e3ebdSchin PPLINESYNC linesync; 282*da2e3ebdSchin } var; 283*da2e3ebdSchin 284*da2e3ebdSchin static char __va_args__[] = "__VA_ARGS__"; 285*da2e3ebdSchin static int i0; 286*da2e3ebdSchin static int i1; 287*da2e3ebdSchin static int i2; 288*da2e3ebdSchin static int i3; 289*da2e3ebdSchin static int i4; 290*da2e3ebdSchin 291*da2e3ebdSchin static long n1; 292*da2e3ebdSchin static long n2; 293*da2e3ebdSchin static long n3; 294*da2e3ebdSchin 295*da2e3ebdSchin static char* p0; 296*da2e3ebdSchin static char* p1; 297*da2e3ebdSchin static char* p2; 298*da2e3ebdSchin static char* p3; 299*da2e3ebdSchin static char* p4; 300*da2e3ebdSchin static char* p5; 301*da2e3ebdSchin static char* p6; 302*da2e3ebdSchin 303*da2e3ebdSchin static struct ppmacro old; 304*da2e3ebdSchin static char* formargs[MAXFORMALS]; 305*da2e3ebdSchin #if MACKEYARGS 306*da2e3ebdSchin static char* formvals[MAXFORMALS]; 307*da2e3ebdSchin #endif 308*da2e3ebdSchin 309*da2e3ebdSchin emitted = 0; 310*da2e3ebdSchin if (pp.state & SKIPCONTROL) pp.level--; 311*da2e3ebdSchin restore = (pp.state & RESTORE)|NEWLINE; 312*da2e3ebdSchin if (pp.state & PASSTHROUGH) restore |= DISABLE; 313*da2e3ebdSchin else restore &= ~DISABLE; 314*da2e3ebdSchin pp.state &= ~(NEWLINE|RESTORE|SKIPCONTROL); 315*da2e3ebdSchin pp.state |= DIRECTIVE|DISABLE|EOF2NL|NOSPACE|NOVERTICAL; 316*da2e3ebdSchin #if COMPATIBLE 317*da2e3ebdSchin if ((pp.state & (COMPATIBILITY|STRICT)) == COMPATIBILITY || (pp.mode & HOSTED)) pp.state &= ~NOVERTICAL; 318*da2e3ebdSchin #else 319*da2e3ebdSchin if (pp.mode & HOSTED) pp.state &= ~NOVERTICAL; 320*da2e3ebdSchin #endif 321*da2e3ebdSchin switch (c = pplex()) 322*da2e3ebdSchin { 323*da2e3ebdSchin case T_DECIMAL: 324*da2e3ebdSchin case T_OCTAL: 325*da2e3ebdSchin if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 326*da2e3ebdSchin error(1, "# <line> [ \"<file>\" [ <type> ] ]: non-standard directive"); 327*da2e3ebdSchin directive = INCLUDE; 328*da2e3ebdSchin goto linesync; 329*da2e3ebdSchin case T_ID: 330*da2e3ebdSchin switch (directive = (int)hashref(pp.dirtab, pp.token)) 331*da2e3ebdSchin { 332*da2e3ebdSchin case ELIF: 333*da2e3ebdSchin else_if: 334*da2e3ebdSchin if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 335*da2e3ebdSchin goto eatdirective; 336*da2e3ebdSchin if (pp.control <= pp.in->control) 337*da2e3ebdSchin { 338*da2e3ebdSchin error(2, "no matching #%s for #%s", dirname(IF), dirname(ELIF)); 339*da2e3ebdSchin goto eatdirective; 340*da2e3ebdSchin } 341*da2e3ebdSchin if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard; 342*da2e3ebdSchin if (*pp.control & HADELSE) 343*da2e3ebdSchin { 344*da2e3ebdSchin error(2, "invalid #%s after #%s", dirname(ELIF), dirname(ELSE)); 345*da2e3ebdSchin *pp.control |= SKIP; 346*da2e3ebdSchin goto eatdirective; 347*da2e3ebdSchin } 348*da2e3ebdSchin if (*pp.control & KEPT) 349*da2e3ebdSchin { 350*da2e3ebdSchin *pp.control |= SKIP; 351*da2e3ebdSchin goto eatdirective; 352*da2e3ebdSchin } 353*da2e3ebdSchin if (directive == IFDEF || directive == IFNDEF) 354*da2e3ebdSchin { 355*da2e3ebdSchin *pp.control &= ~SKIP; 356*da2e3ebdSchin goto else_ifdef; 357*da2e3ebdSchin } 358*da2e3ebdSchin conditional: 359*da2e3ebdSchin if (ppexpr(&i1)) 360*da2e3ebdSchin { 361*da2e3ebdSchin *pp.control &= ~SKIP; 362*da2e3ebdSchin *pp.control |= KEPT; 363*da2e3ebdSchin } 364*da2e3ebdSchin else *pp.control |= SKIP; 365*da2e3ebdSchin c = (pp.state & NEWLINE) ? '\n' : ' '; 366*da2e3ebdSchin goto eatdirective; 367*da2e3ebdSchin case ELSE: 368*da2e3ebdSchin if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 369*da2e3ebdSchin goto eatdirective; 370*da2e3ebdSchin if ((pp.option & ELSEIF) && (c = pplex()) == T_ID && ((n = (int)hashref(pp.dirtab, pp.token)) == IF || n == IFDEF || n == IFNDEF)) 371*da2e3ebdSchin { 372*da2e3ebdSchin error(1, "#%s %s is non-standard -- use #%s", dirname(directive), dirname(n), dirname(ELIF)); 373*da2e3ebdSchin directive = n; 374*da2e3ebdSchin goto else_if; 375*da2e3ebdSchin } 376*da2e3ebdSchin if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ELSE)); 377*da2e3ebdSchin else 378*da2e3ebdSchin { 379*da2e3ebdSchin if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard; 380*da2e3ebdSchin if (!(*pp.control & KEPT)) 381*da2e3ebdSchin { 382*da2e3ebdSchin *pp.control &= ~SKIP; 383*da2e3ebdSchin *pp.control |= HADELSE|KEPT; 384*da2e3ebdSchin } 385*da2e3ebdSchin else 386*da2e3ebdSchin { 387*da2e3ebdSchin if (*pp.control & HADELSE) error(2, "more than one #%s for #%s", dirname(ELSE), dirname(IF)); 388*da2e3ebdSchin *pp.control |= HADELSE|SKIP; 389*da2e3ebdSchin } 390*da2e3ebdSchin } 391*da2e3ebdSchin goto enddirective; 392*da2e3ebdSchin case ENDIF: 393*da2e3ebdSchin if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 394*da2e3ebdSchin goto eatdirective; 395*da2e3ebdSchin if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ENDIF)); 396*da2e3ebdSchin else if (--pp.control == pp.in->control && pp.in->symbol) 397*da2e3ebdSchin { 398*da2e3ebdSchin if (pp.in->flags & IN_endguard) pp.in->flags |= IN_noguard; 399*da2e3ebdSchin else 400*da2e3ebdSchin { 401*da2e3ebdSchin pp.in->flags &= ~IN_tokens; 402*da2e3ebdSchin pp.in->flags |= IN_endguard; 403*da2e3ebdSchin } 404*da2e3ebdSchin } 405*da2e3ebdSchin goto enddirective; 406*da2e3ebdSchin case IF: 407*da2e3ebdSchin case IFDEF: 408*da2e3ebdSchin case IFNDEF: 409*da2e3ebdSchin if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 410*da2e3ebdSchin goto eatdirective; 411*da2e3ebdSchin pushcontrol(); 412*da2e3ebdSchin SETIFBLOCK(pp.control); 413*da2e3ebdSchin if (*pp.control & SKIP) 414*da2e3ebdSchin { 415*da2e3ebdSchin *pp.control |= KEPT; 416*da2e3ebdSchin goto eatdirective; 417*da2e3ebdSchin } 418*da2e3ebdSchin if (directive == IF) goto conditional; 419*da2e3ebdSchin else_ifdef: 420*da2e3ebdSchin if ((c = pplex()) == T_ID) 421*da2e3ebdSchin { 422*da2e3ebdSchin sym = pprefmac(pp.token, REF_IF); 423*da2e3ebdSchin if (directive == IFNDEF && pp.control == pp.in->control + 1) 424*da2e3ebdSchin { 425*da2e3ebdSchin if (pp.in->flags & (IN_defguard|IN_endguard)) 426*da2e3ebdSchin pp.in->flags |= IN_noguard; 427*da2e3ebdSchin else 428*da2e3ebdSchin { 429*da2e3ebdSchin pp.in->flags |= IN_defguard; 430*da2e3ebdSchin if (!(pp.in->flags & IN_tokens)) 431*da2e3ebdSchin pp.in->symbol = sym ? sym : pprefmac(pp.token, REF_CREATE); 432*da2e3ebdSchin } 433*da2e3ebdSchin } 434*da2e3ebdSchin } 435*da2e3ebdSchin else 436*da2e3ebdSchin { 437*da2e3ebdSchin sym = 0; 438*da2e3ebdSchin if (!(pp.mode & HOSTED)) 439*da2e3ebdSchin error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 440*da2e3ebdSchin } 441*da2e3ebdSchin *pp.control |= ((sym != 0) == (directive == IFDEF)) ? KEPT : SKIP; 442*da2e3ebdSchin goto enddirective; 443*da2e3ebdSchin case INCLUDE: 444*da2e3ebdSchin if (*pp.control & SKIP) 445*da2e3ebdSchin { 446*da2e3ebdSchin pp.state |= HEADER; 447*da2e3ebdSchin c = pplex(); 448*da2e3ebdSchin pp.state &= ~HEADER; 449*da2e3ebdSchin goto eatdirective; 450*da2e3ebdSchin } 451*da2e3ebdSchin pp.state &= ~DISABLE; 452*da2e3ebdSchin pp.state |= HEADER|STRIP; 453*da2e3ebdSchin switch (c = pplex()) 454*da2e3ebdSchin { 455*da2e3ebdSchin case T_STRING: 456*da2e3ebdSchin p = pp.token; 457*da2e3ebdSchin do pp.token = pp.toknxt; while ((c = pplex()) == T_STRING); 458*da2e3ebdSchin *pp.token = 0; 459*da2e3ebdSchin pp.token = p; 460*da2e3ebdSchin /*FALLTHROUGH*/ 461*da2e3ebdSchin case T_HEADER: 462*da2e3ebdSchin header: 463*da2e3ebdSchin if (!*pp.token) 464*da2e3ebdSchin { 465*da2e3ebdSchin error(2, "#%s: null file name", dirname(INCLUDE)); 466*da2e3ebdSchin break; 467*da2e3ebdSchin } 468*da2e3ebdSchin if (*pp.token == '/' && !(pp.mode & (HOSTED|RELAX))) 469*da2e3ebdSchin error(1, "#%s: reference to %s is not portable", dirname(INCLUDE), pp.token); 470*da2e3ebdSchin n = ppsearch(pp.token, c, SEARCH_INCLUDE); 471*da2e3ebdSchin break; 472*da2e3ebdSchin case '<': 473*da2e3ebdSchin /* 474*da2e3ebdSchin * HEADEREXPAND|HEADEREXPANDALL gets us here 475*da2e3ebdSchin */ 476*da2e3ebdSchin 477*da2e3ebdSchin if (!(p = pp.hdrbuf) && !(p = pp.hdrbuf = newof(0, char, MAXTOKEN, 0))) 478*da2e3ebdSchin error(3, "out of space"); 479*da2e3ebdSchin pp.state &= ~NOSPACE; 480*da2e3ebdSchin while ((c = pplex()) && c != '>') 481*da2e3ebdSchin { 482*da2e3ebdSchin v = p + 1; 483*da2e3ebdSchin STRCOPY(p, pp.token, s); 484*da2e3ebdSchin if (p == v && *(p - 1) == ' ' && pp.in->type != IN_MACRO) 485*da2e3ebdSchin p--; 486*da2e3ebdSchin } 487*da2e3ebdSchin pp.state |= NOSPACE; 488*da2e3ebdSchin *p++ = 0; 489*da2e3ebdSchin memcpy(pp.token, pp.hdrbuf, p - pp.hdrbuf); 490*da2e3ebdSchin c = T_HEADER; 491*da2e3ebdSchin goto header; 492*da2e3ebdSchin default: 493*da2e3ebdSchin error(2, "#%s: \"...\" or <...> argument expected", dirname(INCLUDE)); 494*da2e3ebdSchin goto eatdirective; 495*da2e3ebdSchin } 496*da2e3ebdSchin goto enddirective; 497*da2e3ebdSchin case 0: 498*da2e3ebdSchin { 499*da2e3ebdSchin regmatch_t match[10]; 500*da2e3ebdSchin 501*da2e3ebdSchin /*UNDENT*/ 502*da2e3ebdSchin p = pp.valbuf; 503*da2e3ebdSchin *p++ = '#'; 504*da2e3ebdSchin STRCOPY(p, pp.token, s); 505*da2e3ebdSchin p0 = p; 506*da2e3ebdSchin pp.mode |= EXPOSE; 507*da2e3ebdSchin pp.state |= HEADER; 508*da2e3ebdSchin p6 = getline(p, &pp.valbuf[MAXTOKEN], 0); 509*da2e3ebdSchin pp.state &= ~HEADER; 510*da2e3ebdSchin pp.mode &= ~EXPOSE; 511*da2e3ebdSchin if (!p6) 512*da2e3ebdSchin { 513*da2e3ebdSchin *p0 = 0; 514*da2e3ebdSchin error(2, "%s: directive too long", pp.valbuf); 515*da2e3ebdSchin c = 0; 516*da2e3ebdSchin goto eatdirective; 517*da2e3ebdSchin } 518*da2e3ebdSchin p1 = p2 = p3 = p4 = 0; 519*da2e3ebdSchin p5 = *p ? p + 1 : 0; 520*da2e3ebdSchin checkmap: 521*da2e3ebdSchin i0 = *p0; 522*da2e3ebdSchin p = pp.valbuf; 523*da2e3ebdSchin var.best = 0; 524*da2e3ebdSchin n = 0; 525*da2e3ebdSchin for (map = (struct map*)pp.maps; map; map = map->next) 526*da2e3ebdSchin if (!(i1 = regexec(&map->re, p, elementsof(match), match, 0))) 527*da2e3ebdSchin { 528*da2e3ebdSchin if ((c = match[0].rm_eo - match[0].rm_so) > n) 529*da2e3ebdSchin { 530*da2e3ebdSchin n = c; 531*da2e3ebdSchin var.best = map; 532*da2e3ebdSchin } 533*da2e3ebdSchin } 534*da2e3ebdSchin else if (i1 != REG_NOMATCH) 535*da2e3ebdSchin regfatal(&map->re, 3, i1); 536*da2e3ebdSchin c = '\n'; 537*da2e3ebdSchin if (map = var.best) 538*da2e3ebdSchin { 539*da2e3ebdSchin if ((pp.state & (STRICT|WARN)) && !(pp.mode & (HOSTED|RELAX))) 540*da2e3ebdSchin { 541*da2e3ebdSchin *p0 = 0; 542*da2e3ebdSchin if (!(pp.state & WARN) || strcmp(p + 1, dirname(PRAGMA))) 543*da2e3ebdSchin error(1, "%s: non-standard directive", p); 544*da2e3ebdSchin *p0 = i0; 545*da2e3ebdSchin } 546*da2e3ebdSchin if (!(*pp.control & SKIP)) 547*da2e3ebdSchin { 548*da2e3ebdSchin n = 0; 549*da2e3ebdSchin for (edit = map->edit; edit; edit = edit->next) 550*da2e3ebdSchin if (!(i0 = regexec(&edit->re, p, elementsof(match), match, 0))) 551*da2e3ebdSchin { 552*da2e3ebdSchin n++; 553*da2e3ebdSchin if (i0 = regsubexec(&edit->re, p, elementsof(match), match)) 554*da2e3ebdSchin regfatal(&edit->re, 3, i0); 555*da2e3ebdSchin p = edit->re.re_sub->re_buf; 556*da2e3ebdSchin if (edit->re.re_sub->re_flags & REG_SUB_STOP) 557*da2e3ebdSchin break; 558*da2e3ebdSchin } 559*da2e3ebdSchin else if (i0 != REG_NOMATCH) 560*da2e3ebdSchin regfatal(&edit->re, 3, i0); 561*da2e3ebdSchin if (n && *p) 562*da2e3ebdSchin { 563*da2e3ebdSchin p1 = s = oldof(0, char, 0, strlen(p) + 32); 564*da2e3ebdSchin while (*s = *p++) s++; 565*da2e3ebdSchin debug((-4, "map: %s", p1)); 566*da2e3ebdSchin *s++ = '\n'; 567*da2e3ebdSchin *s = 0; 568*da2e3ebdSchin error_info.line++; 569*da2e3ebdSchin PUSH_RESCAN(p1); 570*da2e3ebdSchin error_info.line--; 571*da2e3ebdSchin directive = LINE; 572*da2e3ebdSchin } 573*da2e3ebdSchin } 574*da2e3ebdSchin goto donedirective; 575*da2e3ebdSchin } 576*da2e3ebdSchin if (directive != PRAGMA && (!(*pp.control & SKIP) || !(pp.mode & (HOSTED|RELAX)))) 577*da2e3ebdSchin { 578*da2e3ebdSchin *p0 = 0; 579*da2e3ebdSchin error(1, "%s: unknown directive", pptokstr(pp.valbuf, 0)); 580*da2e3ebdSchin *p0 = i0; 581*da2e3ebdSchin } 582*da2e3ebdSchin pass: 583*da2e3ebdSchin if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT) && (directive == PRAGMA || !(pp.mode & INIT))) 584*da2e3ebdSchin { 585*da2e3ebdSchin *p0 = 0; 586*da2e3ebdSchin if (p2) *p2 = 0; 587*da2e3ebdSchin if (p4) 588*da2e3ebdSchin { 589*da2e3ebdSchin if (p4 == p5) 590*da2e3ebdSchin { 591*da2e3ebdSchin p5 = strcpy(pp.tmpbuf, p5); 592*da2e3ebdSchin if (p = strchr(p5, MARK)) 593*da2e3ebdSchin { 594*da2e3ebdSchin s = p; 595*da2e3ebdSchin while (*p) 596*da2e3ebdSchin if ((*s++ = *p++) == MARK && *p == MARK) p++; 597*da2e3ebdSchin *s = 0; 598*da2e3ebdSchin } 599*da2e3ebdSchin } 600*da2e3ebdSchin *p4 = 0; 601*da2e3ebdSchin } 602*da2e3ebdSchin if (p = (char*)memchr(pp.valbuf + 1, MARK, p6 - pp.valbuf - 1)) 603*da2e3ebdSchin { 604*da2e3ebdSchin s = p; 605*da2e3ebdSchin while (p < p6) switch (*s++ = *p++) 606*da2e3ebdSchin { 607*da2e3ebdSchin case 0: 608*da2e3ebdSchin s = p; 609*da2e3ebdSchin break; 610*da2e3ebdSchin case MARK: 611*da2e3ebdSchin p++; 612*da2e3ebdSchin break; 613*da2e3ebdSchin } 614*da2e3ebdSchin *s = 0; 615*da2e3ebdSchin } 616*da2e3ebdSchin (*pp.pragma)(pp.valbuf + 1, p1, p3, p5, (pp.state & COMPILE) || (pp.mode & INIT) != 0); 617*da2e3ebdSchin emitted = 1; 618*da2e3ebdSchin } 619*da2e3ebdSchin goto donedirective; 620*da2e3ebdSchin 621*da2e3ebdSchin /*INDENT*/ 622*da2e3ebdSchin } 623*da2e3ebdSchin } 624*da2e3ebdSchin if (*pp.control & SKIP) goto eatdirective; 625*da2e3ebdSchin switch (directive) 626*da2e3ebdSchin { 627*da2e3ebdSchin #if MACDEF 628*da2e3ebdSchin case ENDMAC: 629*da2e3ebdSchin c = pplex(); 630*da2e3ebdSchin error(2, "no matching #%s for #%s", dirname(MACDEF), dirname(ENDMAC)); 631*da2e3ebdSchin goto enddirective; 632*da2e3ebdSchin #endif 633*da2e3ebdSchin #if MACDEF 634*da2e3ebdSchin case MACDEF: 635*da2e3ebdSchin if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 636*da2e3ebdSchin error(1, "#%s: non-standard directive", pp.token); 637*da2e3ebdSchin /*FALLTHROUGH*/ 638*da2e3ebdSchin #endif 639*da2e3ebdSchin case DEFINE: 640*da2e3ebdSchin n2 = error_info.line; 641*da2e3ebdSchin if ((c = pplex()) == '#' && directive == DEFINE) 642*da2e3ebdSchin goto assertion; 643*da2e3ebdSchin if (c == '<') 644*da2e3ebdSchin { 645*da2e3ebdSchin n = 1; 646*da2e3ebdSchin c = pplex(); 647*da2e3ebdSchin } 648*da2e3ebdSchin else 649*da2e3ebdSchin n = 0; 650*da2e3ebdSchin if (!(sym = macsym(c))) 651*da2e3ebdSchin goto eatdirective; 652*da2e3ebdSchin if (pp.truncate) 653*da2e3ebdSchin ppfsm(FSM_MACRO, pp.token); 654*da2e3ebdSchin mac = sym->macro; 655*da2e3ebdSchin if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev && mac->value) 656*da2e3ebdSchin goto eatdirective; 657*da2e3ebdSchin if (n) 658*da2e3ebdSchin goto tuple; 659*da2e3ebdSchin old = *mac; 660*da2e3ebdSchin i0 = sym->flags; 661*da2e3ebdSchin sym->flags &= ~(SYM_BUILTIN|SYM_EMPTY|SYM_FINAL|SYM_FUNCTION|SYM_INIT|SYM_INITIAL|SYM_MULTILINE|SYM_NOEXPAND|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 662*da2e3ebdSchin #if MACDEF 663*da2e3ebdSchin if (directive == MACDEF) 664*da2e3ebdSchin sym->flags |= SYM_MULTILINE; 665*da2e3ebdSchin #endif 666*da2e3ebdSchin mac->arity = 0; 667*da2e3ebdSchin mac->formals = 0; 668*da2e3ebdSchin mac->value = 0; 669*da2e3ebdSchin pp.state &= ~NOSPACE; 670*da2e3ebdSchin pp.state |= DEFINITION|NOEXPAND; 671*da2e3ebdSchin switch (c = pplex()) 672*da2e3ebdSchin { 673*da2e3ebdSchin case '(': 674*da2e3ebdSchin sym->flags |= SYM_FUNCTION; 675*da2e3ebdSchin pp.state |= NOSPACE; 676*da2e3ebdSchin #if MACKEYARGS 677*da2e3ebdSchin if (pp.option & KEYARGS) 678*da2e3ebdSchin { 679*da2e3ebdSchin n = 2 * MAXTOKEN; 680*da2e3ebdSchin p = mac->formals = oldof(0, char, 0, n); 681*da2e3ebdSchin if ((c = pplex()) == T_ID) for (;;) 682*da2e3ebdSchin { 683*da2e3ebdSchin if (mac->arity < MAXFORMALS) 684*da2e3ebdSchin { 685*da2e3ebdSchin if (mac->arity) p++; 686*da2e3ebdSchin formargs[mac->arity] = p; 687*da2e3ebdSchin STRAPP(p, pp.token, s); 688*da2e3ebdSchin formvals[mac->arity++] = p1 = p; 689*da2e3ebdSchin if (mac->arity == 1) *p++ = ' '; 690*da2e3ebdSchin *p++ = ' '; 691*da2e3ebdSchin *p = 0; 692*da2e3ebdSchin } 693*da2e3ebdSchin else error(2, "%s: formal argument %s ignored", sym->name, pp.token); 694*da2e3ebdSchin switch (c = pplex()) 695*da2e3ebdSchin { 696*da2e3ebdSchin case '=': 697*da2e3ebdSchin c = pplex(); 698*da2e3ebdSchin break; 699*da2e3ebdSchin case ',': 700*da2e3ebdSchin break; 701*da2e3ebdSchin default: 702*da2e3ebdSchin goto endformals; 703*da2e3ebdSchin } 704*da2e3ebdSchin pp.state &= ~NOSPACE; 705*da2e3ebdSchin p0 = 0; 706*da2e3ebdSchin for (;;) 707*da2e3ebdSchin { 708*da2e3ebdSchin switch (c) 709*da2e3ebdSchin { 710*da2e3ebdSchin case '\n': 711*da2e3ebdSchin goto endformals; 712*da2e3ebdSchin case '(': 713*da2e3ebdSchin p0++; 714*da2e3ebdSchin break; 715*da2e3ebdSchin case ')': 716*da2e3ebdSchin if (!p0--) 717*da2e3ebdSchin { 718*da2e3ebdSchin if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0; 719*da2e3ebdSchin goto endformals; 720*da2e3ebdSchin } 721*da2e3ebdSchin break; 722*da2e3ebdSchin case ',': 723*da2e3ebdSchin if (!p0) 724*da2e3ebdSchin { 725*da2e3ebdSchin if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0; 726*da2e3ebdSchin goto nextformal; 727*da2e3ebdSchin } 728*da2e3ebdSchin break; 729*da2e3ebdSchin case ' ': 730*da2e3ebdSchin if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') continue; 731*da2e3ebdSchin break; 732*da2e3ebdSchin } 733*da2e3ebdSchin STRCOPY(p, pp.token, s); 734*da2e3ebdSchin if (p > &mac->formals[n - MAXTOKEN] && (s = newof(mac->formals, char, n += MAXTOKEN, 0)) != mac->formals) 735*da2e3ebdSchin { 736*da2e3ebdSchin n1 = s - mac->formals; 737*da2e3ebdSchin for (n = 0; n < mac->arity; n++) 738*da2e3ebdSchin { 739*da2e3ebdSchin formargs[n] += n1; 740*da2e3ebdSchin formvals[n] += n1; 741*da2e3ebdSchin } 742*da2e3ebdSchin c = p - mac->formals; 743*da2e3ebdSchin mac->formals = s; 744*da2e3ebdSchin p = mac->formals + c; 745*da2e3ebdSchin } 746*da2e3ebdSchin c = pplex(); 747*da2e3ebdSchin } 748*da2e3ebdSchin nextformal: 749*da2e3ebdSchin pp.state |= NOSPACE; 750*da2e3ebdSchin if ((c = pplex()) != T_ID) 751*da2e3ebdSchin { 752*da2e3ebdSchin c = ','; 753*da2e3ebdSchin break; 754*da2e3ebdSchin } 755*da2e3ebdSchin } 756*da2e3ebdSchin endformals: /*NOP*/; 757*da2e3ebdSchin } 758*da2e3ebdSchin else 759*da2e3ebdSchin #endif 760*da2e3ebdSchin { 761*da2e3ebdSchin p = mac->formals = oldof(0, char, 0, MAXFORMALS * (MAXID + 1)); 762*da2e3ebdSchin c = pplex(); 763*da2e3ebdSchin #if COMPATIBLE 764*da2e3ebdSchin if ((pp.state & COMPATIBILITY) && c == ',') 765*da2e3ebdSchin { 766*da2e3ebdSchin if ((pp.state & WARN) && !(pp.mode & HOSTED)) 767*da2e3ebdSchin error(1, "%s: macro formal argument expected", sym->name); 768*da2e3ebdSchin while ((c = pplex()) == ','); 769*da2e3ebdSchin } 770*da2e3ebdSchin #endif 771*da2e3ebdSchin for (;;) 772*da2e3ebdSchin { 773*da2e3ebdSchin if (c == T_VARIADIC) 774*da2e3ebdSchin { 775*da2e3ebdSchin if (sym->flags & SYM_VARIADIC) 776*da2e3ebdSchin error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token); 777*da2e3ebdSchin sym->flags |= SYM_VARIADIC; 778*da2e3ebdSchin v = __va_args__; 779*da2e3ebdSchin } 780*da2e3ebdSchin else if (c == T_ID) 781*da2e3ebdSchin { 782*da2e3ebdSchin v = pp.token; 783*da2e3ebdSchin if (sym->flags & SYM_VARIADIC) 784*da2e3ebdSchin error(2, "%s: %s: macro formal argument cannot follow ...", sym->name, v); 785*da2e3ebdSchin else if (streq(v, __va_args__)) 786*da2e3ebdSchin error(2, "%s: %s: invalid macro formal argument", sym->name, v); 787*da2e3ebdSchin } 788*da2e3ebdSchin else 789*da2e3ebdSchin break; 790*da2e3ebdSchin if (mac->arity < MAXFORMALS) 791*da2e3ebdSchin { 792*da2e3ebdSchin for (n = 0; n < mac->arity; n++) 793*da2e3ebdSchin if (streq(formargs[n], v)) 794*da2e3ebdSchin error(2, "%s: %s: duplicate macro formal argument", sym->name, v); 795*da2e3ebdSchin formargs[mac->arity++] = p; 796*da2e3ebdSchin STRAPP(p, v, s); 797*da2e3ebdSchin } 798*da2e3ebdSchin else 799*da2e3ebdSchin error(2, "%s: %s: macro formal argument ignored", sym->name, v); 800*da2e3ebdSchin if ((c = pplex()) == ',') 801*da2e3ebdSchin { 802*da2e3ebdSchin c = pplex(); 803*da2e3ebdSchin #if COMPATIBLE 804*da2e3ebdSchin if ((pp.state & COMPATIBILITY) && c == ',') 805*da2e3ebdSchin { 806*da2e3ebdSchin if ((pp.state & WARN) && !(pp.mode & HOSTED)) 807*da2e3ebdSchin error(1, "%s: macro formal argument expected", sym->name); 808*da2e3ebdSchin while ((c = pplex()) == ','); 809*da2e3ebdSchin } 810*da2e3ebdSchin #endif 811*da2e3ebdSchin } 812*da2e3ebdSchin else if (c != T_VARIADIC) 813*da2e3ebdSchin break; 814*da2e3ebdSchin else 815*da2e3ebdSchin { 816*da2e3ebdSchin if (sym->flags & SYM_VARIADIC) 817*da2e3ebdSchin error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token); 818*da2e3ebdSchin sym->flags |= SYM_VARIADIC; 819*da2e3ebdSchin c = pplex(); 820*da2e3ebdSchin break; 821*da2e3ebdSchin } 822*da2e3ebdSchin } 823*da2e3ebdSchin if (mac->arity && (s = newof(mac->formals, char, p - mac->formals, 0)) != mac->formals) 824*da2e3ebdSchin { 825*da2e3ebdSchin n1 = s - mac->formals; 826*da2e3ebdSchin for (n = 0; n < mac->arity; n++) 827*da2e3ebdSchin formargs[n] += n1; 828*da2e3ebdSchin mac->formals = s; 829*da2e3ebdSchin } 830*da2e3ebdSchin } 831*da2e3ebdSchin if (!mac->arity) 832*da2e3ebdSchin { 833*da2e3ebdSchin free(mac->formals); 834*da2e3ebdSchin mac->formals = 0; 835*da2e3ebdSchin } 836*da2e3ebdSchin switch (c) 837*da2e3ebdSchin { 838*da2e3ebdSchin case ')': 839*da2e3ebdSchin #if MACKEYARGS 840*da2e3ebdSchin pp.state |= NOEXPAND|NOSPACE; 841*da2e3ebdSchin #else 842*da2e3ebdSchin pp.state |= NOEXPAND; 843*da2e3ebdSchin #endif 844*da2e3ebdSchin c = pplex(); 845*da2e3ebdSchin break; 846*da2e3ebdSchin default: 847*da2e3ebdSchin error(2, "%s: invalid macro formal argument list", sym->name); 848*da2e3ebdSchin if (mac->formals) 849*da2e3ebdSchin { 850*da2e3ebdSchin free(mac->formals); 851*da2e3ebdSchin mac->formals = 0; 852*da2e3ebdSchin mac->arity = 0; 853*da2e3ebdSchin } 854*da2e3ebdSchin free(mac); 855*da2e3ebdSchin sym->macro = 0; 856*da2e3ebdSchin goto eatdirective; 857*da2e3ebdSchin } 858*da2e3ebdSchin pp.state &= ~NOSPACE; 859*da2e3ebdSchin break; 860*da2e3ebdSchin case ' ': 861*da2e3ebdSchin case '\t': 862*da2e3ebdSchin c = pplex(); 863*da2e3ebdSchin break; 864*da2e3ebdSchin } 865*da2e3ebdSchin n = 2 * MAXTOKEN; 866*da2e3ebdSchin #if MACKEYARGS 867*da2e3ebdSchin p1 = p; 868*da2e3ebdSchin #endif 869*da2e3ebdSchin p = mac->value = oldof(0, char, 0, n); 870*da2e3ebdSchin var.type = 0; 871*da2e3ebdSchin n1 = 0; 872*da2e3ebdSchin #if MACDEF 873*da2e3ebdSchin i2 = i3 = 0; 874*da2e3ebdSchin n3 = pp.state; 875*da2e3ebdSchin #endif 876*da2e3ebdSchin if ((pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 877*da2e3ebdSchin switch (c) 878*da2e3ebdSchin { 879*da2e3ebdSchin case '+': 880*da2e3ebdSchin case '-': 881*da2e3ebdSchin case '&': 882*da2e3ebdSchin case '|': 883*da2e3ebdSchin case '<': 884*da2e3ebdSchin case '>': 885*da2e3ebdSchin case ':': 886*da2e3ebdSchin case '=': 887*da2e3ebdSchin *p++ = ' '; 888*da2e3ebdSchin break; 889*da2e3ebdSchin } 890*da2e3ebdSchin o = 0; 891*da2e3ebdSchin for (;;) 892*da2e3ebdSchin { 893*da2e3ebdSchin switch (c) 894*da2e3ebdSchin { 895*da2e3ebdSchin case T_ID: 896*da2e3ebdSchin for (c = 0; c < mac->arity; c++) 897*da2e3ebdSchin if (streq(formargs[c], pp.token)) 898*da2e3ebdSchin { 899*da2e3ebdSchin #if COMPATIBLE 900*da2e3ebdSchin if (!(pp.state & COMPATIBILITY)) 901*da2e3ebdSchin #endif 902*da2e3ebdSchin if (var.type != TOK_TOKCAT && p > mac->value && *(p - 1) != ' ' && !(pp.option & PRESERVE)) *p++ = ' '; 903*da2e3ebdSchin *p++ = MARK; 904*da2e3ebdSchin #if COMPATIBLE 905*da2e3ebdSchin if ((pp.state & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) *p++ = 'C'; 906*da2e3ebdSchin else 907*da2e3ebdSchin #endif 908*da2e3ebdSchin *p++ = (n1 || var.type == TOK_TOKCAT) ? 'C' : 'A'; 909*da2e3ebdSchin *p++ = c + ARGOFFSET; 910*da2e3ebdSchin var.type = TOK_FORMAL|TOK_ID; 911*da2e3ebdSchin c = '>'; 912*da2e3ebdSchin goto checkvalue; 913*da2e3ebdSchin } 914*da2e3ebdSchin if (var.type == TOK_BUILTIN) switch ((int)hashget(pp.strtab, pp.token)) 915*da2e3ebdSchin { 916*da2e3ebdSchin case V_DEFAULT: 917*da2e3ebdSchin case V_EMPTY: 918*da2e3ebdSchin sym->flags |= SYM_EMPTY; 919*da2e3ebdSchin break; 920*da2e3ebdSchin } 921*da2e3ebdSchin else if (pp.hiding && (var.symbol = ppsymref(pp.symtab, pp.token)) && var.symbol->hidden) 922*da2e3ebdSchin { 923*da2e3ebdSchin for (var.inp = pp.in; var.inp->type != IN_FILE && var.inp->prev; var.inp = var.inp->prev); 924*da2e3ebdSchin p += sfsprintf(p, MAXTOKEN, "_%d_%s_hIDe", var.inp->hide, pp.token); 925*da2e3ebdSchin var.type = TOK_ID; 926*da2e3ebdSchin goto checkvalue; 927*da2e3ebdSchin } 928*da2e3ebdSchin var.type = TOK_ID; 929*da2e3ebdSchin break; 930*da2e3ebdSchin case '#': 931*da2e3ebdSchin var.type = 0; 932*da2e3ebdSchin #if MACDEF 933*da2e3ebdSchin if (!(sym->flags & (SYM_FUNCTION|SYM_MULTILINE))) break; 934*da2e3ebdSchin #else 935*da2e3ebdSchin if (!(sym->flags & SYM_FUNCTION)) break; 936*da2e3ebdSchin #endif 937*da2e3ebdSchin pp.state |= NOSPACE; 938*da2e3ebdSchin c = pplex(); 939*da2e3ebdSchin if (c == '@') 940*da2e3ebdSchin { 941*da2e3ebdSchin c = pplex(); 942*da2e3ebdSchin i4 = 'S'; 943*da2e3ebdSchin } 944*da2e3ebdSchin else i4 = 'Q'; 945*da2e3ebdSchin pp.state &= ~NOSPACE; 946*da2e3ebdSchin if (c != T_ID) c = mac->arity; 947*da2e3ebdSchin else for (c = 0; c < mac->arity; c++) 948*da2e3ebdSchin if (streq(formargs[c], pp.token)) 949*da2e3ebdSchin break; 950*da2e3ebdSchin if (c >= mac->arity) 951*da2e3ebdSchin { 952*da2e3ebdSchin #if MACDEF 953*da2e3ebdSchin if (sym->flags & SYM_MULTILINE) 954*da2e3ebdSchin { 955*da2e3ebdSchin if (n3 & NEWLINE) 956*da2e3ebdSchin { 957*da2e3ebdSchin pp.state &= ~NOEXPAND; 958*da2e3ebdSchin switch ((int)hashref(pp.dirtab, pp.token)) 959*da2e3ebdSchin { 960*da2e3ebdSchin case ENDMAC: 961*da2e3ebdSchin if (!i2--) goto gotdefinition; 962*da2e3ebdSchin break; 963*da2e3ebdSchin case INCLUDE: 964*da2e3ebdSchin /* PARSE HEADER constant */ 965*da2e3ebdSchin break; 966*da2e3ebdSchin case MACDEF: 967*da2e3ebdSchin i2++; 968*da2e3ebdSchin break; 969*da2e3ebdSchin } 970*da2e3ebdSchin *p++ = '#'; 971*da2e3ebdSchin } 972*da2e3ebdSchin } 973*da2e3ebdSchin else 974*da2e3ebdSchin #endif 975*da2e3ebdSchin #if COMPATIBLE 976*da2e3ebdSchin if (pp.state & COMPATIBILITY) *p++ = '#'; 977*da2e3ebdSchin else 978*da2e3ebdSchin #endif 979*da2e3ebdSchin error(2, "# must precede a formal parameter"); 980*da2e3ebdSchin } 981*da2e3ebdSchin else 982*da2e3ebdSchin { 983*da2e3ebdSchin if (p > mac->value && ppisidig(*(p - 1)) && !(pp.option & PRESERVE)) *p++ = ' '; 984*da2e3ebdSchin *p++ = MARK; 985*da2e3ebdSchin *p++ = i4; 986*da2e3ebdSchin *p++ = c + ARGOFFSET; 987*da2e3ebdSchin goto checkvalue; 988*da2e3ebdSchin } 989*da2e3ebdSchin break; 990*da2e3ebdSchin case T_TOKCAT: 991*da2e3ebdSchin if (p <= mac->value) error(2, "%s lhs operand omitted", pp.token); 992*da2e3ebdSchin else 993*da2e3ebdSchin { 994*da2e3ebdSchin if (*(p - 1) == ' ') p--; 995*da2e3ebdSchin if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C'; 996*da2e3ebdSchin } 997*da2e3ebdSchin pp.state |= NOSPACE; 998*da2e3ebdSchin c = pplex(); 999*da2e3ebdSchin pp.state &= ~NOSPACE; 1000*da2e3ebdSchin if (c == '\n') error(2, "%s rhs operand omitted", pptokchr(T_TOKCAT)); 1001*da2e3ebdSchin var.type = TOK_TOKCAT; 1002*da2e3ebdSchin continue; 1003*da2e3ebdSchin case '(': 1004*da2e3ebdSchin if (*pp.token == '#') 1005*da2e3ebdSchin { 1006*da2e3ebdSchin var.type = TOK_BUILTIN; 1007*da2e3ebdSchin n1++; 1008*da2e3ebdSchin } 1009*da2e3ebdSchin else 1010*da2e3ebdSchin { 1011*da2e3ebdSchin var.type = 0; 1012*da2e3ebdSchin if (n1) n1++; 1013*da2e3ebdSchin } 1014*da2e3ebdSchin break; 1015*da2e3ebdSchin case ')': 1016*da2e3ebdSchin var.type = 0; 1017*da2e3ebdSchin if (n1) n1--; 1018*da2e3ebdSchin break; 1019*da2e3ebdSchin case T_STRING: 1020*da2e3ebdSchin case T_CHARCONST: 1021*da2e3ebdSchin pp.state &= ~NOEXPAND; 1022*da2e3ebdSchin var.type = 0; 1023*da2e3ebdSchin if (strchr(pp.token, MARK)) pp.state &= ~NOEXPAND; 1024*da2e3ebdSchin #if COMPATIBLE 1025*da2e3ebdSchin /*UNDENT*/ 1026*da2e3ebdSchin 1027*da2e3ebdSchin if ((sym->flags & SYM_FUNCTION) && (pp.state & (COMPATIBILITY|TRANSITION))) 1028*da2e3ebdSchin { 1029*da2e3ebdSchin char* v; 1030*da2e3ebdSchin 1031*da2e3ebdSchin s = pp.token; 1032*da2e3ebdSchin for (;;) 1033*da2e3ebdSchin { 1034*da2e3ebdSchin if (!*s) goto checkvalue; 1035*da2e3ebdSchin if (ppisid(*s)) 1036*da2e3ebdSchin { 1037*da2e3ebdSchin v = s; 1038*da2e3ebdSchin while (ppisid(*++s)); 1039*da2e3ebdSchin i1 = *s; 1040*da2e3ebdSchin *s = 0; 1041*da2e3ebdSchin for (c = 0; c < mac->arity; c++) 1042*da2e3ebdSchin if (streq(formargs[c], v)) 1043*da2e3ebdSchin { 1044*da2e3ebdSchin *p++ = MARK; 1045*da2e3ebdSchin *p++ = 'C'; 1046*da2e3ebdSchin *p++ = c + ARGOFFSET; 1047*da2e3ebdSchin if (!(pp.mode & HOSTED) && (!(pp.state & COMPATIBILITY) || (pp.state & WARN))) switch (*pp.token) 1048*da2e3ebdSchin { 1049*da2e3ebdSchin case '"': 1050*da2e3ebdSchin error(1, "use the # operator to \"...\" quote macro arguments"); 1051*da2e3ebdSchin break; 1052*da2e3ebdSchin case '\'': 1053*da2e3ebdSchin error(1, "macro arguments should be '...' quoted before substitution"); 1054*da2e3ebdSchin break; 1055*da2e3ebdSchin } 1056*da2e3ebdSchin goto quotearg; 1057*da2e3ebdSchin } 1058*da2e3ebdSchin STRCOPY2(p, v); 1059*da2e3ebdSchin quotearg: 1060*da2e3ebdSchin *s = i1; 1061*da2e3ebdSchin } 1062*da2e3ebdSchin else *p++ = *s++; 1063*da2e3ebdSchin } 1064*da2e3ebdSchin } 1065*da2e3ebdSchin /*INDENT*/ 1066*da2e3ebdSchin #endif 1067*da2e3ebdSchin break; 1068*da2e3ebdSchin case '\n': 1069*da2e3ebdSchin #if MACDEF 1070*da2e3ebdSchin if (sym->flags & SYM_MULTILINE) 1071*da2e3ebdSchin { 1072*da2e3ebdSchin if (pp.state & EOF2NL) 1073*da2e3ebdSchin { 1074*da2e3ebdSchin error_info.line++; 1075*da2e3ebdSchin pp.state |= HIDDEN; 1076*da2e3ebdSchin pp.hidden++; 1077*da2e3ebdSchin var.type = 0; 1078*da2e3ebdSchin if (!i3++) 1079*da2e3ebdSchin goto checkvalue; 1080*da2e3ebdSchin break; 1081*da2e3ebdSchin } 1082*da2e3ebdSchin pp.state |= EOF2NL; 1083*da2e3ebdSchin error(2, "%s: missing #%s", sym->name, dirname(ENDMAC)); 1084*da2e3ebdSchin } 1085*da2e3ebdSchin #endif 1086*da2e3ebdSchin goto gotdefinition; 1087*da2e3ebdSchin case 0: 1088*da2e3ebdSchin c = '\n'; 1089*da2e3ebdSchin goto gotdefinition; 1090*da2e3ebdSchin #if COMPATIBLE 1091*da2e3ebdSchin case ' ': 1092*da2e3ebdSchin if (pp.state & COMPATIBILITY) var.type = 0; 1093*da2e3ebdSchin if (pp.option & PRESERVE) break; 1094*da2e3ebdSchin if (p > mac->value && *(p - 1) != ' ') *p++ = ' '; 1095*da2e3ebdSchin goto checkvalue; 1096*da2e3ebdSchin case '\t': 1097*da2e3ebdSchin if (var.type & TOK_ID) 1098*da2e3ebdSchin { 1099*da2e3ebdSchin while ((c = pplex()) == '\t'); 1100*da2e3ebdSchin if (c == T_ID) 1101*da2e3ebdSchin { 1102*da2e3ebdSchin if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C'; 1103*da2e3ebdSchin var.type = TOK_TOKCAT; 1104*da2e3ebdSchin if (pp.state & WARN) error(1, "use the ## operator to concatenate macro arguments"); 1105*da2e3ebdSchin } 1106*da2e3ebdSchin else var.type = 0; 1107*da2e3ebdSchin continue; 1108*da2e3ebdSchin } 1109*da2e3ebdSchin var.type = 0; 1110*da2e3ebdSchin if (pp.option & PRESERVE) break; 1111*da2e3ebdSchin if (p > mac->value && *(p - 1) != ' ') *p++ = ' '; 1112*da2e3ebdSchin goto checkvalue; 1113*da2e3ebdSchin #endif 1114*da2e3ebdSchin case MARK: 1115*da2e3ebdSchin pp.state &= ~NOEXPAND; 1116*da2e3ebdSchin /*FALLTHROUGH*/ 1117*da2e3ebdSchin 1118*da2e3ebdSchin default: 1119*da2e3ebdSchin var.type = 0; 1120*da2e3ebdSchin break; 1121*da2e3ebdSchin } 1122*da2e3ebdSchin STRCOPY(p, pp.token, s); 1123*da2e3ebdSchin checkvalue: 1124*da2e3ebdSchin o = c; 1125*da2e3ebdSchin if (p > &mac->value[n - MAXTOKEN] && (s = newof(mac->value, char, n += MAXTOKEN, 0)) != mac->value) 1126*da2e3ebdSchin { 1127*da2e3ebdSchin c = p - mac->value; 1128*da2e3ebdSchin mac->value = s; 1129*da2e3ebdSchin p = mac->value + c; 1130*da2e3ebdSchin } 1131*da2e3ebdSchin #if MACDEF 1132*da2e3ebdSchin n3 = pp.state; 1133*da2e3ebdSchin #endif 1134*da2e3ebdSchin c = pplex(); 1135*da2e3ebdSchin } 1136*da2e3ebdSchin gotdefinition: 1137*da2e3ebdSchin while (p > mac->value && *(p - 1) == ' ') p--; 1138*da2e3ebdSchin if (p > mac->value && (pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 1139*da2e3ebdSchin switch (o) 1140*da2e3ebdSchin { 1141*da2e3ebdSchin case '+': 1142*da2e3ebdSchin case '-': 1143*da2e3ebdSchin case '&': 1144*da2e3ebdSchin case '|': 1145*da2e3ebdSchin case '<': 1146*da2e3ebdSchin case '>': 1147*da2e3ebdSchin case ':': 1148*da2e3ebdSchin case '=': 1149*da2e3ebdSchin *p++ = ' '; 1150*da2e3ebdSchin break; 1151*da2e3ebdSchin } 1152*da2e3ebdSchin *p = 0; 1153*da2e3ebdSchin #if MACKEYARGS 1154*da2e3ebdSchin if (!mac->arity) /* ok */; 1155*da2e3ebdSchin else if (pp.option & KEYARGS) 1156*da2e3ebdSchin { 1157*da2e3ebdSchin p0 = mac->formals; 1158*da2e3ebdSchin mac->formkeys = newof(0, struct ppkeyarg, n, p1 - p0 + 1); 1159*da2e3ebdSchin s = (char*)&mac->formkeys[mac->arity]; 1160*da2e3ebdSchin (void)memcpy(s, p0, p1 - p0 + 1); 1161*da2e3ebdSchin free(p0); 1162*da2e3ebdSchin for (n = 0; n < mac->arity; n++) 1163*da2e3ebdSchin { 1164*da2e3ebdSchin mac->formkeys[n].name = s + (formargs[n] - p0); 1165*da2e3ebdSchin mac->formkeys[n].value = s + (formvals[n] - p0); 1166*da2e3ebdSchin } 1167*da2e3ebdSchin } 1168*da2e3ebdSchin else 1169*da2e3ebdSchin #endif 1170*da2e3ebdSchin for (n = 1; n < mac->arity; n++) 1171*da2e3ebdSchin *(formargs[n] - 1) = ','; 1172*da2e3ebdSchin if (old.value) 1173*da2e3ebdSchin { 1174*da2e3ebdSchin if ((i0 & SYM_FUNCTION) != (sym->flags & SYM_FUNCTION) || old.arity != mac->arity || !streq(old.value, mac->value)) goto redefined; 1175*da2e3ebdSchin if (!old.formals) 1176*da2e3ebdSchin { 1177*da2e3ebdSchin if (mac->formals) goto redefined; 1178*da2e3ebdSchin } 1179*da2e3ebdSchin else if (mac->formals) 1180*da2e3ebdSchin { 1181*da2e3ebdSchin #if MACKEYARGS 1182*da2e3ebdSchin if (pp.option & KEYARGS) 1183*da2e3ebdSchin { 1184*da2e3ebdSchin for (n = 0; n < mac->arity; n++) 1185*da2e3ebdSchin if (!streq(mac->formkeys[n].name, old.formkeys[n].name) || !streq(mac->formkeys[n].value, old.formkeys[n].value)) 1186*da2e3ebdSchin goto redefined; 1187*da2e3ebdSchin } 1188*da2e3ebdSchin else 1189*da2e3ebdSchin #endif 1190*da2e3ebdSchin if (!streq(mac->formals, old.formals)) goto redefined; 1191*da2e3ebdSchin } 1192*da2e3ebdSchin #if MACKEYARGS 1193*da2e3ebdSchin if (pp.option & KEYARGS) 1194*da2e3ebdSchin { 1195*da2e3ebdSchin if (mac->formkeys) free(mac->formkeys); 1196*da2e3ebdSchin mac->formkeys = old.formkeys; 1197*da2e3ebdSchin } 1198*da2e3ebdSchin else 1199*da2e3ebdSchin #endif 1200*da2e3ebdSchin { 1201*da2e3ebdSchin if (mac->formals) free(mac->formals); 1202*da2e3ebdSchin mac->formals = old.formals; 1203*da2e3ebdSchin } 1204*da2e3ebdSchin free(mac->value); 1205*da2e3ebdSchin mac->value = old.value; 1206*da2e3ebdSchin goto benign; 1207*da2e3ebdSchin redefined: 1208*da2e3ebdSchin if (!(pp.mode & HOSTED) || !(i0 & SYM_INITIAL)) 1209*da2e3ebdSchin error(1, "%s redefined", sym->name); 1210*da2e3ebdSchin #if MACKEYARGS 1211*da2e3ebdSchin if ((pp.option & KEYARGS) && mac->formkeys) 1212*da2e3ebdSchin free(mac->formkeys); 1213*da2e3ebdSchin #endif 1214*da2e3ebdSchin #if MACKEYARGS 1215*da2e3ebdSchin if (!(pp.option & KEYARGS)) 1216*da2e3ebdSchin #endif 1217*da2e3ebdSchin if (old.formals) free(old.formals); 1218*da2e3ebdSchin free(old.value); 1219*da2e3ebdSchin } 1220*da2e3ebdSchin else if (!pp.truncate) ppfsm(FSM_MACRO, sym->name); 1221*da2e3ebdSchin mac->value = newof(mac->value, char, (mac->size = p - mac->value) + 1, 0); 1222*da2e3ebdSchin if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT))) 1223*da2e3ebdSchin { 1224*da2e3ebdSchin ppsync(); 1225*da2e3ebdSchin ppprintf("#%s %s", dirname(DEFINE), sym->name); 1226*da2e3ebdSchin if (sym->flags & SYM_FUNCTION) 1227*da2e3ebdSchin { 1228*da2e3ebdSchin ppputchar('('); 1229*da2e3ebdSchin if (mac->formals) 1230*da2e3ebdSchin ppprintf("%s", mac->formals); 1231*da2e3ebdSchin ppputchar(')'); 1232*da2e3ebdSchin } 1233*da2e3ebdSchin if ((p = mac->value) && *p) 1234*da2e3ebdSchin { 1235*da2e3ebdSchin ppputchar(' '); 1236*da2e3ebdSchin i0 = 0; 1237*da2e3ebdSchin while (n = *p++) 1238*da2e3ebdSchin { 1239*da2e3ebdSchin if (n != MARK || (n = *p++) == MARK) 1240*da2e3ebdSchin { 1241*da2e3ebdSchin ppputchar(n); 1242*da2e3ebdSchin i0 = ppisid(n); 1243*da2e3ebdSchin } 1244*da2e3ebdSchin else 1245*da2e3ebdSchin { 1246*da2e3ebdSchin if (n == 'Q') 1247*da2e3ebdSchin ppputchar('#'); 1248*da2e3ebdSchin else if (i0) 1249*da2e3ebdSchin { 1250*da2e3ebdSchin ppputchar('#'); 1251*da2e3ebdSchin ppputchar('#'); 1252*da2e3ebdSchin } 1253*da2e3ebdSchin s = formargs[*p++ - ARGOFFSET]; 1254*da2e3ebdSchin while ((n = *s++) && n != ',') 1255*da2e3ebdSchin ppputchar(n); 1256*da2e3ebdSchin if (ppisid(*p) || *p == MARK) 1257*da2e3ebdSchin { 1258*da2e3ebdSchin ppputchar('#'); 1259*da2e3ebdSchin ppputchar('#'); 1260*da2e3ebdSchin } 1261*da2e3ebdSchin i0 = 0; 1262*da2e3ebdSchin } 1263*da2e3ebdSchin ppcheckout(); 1264*da2e3ebdSchin } 1265*da2e3ebdSchin } 1266*da2e3ebdSchin emitted = 1; 1267*da2e3ebdSchin } 1268*da2e3ebdSchin benign: 1269*da2e3ebdSchin if (pp.mode & BUILTIN) sym->flags |= SYM_BUILTIN; 1270*da2e3ebdSchin if (pp.option & FINAL) sym->flags |= SYM_FINAL; 1271*da2e3ebdSchin if (pp.mode & INIT) sym->flags |= SYM_INIT; 1272*da2e3ebdSchin if (pp.option & INITIAL) sym->flags |= SYM_INITIAL; 1273*da2e3ebdSchin if (pp.state & NOEXPAND) sym->flags |= SYM_NOEXPAND; 1274*da2e3ebdSchin if (pp.option & PREDEFINED) sym->flags |= SYM_PREDEFINED; 1275*da2e3ebdSchin if (pp.mode & READONLY) sym->flags |= SYM_READONLY; 1276*da2e3ebdSchin if (pp.macref) (*pp.macref)(sym, error_info.file, n2, mac ? error_info.line - n2 + 1 : REF_UNDEF, mac ? strsum(mac->value, (long)mac->arity) : 0L); 1277*da2e3ebdSchin break; 1278*da2e3ebdSchin assertion: 1279*da2e3ebdSchin c = pplex(); 1280*da2e3ebdSchin if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1281*da2e3ebdSchin error(1, "#%s #%s: assertions are non-standard", dirname(directive), pptokstr(pp.token, 0)); 1282*da2e3ebdSchin if (c != T_ID) 1283*da2e3ebdSchin { 1284*da2e3ebdSchin error(2, "%s: invalid predicate name", pptokstr(pp.token, 0)); 1285*da2e3ebdSchin goto eatdirective; 1286*da2e3ebdSchin } 1287*da2e3ebdSchin switch ((int)hashref(pp.strtab, pp.token)) 1288*da2e3ebdSchin { 1289*da2e3ebdSchin case X_DEFINED: 1290*da2e3ebdSchin case X_EXISTS: 1291*da2e3ebdSchin case X_STRCMP: 1292*da2e3ebdSchin error(2, "%s is a builtin predicate", pp.token); 1293*da2e3ebdSchin goto eatdirective; 1294*da2e3ebdSchin case X_SIZEOF: 1295*da2e3ebdSchin error(2, "%s cannot be a predicate", pp.token); 1296*da2e3ebdSchin goto eatdirective; 1297*da2e3ebdSchin } 1298*da2e3ebdSchin strcpy(pp.tmpbuf, pp.token); 1299*da2e3ebdSchin switch (pppredargs()) 1300*da2e3ebdSchin { 1301*da2e3ebdSchin case T_ID: 1302*da2e3ebdSchin case T_STRING: 1303*da2e3ebdSchin assert(directive, pp.tmpbuf, pp.args); 1304*da2e3ebdSchin break; 1305*da2e3ebdSchin case 0: 1306*da2e3ebdSchin assert(directive, pp.tmpbuf, NiL); 1307*da2e3ebdSchin break; 1308*da2e3ebdSchin default: 1309*da2e3ebdSchin error(2, "invalid predicate argument list"); 1310*da2e3ebdSchin goto eatdirective; 1311*da2e3ebdSchin } 1312*da2e3ebdSchin break; 1313*da2e3ebdSchin tuple: 1314*da2e3ebdSchin pp.state |= DEFINITION|NOEXPAND|NOSPACE; 1315*da2e3ebdSchin rp = 0; 1316*da2e3ebdSchin tp = mac->tuple; 1317*da2e3ebdSchin if (!tp && !mac->value) 1318*da2e3ebdSchin ppfsm(FSM_MACRO, sym->name); 1319*da2e3ebdSchin while ((c = pplex()) && c != '>' && c != '\n') 1320*da2e3ebdSchin { 1321*da2e3ebdSchin for (; tp; tp = tp->nomatch) 1322*da2e3ebdSchin if (streq(tp->token, pp.token)) 1323*da2e3ebdSchin break; 1324*da2e3ebdSchin if (!tp) 1325*da2e3ebdSchin { 1326*da2e3ebdSchin if (!(tp = newof(0, struct pptuple, 1, strlen(pp.token)))) 1327*da2e3ebdSchin error(3, "out of space"); 1328*da2e3ebdSchin strcpy(tp->token, pp.token); 1329*da2e3ebdSchin if (rp) 1330*da2e3ebdSchin { 1331*da2e3ebdSchin tp->nomatch = rp; 1332*da2e3ebdSchin rp->nomatch = tp; 1333*da2e3ebdSchin } 1334*da2e3ebdSchin else 1335*da2e3ebdSchin { 1336*da2e3ebdSchin tp->nomatch = mac->tuple; 1337*da2e3ebdSchin mac->tuple = tp; 1338*da2e3ebdSchin } 1339*da2e3ebdSchin } 1340*da2e3ebdSchin rp = tp; 1341*da2e3ebdSchin tp = tp->match; 1342*da2e3ebdSchin } 1343*da2e3ebdSchin pp.state &= ~NOSPACE; 1344*da2e3ebdSchin if (!rp || c != '>') 1345*da2e3ebdSchin error(2, "%s: > omitted in tuple macro definition", sym->name); 1346*da2e3ebdSchin else 1347*da2e3ebdSchin { 1348*da2e3ebdSchin n = 2 * MAXTOKEN; 1349*da2e3ebdSchin p = v = oldof(0, char, 0, n); 1350*da2e3ebdSchin while ((c = pplex()) && c != '\n') 1351*da2e3ebdSchin if (p > v || c != ' ') 1352*da2e3ebdSchin { 1353*da2e3ebdSchin STRCOPY(p, pp.token, s); 1354*da2e3ebdSchin if (p > &v[n - MAXTOKEN] && (s = newof(v, char, n += MAXTOKEN, 0)) != v) 1355*da2e3ebdSchin { 1356*da2e3ebdSchin c = p - v; 1357*da2e3ebdSchin v = s; 1358*da2e3ebdSchin p = v + c; 1359*da2e3ebdSchin } 1360*da2e3ebdSchin } 1361*da2e3ebdSchin while (p > v && *(p - 1) == ' ') 1362*da2e3ebdSchin p--; 1363*da2e3ebdSchin n = p - v; 1364*da2e3ebdSchin tp = newof(0, struct pptuple, 1, n); 1365*da2e3ebdSchin strcpy(tp->token, v); 1366*da2e3ebdSchin tp->match = rp->match; 1367*da2e3ebdSchin rp->match = tp; 1368*da2e3ebdSchin } 1369*da2e3ebdSchin goto benign; 1370*da2e3ebdSchin case WARNING: 1371*da2e3ebdSchin if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1372*da2e3ebdSchin error(1, "#%s: non-standard directive", pp.token); 1373*da2e3ebdSchin /*FALLTHROUGH*/ 1374*da2e3ebdSchin case ERROR: 1375*da2e3ebdSchin pp.state &= ~DISABLE; 1376*da2e3ebdSchin p = pp.tmpbuf; 1377*da2e3ebdSchin while ((c = pplex()) != '\n') 1378*da2e3ebdSchin if (p + strlen(pp.token) < &pp.tmpbuf[MAXTOKEN]) 1379*da2e3ebdSchin { 1380*da2e3ebdSchin STRCOPY(p, pp.token, s); 1381*da2e3ebdSchin pp.state &= ~NOSPACE; 1382*da2e3ebdSchin } 1383*da2e3ebdSchin *p = 0; 1384*da2e3ebdSchin p = *pp.tmpbuf ? pp.tmpbuf : ((directive == WARNING) ? "user warning" : "user error"); 1385*da2e3ebdSchin n = (directive == WARNING) ? 1 : 3; 1386*da2e3ebdSchin error(n, "%s", p); 1387*da2e3ebdSchin break; 1388*da2e3ebdSchin case LET: 1389*da2e3ebdSchin n2 = error_info.line; 1390*da2e3ebdSchin if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1391*da2e3ebdSchin error(1, "#%s: non-standard directive", pp.token); 1392*da2e3ebdSchin if (!(sym = macsym(c = pplex()))) goto eatdirective; 1393*da2e3ebdSchin if ((c = pplex()) != '=') 1394*da2e3ebdSchin { 1395*da2e3ebdSchin error(2, "%s: = expected", sym->name); 1396*da2e3ebdSchin goto eatdirective; 1397*da2e3ebdSchin } 1398*da2e3ebdSchin sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_MULTILINE|SYM_PREDEFINED|SYM_VARIADIC); 1399*da2e3ebdSchin mac = sym->macro; 1400*da2e3ebdSchin mac->arity = 0; 1401*da2e3ebdSchin if (mac->value) 1402*da2e3ebdSchin { 1403*da2e3ebdSchin if (!(sym->flags & SYM_REDEFINE) && !sym->hidden) 1404*da2e3ebdSchin error(1, "%s: redefined", sym->name); 1405*da2e3ebdSchin #if MACKEYARGS 1406*da2e3ebdSchin if ((pp.option & KEYARGS) && mac->formkeys) free(mac->formkeys); 1407*da2e3ebdSchin else 1408*da2e3ebdSchin #endif 1409*da2e3ebdSchin free(mac->formals); 1410*da2e3ebdSchin mac->formals = 0; 1411*da2e3ebdSchin n = strlen(mac->value) + 1; 1412*da2e3ebdSchin } 1413*da2e3ebdSchin else 1414*da2e3ebdSchin { 1415*da2e3ebdSchin ppfsm(FSM_MACRO, sym->name); 1416*da2e3ebdSchin n = 0; 1417*da2e3ebdSchin } 1418*da2e3ebdSchin n1 = ppexpr(&i1); 1419*da2e3ebdSchin if (i1) c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%luU", n1); 1420*da2e3ebdSchin else c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%ld", n1); 1421*da2e3ebdSchin if (n < ++c) 1422*da2e3ebdSchin { 1423*da2e3ebdSchin if (mac->value) free(mac->value); 1424*da2e3ebdSchin mac->value = oldof(0, char, 0, c); 1425*da2e3ebdSchin } 1426*da2e3ebdSchin strcpy(mac->value, pp.tmpbuf); 1427*da2e3ebdSchin sym->flags |= SYM_REDEFINE; 1428*da2e3ebdSchin c = (pp.state & NEWLINE) ? '\n' : ' '; 1429*da2e3ebdSchin goto benign; 1430*da2e3ebdSchin case LINE: 1431*da2e3ebdSchin pp.state &= ~DISABLE; 1432*da2e3ebdSchin if ((c = pplex()) == '#') 1433*da2e3ebdSchin { 1434*da2e3ebdSchin c = pplex(); 1435*da2e3ebdSchin directive = INCLUDE; 1436*da2e3ebdSchin } 1437*da2e3ebdSchin if (c != T_DECIMAL && c != T_OCTAL) 1438*da2e3ebdSchin { 1439*da2e3ebdSchin error(1, "#%s: line number expected", dirname(LINE)); 1440*da2e3ebdSchin goto eatdirective; 1441*da2e3ebdSchin } 1442*da2e3ebdSchin linesync: 1443*da2e3ebdSchin n = error_info.line; 1444*da2e3ebdSchin error_info.line = strtol(pp.token, NiL, 0); 1445*da2e3ebdSchin if (error_info.line == 0 && directive == LINE && (pp.state & STRICT) && !(pp.mode & HOSTED)) 1446*da2e3ebdSchin error(1, "#%s: line number should be > 0", dirname(LINE)); 1447*da2e3ebdSchin pp.state &= ~DISABLE; 1448*da2e3ebdSchin pp.state |= STRIP; 1449*da2e3ebdSchin switch (c = pplex()) 1450*da2e3ebdSchin { 1451*da2e3ebdSchin case T_STRING: 1452*da2e3ebdSchin s = error_info.file; 1453*da2e3ebdSchin if (*(p = pp.token)) pathcanon(p, 0); 1454*da2e3ebdSchin fp = ppsetfile(p); 1455*da2e3ebdSchin error_info.file = fp->name; 1456*da2e3ebdSchin if (error_info.line == 1) 1457*da2e3ebdSchin ppmultiple(fp, INC_TEST); 1458*da2e3ebdSchin switch (c = pplex()) 1459*da2e3ebdSchin { 1460*da2e3ebdSchin case '\n': 1461*da2e3ebdSchin break; 1462*da2e3ebdSchin case T_DECIMAL: 1463*da2e3ebdSchin case T_OCTAL: 1464*da2e3ebdSchin if (directive == LINE && (pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1465*da2e3ebdSchin error(1, "#%s: integer file type argument is non-standard", dirname(LINE)); 1466*da2e3ebdSchin break; 1467*da2e3ebdSchin default: 1468*da2e3ebdSchin error(1, "#%s: integer file type argument expected", dirname(LINE)); 1469*da2e3ebdSchin break; 1470*da2e3ebdSchin } 1471*da2e3ebdSchin if (directive == LINE) pp.in->flags &= ~IN_ignoreline; 1472*da2e3ebdSchin else if (pp.incref) 1473*da2e3ebdSchin { 1474*da2e3ebdSchin if (error_info.file != s) 1475*da2e3ebdSchin { 1476*da2e3ebdSchin switch (*pp.token) 1477*da2e3ebdSchin { 1478*da2e3ebdSchin case PP_sync_push: 1479*da2e3ebdSchin if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1480*da2e3ebdSchin else (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH); 1481*da2e3ebdSchin break; 1482*da2e3ebdSchin case PP_sync_pop: 1483*da2e3ebdSchin if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1484*da2e3ebdSchin else (*pp.incref)(s, error_info.file, n - 1, PP_SYNC_POP); 1485*da2e3ebdSchin break; 1486*da2e3ebdSchin case PP_sync_ignore: 1487*da2e3ebdSchin if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1488*da2e3ebdSchin else 1489*da2e3ebdSchin { 1490*da2e3ebdSchin (*pp.incref)(s, error_info.file, n, PP_SYNC_IGNORE); 1491*da2e3ebdSchin error_info.file = s; 1492*da2e3ebdSchin } 1493*da2e3ebdSchin break; 1494*da2e3ebdSchin default: 1495*da2e3ebdSchin if (*s) 1496*da2e3ebdSchin { 1497*da2e3ebdSchin if (fp == pp.insert) 1498*da2e3ebdSchin pp.insert = 0; 1499*da2e3ebdSchin else if (error_info.line == 1 && !pp.insert) 1500*da2e3ebdSchin (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH); 1501*da2e3ebdSchin else 1502*da2e3ebdSchin { 1503*da2e3ebdSchin if (!pp.insert) pp.insert = ppgetfile(s); 1504*da2e3ebdSchin (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1505*da2e3ebdSchin } 1506*da2e3ebdSchin } 1507*da2e3ebdSchin break; 1508*da2e3ebdSchin } 1509*da2e3ebdSchin } 1510*da2e3ebdSchin } 1511*da2e3ebdSchin break; 1512*da2e3ebdSchin case '\n': 1513*da2e3ebdSchin break; 1514*da2e3ebdSchin default: 1515*da2e3ebdSchin error(1, "#%s: \"file-name\" expected", dirname(LINE)); 1516*da2e3ebdSchin break; 1517*da2e3ebdSchin } 1518*da2e3ebdSchin if (directive == LINE && (pp.in->flags & IN_ignoreline)) 1519*da2e3ebdSchin error_info.line = n + 1; 1520*da2e3ebdSchin else 1521*da2e3ebdSchin { 1522*da2e3ebdSchin pp.hidden = 0; 1523*da2e3ebdSchin pp.state &= ~HIDDEN; 1524*da2e3ebdSchin if (pp.linesync) 1525*da2e3ebdSchin { 1526*da2e3ebdSchin #if CATSTRINGS 1527*da2e3ebdSchin if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE; 1528*da2e3ebdSchin else 1529*da2e3ebdSchin #endif 1530*da2e3ebdSchin { 1531*da2e3ebdSchin s = pp.lineid; 1532*da2e3ebdSchin n = pp.flags; 1533*da2e3ebdSchin if (directive == LINE) 1534*da2e3ebdSchin { 1535*da2e3ebdSchin pp.flags &= ~PP_linetype; 1536*da2e3ebdSchin if (pp.macref) pp.lineid = dirname(LINE); 1537*da2e3ebdSchin } 1538*da2e3ebdSchin (*pp.linesync)(error_info.line, error_info.file); 1539*da2e3ebdSchin pp.flags = n; 1540*da2e3ebdSchin pp.lineid = s; 1541*da2e3ebdSchin } 1542*da2e3ebdSchin } 1543*da2e3ebdSchin } 1544*da2e3ebdSchin directive = LINE; 1545*da2e3ebdSchin break; 1546*da2e3ebdSchin case PRAGMA: 1547*da2e3ebdSchin /* 1548*da2e3ebdSchin * #pragma [STDC] [pass:] [no]option [arg ...] 1549*da2e3ebdSchin * 1550*da2e3ebdSchin * pragma args are not expanded by default 1551*da2e3ebdSchin * 1552*da2e3ebdSchin * if STDC is present then it is silently passed on 1553*da2e3ebdSchin * 1554*da2e3ebdSchin * if pass is pp.pass then the option is used 1555*da2e3ebdSchin * and verified but is not passed on 1556*da2e3ebdSchin * 1557*da2e3ebdSchin * if pass is omitted then the option is passed on 1558*da2e3ebdSchin * 1559*da2e3ebdSchin * otherwise if pass is non-null and not pp.pass then 1560*da2e3ebdSchin * the option is passed on but not used 1561*da2e3ebdSchin * 1562*da2e3ebdSchin * if the line does not match this form then 1563*da2e3ebdSchin * it is passed on unchanged 1564*da2e3ebdSchin * 1565*da2e3ebdSchin * #directive pass: option [...] 1566*da2e3ebdSchin * ^ ^ ^ ^ ^ ^ ^ ^ 1567*da2e3ebdSchin * pp.valbuf p0 p1 p2 p3 p4 p5 p6 1568*da2e3ebdSchin * 1569*da2e3ebdSchin * p? 0 if component omitted 1570*da2e3ebdSchin * i0 0 if ``no''option 1571*da2e3ebdSchin */ 1572*da2e3ebdSchin 1573*da2e3ebdSchin p = pp.valbuf; 1574*da2e3ebdSchin *p++ = '#'; 1575*da2e3ebdSchin STRCOPY(p, pp.token, s); 1576*da2e3ebdSchin p0 = p; 1577*da2e3ebdSchin if (pp.option & PRAGMAEXPAND) 1578*da2e3ebdSchin pp.state &= ~DISABLE; 1579*da2e3ebdSchin if (!(p6 = getline(p, &pp.valbuf[MAXTOKEN], !!(pp.option & PRAGMAEXPAND)))) 1580*da2e3ebdSchin { 1581*da2e3ebdSchin *p0 = 0; 1582*da2e3ebdSchin error(2, "%s: directive too long", pp.valbuf); 1583*da2e3ebdSchin c = 0; 1584*da2e3ebdSchin goto eatdirective; 1585*da2e3ebdSchin } 1586*da2e3ebdSchin p1 = ++p; 1587*da2e3ebdSchin while (ppisid(*p)) 1588*da2e3ebdSchin p++; 1589*da2e3ebdSchin if (p == p1) 1590*da2e3ebdSchin { 1591*da2e3ebdSchin p5 = p; 1592*da2e3ebdSchin p4 = 0; 1593*da2e3ebdSchin p3 = 0; 1594*da2e3ebdSchin p2 = 0; 1595*da2e3ebdSchin p1 = 0; 1596*da2e3ebdSchin } 1597*da2e3ebdSchin else if (*p != ':') 1598*da2e3ebdSchin { 1599*da2e3ebdSchin p5 = *p ? p + (*p == ' ') : 0; 1600*da2e3ebdSchin p4 = p; 1601*da2e3ebdSchin p3 = p1; 1602*da2e3ebdSchin p2 = 0; 1603*da2e3ebdSchin p1 = 0; 1604*da2e3ebdSchin } 1605*da2e3ebdSchin else 1606*da2e3ebdSchin { 1607*da2e3ebdSchin p2 = p++; 1608*da2e3ebdSchin p3 = p; 1609*da2e3ebdSchin while (ppisid(*p)) 1610*da2e3ebdSchin p++; 1611*da2e3ebdSchin if (p == p3) 1612*da2e3ebdSchin { 1613*da2e3ebdSchin p4 = p1; 1614*da2e3ebdSchin p3 = 0; 1615*da2e3ebdSchin p2 = 0; 1616*da2e3ebdSchin p1 = 0; 1617*da2e3ebdSchin } 1618*da2e3ebdSchin else 1619*da2e3ebdSchin p4 = p; 1620*da2e3ebdSchin p5 = *p4 ? p4 + (*p4 == ' ') : 0; 1621*da2e3ebdSchin } 1622*da2e3ebdSchin if (!p1 && p3 && (p4 - p3) == 4 && strneq(p3, "STDC", 4)) 1623*da2e3ebdSchin goto pass; 1624*da2e3ebdSchin if ((pp.state & WARN) && !(pp.mode & (HOSTED|RELAX))) 1625*da2e3ebdSchin error(1, "#%s: non-standard directive", dirname(PRAGMA)); 1626*da2e3ebdSchin i0 = !p3 || *p3 != 'n' || *(p3 + 1) != 'o'; 1627*da2e3ebdSchin if (!p3) 1628*da2e3ebdSchin goto checkmap; 1629*da2e3ebdSchin if (p1) 1630*da2e3ebdSchin { 1631*da2e3ebdSchin *p2 = 0; 1632*da2e3ebdSchin n = streq(p1, pp.pass); 1633*da2e3ebdSchin *p2 = ':'; 1634*da2e3ebdSchin if (!n) 1635*da2e3ebdSchin goto checkmap; 1636*da2e3ebdSchin } 1637*da2e3ebdSchin else 1638*da2e3ebdSchin n = 0; 1639*da2e3ebdSchin i2 = *p4; 1640*da2e3ebdSchin *p4 = 0; 1641*da2e3ebdSchin if (((i1 = (int)hashref(pp.strtab, p3 + (i0 ? 0 : 2))) < 1 || i1 > X_last_option) && (i0 || (i1 = (int)hashref(pp.strtab, p3)) > X_last_option)) 1642*da2e3ebdSchin i1 = 0; 1643*da2e3ebdSchin if ((pp.state & (COMPATIBILITY|STRICT)) == STRICT && !(pp.mode & (HOSTED|RELAX))) 1644*da2e3ebdSchin { 1645*da2e3ebdSchin if (pp.optflags[i1] & OPT_GLOBAL) 1646*da2e3ebdSchin goto donedirective; 1647*da2e3ebdSchin if (n || (pp.mode & WARN)) 1648*da2e3ebdSchin { 1649*da2e3ebdSchin n = 0; 1650*da2e3ebdSchin error(1, "#%s: non-standard directive ignored", dirname(PRAGMA)); 1651*da2e3ebdSchin } 1652*da2e3ebdSchin i1 = 0; 1653*da2e3ebdSchin } 1654*da2e3ebdSchin if (!n) 1655*da2e3ebdSchin { 1656*da2e3ebdSchin if (!(pp.optflags[i1] & OPT_GLOBAL)) 1657*da2e3ebdSchin { 1658*da2e3ebdSchin *p4 = i2; 1659*da2e3ebdSchin goto checkmap; 1660*da2e3ebdSchin } 1661*da2e3ebdSchin if (!(pp.optflags[i1] & OPT_PASS)) 1662*da2e3ebdSchin n = 1; 1663*da2e3ebdSchin } 1664*da2e3ebdSchin else if (!i1) 1665*da2e3ebdSchin error(2, "%s: unknown option", p1); 1666*da2e3ebdSchin else if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1667*da2e3ebdSchin error(1, "%s: non-standard option", p1); 1668*da2e3ebdSchin p = p5; 1669*da2e3ebdSchin switch (i1) 1670*da2e3ebdSchin { 1671*da2e3ebdSchin case X_ALLMULTIPLE: 1672*da2e3ebdSchin ppop(PP_MULTIPLE, i0); 1673*da2e3ebdSchin break; 1674*da2e3ebdSchin case X_ALLPOSSIBLE: 1675*da2e3ebdSchin setoption(ALLPOSSIBLE, i0); 1676*da2e3ebdSchin break; 1677*da2e3ebdSchin case X_BUILTIN: 1678*da2e3ebdSchin setmode(BUILTIN, i0); 1679*da2e3ebdSchin break; 1680*da2e3ebdSchin case X_CATLITERAL: 1681*da2e3ebdSchin setmode(CATLITERAL, i0); 1682*da2e3ebdSchin if (pp.mode & CATLITERAL) 1683*da2e3ebdSchin setoption(STRINGSPLIT, 0); 1684*da2e3ebdSchin break; 1685*da2e3ebdSchin case X_CDIR: 1686*da2e3ebdSchin tokop(PP_CDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 1687*da2e3ebdSchin break; 1688*da2e3ebdSchin case X_CHECKPOINT: 1689*da2e3ebdSchin #if CHECKPOINT 1690*da2e3ebdSchin ppload(p); 1691*da2e3ebdSchin #else 1692*da2e3ebdSchin error(3, "%s: preprocessor not compiled with checkpoint enabled", p3); 1693*da2e3ebdSchin #endif 1694*da2e3ebdSchin break; 1695*da2e3ebdSchin case X_CHOP: 1696*da2e3ebdSchin tokop(PP_CHOP, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1697*da2e3ebdSchin break; 1698*da2e3ebdSchin case X_COMPATIBILITY: 1699*da2e3ebdSchin ppop(PP_COMPATIBILITY, i0); 1700*da2e3ebdSchin break; 1701*da2e3ebdSchin case X_DEBUG: 1702*da2e3ebdSchin error_info.trace = i0 ? (p ? -strtol(p, NiL, 0) : -1) : 0; 1703*da2e3ebdSchin break; 1704*da2e3ebdSchin case X_ELSEIF: 1705*da2e3ebdSchin setoption(ELSEIF, i0); 1706*da2e3ebdSchin break; 1707*da2e3ebdSchin case X_EXTERNALIZE: 1708*da2e3ebdSchin setmode(EXTERNALIZE, i0); 1709*da2e3ebdSchin break; 1710*da2e3ebdSchin case X_FINAL: 1711*da2e3ebdSchin setoption(FINAL, i0); 1712*da2e3ebdSchin break; 1713*da2e3ebdSchin case X_HEADEREXPAND: 1714*da2e3ebdSchin setoption(HEADEREXPAND, i0); 1715*da2e3ebdSchin break; 1716*da2e3ebdSchin case X_HEADEREXPANDALL: 1717*da2e3ebdSchin setoption(HEADEREXPANDALL, i0); 1718*da2e3ebdSchin break; 1719*da2e3ebdSchin case X_HIDE: 1720*da2e3ebdSchin case X_NOTE: 1721*da2e3ebdSchin PUSH_LINE(p); 1722*da2e3ebdSchin /* UNDENT...*/ 1723*da2e3ebdSchin while (c = pplex()) 1724*da2e3ebdSchin { 1725*da2e3ebdSchin if (c != T_ID) error(1, "%s: %s: identifier expected", p3, pp.token); 1726*da2e3ebdSchin else if (sym = ppsymset(pp.symtab, pp.token)) 1727*da2e3ebdSchin { 1728*da2e3ebdSchin if (i1 == X_NOTE) 1729*da2e3ebdSchin { 1730*da2e3ebdSchin sym->flags &= ~SYM_NOTICED; 1731*da2e3ebdSchin ppfsm(FSM_MACRO, sym->name); 1732*da2e3ebdSchin } 1733*da2e3ebdSchin else if (i0) 1734*da2e3ebdSchin { 1735*da2e3ebdSchin if (!sym->hidden && !(sym->hidden = newof(0, struct pphide, 1, 0))) 1736*da2e3ebdSchin error(3, "out of space"); 1737*da2e3ebdSchin if (!sym->macro) 1738*da2e3ebdSchin ppfsm(FSM_MACRO, sym->name); 1739*da2e3ebdSchin if (!sym->hidden->level++) 1740*da2e3ebdSchin { 1741*da2e3ebdSchin pp.hiding++; 1742*da2e3ebdSchin if (sym->macro && !(sym->flags & (SYM_ACTIVE|SYM_READONLY))) 1743*da2e3ebdSchin { 1744*da2e3ebdSchin sym->hidden->macro = sym->macro; 1745*da2e3ebdSchin sym->macro = 0; 1746*da2e3ebdSchin sym->hidden->flags = sym->flags; 1747*da2e3ebdSchin sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 1748*da2e3ebdSchin } 1749*da2e3ebdSchin } 1750*da2e3ebdSchin } 1751*da2e3ebdSchin else if (sym->hidden) 1752*da2e3ebdSchin { 1753*da2e3ebdSchin if ((mac = sym->macro) && !(sym->flags & (SYM_ACTIVE|SYM_READONLY))) 1754*da2e3ebdSchin { 1755*da2e3ebdSchin if (mac->formals) free(mac->formals); 1756*da2e3ebdSchin free(mac->value); 1757*da2e3ebdSchin free(mac); 1758*da2e3ebdSchin sym->macro = 0; 1759*da2e3ebdSchin sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 1760*da2e3ebdSchin } 1761*da2e3ebdSchin if (!--sym->hidden->level) 1762*da2e3ebdSchin { 1763*da2e3ebdSchin pp.hiding--; 1764*da2e3ebdSchin if (sym->hidden->macro) 1765*da2e3ebdSchin { 1766*da2e3ebdSchin sym->macro = sym->hidden->macro; 1767*da2e3ebdSchin sym->flags = sym->hidden->flags; 1768*da2e3ebdSchin } 1769*da2e3ebdSchin free(sym->hidden); 1770*da2e3ebdSchin sym->hidden = 0; 1771*da2e3ebdSchin } 1772*da2e3ebdSchin } 1773*da2e3ebdSchin } 1774*da2e3ebdSchin } 1775*da2e3ebdSchin /*...INDENT*/ 1776*da2e3ebdSchin POP_LINE(); 1777*da2e3ebdSchin break; 1778*da2e3ebdSchin case X_HOSTDIR: 1779*da2e3ebdSchin tokop(PP_HOSTDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 1780*da2e3ebdSchin break; 1781*da2e3ebdSchin case X_HOSTED: 1782*da2e3ebdSchin setmode(HOSTED, i0); 1783*da2e3ebdSchin break; 1784*da2e3ebdSchin case X_HOSTEDTRANSITION: 1785*da2e3ebdSchin setmode(HOSTEDTRANSITION, i0); 1786*da2e3ebdSchin break; 1787*da2e3ebdSchin case X_ID: 1788*da2e3ebdSchin tokop(PP_ID, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1789*da2e3ebdSchin break; 1790*da2e3ebdSchin case X_IGNORE: 1791*da2e3ebdSchin tokop(PP_IGNORE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1792*da2e3ebdSchin break; 1793*da2e3ebdSchin case X_INCLUDE: 1794*da2e3ebdSchin tokop(PP_INCLUDE, p3, p, i0, TOKOP_STRING|TOKOP_DUP); 1795*da2e3ebdSchin break; 1796*da2e3ebdSchin case X_INITIAL: 1797*da2e3ebdSchin setoption(INITIAL, i0); 1798*da2e3ebdSchin break; 1799*da2e3ebdSchin case X_KEYARGS: 1800*da2e3ebdSchin ppop(PP_KEYARGS, i0); 1801*da2e3ebdSchin break; 1802*da2e3ebdSchin case X_LINE: 1803*da2e3ebdSchin if (pp.linesync) pp.olinesync = pp.linesync; 1804*da2e3ebdSchin pp.linesync = i0 ? pp.olinesync : (PPLINESYNC)0; 1805*da2e3ebdSchin break; 1806*da2e3ebdSchin case X_LINEBASE: 1807*da2e3ebdSchin ppop(PP_LINEBASE, i0); 1808*da2e3ebdSchin break; 1809*da2e3ebdSchin case X_LINEFILE: 1810*da2e3ebdSchin ppop(PP_LINEFILE, i0); 1811*da2e3ebdSchin break; 1812*da2e3ebdSchin case X_LINEID: 1813*da2e3ebdSchin ppop(PP_LINEID, i0 ? p : (char*)0); 1814*da2e3ebdSchin break; 1815*da2e3ebdSchin case X_LINETYPE: 1816*da2e3ebdSchin ppop(PP_LINETYPE, i0 ? (p ? strtol(p, NiL, 0) : 1) : 0); 1817*da2e3ebdSchin break; 1818*da2e3ebdSchin case X_MACREF: 1819*da2e3ebdSchin if (!p) 1820*da2e3ebdSchin { 1821*da2e3ebdSchin if (i0 && !pp.macref) 1822*da2e3ebdSchin { 1823*da2e3ebdSchin ppop(PP_LINETYPE, 1); 1824*da2e3ebdSchin ppop(PP_MACREF, ppmacref); 1825*da2e3ebdSchin } 1826*da2e3ebdSchin else error(2, "%s: option cannot be unset", p3); 1827*da2e3ebdSchin } 1828*da2e3ebdSchin else if (s = strchr(p, ' ')) 1829*da2e3ebdSchin { 1830*da2e3ebdSchin if (pp.macref && (s = strchr(p, ' '))) 1831*da2e3ebdSchin { 1832*da2e3ebdSchin *s++ = 0; 1833*da2e3ebdSchin c = strtol(s, NiL, 0); 1834*da2e3ebdSchin var.type = pp.truncate; 1835*da2e3ebdSchin pp.truncate = PPTOKSIZ; 1836*da2e3ebdSchin (*pp.macref)(pprefmac(p, REF_CREATE), error_info.file, error_info.line - (c == REF_NORMAL ? 2 : 1), c, (s = strchr(s, ' ')) ? strtol(s, NiL, 0) : 0L); 1837*da2e3ebdSchin pp.truncate = var.type; 1838*da2e3ebdSchin } 1839*da2e3ebdSchin error_info.line -= 2; 1840*da2e3ebdSchin } 1841*da2e3ebdSchin break; 1842*da2e3ebdSchin case X_MAP: 1843*da2e3ebdSchin /*UNDENT*/ 1844*da2e3ebdSchin /* 1845*da2e3ebdSchin * #pragma pp:map [id ...] "/from/[,/to/]" [ "/old/new/[glnu]" ... ] 1846*da2e3ebdSchin */ 1847*da2e3ebdSchin 1848*da2e3ebdSchin if (!i0) 1849*da2e3ebdSchin { 1850*da2e3ebdSchin error(2, "%s: option cannot be unset", p3); 1851*da2e3ebdSchin goto donedirective; 1852*da2e3ebdSchin } 1853*da2e3ebdSchin if (!p5) 1854*da2e3ebdSchin { 1855*da2e3ebdSchin error(2, "%s: address argument expected", p3); 1856*da2e3ebdSchin goto donedirective; 1857*da2e3ebdSchin } 1858*da2e3ebdSchin PUSH_LINE(p5); 1859*da2e3ebdSchin while ((c = pplex()) == T_ID) 1860*da2e3ebdSchin { 1861*da2e3ebdSchin sfsprintf(pp.tmpbuf, MAXTOKEN, "__%s__", s = pp.token); 1862*da2e3ebdSchin if (c = (int)hashget(pp.dirtab, s)) 1863*da2e3ebdSchin { 1864*da2e3ebdSchin hashput(pp.dirtab, 0, 0); 1865*da2e3ebdSchin hashput(pp.dirtab, pp.tmpbuf, c); 1866*da2e3ebdSchin } 1867*da2e3ebdSchin if (c = (int)hashget(pp.strtab, s)) 1868*da2e3ebdSchin { 1869*da2e3ebdSchin hashput(pp.strtab, 0, 0); 1870*da2e3ebdSchin hashput(pp.strtab, pp.tmpbuf, c); 1871*da2e3ebdSchin } 1872*da2e3ebdSchin } 1873*da2e3ebdSchin if (c != T_STRING || !*(s = pp.token)) 1874*da2e3ebdSchin { 1875*da2e3ebdSchin if (c) 1876*da2e3ebdSchin error(2, "%s: %s: address argument expected", p3, pptokstr(pp.token, 0)); 1877*da2e3ebdSchin goto eatmap; 1878*da2e3ebdSchin } 1879*da2e3ebdSchin map = newof(0, struct map, 1, 0); 1880*da2e3ebdSchin 1881*da2e3ebdSchin /* 1882*da2e3ebdSchin * /from/ 1883*da2e3ebdSchin */ 1884*da2e3ebdSchin 1885*da2e3ebdSchin if (i0 = regcomp(&map->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) 1886*da2e3ebdSchin regfatal(&map->re, 3, i0); 1887*da2e3ebdSchin if (*(s += map->re.re_npat)) 1888*da2e3ebdSchin { 1889*da2e3ebdSchin error(2, "%s: invalid characters after pattern: %s ", p3, s); 1890*da2e3ebdSchin goto eatmap; 1891*da2e3ebdSchin } 1892*da2e3ebdSchin 1893*da2e3ebdSchin /* 1894*da2e3ebdSchin * /old/new/[flags] 1895*da2e3ebdSchin */ 1896*da2e3ebdSchin 1897*da2e3ebdSchin edit = 0; 1898*da2e3ebdSchin while ((c = pplex()) == T_STRING) 1899*da2e3ebdSchin { 1900*da2e3ebdSchin if (!*(s = pp.token)) 1901*da2e3ebdSchin { 1902*da2e3ebdSchin error(2, "%s: substitution argument expected", p3); 1903*da2e3ebdSchin goto eatmap; 1904*da2e3ebdSchin } 1905*da2e3ebdSchin if (edit) 1906*da2e3ebdSchin edit = edit->next = newof(0, struct edit, 1, 0); 1907*da2e3ebdSchin else 1908*da2e3ebdSchin edit = map->edit = newof(0, struct edit, 1, 0); 1909*da2e3ebdSchin if (!(i0 = regcomp(&edit->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) && !(i0 = regsubcomp(&edit->re, s += edit->re.re_npat, NiL, 0, 0))) 1910*da2e3ebdSchin s += edit->re.re_npat; 1911*da2e3ebdSchin if (i0) 1912*da2e3ebdSchin regfatal(&edit->re, 3, i0); 1913*da2e3ebdSchin if (*s) 1914*da2e3ebdSchin { 1915*da2e3ebdSchin error(2, "%s: invalid characters after substitution: %s ", p3, s); 1916*da2e3ebdSchin goto eatmap; 1917*da2e3ebdSchin } 1918*da2e3ebdSchin } 1919*da2e3ebdSchin if (c) 1920*da2e3ebdSchin { 1921*da2e3ebdSchin error(2, "%s: %s: substitution argument expected", p3, pptokstr(pp.token, 0)); 1922*da2e3ebdSchin goto eatmap; 1923*da2e3ebdSchin } 1924*da2e3ebdSchin map->next = (struct map*)pp.maps; 1925*da2e3ebdSchin pp.maps = (char*)map; 1926*da2e3ebdSchin eatmap: 1927*da2e3ebdSchin POP_LINE(); 1928*da2e3ebdSchin /*INDENT*/ 1929*da2e3ebdSchin break; 1930*da2e3ebdSchin case X_MAPINCLUDE: 1931*da2e3ebdSchin ppmapinclude(NiL, p5); 1932*da2e3ebdSchin break; 1933*da2e3ebdSchin case X_MODERN: 1934*da2e3ebdSchin setoption(MODERN, i0); 1935*da2e3ebdSchin break; 1936*da2e3ebdSchin case X_MULTIPLE: 1937*da2e3ebdSchin n = 1; 1938*da2e3ebdSchin if (pp.in->type == IN_FILE) 1939*da2e3ebdSchin ppmultiple(ppsetfile(error_info.file), i0 ? INC_CLEAR : INC_TEST); 1940*da2e3ebdSchin break; 1941*da2e3ebdSchin case X_NATIVE: 1942*da2e3ebdSchin setoption(NATIVE, i0); 1943*da2e3ebdSchin break; 1944*da2e3ebdSchin case X_OPSPACE: 1945*da2e3ebdSchin ppfsm(FSM_OPSPACE, i0 ? p4 : (char*)0); 1946*da2e3ebdSchin break; 1947*da2e3ebdSchin case X_PASSTHROUGH: 1948*da2e3ebdSchin ppop(PP_PASSTHROUGH, i0); 1949*da2e3ebdSchin break; 1950*da2e3ebdSchin case X_PEDANTIC: 1951*da2e3ebdSchin ppop(PP_PEDANTIC, i0); 1952*da2e3ebdSchin break; 1953*da2e3ebdSchin case X_PLUSCOMMENT: 1954*da2e3ebdSchin ppop(PP_PLUSCOMMENT, i0); 1955*da2e3ebdSchin break; 1956*da2e3ebdSchin case X_PLUSPLUS: 1957*da2e3ebdSchin ppop(PP_PLUSPLUS, i0); 1958*da2e3ebdSchin break; 1959*da2e3ebdSchin case X_PLUSSPLICE: 1960*da2e3ebdSchin setoption(PLUSSPLICE, i0); 1961*da2e3ebdSchin break; 1962*da2e3ebdSchin case X_PRAGMAEXPAND: 1963*da2e3ebdSchin setoption(PRAGMAEXPAND, i0); 1964*da2e3ebdSchin break; 1965*da2e3ebdSchin case X_PRAGMAFLAGS: 1966*da2e3ebdSchin tokop(PP_PRAGMAFLAGS, p3, p, i0, 0); 1967*da2e3ebdSchin break; 1968*da2e3ebdSchin case X_PREDEFINED: 1969*da2e3ebdSchin setoption(PREDEFINED, i0); 1970*da2e3ebdSchin break; 1971*da2e3ebdSchin case X_PREFIX: 1972*da2e3ebdSchin setoption(PREFIX, i0); 1973*da2e3ebdSchin break; 1974*da2e3ebdSchin case X_PRESERVE: 1975*da2e3ebdSchin setoption(PRESERVE, i0); 1976*da2e3ebdSchin if (pp.option & PRESERVE) 1977*da2e3ebdSchin { 1978*da2e3ebdSchin setmode(CATLITERAL, 0); 1979*da2e3ebdSchin ppop(PP_COMPATIBILITY, 1); 1980*da2e3ebdSchin ppop(PP_TRANSITION, 0); 1981*da2e3ebdSchin ppop(PP_PLUSCOMMENT, 1); 1982*da2e3ebdSchin ppop(PP_SPACEOUT, 1); 1983*da2e3ebdSchin setoption(STRINGSPAN, 1); 1984*da2e3ebdSchin setoption(STRINGSPLIT, 0); 1985*da2e3ebdSchin ppop(PP_HOSTDIR, "-", 1); 1986*da2e3ebdSchin } 1987*da2e3ebdSchin break; 1988*da2e3ebdSchin case X_PROTOTYPED: 1989*da2e3ebdSchin /* 1990*da2e3ebdSchin * this option doesn't bump the token count 1991*da2e3ebdSchin */ 1992*da2e3ebdSchin 1993*da2e3ebdSchin n = 1; 1994*da2e3ebdSchin directive = ENDIF; 1995*da2e3ebdSchin #if PROTOTYPE 1996*da2e3ebdSchin setoption(PROTOTYPED, i0); 1997*da2e3ebdSchin #else 1998*da2e3ebdSchin error(1, "preprocessor not compiled with prototype conversion enabled"); 1999*da2e3ebdSchin #endif 2000*da2e3ebdSchin break; 2001*da2e3ebdSchin case X_PROTO: 2002*da2e3ebdSchin setoption(NOPROTO, !i0); 2003*da2e3ebdSchin break; 2004*da2e3ebdSchin case X_QUOTE: 2005*da2e3ebdSchin tokop(PP_QUOTE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 2006*da2e3ebdSchin break; 2007*da2e3ebdSchin case X_READONLY: 2008*da2e3ebdSchin setmode(READONLY, i0); 2009*da2e3ebdSchin break; 2010*da2e3ebdSchin case X_REGUARD: 2011*da2e3ebdSchin setoption(REGUARD, i0); 2012*da2e3ebdSchin break; 2013*da2e3ebdSchin case X_RESERVED: 2014*da2e3ebdSchin tokop(PP_RESERVED, p3, p, i0, 0); 2015*da2e3ebdSchin break; 2016*da2e3ebdSchin case X_SPACEOUT: 2017*da2e3ebdSchin if (!(pp.state & (COMPATIBILITY|COMPILE))) 2018*da2e3ebdSchin ppop(PP_SPACEOUT, i0); 2019*da2e3ebdSchin break; 2020*da2e3ebdSchin case X_SPLICECAT: 2021*da2e3ebdSchin setoption(SPLICECAT, i0); 2022*da2e3ebdSchin break; 2023*da2e3ebdSchin case X_SPLICESPACE: 2024*da2e3ebdSchin setoption(SPLICESPACE, i0); 2025*da2e3ebdSchin break; 2026*da2e3ebdSchin case X_STANDARD: 2027*da2e3ebdSchin tokop(PP_STANDARD, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 2028*da2e3ebdSchin break; 2029*da2e3ebdSchin case X_STRICT: 2030*da2e3ebdSchin ppop(PP_STRICT, i0); 2031*da2e3ebdSchin break; 2032*da2e3ebdSchin case X_STRINGSPAN: 2033*da2e3ebdSchin setoption(STRINGSPAN, i0); 2034*da2e3ebdSchin break; 2035*da2e3ebdSchin case X_STRINGSPLIT: 2036*da2e3ebdSchin setoption(STRINGSPLIT, i0); 2037*da2e3ebdSchin if (pp.option & STRINGSPLIT) 2038*da2e3ebdSchin setmode(CATLITERAL, 0); 2039*da2e3ebdSchin break; 2040*da2e3ebdSchin case X_SYSTEM_HEADER: 2041*da2e3ebdSchin if (i0) 2042*da2e3ebdSchin { 2043*da2e3ebdSchin pp.mode |= HOSTED; 2044*da2e3ebdSchin pp.flags |= PP_hosted; 2045*da2e3ebdSchin pp.in->flags |= IN_hosted; 2046*da2e3ebdSchin } 2047*da2e3ebdSchin else 2048*da2e3ebdSchin { 2049*da2e3ebdSchin pp.mode &= ~HOSTED; 2050*da2e3ebdSchin pp.flags &= ~PP_hosted; 2051*da2e3ebdSchin pp.in->flags &= ~PP_hosted; 2052*da2e3ebdSchin } 2053*da2e3ebdSchin break; 2054*da2e3ebdSchin case X_TEST: 2055*da2e3ebdSchin ppop(PP_TEST, p); 2056*da2e3ebdSchin break; 2057*da2e3ebdSchin case X_TEXT: 2058*da2e3ebdSchin if (!(pp.option & KEEPNOTEXT)) 2059*da2e3ebdSchin setstate(NOTEXT, !i0); 2060*da2e3ebdSchin break; 2061*da2e3ebdSchin case X_TRANSITION: 2062*da2e3ebdSchin ppop(PP_TRANSITION, i0); 2063*da2e3ebdSchin if (pp.state & TRANSITION) ppop(PP_COMPATIBILITY, i0); 2064*da2e3ebdSchin break; 2065*da2e3ebdSchin case X_TRUNCATE: 2066*da2e3ebdSchin ppop(PP_TRUNCATE, i0 ? (p ? strtol(p, NiL, 0) : TRUNCLENGTH) : 0); 2067*da2e3ebdSchin break; 2068*da2e3ebdSchin case X_VENDOR: 2069*da2e3ebdSchin tokop(PP_VENDOR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 2070*da2e3ebdSchin break; 2071*da2e3ebdSchin case X_VERSION: 2072*da2e3ebdSchin if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT)) 2073*da2e3ebdSchin { 2074*da2e3ebdSchin sfsprintf(pp.tmpbuf, MAXTOKEN, "\"%s\"", pp.version); 2075*da2e3ebdSchin (*pp.pragma)(dirname(PRAGMA), pp.pass, p3, pp.tmpbuf, !n); 2076*da2e3ebdSchin if (pp.linesync && !n) 2077*da2e3ebdSchin (*pp.linesync)(error_info.line, error_info.file); 2078*da2e3ebdSchin emitted = 1; 2079*da2e3ebdSchin } 2080*da2e3ebdSchin break; 2081*da2e3ebdSchin case X_WARN: 2082*da2e3ebdSchin ppop(PP_WARN, i0); 2083*da2e3ebdSchin break; 2084*da2e3ebdSchin case X_ZEOF: 2085*da2e3ebdSchin setoption(ZEOF, i0); 2086*da2e3ebdSchin break; 2087*da2e3ebdSchin #if DEBUG 2088*da2e3ebdSchin case 0: 2089*da2e3ebdSchin case X_INCLUDED: 2090*da2e3ebdSchin case X_NOTICED: 2091*da2e3ebdSchin case X_OPTION: 2092*da2e3ebdSchin case X_STATEMENT: 2093*da2e3ebdSchin break; 2094*da2e3ebdSchin default: 2095*da2e3ebdSchin error(PANIC, "%s: option recognized but not implemented", pp.valbuf); 2096*da2e3ebdSchin break; 2097*da2e3ebdSchin #endif 2098*da2e3ebdSchin } 2099*da2e3ebdSchin *p4 = i2; 2100*da2e3ebdSchin if (!n) 2101*da2e3ebdSchin goto checkmap; 2102*da2e3ebdSchin goto donedirective; 2103*da2e3ebdSchin case RENAME: 2104*da2e3ebdSchin if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 2105*da2e3ebdSchin error(1, "#%s: non-standard directive", pp.token); 2106*da2e3ebdSchin if ((c = pplex()) != T_ID) 2107*da2e3ebdSchin { 2108*da2e3ebdSchin error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2109*da2e3ebdSchin goto eatdirective; 2110*da2e3ebdSchin } 2111*da2e3ebdSchin if (!(sym = pprefmac(pp.token, REF_DELETE)) || !sym->macro) 2112*da2e3ebdSchin goto eatdirective; 2113*da2e3ebdSchin if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 2114*da2e3ebdSchin { 2115*da2e3ebdSchin if (!(pp.option & ALLPOSSIBLE)) 2116*da2e3ebdSchin error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 2117*da2e3ebdSchin goto eatdirective; 2118*da2e3ebdSchin } 2119*da2e3ebdSchin if ((c = pplex()) != T_ID) 2120*da2e3ebdSchin { 2121*da2e3ebdSchin error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2122*da2e3ebdSchin goto eatdirective; 2123*da2e3ebdSchin } 2124*da2e3ebdSchin var.symbol = pprefmac(pp.token, REF_CREATE); 2125*da2e3ebdSchin if (mac = var.symbol->macro) 2126*da2e3ebdSchin { 2127*da2e3ebdSchin if (var.symbol->flags & (SYM_ACTIVE|SYM_READONLY)) 2128*da2e3ebdSchin { 2129*da2e3ebdSchin if (!(pp.option & ALLPOSSIBLE)) 2130*da2e3ebdSchin error(2, "%s: macro is %s", var.symbol->name, (var.symbol->flags & SYM_READONLY) ? "readonly" : "active"); 2131*da2e3ebdSchin goto eatdirective; 2132*da2e3ebdSchin } 2133*da2e3ebdSchin if (!(pp.mode & HOSTED) || !(var.symbol->flags & SYM_INITIAL)) 2134*da2e3ebdSchin error(1, "%s redefined", var.symbol->name); 2135*da2e3ebdSchin if (mac->formals) free(mac->formals); 2136*da2e3ebdSchin free(mac->value); 2137*da2e3ebdSchin free(mac); 2138*da2e3ebdSchin } 2139*da2e3ebdSchin ppfsm(FSM_MACRO, var.symbol->name); 2140*da2e3ebdSchin var.symbol->flags = sym->flags; 2141*da2e3ebdSchin sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 2142*da2e3ebdSchin var.symbol->macro = sym->macro; 2143*da2e3ebdSchin sym->macro = 0; 2144*da2e3ebdSchin break; 2145*da2e3ebdSchin case UNDEF: 2146*da2e3ebdSchin if ((c = pplex()) != T_ID) 2147*da2e3ebdSchin { 2148*da2e3ebdSchin error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2149*da2e3ebdSchin goto eatdirective; 2150*da2e3ebdSchin } 2151*da2e3ebdSchin if (sym = pprefmac(pp.token, REF_DELETE)) 2152*da2e3ebdSchin { 2153*da2e3ebdSchin if (mac = sym->macro) 2154*da2e3ebdSchin { 2155*da2e3ebdSchin if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 2156*da2e3ebdSchin { 2157*da2e3ebdSchin if (!(pp.option & ALLPOSSIBLE)) 2158*da2e3ebdSchin error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 2159*da2e3ebdSchin goto eatdirective; 2160*da2e3ebdSchin } 2161*da2e3ebdSchin if (mac->formals) free(mac->formals); 2162*da2e3ebdSchin free(mac->value); 2163*da2e3ebdSchin free(mac); 2164*da2e3ebdSchin mac = sym->macro = 0; 2165*da2e3ebdSchin } 2166*da2e3ebdSchin if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT))) 2167*da2e3ebdSchin { 2168*da2e3ebdSchin ppsync(); 2169*da2e3ebdSchin ppprintf("#%s %s", dirname(UNDEF), sym->name); 2170*da2e3ebdSchin emitted = 1; 2171*da2e3ebdSchin } 2172*da2e3ebdSchin sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 2173*da2e3ebdSchin n2 = error_info.line; 2174*da2e3ebdSchin goto benign; 2175*da2e3ebdSchin } 2176*da2e3ebdSchin else pprefmac(pp.token, REF_UNDEF); 2177*da2e3ebdSchin break; 2178*da2e3ebdSchin #if DEBUG 2179*da2e3ebdSchin default: 2180*da2e3ebdSchin error(PANIC, "#%s: directive recognized but not implemented", pp.token); 2181*da2e3ebdSchin goto eatdirective; 2182*da2e3ebdSchin #endif 2183*da2e3ebdSchin } 2184*da2e3ebdSchin break; 2185*da2e3ebdSchin case '\n': 2186*da2e3ebdSchin break; 2187*da2e3ebdSchin default: 2188*da2e3ebdSchin error(1, "%s: invalid directive name", pptokstr(pp.token, 0)); 2189*da2e3ebdSchin goto eatdirective; 2190*da2e3ebdSchin } 2191*da2e3ebdSchin enddirective: 2192*da2e3ebdSchin #if COMPATIBLE 2193*da2e3ebdSchin if (c != '\n' && !(pp.state & COMPATIBILITY)) 2194*da2e3ebdSchin #else 2195*da2e3ebdSchin if (c != '\n') 2196*da2e3ebdSchin #endif 2197*da2e3ebdSchin { 2198*da2e3ebdSchin pp.state |= DISABLE|NOSPACE; 2199*da2e3ebdSchin if ((c = pplex()) != '\n' && (pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC) 2200*da2e3ebdSchin error(1, "%s: invalid characters after directive", pptokstr(pp.token, 0)); 2201*da2e3ebdSchin } 2202*da2e3ebdSchin eatdirective: 2203*da2e3ebdSchin if (c != '\n') 2204*da2e3ebdSchin { 2205*da2e3ebdSchin pp.state |= DISABLE; 2206*da2e3ebdSchin while (pplex() != '\n'); 2207*da2e3ebdSchin } 2208*da2e3ebdSchin donedirective: 2209*da2e3ebdSchin #if _HUH_2002_05_09 2210*da2e3ebdSchin if (!(pp.state & EOF2NL)) 2211*da2e3ebdSchin error(2, "%s in directive", pptokchr(0)); 2212*da2e3ebdSchin #endif 2213*da2e3ebdSchin pp.state &= ~RESTORE; 2214*da2e3ebdSchin pp.mode &= ~RELAX; 2215*da2e3ebdSchin if (!(*pp.control & SKIP)) 2216*da2e3ebdSchin { 2217*da2e3ebdSchin pp.state |= restore; 2218*da2e3ebdSchin switch (directive) 2219*da2e3ebdSchin { 2220*da2e3ebdSchin case LINE: 2221*da2e3ebdSchin return 0; 2222*da2e3ebdSchin case INCLUDE: 2223*da2e3ebdSchin if (pp.include) 2224*da2e3ebdSchin { 2225*da2e3ebdSchin error_info.line++; 2226*da2e3ebdSchin PUSH_FILE(pp.include, n); 2227*da2e3ebdSchin if (!pp.vendor && (pp.found->type & TYPE_VENDOR)) 2228*da2e3ebdSchin pp.vendor = 1; 2229*da2e3ebdSchin pp.include = 0; 2230*da2e3ebdSchin return 0; 2231*da2e3ebdSchin } 2232*da2e3ebdSchin if (pp.incref) 2233*da2e3ebdSchin (*pp.incref)(error_info.file, ppgetfile(pp.path)->name, error_info.line, PP_SYNC_IGNORE); 2234*da2e3ebdSchin else if (pp.linesync && pp.macref) 2235*da2e3ebdSchin { 2236*da2e3ebdSchin pp.flags |= PP_lineignore; 2237*da2e3ebdSchin (*pp.linesync)(error_info.line, ppgetfile(pp.path)->name); 2238*da2e3ebdSchin } 2239*da2e3ebdSchin /*FALLTHROUGH*/ 2240*da2e3ebdSchin default: 2241*da2e3ebdSchin pp.in->flags |= IN_tokens; 2242*da2e3ebdSchin /*FALLTHROUGH*/ 2243*da2e3ebdSchin case ENDIF: 2244*da2e3ebdSchin error_info.line++; 2245*da2e3ebdSchin if (emitted) 2246*da2e3ebdSchin { 2247*da2e3ebdSchin ppputchar('\n'); 2248*da2e3ebdSchin ppcheckout(); 2249*da2e3ebdSchin } 2250*da2e3ebdSchin else 2251*da2e3ebdSchin { 2252*da2e3ebdSchin pp.state |= HIDDEN; 2253*da2e3ebdSchin pp.hidden++; 2254*da2e3ebdSchin } 2255*da2e3ebdSchin return 0; 2256*da2e3ebdSchin } 2257*da2e3ebdSchin } 2258*da2e3ebdSchin pp.state |= restore|HIDDEN|SKIPCONTROL; 2259*da2e3ebdSchin pp.hidden++; 2260*da2e3ebdSchin pp.level++; 2261*da2e3ebdSchin error_info.line++; 2262*da2e3ebdSchin return 0; 2263*da2e3ebdSchin } 2264*da2e3ebdSchin 2265*da2e3ebdSchin /* 2266*da2e3ebdSchin * grow the pp nesting control stack 2267*da2e3ebdSchin */ 2268*da2e3ebdSchin 2269*da2e3ebdSchin void 2270*da2e3ebdSchin ppnest(void) 2271*da2e3ebdSchin { 2272*da2e3ebdSchin register struct ppinstk* ip; 2273*da2e3ebdSchin int oz; 2274*da2e3ebdSchin int nz; 2275*da2e3ebdSchin long adjust; 2276*da2e3ebdSchin long* op; 2277*da2e3ebdSchin long* np; 2278*da2e3ebdSchin 2279*da2e3ebdSchin oz = pp.constack; 2280*da2e3ebdSchin op = pp.maxcon - oz + 1; 2281*da2e3ebdSchin nz = oz * 2; 2282*da2e3ebdSchin np = newof(op, long, nz, 0); 2283*da2e3ebdSchin if (adjust = (np - op)) 2284*da2e3ebdSchin { 2285*da2e3ebdSchin ip = pp.in; 2286*da2e3ebdSchin do 2287*da2e3ebdSchin { 2288*da2e3ebdSchin if (ip->control) 2289*da2e3ebdSchin ip->control += adjust; 2290*da2e3ebdSchin } while (ip = ip->prev); 2291*da2e3ebdSchin } 2292*da2e3ebdSchin pp.control = np + oz; 2293*da2e3ebdSchin pp.constack = nz; 2294*da2e3ebdSchin pp.maxcon = np + nz - 1; 2295*da2e3ebdSchin } 2296