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 library control interface 26*da2e3ebdSchin */ 27*da2e3ebdSchin 28*da2e3ebdSchin #include "pplib.h" 29*da2e3ebdSchin #include "pptab.h" 30*da2e3ebdSchin 31*da2e3ebdSchin #include <ls.h> 32*da2e3ebdSchin 33*da2e3ebdSchin #define REFONE (pp.truncate?(Hash_table_t*)0:pp.symtab) 34*da2e3ebdSchin #define REFALL (pp.truncate?pp.dirtab:pp.symtab) 35*da2e3ebdSchin 36*da2e3ebdSchin #define ppiskey(t,v,p) (p=t,v>=p->value&&value<=(p+elementsof(t)-2)->value) 37*da2e3ebdSchin 38*da2e3ebdSchin /* 39*da2e3ebdSchin * set option value 40*da2e3ebdSchin * initialization files have lowest precedence 41*da2e3ebdSchin */ 42*da2e3ebdSchin 43*da2e3ebdSchin static void 44*da2e3ebdSchin set(register long* p, register long op, int val) 45*da2e3ebdSchin { 46*da2e3ebdSchin long* r; 47*da2e3ebdSchin 48*da2e3ebdSchin r = p == &pp.state ? &pp.ro_state : p == &pp.mode ? &pp.ro_mode : &pp.ro_option; 49*da2e3ebdSchin if (!(pp.mode & INIT) || !(pp.in->type == IN_FILE) || !(*r & op)) 50*da2e3ebdSchin { 51*da2e3ebdSchin if (!pp.initialized && !(pp.mode & INIT)) 52*da2e3ebdSchin *r |= op; 53*da2e3ebdSchin if (val) 54*da2e3ebdSchin *p |= op; 55*da2e3ebdSchin else 56*da2e3ebdSchin *p &= ~op; 57*da2e3ebdSchin } 58*da2e3ebdSchin debug((-7, "set(%s)=%s", p == &pp.state ? "state" : p == &pp.mode ? "mode" : "option", p == &pp.state ? ppstatestr(*p) : p == &pp.mode ? ppmodestr(*p) : ppoptionstr(*p))); 59*da2e3ebdSchin } 60*da2e3ebdSchin 61*da2e3ebdSchin /* 62*da2e3ebdSchin * initialize hash table with keywords from key 63*da2e3ebdSchin */ 64*da2e3ebdSchin 65*da2e3ebdSchin static void 66*da2e3ebdSchin inithash(register Hash_table_t* tab, register struct ppkeyword* key) 67*da2e3ebdSchin { 68*da2e3ebdSchin register char* s; 69*da2e3ebdSchin 70*da2e3ebdSchin for (; s = key->name; key++) 71*da2e3ebdSchin { 72*da2e3ebdSchin if (!ppisid(*s)) 73*da2e3ebdSchin s++; 74*da2e3ebdSchin hashput(tab, s, key->value); 75*da2e3ebdSchin } 76*da2e3ebdSchin } 77*da2e3ebdSchin 78*da2e3ebdSchin /* 79*da2e3ebdSchin * return ppkeyword table name given value 80*da2e3ebdSchin */ 81*da2e3ebdSchin 82*da2e3ebdSchin char* 83*da2e3ebdSchin ppkeyname(register int value, int dir) 84*da2e3ebdSchin { 85*da2e3ebdSchin register char* s; 86*da2e3ebdSchin register struct ppkeyword* p; 87*da2e3ebdSchin 88*da2e3ebdSchin if (dir && ppiskey(directives, value, p) || !dir && (ppiskey(options, value, p) || ppiskey(predicates, value, p) || ppiskey(variables, value, p))) 89*da2e3ebdSchin { 90*da2e3ebdSchin s = (p + (value - p->value))->name; 91*da2e3ebdSchin return s + !ppisid(*s); 92*da2e3ebdSchin } 93*da2e3ebdSchin #if DEBUG 94*da2e3ebdSchin error(PANIC, "no keyword table name for value=%d", value); 95*da2e3ebdSchin #endif 96*da2e3ebdSchin return "UNKNOWN"; 97*da2e3ebdSchin } 98*da2e3ebdSchin 99*da2e3ebdSchin /* 100*da2e3ebdSchin * add to the include maps 101*da2e3ebdSchin */ 102*da2e3ebdSchin 103*da2e3ebdSchin void 104*da2e3ebdSchin ppmapinclude(char* file, register char* s) 105*da2e3ebdSchin { 106*da2e3ebdSchin register int c; 107*da2e3ebdSchin register struct ppdirs* dp; 108*da2e3ebdSchin int fd; 109*da2e3ebdSchin int flags; 110*da2e3ebdSchin int index; 111*da2e3ebdSchin int token; 112*da2e3ebdSchin char* t; 113*da2e3ebdSchin char* old_file; 114*da2e3ebdSchin long old_state; 115*da2e3ebdSchin struct ppfile* fp; 116*da2e3ebdSchin struct ppfile* mp; 117*da2e3ebdSchin 118*da2e3ebdSchin old_file = error_info.file; 119*da2e3ebdSchin old_state = pp.state; 120*da2e3ebdSchin if (s) 121*da2e3ebdSchin PUSH_BUFFER("mapinclude", s, 1); 122*da2e3ebdSchin else if (file) 123*da2e3ebdSchin { 124*da2e3ebdSchin if (*file == '-') 125*da2e3ebdSchin { 126*da2e3ebdSchin if (!error_info.file) 127*da2e3ebdSchin { 128*da2e3ebdSchin error(1, "%s: input file name required for %s ignore", file, dirname(INCLUDE)); 129*da2e3ebdSchin return; 130*da2e3ebdSchin } 131*da2e3ebdSchin s = t = strcopy(pp.tmpbuf, error_info.file); 132*da2e3ebdSchin c = *++file; 133*da2e3ebdSchin for (;;) 134*da2e3ebdSchin { 135*da2e3ebdSchin if (s <= pp.tmpbuf || *s == '/') 136*da2e3ebdSchin { 137*da2e3ebdSchin s = t; 138*da2e3ebdSchin break; 139*da2e3ebdSchin } 140*da2e3ebdSchin else if (*s == c) 141*da2e3ebdSchin break; 142*da2e3ebdSchin s--; 143*da2e3ebdSchin } 144*da2e3ebdSchin strcpy(s, file); 145*da2e3ebdSchin file = pp.tmpbuf; 146*da2e3ebdSchin } 147*da2e3ebdSchin if ((fd = ppsearch(file, INC_LOCAL, SEARCH_INCLUDE)) < 0) 148*da2e3ebdSchin return; 149*da2e3ebdSchin PUSH_FILE(file, fd); 150*da2e3ebdSchin } 151*da2e3ebdSchin else 152*da2e3ebdSchin return; 153*da2e3ebdSchin #if CATSTRINGS 154*da2e3ebdSchin pp.state |= (COMPILE|FILEPOP|HEADER|JOINING|STRIP|NOSPACE|PASSEOF); 155*da2e3ebdSchin #else 156*da2e3ebdSchin pp.state |= (COMPILE|FILEPOP|HEADER|STRIP|NOSPACE|PASSEOF); 157*da2e3ebdSchin #endif 158*da2e3ebdSchin pp.level++; 159*da2e3ebdSchin flags = INC_MAPALL; 160*da2e3ebdSchin fp = mp = 0; 161*da2e3ebdSchin for (;;) 162*da2e3ebdSchin { 163*da2e3ebdSchin switch (token = pplex()) 164*da2e3ebdSchin { 165*da2e3ebdSchin case 0: 166*da2e3ebdSchin case T_STRING: 167*da2e3ebdSchin case T_HEADER: 168*da2e3ebdSchin if (fp) 169*da2e3ebdSchin { 170*da2e3ebdSchin fp->guard = INC_IGNORE; 171*da2e3ebdSchin for (dp = pp.firstdir->next; dp; dp = dp->next) 172*da2e3ebdSchin if (dp->name && (c = strlen(dp->name)) && !strncmp(dp->name, fp->name, c) && fp->name[c] == '/') 173*da2e3ebdSchin { 174*da2e3ebdSchin ppsetfile(fp->name + c + 1)->guard = INC_IGNORE; 175*da2e3ebdSchin break; 176*da2e3ebdSchin } 177*da2e3ebdSchin } 178*da2e3ebdSchin if (!token) 179*da2e3ebdSchin break; 180*da2e3ebdSchin pathcanon(pp.token, 0); 181*da2e3ebdSchin fp = ppsetfile(pp.token); 182*da2e3ebdSchin if (mp) 183*da2e3ebdSchin { 184*da2e3ebdSchin mp->flags |= flags; 185*da2e3ebdSchin if (streq(fp->name, ".")) 186*da2e3ebdSchin mp->flags |= INC_MAPNOLOCAL; 187*da2e3ebdSchin else 188*da2e3ebdSchin mp->bound[index] = fp; 189*da2e3ebdSchin 190*da2e3ebdSchin fp = mp = 0; 191*da2e3ebdSchin } 192*da2e3ebdSchin else 193*da2e3ebdSchin index = token == T_HEADER ? INC_STANDARD : INC_LOCAL; 194*da2e3ebdSchin continue; 195*da2e3ebdSchin case '=': 196*da2e3ebdSchin if (!(mp = fp)) 197*da2e3ebdSchin error(3, "%s: \"name\" = \"binding\" expected"); 198*da2e3ebdSchin fp = 0; 199*da2e3ebdSchin continue; 200*da2e3ebdSchin case '\n': 201*da2e3ebdSchin continue; 202*da2e3ebdSchin case T_ID: 203*da2e3ebdSchin if (streq(pp.token, "all")) 204*da2e3ebdSchin { 205*da2e3ebdSchin flags = INC_MAPALL; 206*da2e3ebdSchin continue; 207*da2e3ebdSchin } 208*da2e3ebdSchin else if (streq(pp.token, "hosted")) 209*da2e3ebdSchin { 210*da2e3ebdSchin flags = INC_MAPHOSTED; 211*da2e3ebdSchin continue; 212*da2e3ebdSchin } 213*da2e3ebdSchin else if (streq(pp.token, "nohosted")) 214*da2e3ebdSchin { 215*da2e3ebdSchin flags = INC_MAPNOHOSTED; 216*da2e3ebdSchin continue; 217*da2e3ebdSchin } 218*da2e3ebdSchin /*FALLTHROUGH*/ 219*da2e3ebdSchin default: 220*da2e3ebdSchin error(3, "%s unexpected in %s map list", pptokstr(pp.token, 0), dirname(INCLUDE)); 221*da2e3ebdSchin break; 222*da2e3ebdSchin } 223*da2e3ebdSchin break; 224*da2e3ebdSchin } 225*da2e3ebdSchin pp.level--; 226*da2e3ebdSchin error_info.file = old_file; 227*da2e3ebdSchin pp.state = old_state; 228*da2e3ebdSchin } 229*da2e3ebdSchin 230*da2e3ebdSchin /* 231*da2e3ebdSchin * return non-0 if file is identical to fd 232*da2e3ebdSchin */ 233*da2e3ebdSchin 234*da2e3ebdSchin static int 235*da2e3ebdSchin identical(char* file, int fd) 236*da2e3ebdSchin { 237*da2e3ebdSchin struct stat a; 238*da2e3ebdSchin struct stat b; 239*da2e3ebdSchin 240*da2e3ebdSchin return !stat(file, &a) && !fstat(fd, &b) && a.st_dev == b.st_dev && a.st_ino == b.st_ino; 241*da2e3ebdSchin } 242*da2e3ebdSchin 243*da2e3ebdSchin /* 244*da2e3ebdSchin * compare up to pp.truncate chars 245*da2e3ebdSchin * 246*da2e3ebdSchin * NOTE: __STD* and symbols containing ' ' are not truncated 247*da2e3ebdSchin */ 248*da2e3ebdSchin 249*da2e3ebdSchin static int 250*da2e3ebdSchin trunccomp(register char* a, register char* b) 251*da2e3ebdSchin { 252*da2e3ebdSchin return !strchr(b, ' ') && !strneq(b, "__STD", 5) ? strncmp(a, b, pp.truncate) : strcmp(a, b); 253*da2e3ebdSchin } 254*da2e3ebdSchin 255*da2e3ebdSchin /* 256*da2e3ebdSchin * hash up to pp.truncate chars 257*da2e3ebdSchin * 258*da2e3ebdSchin * NOTE: __STD* and symbols containing ' ' are not truncated 259*da2e3ebdSchin */ 260*da2e3ebdSchin 261*da2e3ebdSchin static unsigned int 262*da2e3ebdSchin trunchash(char* a) 263*da2e3ebdSchin { 264*da2e3ebdSchin int n; 265*da2e3ebdSchin 266*da2e3ebdSchin return memhash(a, (n = strlen(a)) > pp.truncate && !strchr(a, ' ') && !strneq(a, "__STD", 5) ? pp.truncate : n); 267*da2e3ebdSchin } 268*da2e3ebdSchin 269*da2e3ebdSchin #if DEBUG & TRACE_debug 270*da2e3ebdSchin /* 271*da2e3ebdSchin * append context to debug trace 272*da2e3ebdSchin */ 273*da2e3ebdSchin 274*da2e3ebdSchin static int 275*da2e3ebdSchin context(Sfio_t* sp, int level, int flags) 276*da2e3ebdSchin { 277*da2e3ebdSchin static int state; 278*da2e3ebdSchin 279*da2e3ebdSchin NoP(level); 280*da2e3ebdSchin NoP(flags); 281*da2e3ebdSchin if (error_info.trace <= -10 && pp.state != state) 282*da2e3ebdSchin { 283*da2e3ebdSchin state = pp.state; 284*da2e3ebdSchin sfprintf(sp, " %s", ppstatestr(pp.state)); 285*da2e3ebdSchin } 286*da2e3ebdSchin return 1; 287*da2e3ebdSchin } 288*da2e3ebdSchin #endif 289*da2e3ebdSchin 290*da2e3ebdSchin /* 291*da2e3ebdSchin * reset include guard 292*da2e3ebdSchin */ 293*da2e3ebdSchin 294*da2e3ebdSchin static int 295*da2e3ebdSchin unguard(const char* name, char* v, void* handle) 296*da2e3ebdSchin { 297*da2e3ebdSchin register struct ppfile* fp = (struct ppfile*)v; 298*da2e3ebdSchin 299*da2e3ebdSchin fp->guard = 0; 300*da2e3ebdSchin return 0; 301*da2e3ebdSchin } 302*da2e3ebdSchin 303*da2e3ebdSchin /* 304*da2e3ebdSchin * reset macro definition 305*da2e3ebdSchin */ 306*da2e3ebdSchin 307*da2e3ebdSchin static void 308*da2e3ebdSchin undefine(void* p) 309*da2e3ebdSchin { 310*da2e3ebdSchin struct ppmacro* mac = ((struct ppsymbol*)p)->macro; 311*da2e3ebdSchin 312*da2e3ebdSchin if (mac) 313*da2e3ebdSchin { 314*da2e3ebdSchin if (mac->formals) 315*da2e3ebdSchin free(mac->formals); 316*da2e3ebdSchin free(mac->value); 317*da2e3ebdSchin free(mac); 318*da2e3ebdSchin } 319*da2e3ebdSchin } 320*da2e3ebdSchin 321*da2e3ebdSchin /* 322*da2e3ebdSchin * pp operations 323*da2e3ebdSchin * 324*da2e3ebdSchin * NOTE: PP_INIT must be done before the first pplex() call 325*da2e3ebdSchin * PP_DONE must be done after the last pplex() call 326*da2e3ebdSchin * PP_INIT-PP_DONE must be done for each new PP_INPUT 327*da2e3ebdSchin */ 328*da2e3ebdSchin 329*da2e3ebdSchin void 330*da2e3ebdSchin ppop(int op, ...) 331*da2e3ebdSchin { 332*da2e3ebdSchin va_list ap; 333*da2e3ebdSchin register char* p; 334*da2e3ebdSchin register struct ppkeyword* kp; 335*da2e3ebdSchin register char* s; 336*da2e3ebdSchin int c; 337*da2e3ebdSchin long n; 338*da2e3ebdSchin char* t; 339*da2e3ebdSchin struct ppdirs* dp; 340*da2e3ebdSchin struct ppdirs* hp; 341*da2e3ebdSchin struct ppsymkey* key; 342*da2e3ebdSchin struct oplist* xp; 343*da2e3ebdSchin Sfio_t* sp; 344*da2e3ebdSchin struct stat st; 345*da2e3ebdSchin PPCOMMENT ppcomment; 346*da2e3ebdSchin PPLINESYNC pplinesync; 347*da2e3ebdSchin 348*da2e3ebdSchin static int initialized; 349*da2e3ebdSchin 350*da2e3ebdSchin va_start(ap, op); 351*da2e3ebdSchin switch (op) 352*da2e3ebdSchin { 353*da2e3ebdSchin case PP_ASSERT: 354*da2e3ebdSchin case PP_DEFINE: 355*da2e3ebdSchin case PP_DIRECTIVE: 356*da2e3ebdSchin case PP_OPTION: 357*da2e3ebdSchin case PP_READ: 358*da2e3ebdSchin case PP_UNDEF: 359*da2e3ebdSchin if (pp.initialized) 360*da2e3ebdSchin goto before; 361*da2e3ebdSchin if ((p = va_arg(ap, char*)) && *p) 362*da2e3ebdSchin { 363*da2e3ebdSchin if (pp.lastop) 364*da2e3ebdSchin pp.lastop = (pp.lastop->next = newof(0, struct oplist, 1, 0)); 365*da2e3ebdSchin else 366*da2e3ebdSchin pp.firstop = pp.lastop = newof(0, struct oplist, 1, 0); 367*da2e3ebdSchin pp.lastop->op = op; 368*da2e3ebdSchin pp.lastop->value = p; 369*da2e3ebdSchin } 370*da2e3ebdSchin break; 371*da2e3ebdSchin case PP_BUILTIN: 372*da2e3ebdSchin pp.builtin = va_arg(ap, PPBUILTIN); 373*da2e3ebdSchin break; 374*da2e3ebdSchin case PP_CDIR: 375*da2e3ebdSchin p = va_arg(ap, char*); 376*da2e3ebdSchin c = va_arg(ap, int); 377*da2e3ebdSchin pp.cdir.path = 0; 378*da2e3ebdSchin if (!p) 379*da2e3ebdSchin pp.c = c; 380*da2e3ebdSchin else if (streq(p, "-")) 381*da2e3ebdSchin { 382*da2e3ebdSchin pp.c = c; 383*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 384*da2e3ebdSchin dp->c = c; 385*da2e3ebdSchin } 386*da2e3ebdSchin else if (!pp.c) 387*da2e3ebdSchin { 388*da2e3ebdSchin if (!*p || stat((pathcanon(p, 0), p), &st)) 389*da2e3ebdSchin pp.c = c; 390*da2e3ebdSchin else 391*da2e3ebdSchin { 392*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 393*da2e3ebdSchin { 394*da2e3ebdSchin if (!pp.c && (dp->c || dp->name && SAMEID(&dp->id, &st))) 395*da2e3ebdSchin pp.c = 1; 396*da2e3ebdSchin dp->c = pp.c == 1; 397*da2e3ebdSchin } 398*da2e3ebdSchin if (!pp.c) 399*da2e3ebdSchin { 400*da2e3ebdSchin pp.cdir.path = p; 401*da2e3ebdSchin SAVEID(&pp.cdir.id, &st); 402*da2e3ebdSchin } 403*da2e3ebdSchin } 404*da2e3ebdSchin } 405*da2e3ebdSchin break; 406*da2e3ebdSchin case PP_CHOP: 407*da2e3ebdSchin if (p = va_arg(ap, char*)) 408*da2e3ebdSchin { 409*da2e3ebdSchin c = strlen(p); 410*da2e3ebdSchin xp = newof(0, struct oplist, 1, c + 1); 411*da2e3ebdSchin xp->value = ((char*)xp) + sizeof(struct oplist); 412*da2e3ebdSchin s = xp->value; 413*da2e3ebdSchin c = *p++; 414*da2e3ebdSchin while (*p && *p != c) 415*da2e3ebdSchin *s++ = *p++; 416*da2e3ebdSchin *s++ = '/'; 417*da2e3ebdSchin xp->op = s - xp->value; 418*da2e3ebdSchin *s++ = 0; 419*da2e3ebdSchin if (*p && *++p && *p != c) 420*da2e3ebdSchin { 421*da2e3ebdSchin while (*p && *p != c) 422*da2e3ebdSchin *s++ = *p++; 423*da2e3ebdSchin *s++ = '/'; 424*da2e3ebdSchin } 425*da2e3ebdSchin *s = 0; 426*da2e3ebdSchin xp->next = pp.chop; 427*da2e3ebdSchin pp.chop = xp; 428*da2e3ebdSchin } 429*da2e3ebdSchin break; 430*da2e3ebdSchin case PP_COMMENT: 431*da2e3ebdSchin if (pp.comment = va_arg(ap, PPCOMMENT)) 432*da2e3ebdSchin pp.flags |= PP_comment; 433*da2e3ebdSchin else 434*da2e3ebdSchin pp.flags &= ~PP_comment; 435*da2e3ebdSchin break; 436*da2e3ebdSchin case PP_COMPATIBILITY: 437*da2e3ebdSchin set(&pp.state, COMPATIBILITY, va_arg(ap, int)); 438*da2e3ebdSchin #if COMPATIBLE 439*da2e3ebdSchin if (pp.initialized) 440*da2e3ebdSchin ppfsm(FSM_COMPATIBILITY, NiL); 441*da2e3ebdSchin #else 442*da2e3ebdSchin if (pp.state & COMPATIBILITY) 443*da2e3ebdSchin error(3, "preprocessor not compiled with compatibility dialect enabled [COMPATIBLE]"); 444*da2e3ebdSchin #endif 445*da2e3ebdSchin if (pp.state & COMPATIBILITY) 446*da2e3ebdSchin pp.flags |= PP_compatibility; 447*da2e3ebdSchin else 448*da2e3ebdSchin pp.flags &= ~PP_compatibility; 449*da2e3ebdSchin break; 450*da2e3ebdSchin case PP_COMPILE: 451*da2e3ebdSchin if (pp.initialized) 452*da2e3ebdSchin goto before; 453*da2e3ebdSchin pp.state |= COMPILE; 454*da2e3ebdSchin if (!pp.symtab) 455*da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0); 456*da2e3ebdSchin if (kp = va_arg(ap, struct ppkeyword*)) 457*da2e3ebdSchin for (; s = kp->name; kp++) 458*da2e3ebdSchin { 459*da2e3ebdSchin n = SYM_LEX; 460*da2e3ebdSchin switch (*s) 461*da2e3ebdSchin { 462*da2e3ebdSchin case '-': 463*da2e3ebdSchin s++; 464*da2e3ebdSchin break; 465*da2e3ebdSchin case '+': 466*da2e3ebdSchin s++; 467*da2e3ebdSchin if (!(pp.option & PLUSPLUS)) 468*da2e3ebdSchin break; 469*da2e3ebdSchin /*FALLTHROUGH*/ 470*da2e3ebdSchin default: 471*da2e3ebdSchin n |= SYM_KEYWORD; 472*da2e3ebdSchin break; 473*da2e3ebdSchin } 474*da2e3ebdSchin if (key = ppkeyset(pp.symtab, s)) 475*da2e3ebdSchin { 476*da2e3ebdSchin key->sym.flags = n; 477*da2e3ebdSchin key->lex = kp->value; 478*da2e3ebdSchin } 479*da2e3ebdSchin } 480*da2e3ebdSchin break; 481*da2e3ebdSchin case PP_DEBUG: 482*da2e3ebdSchin error_info.trace = va_arg(ap, int); 483*da2e3ebdSchin break; 484*da2e3ebdSchin case PP_DEFAULT: 485*da2e3ebdSchin if (p = va_arg(ap, char*)) 486*da2e3ebdSchin p = strdup(p); 487*da2e3ebdSchin if (pp.ppdefault) 488*da2e3ebdSchin free(pp.ppdefault); 489*da2e3ebdSchin pp.ppdefault = p; 490*da2e3ebdSchin break; 491*da2e3ebdSchin case PP_DONE: 492*da2e3ebdSchin #if CHECKPOINT 493*da2e3ebdSchin if (pp.mode & DUMP) 494*da2e3ebdSchin ppdump(); 495*da2e3ebdSchin #endif 496*da2e3ebdSchin if (pp.mode & FILEDEPS) 497*da2e3ebdSchin { 498*da2e3ebdSchin sfputc(pp.filedeps.sp, '\n'); 499*da2e3ebdSchin if (pp.filedeps.sp == sfstdout) 500*da2e3ebdSchin sfsync(pp.filedeps.sp); 501*da2e3ebdSchin else 502*da2e3ebdSchin sfclose(pp.filedeps.sp); 503*da2e3ebdSchin } 504*da2e3ebdSchin if (pp.state & STANDALONE) 505*da2e3ebdSchin { 506*da2e3ebdSchin if ((pp.state & (NOTEXT|HIDDEN)) == HIDDEN && pplastout() != '\n') 507*da2e3ebdSchin ppputchar('\n'); 508*da2e3ebdSchin ppflushout(); 509*da2e3ebdSchin } 510*da2e3ebdSchin error_info.file = 0; 511*da2e3ebdSchin break; 512*da2e3ebdSchin case PP_DUMP: 513*da2e3ebdSchin set(&pp.mode, DUMP, va_arg(ap, int)); 514*da2e3ebdSchin #if !CHECKPOINT 515*da2e3ebdSchin if (pp.mode & DUMP) 516*da2e3ebdSchin error(3, "preprocessor not compiled with checkpoint enabled [CHECKPOINT]"); 517*da2e3ebdSchin #endif 518*da2e3ebdSchin break; 519*da2e3ebdSchin case PP_FILEDEPS: 520*da2e3ebdSchin if (n = va_arg(ap, int)) 521*da2e3ebdSchin pp.filedeps.flags |= n; 522*da2e3ebdSchin else 523*da2e3ebdSchin pp.filedeps.flags = 0; 524*da2e3ebdSchin break; 525*da2e3ebdSchin case PP_FILENAME: 526*da2e3ebdSchin error_info.file = va_arg(ap, char*); 527*da2e3ebdSchin break; 528*da2e3ebdSchin case PP_HOSTDIR: 529*da2e3ebdSchin if (!(pp.mode & INIT)) 530*da2e3ebdSchin pp.ro_mode |= HOSTED; 531*da2e3ebdSchin else if (pp.ro_mode & HOSTED) 532*da2e3ebdSchin break; 533*da2e3ebdSchin pp.ro_mode |= INIT; 534*da2e3ebdSchin p = va_arg(ap, char*); 535*da2e3ebdSchin c = va_arg(ap, int); 536*da2e3ebdSchin pp.hostdir.path = 0; 537*da2e3ebdSchin if (!p) 538*da2e3ebdSchin pp.hosted = c; 539*da2e3ebdSchin else if (streq(p, "-")) 540*da2e3ebdSchin { 541*da2e3ebdSchin if (pp.initialized) 542*da2e3ebdSchin set(&pp.mode, HOSTED, c); 543*da2e3ebdSchin else 544*da2e3ebdSchin { 545*da2e3ebdSchin pp.hosted = c ? 1 : 2; 546*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 547*da2e3ebdSchin if (pp.hosted == 1) 548*da2e3ebdSchin dp->type |= TYPE_HOSTED; 549*da2e3ebdSchin else 550*da2e3ebdSchin dp->type &= ~TYPE_HOSTED; 551*da2e3ebdSchin } 552*da2e3ebdSchin } 553*da2e3ebdSchin else if (!pp.hosted) 554*da2e3ebdSchin { 555*da2e3ebdSchin if (!*p || stat((pathcanon(p, 0), p), &st)) 556*da2e3ebdSchin pp.hosted = 1; 557*da2e3ebdSchin else 558*da2e3ebdSchin { 559*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 560*da2e3ebdSchin { 561*da2e3ebdSchin if (!pp.hosted && ((dp->type & TYPE_HOSTED) || dp->name && SAMEID(&dp->id, &st))) 562*da2e3ebdSchin pp.hosted = 1; 563*da2e3ebdSchin if (pp.hosted == 1) 564*da2e3ebdSchin dp->type |= TYPE_HOSTED; 565*da2e3ebdSchin else 566*da2e3ebdSchin dp->type &= ~TYPE_HOSTED; 567*da2e3ebdSchin } 568*da2e3ebdSchin if (!pp.hosted) 569*da2e3ebdSchin { 570*da2e3ebdSchin pp.hostdir.path = p; 571*da2e3ebdSchin SAVEID(&pp.hostdir.id, &st); 572*da2e3ebdSchin } 573*da2e3ebdSchin } 574*da2e3ebdSchin } 575*da2e3ebdSchin break; 576*da2e3ebdSchin case PP_ID: 577*da2e3ebdSchin p = va_arg(ap, char*); 578*da2e3ebdSchin c = va_arg(ap, int); 579*da2e3ebdSchin if (p) 580*da2e3ebdSchin ppfsm(c ? FSM_IDADD : FSM_IDDEL, p); 581*da2e3ebdSchin break; 582*da2e3ebdSchin case PP_IGNORE: 583*da2e3ebdSchin if (p = va_arg(ap, char*)) 584*da2e3ebdSchin { 585*da2e3ebdSchin pathcanon(p, 0); 586*da2e3ebdSchin ppsetfile(p)->guard = INC_IGNORE; 587*da2e3ebdSchin message((-3, "%s: ignore", p)); 588*da2e3ebdSchin } 589*da2e3ebdSchin break; 590*da2e3ebdSchin case PP_IGNORELIST: 591*da2e3ebdSchin if (pp.initialized) 592*da2e3ebdSchin goto before; 593*da2e3ebdSchin pp.ignore = va_arg(ap, char*); 594*da2e3ebdSchin break; 595*da2e3ebdSchin case PP_INCLUDE: 596*da2e3ebdSchin if ((p = va_arg(ap, char*)) && *p) 597*da2e3ebdSchin { 598*da2e3ebdSchin pathcanon(p, 0); 599*da2e3ebdSchin if (stat(p, &st)) 600*da2e3ebdSchin break; 601*da2e3ebdSchin for (dp = pp.stddirs; dp = dp->next;) 602*da2e3ebdSchin if (dp->name && SAMEID(&dp->id, &st)) 603*da2e3ebdSchin break; 604*da2e3ebdSchin if (pp.cdir.path && SAMEID(&pp.cdir.id, &st)) 605*da2e3ebdSchin { 606*da2e3ebdSchin pp.cdir.path = 0; 607*da2e3ebdSchin pp.c = 1; 608*da2e3ebdSchin } 609*da2e3ebdSchin if (pp.hostdir.path && SAMEID(&pp.hostdir.id, &st)) 610*da2e3ebdSchin { 611*da2e3ebdSchin pp.hostdir.path = 0; 612*da2e3ebdSchin pp.hosted = 1; 613*da2e3ebdSchin } 614*da2e3ebdSchin if ((pp.mode & INIT) && !(pp.ro_mode & INIT)) 615*da2e3ebdSchin pp.hosted = 1; 616*da2e3ebdSchin c = dp && dp->c || pp.c == 1; 617*da2e3ebdSchin n = dp && (dp->type & TYPE_HOSTED) || pp.hosted == 1; 618*da2e3ebdSchin if (!dp || dp == pp.lastdir->next) 619*da2e3ebdSchin { 620*da2e3ebdSchin if (dp) 621*da2e3ebdSchin { 622*da2e3ebdSchin c = dp->c; 623*da2e3ebdSchin n = dp->type & TYPE_HOSTED; 624*da2e3ebdSchin } 625*da2e3ebdSchin dp = newof(0, struct ppdirs, 1, 0); 626*da2e3ebdSchin dp->name = p; 627*da2e3ebdSchin SAVEID(&dp->id, &st); 628*da2e3ebdSchin dp->type |= TYPE_INCLUDE; 629*da2e3ebdSchin dp->index = INC_LOCAL + pp.ignoresrc != 0; 630*da2e3ebdSchin dp->next = pp.lastdir->next; 631*da2e3ebdSchin pp.lastdir = pp.lastdir->next = dp; 632*da2e3ebdSchin } 633*da2e3ebdSchin dp->c = c; 634*da2e3ebdSchin if (n) 635*da2e3ebdSchin dp->type |= TYPE_HOSTED; 636*da2e3ebdSchin else 637*da2e3ebdSchin dp->type &= ~TYPE_HOSTED; 638*da2e3ebdSchin } 639*da2e3ebdSchin break; 640*da2e3ebdSchin case PP_INCREF: 641*da2e3ebdSchin pp.incref = va_arg(ap, PPINCREF); 642*da2e3ebdSchin break; 643*da2e3ebdSchin case PP_RESET: 644*da2e3ebdSchin pp.reset.on = 1; 645*da2e3ebdSchin break; 646*da2e3ebdSchin case PP_INIT: 647*da2e3ebdSchin if (pp.initialized) 648*da2e3ebdSchin { 649*da2e3ebdSchin error_info.errors = 0; 650*da2e3ebdSchin error_info.warnings = 0; 651*da2e3ebdSchin } 652*da2e3ebdSchin else 653*da2e3ebdSchin { 654*da2e3ebdSchin /* 655*da2e3ebdSchin * context initialization 656*da2e3ebdSchin */ 657*da2e3ebdSchin 658*da2e3ebdSchin if (!initialized) 659*da2e3ebdSchin { 660*da2e3ebdSchin /* 661*da2e3ebdSchin * out of malloc is fatal 662*da2e3ebdSchin */ 663*da2e3ebdSchin 664*da2e3ebdSchin memfatal(); 665*da2e3ebdSchin 666*da2e3ebdSchin /* 667*da2e3ebdSchin * initialize the error message interface 668*da2e3ebdSchin */ 669*da2e3ebdSchin 670*da2e3ebdSchin error_info.version = (char*)pp.version; 671*da2e3ebdSchin #if DEBUG & TRACE_debug 672*da2e3ebdSchin error_info.auxilliary = context; 673*da2e3ebdSchin pptrace(0); 674*da2e3ebdSchin #endif 675*da2e3ebdSchin 676*da2e3ebdSchin /* 677*da2e3ebdSchin * initialize pplex tables 678*da2e3ebdSchin */ 679*da2e3ebdSchin 680*da2e3ebdSchin ppfsm(FSM_INIT, NiL); 681*da2e3ebdSchin 682*da2e3ebdSchin /* 683*da2e3ebdSchin * fixed macro stack size -- room for improvement 684*da2e3ebdSchin */ 685*da2e3ebdSchin 686*da2e3ebdSchin pp.macp = newof(0, struct ppmacstk, DEFMACSTACK, 0); 687*da2e3ebdSchin pp.macp->next = pp.macp + 1; 688*da2e3ebdSchin pp.maxmac = (char*)pp.macp + DEFMACSTACK; 689*da2e3ebdSchin initialized = 1; 690*da2e3ebdSchin 691*da2e3ebdSchin /* 692*da2e3ebdSchin * initial include/if control stack 693*da2e3ebdSchin */ 694*da2e3ebdSchin 695*da2e3ebdSchin pp.control = newof(0, long, pp.constack, 0); 696*da2e3ebdSchin pp.maxcon = pp.control + pp.constack - 1; 697*da2e3ebdSchin } 698*da2e3ebdSchin 699*da2e3ebdSchin /* 700*da2e3ebdSchin * validate modes 701*da2e3ebdSchin */ 702*da2e3ebdSchin 703*da2e3ebdSchin switch (pp.arg_mode) 704*da2e3ebdSchin { 705*da2e3ebdSchin case 'a': 706*da2e3ebdSchin case 'C': 707*da2e3ebdSchin ppop(PP_COMPATIBILITY, 0); 708*da2e3ebdSchin ppop(PP_TRANSITION, 1); 709*da2e3ebdSchin break; 710*da2e3ebdSchin case 'A': 711*da2e3ebdSchin case 'c': 712*da2e3ebdSchin ppop(PP_COMPATIBILITY, 0); 713*da2e3ebdSchin ppop(PP_STRICT, 1); 714*da2e3ebdSchin break; 715*da2e3ebdSchin case 'f': 716*da2e3ebdSchin ppop(PP_COMPATIBILITY, 1); 717*da2e3ebdSchin ppop(PP_PLUSPLUS, 1); 718*da2e3ebdSchin ppop(PP_TRANSITION, 1); 719*da2e3ebdSchin break; 720*da2e3ebdSchin case 'F': 721*da2e3ebdSchin ppop(PP_COMPATIBILITY, 0); 722*da2e3ebdSchin ppop(PP_PLUSPLUS, 1); 723*da2e3ebdSchin break; 724*da2e3ebdSchin case 'k': 725*da2e3ebdSchin case 's': 726*da2e3ebdSchin ppop(PP_COMPATIBILITY, 1); 727*da2e3ebdSchin ppop(PP_STRICT, 1); 728*da2e3ebdSchin break; 729*da2e3ebdSchin case 'o': 730*da2e3ebdSchin case 'O': 731*da2e3ebdSchin ppop(PP_COMPATIBILITY, 1); 732*da2e3ebdSchin ppop(PP_TRANSITION, 0); 733*da2e3ebdSchin break; 734*da2e3ebdSchin case 't': 735*da2e3ebdSchin ppop(PP_COMPATIBILITY, 1); 736*da2e3ebdSchin ppop(PP_TRANSITION, 1); 737*da2e3ebdSchin break; 738*da2e3ebdSchin } 739*da2e3ebdSchin if (!(pp.arg_style & STYLE_gnu)) 740*da2e3ebdSchin ppop(PP_PEDANTIC, 1); 741*da2e3ebdSchin if (pp.state & PASSTHROUGH) 742*da2e3ebdSchin { 743*da2e3ebdSchin if (pp.state & COMPILE) 744*da2e3ebdSchin { 745*da2e3ebdSchin pp.state &= ~PASSTHROUGH; 746*da2e3ebdSchin error(1, "passthrough ignored for compile"); 747*da2e3ebdSchin } 748*da2e3ebdSchin else 749*da2e3ebdSchin { 750*da2e3ebdSchin ppop(PP_COMPATIBILITY, 1); 751*da2e3ebdSchin ppop(PP_HOSTDIR, "-", 1); 752*da2e3ebdSchin ppop(PP_SPACEOUT, 1); 753*da2e3ebdSchin set(&pp.state, DISABLE, va_arg(ap, int)); 754*da2e3ebdSchin } 755*da2e3ebdSchin } 756*da2e3ebdSchin 757*da2e3ebdSchin /* 758*da2e3ebdSchin * create the hash tables 759*da2e3ebdSchin */ 760*da2e3ebdSchin 761*da2e3ebdSchin if (!pp.symtab) 762*da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0); 763*da2e3ebdSchin if (!pp.dirtab) 764*da2e3ebdSchin { 765*da2e3ebdSchin pp.dirtab = hashalloc(REFONE, HASH_name, "directives", 0); 766*da2e3ebdSchin inithash(pp.dirtab, directives); 767*da2e3ebdSchin } 768*da2e3ebdSchin if (!pp.filtab) 769*da2e3ebdSchin pp.filtab = hashalloc(REFALL, HASH_name, "files", 0); 770*da2e3ebdSchin if (!pp.prdtab) 771*da2e3ebdSchin pp.prdtab = hashalloc(REFALL, HASH_name, "predicates", 0); 772*da2e3ebdSchin if (!pp.strtab) 773*da2e3ebdSchin { 774*da2e3ebdSchin pp.strtab = hashalloc(REFALL, HASH_name, "strings", 0); 775*da2e3ebdSchin inithash(pp.strtab, options); 776*da2e3ebdSchin inithash(pp.strtab, predicates); 777*da2e3ebdSchin inithash(pp.strtab, variables); 778*da2e3ebdSchin } 779*da2e3ebdSchin pp.optflags[X_PROTOTYPED] = OPT_GLOBAL; 780*da2e3ebdSchin pp.optflags[X_SYSTEM_HEADER] = OPT_GLOBAL|OPT_PASS; 781*da2e3ebdSchin 782*da2e3ebdSchin /* 783*da2e3ebdSchin * mark macros that are builtin predicates 784*da2e3ebdSchin */ 785*da2e3ebdSchin 786*da2e3ebdSchin for (kp = predicates; s = kp->name; kp++) 787*da2e3ebdSchin { 788*da2e3ebdSchin if (!ppisid(*s)) 789*da2e3ebdSchin s++; 790*da2e3ebdSchin ppassert(DEFINE, s, 0); 791*da2e3ebdSchin } 792*da2e3ebdSchin 793*da2e3ebdSchin /* 794*da2e3ebdSchin * the remaining entry names must be allocated 795*da2e3ebdSchin */ 796*da2e3ebdSchin 797*da2e3ebdSchin hashset(pp.dirtab, HASH_ALLOCATE); 798*da2e3ebdSchin hashset(pp.filtab, HASH_ALLOCATE); 799*da2e3ebdSchin hashset(pp.prdtab, HASH_ALLOCATE); 800*da2e3ebdSchin hashset(pp.strtab, HASH_ALLOCATE); 801*da2e3ebdSchin hashset(pp.symtab, HASH_ALLOCATE); 802*da2e3ebdSchin if (pp.test & TEST_nonoise) 803*da2e3ebdSchin { 804*da2e3ebdSchin c = error_info.trace; 805*da2e3ebdSchin error_info.trace = 0; 806*da2e3ebdSchin } 807*da2e3ebdSchin #if DEBUG 808*da2e3ebdSchin if (!(pp.test & TEST_noinit)) 809*da2e3ebdSchin { 810*da2e3ebdSchin #endif 811*da2e3ebdSchin 812*da2e3ebdSchin /* 813*da2e3ebdSchin * compose, push and read the builtin initialization script 814*da2e3ebdSchin */ 815*da2e3ebdSchin 816*da2e3ebdSchin if (!(sp = sfstropen())) 817*da2e3ebdSchin error(3, "temporary buffer allocation error"); 818*da2e3ebdSchin sfprintf(sp, 819*da2e3ebdSchin "\ 820*da2e3ebdSchin #%s %s:%s \"/#<assert> /\" \"/assert /%s #/\"\n\ 821*da2e3ebdSchin #%s %s:%s \"/#<unassert> /\" \"/unassert /%s #/\"\n\ 822*da2e3ebdSchin ", 823*da2e3ebdSchin dirname(PRAGMA), 824*da2e3ebdSchin pp.pass, 825*da2e3ebdSchin keyname(X_MAP), 826*da2e3ebdSchin dirname(DEFINE), 827*da2e3ebdSchin dirname(PRAGMA), 828*da2e3ebdSchin pp.pass, 829*da2e3ebdSchin keyname(X_MAP), 830*da2e3ebdSchin dirname(UNDEF)); 831*da2e3ebdSchin if (pp.ppdefault && *pp.ppdefault) 832*da2e3ebdSchin { 833*da2e3ebdSchin if (pp.probe) 834*da2e3ebdSchin { 835*da2e3ebdSchin c = pp.lastdir->next->type; 836*da2e3ebdSchin pp.lastdir->next->type = 0; 837*da2e3ebdSchin } 838*da2e3ebdSchin if (ppsearch(pp.ppdefault, T_STRING, SEARCH_EXISTS) < 0) 839*da2e3ebdSchin { 840*da2e3ebdSchin free(pp.ppdefault); 841*da2e3ebdSchin if (!(pp.ppdefault = pathprobe(pp.path, NiL, "C", pp.pass, pp.probe ? pp.probe : PPPROBE, 0))) 842*da2e3ebdSchin error(1, "cannot determine default definitions for %s", pp.probe ? pp.probe : PPPROBE); 843*da2e3ebdSchin } 844*da2e3ebdSchin if (pp.ppdefault) 845*da2e3ebdSchin sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.ppdefault); 846*da2e3ebdSchin if (pp.probe) 847*da2e3ebdSchin pp.lastdir->next->type = c; 848*da2e3ebdSchin } 849*da2e3ebdSchin while (pp.firstop) 850*da2e3ebdSchin { 851*da2e3ebdSchin switch (pp.firstop->op) 852*da2e3ebdSchin { 853*da2e3ebdSchin case PP_ASSERT: 854*da2e3ebdSchin sfprintf(sp, "#%s #%s\n", dirname(DEFINE), pp.firstop->value); 855*da2e3ebdSchin break; 856*da2e3ebdSchin case PP_DEFINE: 857*da2e3ebdSchin if (*pp.firstop->value == '#') 858*da2e3ebdSchin sfprintf(sp, "#%s %s\n", dirname(DEFINE), pp.firstop->value); 859*da2e3ebdSchin else 860*da2e3ebdSchin { 861*da2e3ebdSchin if (s = strchr(pp.firstop->value, '=')) 862*da2e3ebdSchin sfprintf(sp, "#%s %-.*s %s\n", dirname(DEFINE), s - pp.firstop->value, pp.firstop->value, s + 1); 863*da2e3ebdSchin else 864*da2e3ebdSchin sfprintf(sp, "#%s %s 1\n", dirname(DEFINE), pp.firstop->value); 865*da2e3ebdSchin } 866*da2e3ebdSchin break; 867*da2e3ebdSchin case PP_DIRECTIVE: 868*da2e3ebdSchin sfprintf(sp, "#%s\n", pp.firstop->value); 869*da2e3ebdSchin break; 870*da2e3ebdSchin case PP_OPTION: 871*da2e3ebdSchin if (s = strchr(pp.firstop->value, '=')) 872*da2e3ebdSchin sfprintf(sp, "#%s %s:%-.*s %s\n", dirname(PRAGMA), pp.pass, s - pp.firstop->value, pp.firstop->value, s + 1); 873*da2e3ebdSchin else 874*da2e3ebdSchin sfprintf(sp, "#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.firstop->value); 875*da2e3ebdSchin break; 876*da2e3ebdSchin case PP_READ: 877*da2e3ebdSchin sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.firstop->value); 878*da2e3ebdSchin break; 879*da2e3ebdSchin case PP_UNDEF: 880*da2e3ebdSchin sfprintf(sp, "#%s %s\n", dirname(UNDEF), pp.firstop->value); 881*da2e3ebdSchin break; 882*da2e3ebdSchin } 883*da2e3ebdSchin pp.lastop = pp.firstop; 884*da2e3ebdSchin pp.firstop = pp.firstop->next; 885*da2e3ebdSchin free(pp.lastop); 886*da2e3ebdSchin } 887*da2e3ebdSchin sfprintf(sp, 888*da2e3ebdSchin "\ 889*da2e3ebdSchin #%s %s:%s\n\ 890*da2e3ebdSchin #%s %s:%s\n\ 891*da2e3ebdSchin #%s !#%s(%s)\n\ 892*da2e3ebdSchin #%s !#%s(%s) || #%s(%s)\n\ 893*da2e3ebdSchin " 894*da2e3ebdSchin , dirname(PRAGMA) 895*da2e3ebdSchin , pp.pass 896*da2e3ebdSchin , keyname(X_BUILTIN) 897*da2e3ebdSchin , dirname(PRAGMA) 898*da2e3ebdSchin , pp.pass 899*da2e3ebdSchin , keyname(X_PREDEFINED) 900*da2e3ebdSchin , dirname(IF) 901*da2e3ebdSchin , keyname(X_OPTION) 902*da2e3ebdSchin , keyname(X_PLUSPLUS) 903*da2e3ebdSchin , dirname(IF) 904*da2e3ebdSchin , keyname(X_OPTION) 905*da2e3ebdSchin , keyname(X_COMPATIBILITY) 906*da2e3ebdSchin , keyname(X_OPTION) 907*da2e3ebdSchin , keyname(X_TRANSITION) 908*da2e3ebdSchin ); 909*da2e3ebdSchin sfprintf(sp, 910*da2e3ebdSchin "\ 911*da2e3ebdSchin #%s __STDC__\n\ 912*da2e3ebdSchin #%s __STDC__ #(STDC)\n\ 913*da2e3ebdSchin #%s\n\ 914*da2e3ebdSchin #%s #%s(%s)\n\ 915*da2e3ebdSchin #%s %s:%s\n\ 916*da2e3ebdSchin #%s %s:%s\n\ 917*da2e3ebdSchin #%s __STRICT__ 1\n\ 918*da2e3ebdSchin #%s\n\ 919*da2e3ebdSchin #%s\n\ 920*da2e3ebdSchin " 921*da2e3ebdSchin , dirname(IFNDEF) 922*da2e3ebdSchin , dirname(DEFINE) 923*da2e3ebdSchin , dirname(ENDIF) 924*da2e3ebdSchin , dirname(IF) 925*da2e3ebdSchin , keyname(X_OPTION) 926*da2e3ebdSchin , keyname(X_STRICT) 927*da2e3ebdSchin , dirname(PRAGMA) 928*da2e3ebdSchin , pp.pass 929*da2e3ebdSchin , keyname(X_ALLMULTIPLE) 930*da2e3ebdSchin , dirname(PRAGMA) 931*da2e3ebdSchin , pp.pass 932*da2e3ebdSchin , keyname(X_READONLY) 933*da2e3ebdSchin , dirname(DEFINE) 934*da2e3ebdSchin , dirname(ENDIF) 935*da2e3ebdSchin , dirname(ENDIF) 936*da2e3ebdSchin ); 937*da2e3ebdSchin for (kp = readonlys; s = kp->name; kp++) 938*da2e3ebdSchin { 939*da2e3ebdSchin if (!ppisid(*s)) 940*da2e3ebdSchin s++; 941*da2e3ebdSchin sfprintf(sp, "#%s %s\n", dirname(UNDEF), s); 942*da2e3ebdSchin } 943*da2e3ebdSchin sfprintf(sp, 944*da2e3ebdSchin "\ 945*da2e3ebdSchin #%s\n\ 946*da2e3ebdSchin #%s __STDPP__ 1\n\ 947*da2e3ebdSchin #%s %s:no%s\n\ 948*da2e3ebdSchin " 949*da2e3ebdSchin , dirname(ENDIF) 950*da2e3ebdSchin , dirname(DEFINE) 951*da2e3ebdSchin , dirname(PRAGMA) 952*da2e3ebdSchin , pp.pass 953*da2e3ebdSchin , keyname(X_PREDEFINED) 954*da2e3ebdSchin ); 955*da2e3ebdSchin if (!pp.truncate) 956*da2e3ebdSchin sfprintf(sp, 957*da2e3ebdSchin "\ 958*da2e3ebdSchin #%s __STDPP__directive #(%s)\n\ 959*da2e3ebdSchin " 960*da2e3ebdSchin , dirname(DEFINE) 961*da2e3ebdSchin , keyname(V_DIRECTIVE) 962*da2e3ebdSchin ); 963*da2e3ebdSchin for (kp = variables; s = kp->name; kp++) 964*da2e3ebdSchin if (ppisid(*s) || *s++ == '+') 965*da2e3ebdSchin { 966*da2e3ebdSchin t = *s == '_' ? "" : "__"; 967*da2e3ebdSchin sfprintf(sp, "#%s %s%s%s #(%s)\n" , dirname(DEFINE), t, s, t, s); 968*da2e3ebdSchin } 969*da2e3ebdSchin sfprintf(sp, 970*da2e3ebdSchin "\ 971*da2e3ebdSchin #%s %s:no%s\n\ 972*da2e3ebdSchin #%s %s:no%s\n\ 973*da2e3ebdSchin " 974*da2e3ebdSchin , dirname(PRAGMA) 975*da2e3ebdSchin , pp.pass 976*da2e3ebdSchin , keyname(X_READONLY) 977*da2e3ebdSchin , dirname(PRAGMA) 978*da2e3ebdSchin , pp.pass 979*da2e3ebdSchin , keyname(X_BUILTIN) 980*da2e3ebdSchin ); 981*da2e3ebdSchin t = sfstruse(sp); 982*da2e3ebdSchin debug((-9, "\n/* begin initialization */\n%s/* end initialization */", t)); 983*da2e3ebdSchin ppcomment = pp.comment; 984*da2e3ebdSchin pp.comment = 0; 985*da2e3ebdSchin pplinesync = pp.linesync; 986*da2e3ebdSchin pp.linesync = 0; 987*da2e3ebdSchin PUSH_INIT(pp.pass, t); 988*da2e3ebdSchin pp.mode |= INIT; 989*da2e3ebdSchin while (pplex()); 990*da2e3ebdSchin pp.mode &= ~INIT; 991*da2e3ebdSchin pp.comment = ppcomment; 992*da2e3ebdSchin pp.linesync = pplinesync; 993*da2e3ebdSchin pp.prefix = 0; 994*da2e3ebdSchin sfstrclose(sp); 995*da2e3ebdSchin if (error_info.trace) 996*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 997*da2e3ebdSchin message((-1, "include directory %s%s%s%s", dp->name, (dp->type & TYPE_VENDOR) ? " [VENDOR]" : "", (dp->type & TYPE_HOSTED) ? " [HOSTED]" : "", dp->c ? " [C]" : "")); 998*da2e3ebdSchin #if DEBUG 999*da2e3ebdSchin } 1000*da2e3ebdSchin if (pp.test & TEST_nonoise) 1001*da2e3ebdSchin error_info.trace = c; 1002*da2e3ebdSchin #endif 1003*da2e3ebdSchin { 1004*da2e3ebdSchin /* 1005*da2e3ebdSchin * this is sleazy but at least it's 1006*da2e3ebdSchin * hidden in the library 1007*da2e3ebdSchin */ 1008*da2e3ebdSchin #include <preroot.h> 1009*da2e3ebdSchin #if FS_PREROOT 1010*da2e3ebdSchin struct pplist* preroot; 1011*da2e3ebdSchin 1012*da2e3ebdSchin if ((preroot = (struct pplist*)hashget(pp.prdtab, "preroot"))) 1013*da2e3ebdSchin setpreroot(NiL, preroot->value); 1014*da2e3ebdSchin #endif 1015*da2e3ebdSchin } 1016*da2e3ebdSchin if (pp.ignoresrc) 1017*da2e3ebdSchin { 1018*da2e3ebdSchin if (pp.ignoresrc > 1 && pp.stddirs != pp.firstdir) 1019*da2e3ebdSchin error(1, "directories up to and including %s are for \"...\" include files only", pp.stddirs->name); 1020*da2e3ebdSchin pp.lcldirs = pp.lcldirs->next; 1021*da2e3ebdSchin } 1022*da2e3ebdSchin if (pp.ignore) 1023*da2e3ebdSchin { 1024*da2e3ebdSchin if (*pp.ignore) 1025*da2e3ebdSchin ppmapinclude(pp.ignore, NiL); 1026*da2e3ebdSchin else 1027*da2e3ebdSchin pp.ignore = 0; 1028*da2e3ebdSchin } 1029*da2e3ebdSchin if (pp.standalone) 1030*da2e3ebdSchin pp.state |= STANDALONE; 1031*da2e3ebdSchin #if COMPATIBLE 1032*da2e3ebdSchin ppfsm(FSM_COMPATIBILITY, NiL); 1033*da2e3ebdSchin #endif 1034*da2e3ebdSchin ppfsm(FSM_PLUSPLUS, NiL); 1035*da2e3ebdSchin pp.initialized = 1; 1036*da2e3ebdSchin if (pp.reset.on) 1037*da2e3ebdSchin { 1038*da2e3ebdSchin pp.reset.symtab = pp.symtab; 1039*da2e3ebdSchin pp.symtab = 0; 1040*da2e3ebdSchin pp.reset.ro_state = pp.ro_state; 1041*da2e3ebdSchin pp.reset.ro_mode = pp.ro_mode; 1042*da2e3ebdSchin pp.reset.ro_option = pp.ro_option; 1043*da2e3ebdSchin } 1044*da2e3ebdSchin } 1045*da2e3ebdSchin if (pp.reset.on) 1046*da2e3ebdSchin { 1047*da2e3ebdSchin if (pp.symtab) 1048*da2e3ebdSchin { 1049*da2e3ebdSchin hashwalk(pp.filtab, 0, unguard, NiL); 1050*da2e3ebdSchin hashfree(pp.symtab); 1051*da2e3ebdSchin } 1052*da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_name, "symbols", HASH_free, undefine, HASH_set, HASH_ALLOCATE|HASH_BUCKET, 0); 1053*da2e3ebdSchin hashview(pp.symtab, pp.reset.symtab); 1054*da2e3ebdSchin pp.ro_state = pp.reset.ro_state; 1055*da2e3ebdSchin pp.ro_mode = pp.reset.ro_mode; 1056*da2e3ebdSchin pp.ro_option = pp.reset.ro_option; 1057*da2e3ebdSchin } 1058*da2e3ebdSchin #if CHECKPOINT 1059*da2e3ebdSchin if (pp.mode & DUMP) 1060*da2e3ebdSchin { 1061*da2e3ebdSchin if (!pp.pragma) 1062*da2e3ebdSchin error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA)); 1063*da2e3ebdSchin (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1); 1064*da2e3ebdSchin } 1065*da2e3ebdSchin #endif 1066*da2e3ebdSchin if (n = pp.filedeps.flags) 1067*da2e3ebdSchin { 1068*da2e3ebdSchin if (!(n & PP_deps_file)) 1069*da2e3ebdSchin { 1070*da2e3ebdSchin pp.state |= NOTEXT; 1071*da2e3ebdSchin pp.option |= KEEPNOTEXT; 1072*da2e3ebdSchin pp.linesync = 0; 1073*da2e3ebdSchin } 1074*da2e3ebdSchin if (n & PP_deps_generated) 1075*da2e3ebdSchin pp.mode |= GENDEPS; 1076*da2e3ebdSchin if (n & PP_deps_local) 1077*da2e3ebdSchin pp.mode &= ~HEADERDEPS; 1078*da2e3ebdSchin else if (!(pp.mode & FILEDEPS)) 1079*da2e3ebdSchin pp.mode |= HEADERDEPS; 1080*da2e3ebdSchin pp.mode |= FILEDEPS; 1081*da2e3ebdSchin } 1082*da2e3ebdSchin 1083*da2e3ebdSchin /* 1084*da2e3ebdSchin * push the main input file -- special case for hosted mark 1085*da2e3ebdSchin */ 1086*da2e3ebdSchin 1087*da2e3ebdSchin if (pp.firstdir->type & TYPE_HOSTED) 1088*da2e3ebdSchin pp.mode |= MARKHOSTED; 1089*da2e3ebdSchin else 1090*da2e3ebdSchin pp.mode &= ~MARKHOSTED; 1091*da2e3ebdSchin #if CHECKPOINT 1092*da2e3ebdSchin if (!(pp.mode & DUMP)) 1093*da2e3ebdSchin #endif 1094*da2e3ebdSchin { 1095*da2e3ebdSchin if (!(p = error_info.file)) 1096*da2e3ebdSchin p = ""; 1097*da2e3ebdSchin else 1098*da2e3ebdSchin { 1099*da2e3ebdSchin error_info.file = 0; 1100*da2e3ebdSchin if (*p) 1101*da2e3ebdSchin { 1102*da2e3ebdSchin pathcanon(p, 0); 1103*da2e3ebdSchin p = ppsetfile(p)->name; 1104*da2e3ebdSchin } 1105*da2e3ebdSchin } 1106*da2e3ebdSchin PUSH_FILE(p, 0); 1107*da2e3ebdSchin } 1108*da2e3ebdSchin if (pp.mode & FILEDEPS) 1109*da2e3ebdSchin { 1110*da2e3ebdSchin if (s = strrchr(error_info.file, '/')) 1111*da2e3ebdSchin s++; 1112*da2e3ebdSchin else 1113*da2e3ebdSchin s = error_info.file; 1114*da2e3ebdSchin if (!*s) 1115*da2e3ebdSchin s = "-"; 1116*da2e3ebdSchin s = strcpy(pp.tmpbuf, s); 1117*da2e3ebdSchin if ((t = p = strrchr(s, '.')) && (*++p == 'c' || *p == 'C')) 1118*da2e3ebdSchin { 1119*da2e3ebdSchin if (c = *++p) 1120*da2e3ebdSchin while (*++p == c); 1121*da2e3ebdSchin if (*p) 1122*da2e3ebdSchin t = 0; 1123*da2e3ebdSchin else 1124*da2e3ebdSchin t++; 1125*da2e3ebdSchin } 1126*da2e3ebdSchin if (!t) 1127*da2e3ebdSchin { 1128*da2e3ebdSchin t = s + strlen(s); 1129*da2e3ebdSchin *t++ = '.'; 1130*da2e3ebdSchin } 1131*da2e3ebdSchin *(t + 1) = 0; 1132*da2e3ebdSchin if (pp.state & NOTEXT) 1133*da2e3ebdSchin pp.filedeps.sp = sfstdout; 1134*da2e3ebdSchin else 1135*da2e3ebdSchin { 1136*da2e3ebdSchin *t = 'd'; 1137*da2e3ebdSchin if (!(pp.filedeps.sp = sfopen(NiL, s, "w"))) 1138*da2e3ebdSchin error(ERROR_SYSTEM|3, "%s: cannot create", s); 1139*da2e3ebdSchin } 1140*da2e3ebdSchin *t = 'o'; 1141*da2e3ebdSchin pp.column = sfprintf(pp.filedeps.sp, "%s :", s); 1142*da2e3ebdSchin if (*error_info.file) 1143*da2e3ebdSchin pp.column += sfprintf(pp.filedeps.sp, " %s", error_info.file); 1144*da2e3ebdSchin } 1145*da2e3ebdSchin if (xp = pp.firsttx) 1146*da2e3ebdSchin { 1147*da2e3ebdSchin if (!(sp = sfstropen())) 1148*da2e3ebdSchin error(3, "temporary buffer allocation error"); 1149*da2e3ebdSchin while (xp) 1150*da2e3ebdSchin { 1151*da2e3ebdSchin sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), xp->value); 1152*da2e3ebdSchin xp = xp->next; 1153*da2e3ebdSchin } 1154*da2e3ebdSchin t = sfstruse(sp); 1155*da2e3ebdSchin PUSH_BUFFER("options", t, 1); 1156*da2e3ebdSchin sfstrclose(sp); 1157*da2e3ebdSchin } 1158*da2e3ebdSchin break; 1159*da2e3ebdSchin case PP_INPUT: 1160*da2e3ebdSchin #if CHECKPOINT && POOL 1161*da2e3ebdSchin if (!(pp.mode & DUMP) || pp.pool.input) 1162*da2e3ebdSchin #else 1163*da2e3ebdSchin #if CHECKPOINT 1164*da2e3ebdSchin if (!(pp.mode & DUMP)) 1165*da2e3ebdSchin #else 1166*da2e3ebdSchin #if POOL 1167*da2e3ebdSchin if (pp.pool.input) 1168*da2e3ebdSchin #endif 1169*da2e3ebdSchin #endif 1170*da2e3ebdSchin #endif 1171*da2e3ebdSchin { 1172*da2e3ebdSchin p = va_arg(ap, char*); 1173*da2e3ebdSchin if (!error_info.file) 1174*da2e3ebdSchin error_info.file = p; 1175*da2e3ebdSchin close(0); 1176*da2e3ebdSchin if (open(p, O_RDONLY) != 0) 1177*da2e3ebdSchin error(ERROR_SYSTEM|3, "%s: cannot read", p); 1178*da2e3ebdSchin if (strmatch(p, "*.(s|S|as|AS|asm|ASM)")) 1179*da2e3ebdSchin { 1180*da2e3ebdSchin set(&pp.mode, CATLITERAL, 0); 1181*da2e3ebdSchin ppop(PP_SPACEOUT, 1); 1182*da2e3ebdSchin } 1183*da2e3ebdSchin break; 1184*da2e3ebdSchin } 1185*da2e3ebdSchin /*FALLTHROUGH*/ 1186*da2e3ebdSchin case PP_TEXT: 1187*da2e3ebdSchin if (pp.initialized) 1188*da2e3ebdSchin goto before; 1189*da2e3ebdSchin if ((p = va_arg(ap, char*)) && *p) 1190*da2e3ebdSchin { 1191*da2e3ebdSchin if (pp.lasttx) 1192*da2e3ebdSchin pp.lasttx = pp.lasttx->next = newof(0, struct oplist, 1, 0); 1193*da2e3ebdSchin else 1194*da2e3ebdSchin pp.firsttx = pp.lasttx = newof(0, struct oplist, 1, 0); 1195*da2e3ebdSchin pp.lasttx->op = op; 1196*da2e3ebdSchin pp.lasttx->value = p; 1197*da2e3ebdSchin } 1198*da2e3ebdSchin break; 1199*da2e3ebdSchin case PP_KEYARGS: 1200*da2e3ebdSchin if (pp.initialized) 1201*da2e3ebdSchin goto before; 1202*da2e3ebdSchin set(&pp.option, KEYARGS, va_arg(ap, int)); 1203*da2e3ebdSchin if (pp.option & KEYARGS) 1204*da2e3ebdSchin #if MACKEYARGS 1205*da2e3ebdSchin set(&pp.mode, CATLITERAL, 1); 1206*da2e3ebdSchin #else 1207*da2e3ebdSchin error(3, "preprocessor not compiled with macro keyword arguments enabled [MACKEYARGS]"); 1208*da2e3ebdSchin #endif 1209*da2e3ebdSchin break; 1210*da2e3ebdSchin case PP_LINE: 1211*da2e3ebdSchin pp.linesync = va_arg(ap, PPLINESYNC); 1212*da2e3ebdSchin break; 1213*da2e3ebdSchin case PP_LINEBASE: 1214*da2e3ebdSchin if (va_arg(ap, int)) 1215*da2e3ebdSchin pp.flags |= PP_linebase; 1216*da2e3ebdSchin else 1217*da2e3ebdSchin pp.flags &= ~PP_linebase; 1218*da2e3ebdSchin break; 1219*da2e3ebdSchin case PP_LINEFILE: 1220*da2e3ebdSchin if (va_arg(ap, int)) 1221*da2e3ebdSchin pp.flags |= PP_linefile; 1222*da2e3ebdSchin else 1223*da2e3ebdSchin pp.flags &= ~PP_linefile; 1224*da2e3ebdSchin break; 1225*da2e3ebdSchin case PP_LINEID: 1226*da2e3ebdSchin if (!(p = va_arg(ap, char*))) 1227*da2e3ebdSchin pp.lineid = ""; 1228*da2e3ebdSchin else if (*p != '-') 1229*da2e3ebdSchin pp.lineid = strdup(p); 1230*da2e3ebdSchin else 1231*da2e3ebdSchin pp.option |= IGNORELINE; 1232*da2e3ebdSchin break; 1233*da2e3ebdSchin case PP_LINETYPE: 1234*da2e3ebdSchin if ((n = va_arg(ap, int)) >= 1) 1235*da2e3ebdSchin pp.flags |= PP_linetype; 1236*da2e3ebdSchin else 1237*da2e3ebdSchin pp.flags &= ~PP_linetype; 1238*da2e3ebdSchin if (n >= 2) 1239*da2e3ebdSchin pp.flags |= PP_linehosted; 1240*da2e3ebdSchin else 1241*da2e3ebdSchin pp.flags &= ~PP_linehosted; 1242*da2e3ebdSchin break; 1243*da2e3ebdSchin case PP_LOCAL: 1244*da2e3ebdSchin if (pp.initialized) 1245*da2e3ebdSchin goto before; 1246*da2e3ebdSchin pp.ignoresrc++; 1247*da2e3ebdSchin pp.stddirs = pp.lastdir; 1248*da2e3ebdSchin if (!(pp.ro_option & PREFIX)) 1249*da2e3ebdSchin pp.option &= ~PREFIX; 1250*da2e3ebdSchin break; 1251*da2e3ebdSchin case PP_MACREF: 1252*da2e3ebdSchin pp.macref = va_arg(ap, PPMACREF); 1253*da2e3ebdSchin break; 1254*da2e3ebdSchin case PP_MULTIPLE: 1255*da2e3ebdSchin set(&pp.mode, ALLMULTIPLE, va_arg(ap, int)); 1256*da2e3ebdSchin break; 1257*da2e3ebdSchin case PP_NOHASH: 1258*da2e3ebdSchin set(&pp.option, NOHASH, va_arg(ap, int)); 1259*da2e3ebdSchin break; 1260*da2e3ebdSchin case PP_NOISE: 1261*da2e3ebdSchin op = va_arg(ap, int); 1262*da2e3ebdSchin set(&pp.option, NOISE, op); 1263*da2e3ebdSchin set(&pp.option, NOISEFILTER, op < 0); 1264*da2e3ebdSchin break; 1265*da2e3ebdSchin case PP_OPTARG: 1266*da2e3ebdSchin pp.optarg = va_arg(ap, PPOPTARG); 1267*da2e3ebdSchin break; 1268*da2e3ebdSchin case PP_OUTPUT: 1269*da2e3ebdSchin pp.outfile = va_arg(ap, char*); 1270*da2e3ebdSchin if (identical(pp.outfile, 0)) 1271*da2e3ebdSchin error(3, "%s: identical to input", pp.outfile); 1272*da2e3ebdSchin close(1); 1273*da2e3ebdSchin if (open(pp.outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1) 1274*da2e3ebdSchin error(ERROR_SYSTEM|3, "%s: cannot create", pp.outfile); 1275*da2e3ebdSchin break; 1276*da2e3ebdSchin case PP_PASSTHROUGH: 1277*da2e3ebdSchin if (!(pp.state & COMPILE)) 1278*da2e3ebdSchin set(&pp.state, PASSTHROUGH, va_arg(ap, int)); 1279*da2e3ebdSchin break; 1280*da2e3ebdSchin case PP_PEDANTIC: 1281*da2e3ebdSchin set(&pp.mode, PEDANTIC, va_arg(ap, int)); 1282*da2e3ebdSchin break; 1283*da2e3ebdSchin case PP_PLUSCOMMENT: 1284*da2e3ebdSchin set(&pp.option, PLUSCOMMENT, va_arg(ap, int)); 1285*da2e3ebdSchin if (pp.initialized) 1286*da2e3ebdSchin ppfsm(FSM_PLUSPLUS, NiL); 1287*da2e3ebdSchin break; 1288*da2e3ebdSchin case PP_PLUSPLUS: 1289*da2e3ebdSchin set(&pp.option, PLUSPLUS, va_arg(ap, int)); 1290*da2e3ebdSchin set(&pp.option, PLUSCOMMENT, va_arg(ap, int)); 1291*da2e3ebdSchin if (pp.initialized) 1292*da2e3ebdSchin ppfsm(FSM_PLUSPLUS, NiL); 1293*da2e3ebdSchin break; 1294*da2e3ebdSchin case PP_POOL: 1295*da2e3ebdSchin if (pp.initialized) 1296*da2e3ebdSchin goto before; 1297*da2e3ebdSchin if (va_arg(ap, int)) 1298*da2e3ebdSchin { 1299*da2e3ebdSchin #if POOL 1300*da2e3ebdSchin pp.pool.input = dup(0); 1301*da2e3ebdSchin pp.pool.output = dup(1); 1302*da2e3ebdSchin p = "/dev/null"; 1303*da2e3ebdSchin if (!identical(p, 0)) 1304*da2e3ebdSchin { 1305*da2e3ebdSchin if (!identical(p, 1)) 1306*da2e3ebdSchin ppop(PP_OUTPUT, p); 1307*da2e3ebdSchin ppop(PP_INPUT, p); 1308*da2e3ebdSchin } 1309*da2e3ebdSchin #else 1310*da2e3ebdSchin error(3, "preprocessor not compiled with input pool enabled [POOL]"); 1311*da2e3ebdSchin #endif 1312*da2e3ebdSchin } 1313*da2e3ebdSchin break; 1314*da2e3ebdSchin case PP_PRAGMA: 1315*da2e3ebdSchin pp.pragma = va_arg(ap, PPPRAGMA); 1316*da2e3ebdSchin break; 1317*da2e3ebdSchin case PP_PRAGMAFLAGS: 1318*da2e3ebdSchin if (p = va_arg(ap, char*)) 1319*da2e3ebdSchin { 1320*da2e3ebdSchin n = OPT_GLOBAL; 1321*da2e3ebdSchin if (*p == '-') 1322*da2e3ebdSchin p++; 1323*da2e3ebdSchin else 1324*da2e3ebdSchin n |= OPT_PASS; 1325*da2e3ebdSchin if ((c = (int)hashref(pp.strtab, p)) > 0 && c <= X_last_option) 1326*da2e3ebdSchin pp.optflags[c] = n; 1327*da2e3ebdSchin } 1328*da2e3ebdSchin break; 1329*da2e3ebdSchin case PP_PROBE: 1330*da2e3ebdSchin pp.probe = va_arg(ap, char*); 1331*da2e3ebdSchin break; 1332*da2e3ebdSchin case PP_QUOTE: 1333*da2e3ebdSchin p = va_arg(ap, char*); 1334*da2e3ebdSchin c = va_arg(ap, int); 1335*da2e3ebdSchin if (p) 1336*da2e3ebdSchin ppfsm(c ? FSM_QUOTADD : FSM_QUOTDEL, p); 1337*da2e3ebdSchin break; 1338*da2e3ebdSchin case PP_REGUARD: 1339*da2e3ebdSchin set(&pp.option, REGUARD, va_arg(ap, int)); 1340*da2e3ebdSchin break; 1341*da2e3ebdSchin case PP_RESERVED: 1342*da2e3ebdSchin if ((pp.state & COMPILE) && (p = va_arg(ap, char*))) 1343*da2e3ebdSchin { 1344*da2e3ebdSchin if (!(sp = sfstropen())) 1345*da2e3ebdSchin error(3, "temporary buffer allocation error"); 1346*da2e3ebdSchin sfputr(sp, p, -1); 1347*da2e3ebdSchin p = sfstruse(sp); 1348*da2e3ebdSchin if (s = strchr(p, '=')) 1349*da2e3ebdSchin *s++ = 0; 1350*da2e3ebdSchin else 1351*da2e3ebdSchin s = p; 1352*da2e3ebdSchin while (*s == '_') 1353*da2e3ebdSchin s++; 1354*da2e3ebdSchin for (t = s + strlen(s); t > s && *(t - 1) == '_'; t--); 1355*da2e3ebdSchin if (*t == '_') 1356*da2e3ebdSchin *t = 0; 1357*da2e3ebdSchin else 1358*da2e3ebdSchin t = 0; 1359*da2e3ebdSchin op = ((key = ppkeyref(pp.symtab, s)) && (key->sym.flags & SYM_LEX)) ? key->lex : T_NOISE; 1360*da2e3ebdSchin if (pp.test & 0x0400) 1361*da2e3ebdSchin error(1, "reserved#1 `%s' %d", s, op); 1362*da2e3ebdSchin if (t) 1363*da2e3ebdSchin *t = '_'; 1364*da2e3ebdSchin if (!(key = ppkeyget(pp.symtab, p))) 1365*da2e3ebdSchin key = ppkeyset(pp.symtab, NiL); 1366*da2e3ebdSchin else if (!(key->sym.flags & SYM_LEX)) 1367*da2e3ebdSchin { 1368*da2e3ebdSchin struct ppsymbol tmp; 1369*da2e3ebdSchin 1370*da2e3ebdSchin tmp = key->sym; 1371*da2e3ebdSchin hashlook(pp.symtab, p, HASH_DELETE, NiL); 1372*da2e3ebdSchin key = ppkeyset(pp.symtab, NiL); 1373*da2e3ebdSchin key->sym.flags = tmp.flags; 1374*da2e3ebdSchin key->sym.macro = tmp.macro; 1375*da2e3ebdSchin key->sym.value = tmp.value; 1376*da2e3ebdSchin key->sym.hidden = tmp.hidden; 1377*da2e3ebdSchin } 1378*da2e3ebdSchin if (!(key->sym.flags & SYM_KEYWORD)) 1379*da2e3ebdSchin { 1380*da2e3ebdSchin key->sym.flags |= SYM_KEYWORD|SYM_LEX; 1381*da2e3ebdSchin key->lex = op; 1382*da2e3ebdSchin if (pp.test & 0x0400) 1383*da2e3ebdSchin error(1, "reserved#2 `%s' %d", p, op); 1384*da2e3ebdSchin } 1385*da2e3ebdSchin sfstrclose(sp); 1386*da2e3ebdSchin } 1387*da2e3ebdSchin break; 1388*da2e3ebdSchin case PP_SPACEOUT: 1389*da2e3ebdSchin set(&pp.state, SPACEOUT, va_arg(ap, int)); 1390*da2e3ebdSchin break; 1391*da2e3ebdSchin case PP_STANDALONE: 1392*da2e3ebdSchin if (pp.initialized) 1393*da2e3ebdSchin goto before; 1394*da2e3ebdSchin pp.standalone = 1; 1395*da2e3ebdSchin break; 1396*da2e3ebdSchin case PP_STANDARD: 1397*da2e3ebdSchin if ((pp.lastdir->next->name = ((p = va_arg(ap, char*)) && *p) ? p : NiL) && !stat(p, &st)) 1398*da2e3ebdSchin SAVEID(&pp.lastdir->next->id, &st); 1399*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 1400*da2e3ebdSchin if (dp->name) 1401*da2e3ebdSchin for (hp = pp.firstdir; hp != dp; hp = hp->next) 1402*da2e3ebdSchin if (hp->name && SAMEID(&hp->id, &dp->id)) 1403*da2e3ebdSchin { 1404*da2e3ebdSchin hp->c = dp->c; 1405*da2e3ebdSchin if (dp->type & TYPE_HOSTED) 1406*da2e3ebdSchin hp->type |= TYPE_HOSTED; 1407*da2e3ebdSchin else 1408*da2e3ebdSchin hp->type &= ~TYPE_HOSTED; 1409*da2e3ebdSchin } 1410*da2e3ebdSchin break; 1411*da2e3ebdSchin case PP_STRICT: 1412*da2e3ebdSchin set(&pp.state, TRANSITION, 0); 1413*da2e3ebdSchin pp.flags &= ~PP_transition; 1414*da2e3ebdSchin set(&pp.state, STRICT, va_arg(ap, int)); 1415*da2e3ebdSchin if (pp.state & STRICT) 1416*da2e3ebdSchin pp.flags |= PP_strict; 1417*da2e3ebdSchin else 1418*da2e3ebdSchin pp.flags &= ~PP_strict; 1419*da2e3ebdSchin break; 1420*da2e3ebdSchin case PP_TEST: 1421*da2e3ebdSchin if (p = va_arg(ap, char*)) 1422*da2e3ebdSchin for (;;) 1423*da2e3ebdSchin { 1424*da2e3ebdSchin while (*p == ' ' || *p == '\t') p++; 1425*da2e3ebdSchin for (s = p; n = *s; s++) 1426*da2e3ebdSchin if (n == ',' || n == ' ' || n == '\t') 1427*da2e3ebdSchin { 1428*da2e3ebdSchin *s++ = 0; 1429*da2e3ebdSchin break; 1430*da2e3ebdSchin } 1431*da2e3ebdSchin if (!*p) 1432*da2e3ebdSchin break; 1433*da2e3ebdSchin n = 0; 1434*da2e3ebdSchin if (*p == 'n' && *(p + 1) == 'o') 1435*da2e3ebdSchin { 1436*da2e3ebdSchin p += 2; 1437*da2e3ebdSchin op = 0; 1438*da2e3ebdSchin } 1439*da2e3ebdSchin else 1440*da2e3ebdSchin op = 1; 1441*da2e3ebdSchin if (streq(p, "count")) 1442*da2e3ebdSchin n = TEST_count; 1443*da2e3ebdSchin else if (streq(p, "hashcount")) 1444*da2e3ebdSchin n = TEST_hashcount; 1445*da2e3ebdSchin else if (streq(p, "hashdump")) 1446*da2e3ebdSchin n = TEST_hashdump; 1447*da2e3ebdSchin else if (streq(p, "hit")) 1448*da2e3ebdSchin n = TEST_hit; 1449*da2e3ebdSchin else if (streq(p, "init")) 1450*da2e3ebdSchin n = TEST_noinit|TEST_INVERT; 1451*da2e3ebdSchin else if (streq(p, "noise")) 1452*da2e3ebdSchin n = TEST_nonoise|TEST_INVERT; 1453*da2e3ebdSchin else if (streq(p, "proto")) 1454*da2e3ebdSchin n = TEST_noproto|TEST_INVERT; 1455*da2e3ebdSchin else if (*p >= '0' && *p <= '9') 1456*da2e3ebdSchin n = strtoul(p, NiL, 0); 1457*da2e3ebdSchin else 1458*da2e3ebdSchin { 1459*da2e3ebdSchin error(1, "%s: unknown test", p); 1460*da2e3ebdSchin break; 1461*da2e3ebdSchin } 1462*da2e3ebdSchin if (n & TEST_INVERT) 1463*da2e3ebdSchin { 1464*da2e3ebdSchin n &= ~TEST_INVERT; 1465*da2e3ebdSchin op = !op; 1466*da2e3ebdSchin } 1467*da2e3ebdSchin if (op) 1468*da2e3ebdSchin pp.test |= n; 1469*da2e3ebdSchin else 1470*da2e3ebdSchin pp.test &= ~n; 1471*da2e3ebdSchin p = s; 1472*da2e3ebdSchin debug((-4, "test = 0%o", pp.test)); 1473*da2e3ebdSchin } 1474*da2e3ebdSchin break; 1475*da2e3ebdSchin case PP_TRANSITION: 1476*da2e3ebdSchin set(&pp.state, STRICT, 0); 1477*da2e3ebdSchin pp.flags &= ~PP_strict; 1478*da2e3ebdSchin set(&pp.state, TRANSITION, va_arg(ap, int)); 1479*da2e3ebdSchin if (pp.state & TRANSITION) 1480*da2e3ebdSchin pp.flags |= PP_transition; 1481*da2e3ebdSchin else 1482*da2e3ebdSchin pp.flags &= ~PP_transition; 1483*da2e3ebdSchin break; 1484*da2e3ebdSchin case PP_TRUNCATE: 1485*da2e3ebdSchin if (pp.initialized) 1486*da2e3ebdSchin goto before; 1487*da2e3ebdSchin if ((op = va_arg(ap, int)) < 0) 1488*da2e3ebdSchin op = 0; 1489*da2e3ebdSchin set(&pp.option, TRUNCATE, op); 1490*da2e3ebdSchin if (pp.option & TRUNCATE) 1491*da2e3ebdSchin { 1492*da2e3ebdSchin Hash_bucket_t* b; 1493*da2e3ebdSchin Hash_bucket_t* p; 1494*da2e3ebdSchin Hash_position_t* pos; 1495*da2e3ebdSchin Hash_table_t* tab; 1496*da2e3ebdSchin 1497*da2e3ebdSchin pp.truncate = op; 1498*da2e3ebdSchin tab = pp.symtab; 1499*da2e3ebdSchin pp.symtab = hashalloc(NiL, HASH_set, tab ? HASH_ALLOCATE : 0, HASH_compare, trunccomp, HASH_hash, trunchash, HASH_name, "truncate", 0); 1500*da2e3ebdSchin if (tab && (pos = hashscan(tab, 0))) 1501*da2e3ebdSchin { 1502*da2e3ebdSchin if (p = hashnext(pos)) 1503*da2e3ebdSchin do 1504*da2e3ebdSchin { 1505*da2e3ebdSchin b = hashnext(pos); 1506*da2e3ebdSchin hashlook(pp.symtab, (char*)p, HASH_BUCKET|HASH_INSTALL, NiL); 1507*da2e3ebdSchin } while (p = b); 1508*da2e3ebdSchin hashdone(pos); 1509*da2e3ebdSchin } 1510*da2e3ebdSchin } 1511*da2e3ebdSchin else 1512*da2e3ebdSchin pp.truncate = 0; 1513*da2e3ebdSchin break; 1514*da2e3ebdSchin case PP_VENDOR: 1515*da2e3ebdSchin p = va_arg(ap, char*); 1516*da2e3ebdSchin c = va_arg(ap, int) != 0; 1517*da2e3ebdSchin if (!p || !*p) 1518*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 1519*da2e3ebdSchin dp->type &= ~TYPE_VENDOR; 1520*da2e3ebdSchin else if (streq(p, "-")) 1521*da2e3ebdSchin { 1522*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 1523*da2e3ebdSchin if (c) 1524*da2e3ebdSchin dp->type |= TYPE_VENDOR; 1525*da2e3ebdSchin else 1526*da2e3ebdSchin dp->type &= ~TYPE_VENDOR; 1527*da2e3ebdSchin } 1528*da2e3ebdSchin else if (!stat((pathcanon(p, 0), p), &st)) 1529*da2e3ebdSchin { 1530*da2e3ebdSchin c = 0; 1531*da2e3ebdSchin for (dp = pp.firstdir; dp; dp = dp->next) 1532*da2e3ebdSchin { 1533*da2e3ebdSchin if (!c && ((dp->type & TYPE_VENDOR) || dp->name && SAMEID(&dp->id, &st))) 1534*da2e3ebdSchin c = 1; 1535*da2e3ebdSchin if (c) 1536*da2e3ebdSchin dp->type |= TYPE_VENDOR; 1537*da2e3ebdSchin else 1538*da2e3ebdSchin dp->type &= ~TYPE_VENDOR; 1539*da2e3ebdSchin } 1540*da2e3ebdSchin } 1541*da2e3ebdSchin break; 1542*da2e3ebdSchin case PP_WARN: 1543*da2e3ebdSchin set(&pp.state, WARN, va_arg(ap, int)); 1544*da2e3ebdSchin break; 1545*da2e3ebdSchin before: 1546*da2e3ebdSchin error(3, "ppop(%d): preprocessor operation must be done before PP_INIT", op); 1547*da2e3ebdSchin break; 1548*da2e3ebdSchin default: 1549*da2e3ebdSchin error(3, "ppop(%d): invalid preprocessor operation", op); 1550*da2e3ebdSchin break; 1551*da2e3ebdSchin } 1552*da2e3ebdSchin va_end(ap); 1553*da2e3ebdSchin } 1554