1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * Glenn Fowler 23*4887Schin * AT&T Research 24*4887Schin * 25*4887Schin * preprocessor expression evaluation support 26*4887Schin */ 27*4887Schin 28*4887Schin #include "pplib.h" 29*4887Schin 30*4887Schin #include <regex.h> 31*4887Schin 32*4887Schin #define lex(c) ((((c)=peektoken)>=0?(peektoken=(-1)):((c)=pplex())),(c)) 33*4887Schin #define unlex(c) (peektoken=(c)) 34*4887Schin 35*4887Schin static int peektoken; /* expression lookahead token */ 36*4887Schin static char* errmsg; /* subexpr() error message */ 37*4887Schin 38*4887Schin /* 39*4887Schin * exists predicate evaluation 40*4887Schin */ 41*4887Schin 42*4887Schin static int 43*4887Schin exists(int op, char* pred, register char* args) 44*4887Schin { 45*4887Schin register int c; 46*4887Schin register int type; 47*4887Schin char* pptoken; 48*4887Schin long state; 49*4887Schin char file[MAXTOKEN + 1]; 50*4887Schin 51*4887Schin state = (pp.state & ~DISABLE); 52*4887Schin PUSH_STRING(args); 53*4887Schin pptoken = pp.token; 54*4887Schin pp.token = file; 55*4887Schin pp.state |= HEADER|PASSEOF; 56*4887Schin type = pplex(); 57*4887Schin pp.state &= ~HEADER; 58*4887Schin pp.token = pptoken; 59*4887Schin switch (type) 60*4887Schin { 61*4887Schin case T_STRING: 62*4887Schin case T_HEADER: 63*4887Schin break; 64*4887Schin default: 65*4887Schin error(1, "%s: \"...\" or <...> argument expected", pred); 66*4887Schin c = 0; 67*4887Schin goto done; 68*4887Schin } 69*4887Schin if (op == X_EXISTS) 70*4887Schin { 71*4887Schin if ((c = pplex()) == ',') 72*4887Schin { 73*4887Schin while ((c = pplex()) == T_STRING) 74*4887Schin { 75*4887Schin if (pathaccess(pp.path, pp.token, file, NiL, 0)) 76*4887Schin { 77*4887Schin pathcanon(pp.path, 0); 78*4887Schin message((-2, "%s: %s found", pred, pp.path)); 79*4887Schin c = 1; 80*4887Schin goto done; 81*4887Schin } 82*4887Schin if ((c = pplex()) != ',') break; 83*4887Schin } 84*4887Schin if (c) error(1, "%s: \"...\" arguments expected", pred); 85*4887Schin strcpy(pp.path, file); 86*4887Schin message((-2, "%s: %s not found", pred, file)); 87*4887Schin c = 0; 88*4887Schin } 89*4887Schin else c = ppsearch(file, type, SEARCH_EXISTS) >= 0; 90*4887Schin } 91*4887Schin else 92*4887Schin { 93*4887Schin register struct ppfile* fp; 94*4887Schin 95*4887Schin fp = ppsetfile(file); 96*4887Schin c = fp->flags || fp->guard == INC_IGNORE; 97*4887Schin } 98*4887Schin done: 99*4887Schin while (pplex()); 100*4887Schin pp.state = state; 101*4887Schin return c; 102*4887Schin } 103*4887Schin 104*4887Schin /* 105*4887Schin * strcmp/match predicate evaluation 106*4887Schin */ 107*4887Schin 108*4887Schin static int 109*4887Schin compare(char* pred, char* args, int match) 110*4887Schin { 111*4887Schin register int c; 112*4887Schin char* pptoken; 113*4887Schin long state; 114*4887Schin regex_t re; 115*4887Schin char tmp[MAXTOKEN + 1]; 116*4887Schin 117*4887Schin state = (pp.state & ~DISABLE); 118*4887Schin PUSH_STRING(args); 119*4887Schin pp.state |= PASSEOF; 120*4887Schin pptoken = pp.token; 121*4887Schin pp.token = tmp; 122*4887Schin if (!pplex()) 123*4887Schin goto bad; 124*4887Schin pp.token = pptoken; 125*4887Schin if (pplex() != ',' || !pplex()) 126*4887Schin goto bad; 127*4887Schin if (!match) 128*4887Schin c = strcmp(tmp, pp.token); 129*4887Schin else if ((c = regcomp(&re, pp.token, REG_AUGMENTED|REG_LENIENT|REG_NULL)) || (c = regexec(&re, tmp, NiL, 0, 0)) && c != REG_NOMATCH) 130*4887Schin regfatal(&re, 3, c); 131*4887Schin else 132*4887Schin { 133*4887Schin c = !c; 134*4887Schin regfree(&re); 135*4887Schin } 136*4887Schin if ((pp.state & PASSEOF) && pplex()) 137*4887Schin goto bad; 138*4887Schin pp.state = state; 139*4887Schin return c; 140*4887Schin bad: 141*4887Schin pp.token = pptoken; 142*4887Schin error(2, "%s: 2 arguments expected", pred); 143*4887Schin while (pplex()); 144*4887Schin pp.state = state; 145*4887Schin return 0; 146*4887Schin } 147*4887Schin 148*4887Schin /* 149*4887Schin * #if predicate parse and evaluation 150*4887Schin */ 151*4887Schin 152*4887Schin static int 153*4887Schin predicate(int warn) 154*4887Schin { 155*4887Schin register char* args; 156*4887Schin register struct pplist* p; 157*4887Schin register struct ppsymbol* sym; 158*4887Schin register int type; 159*4887Schin int index; 160*4887Schin 161*4887Schin static char pred[MAXID + 1]; 162*4887Schin 163*4887Schin /* 164*4887Schin * first gather the args 165*4887Schin */ 166*4887Schin 167*4887Schin index = (int)hashref(pp.strtab, pp.token); 168*4887Schin if (warn && peekchr() != '(') switch (index) 169*4887Schin { 170*4887Schin case X_DEFINED: 171*4887Schin case X_EXISTS: 172*4887Schin case X_INCLUDED: 173*4887Schin case X_MATCH: 174*4887Schin case X_NOTICED: 175*4887Schin case X_OPTION: 176*4887Schin case X_SIZEOF: 177*4887Schin case X_STRCMP: 178*4887Schin break; 179*4887Schin default: 180*4887Schin if (pp.macref) pprefmac(pp.token, REF_IF); 181*4887Schin return 0; 182*4887Schin } 183*4887Schin strcpy(pred, pp.token); 184*4887Schin pp.state |= DISABLE; 185*4887Schin type = pppredargs(); 186*4887Schin pp.state &= ~DISABLE; 187*4887Schin switch (type) 188*4887Schin { 189*4887Schin case T_ID: 190*4887Schin case T_STRING: 191*4887Schin break; 192*4887Schin default: 193*4887Schin unlex(type); 194*4887Schin /*FALLTHROUGH*/ 195*4887Schin case 0: 196*4887Schin if (index && !(pp.state & STRICT)) 197*4887Schin error(1, "%s: predicate argument expected", pred); 198*4887Schin if (pp.macref) pprefmac(pred, REF_IF); 199*4887Schin return 0; 200*4887Schin } 201*4887Schin args = pp.args; 202*4887Schin 203*4887Schin /* 204*4887Schin * now evaluate 205*4887Schin */ 206*4887Schin 207*4887Schin debug((-6, "pred=%s args=%s", pred, args)); 208*4887Schin if ((pp.state & STRICT) && !(pp.mode & HOSTED)) switch (index) 209*4887Schin { 210*4887Schin case X_DEFINED: 211*4887Schin case X_SIZEOF: 212*4887Schin break; 213*4887Schin default: 214*4887Schin error(1, "%s(%s): non-standard predicate test", pred, args); 215*4887Schin return 0; 216*4887Schin } 217*4887Schin switch (index) 218*4887Schin { 219*4887Schin case X_DEFINED: 220*4887Schin if (type != T_ID) error(1, "%s: identifier argument expected", pred); 221*4887Schin else if ((sym = pprefmac(args, REF_IF)) && sym->macro) return 1; 222*4887Schin else if (args[0] == '_' && args[1] == '_' && !strncmp(args, "__STDPP__", 9)) 223*4887Schin { 224*4887Schin if (pp.hosted == 1 && pp.in->prev->type == IN_FILE) 225*4887Schin { 226*4887Schin pp.mode |= HOSTED; 227*4887Schin pp.flags |= PP_hosted; 228*4887Schin } 229*4887Schin return *(args + 9) ? (int)hashref(pp.strtab, args + 9) : 1; 230*4887Schin } 231*4887Schin break; 232*4887Schin case X_EXISTS: 233*4887Schin case X_INCLUDED: 234*4887Schin return exists(index, pred, args); 235*4887Schin case X_MATCH: 236*4887Schin case X_STRCMP: 237*4887Schin return compare(pred, args, index == X_MATCH); 238*4887Schin case X_NOTICED: 239*4887Schin if (type != T_ID) error(1, "%s: identifier argument expected", pred); 240*4887Schin else if (((sym = pprefmac(args, REF_IF)) || (sym = ppsymref(pp.symtab, args))) && (sym->flags & SYM_NOTICED)) return 1; 241*4887Schin break; 242*4887Schin case X_OPTION: 243*4887Schin return ppoption(args); 244*4887Schin case X_SIZEOF: 245*4887Schin error(2, "%s invalid in #%s expressions", pred, dirname(IF)); 246*4887Schin break; 247*4887Schin default: 248*4887Schin if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE)) 249*4887Schin error(1, "use #%s(%s) to disambiguate", pred, args); 250*4887Schin if (p = (struct pplist*)hashget(pp.prdtab, pred)) 251*4887Schin { 252*4887Schin if (!*args) return 1; 253*4887Schin while (p) 254*4887Schin { 255*4887Schin if (streq(p->value, args)) return 1; 256*4887Schin p = p->next; 257*4887Schin } 258*4887Schin } 259*4887Schin break; 260*4887Schin } 261*4887Schin return 0; 262*4887Schin } 263*4887Schin 264*4887Schin /* 265*4887Schin * evaluate a long integer subexpression with precedence 266*4887Schin * taken from the library routine streval() 267*4887Schin * may be called recursively 268*4887Schin * 269*4887Schin * NOTE: all operands are evaluated as both the parse 270*4887Schin * and evaluation are done on the fly 271*4887Schin */ 272*4887Schin 273*4887Schin static long 274*4887Schin subexpr(register int precedence, int* pun) 275*4887Schin { 276*4887Schin register int c; 277*4887Schin register long n; 278*4887Schin register long x; 279*4887Schin register int operand = 1; 280*4887Schin int un = 0; 281*4887Schin int xn; 282*4887Schin 283*4887Schin switch (lex(c)) 284*4887Schin { 285*4887Schin case 0: 286*4887Schin case '\n': 287*4887Schin unlex(c); 288*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected"; 289*4887Schin return 0; 290*4887Schin case '-': 291*4887Schin n = -subexpr(13, &un); 292*4887Schin break; 293*4887Schin case '+': 294*4887Schin n = subexpr(13, &un); 295*4887Schin break; 296*4887Schin case '!': 297*4887Schin n = !subexpr(13, &un); 298*4887Schin break; 299*4887Schin case '~': 300*4887Schin n = ~subexpr(13, &un); 301*4887Schin break; 302*4887Schin default: 303*4887Schin unlex(c); 304*4887Schin n = 0; 305*4887Schin operand = 0; 306*4887Schin break; 307*4887Schin } 308*4887Schin un <<= 1; 309*4887Schin for (;;) 310*4887Schin { 311*4887Schin switch (lex(c)) 312*4887Schin { 313*4887Schin case 0: 314*4887Schin case '\n': 315*4887Schin goto done; 316*4887Schin case ')': 317*4887Schin if (!precedence) 318*4887Schin { 319*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s"; 320*4887Schin return 0; 321*4887Schin } 322*4887Schin goto done; 323*4887Schin case '(': 324*4887Schin n = subexpr(1, &un); 325*4887Schin if (lex(c) != ')') 326*4887Schin { 327*4887Schin unlex(c); 328*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected"; 329*4887Schin return 0; 330*4887Schin } 331*4887Schin gotoperand: 332*4887Schin if (operand) 333*4887Schin { 334*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected"; 335*4887Schin return 0; 336*4887Schin } 337*4887Schin operand = 1; 338*4887Schin un <<= 1; 339*4887Schin continue; 340*4887Schin case '?': 341*4887Schin if (precedence > 1) goto done; 342*4887Schin un = 0; 343*4887Schin if (lex(c) == ':') 344*4887Schin { 345*4887Schin if (!n) n = subexpr(2, &un); 346*4887Schin else 347*4887Schin { 348*4887Schin x = pp.mode; 349*4887Schin pp.mode |= INACTIVE; 350*4887Schin subexpr(2, &xn); 351*4887Schin pp.mode = x; 352*4887Schin } 353*4887Schin } 354*4887Schin else 355*4887Schin { 356*4887Schin unlex(c); 357*4887Schin x = subexpr(2, &xn); 358*4887Schin if (lex(c) != ':') 359*4887Schin { 360*4887Schin unlex(c); 361*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator"; 362*4887Schin return 0; 363*4887Schin } 364*4887Schin if (n) 365*4887Schin { 366*4887Schin n = x; 367*4887Schin un = xn; 368*4887Schin subexpr(2, &xn); 369*4887Schin } 370*4887Schin else n = subexpr(2, &un); 371*4887Schin } 372*4887Schin break; 373*4887Schin case ':': 374*4887Schin goto done; 375*4887Schin case T_ANDAND: 376*4887Schin case T_OROR: 377*4887Schin xn = (c == T_ANDAND) ? 4 : 3; 378*4887Schin if (precedence >= xn) goto done; 379*4887Schin if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0; 380*4887Schin else 381*4887Schin { 382*4887Schin x = pp.mode; 383*4887Schin pp.mode |= INACTIVE; 384*4887Schin subexpr(xn, &un); 385*4887Schin pp.mode = x; 386*4887Schin } 387*4887Schin un = 0; 388*4887Schin break; 389*4887Schin case '|': 390*4887Schin if (precedence > 4) goto done; 391*4887Schin n |= subexpr(5, &un); 392*4887Schin break; 393*4887Schin case '^': 394*4887Schin if (precedence > 5) goto done; 395*4887Schin n ^= subexpr(6, &un); 396*4887Schin break; 397*4887Schin case '&': 398*4887Schin if (precedence > 6) goto done; 399*4887Schin n &= subexpr(7, &un); 400*4887Schin break; 401*4887Schin case T_EQ: 402*4887Schin case T_NE: 403*4887Schin if (precedence > 7) goto done; 404*4887Schin n = (n == subexpr(8, &un)) == (c == T_EQ); 405*4887Schin un = 0; 406*4887Schin break; 407*4887Schin case '<': 408*4887Schin case T_LE: 409*4887Schin case T_GE: 410*4887Schin case '>': 411*4887Schin if (precedence > 8) goto done; 412*4887Schin x = subexpr(9, &un); 413*4887Schin switch (c) 414*4887Schin { 415*4887Schin case '<': 416*4887Schin switch (un) 417*4887Schin { 418*4887Schin case 01: 419*4887Schin n = n < (unsigned long)x; 420*4887Schin break; 421*4887Schin case 02: 422*4887Schin n = (unsigned long)n < x; 423*4887Schin break; 424*4887Schin case 03: 425*4887Schin n = (unsigned long)n < (unsigned long)x; 426*4887Schin break; 427*4887Schin default: 428*4887Schin n = n < x; 429*4887Schin break; 430*4887Schin } 431*4887Schin break; 432*4887Schin case T_LE: 433*4887Schin switch (un) 434*4887Schin { 435*4887Schin case 01: 436*4887Schin n = n <= (unsigned long)x; 437*4887Schin break; 438*4887Schin case 02: 439*4887Schin n = (unsigned long)n <= x; 440*4887Schin break; 441*4887Schin case 03: 442*4887Schin n = (unsigned long)n <= (unsigned long)x; 443*4887Schin break; 444*4887Schin default: 445*4887Schin n = n <= x; 446*4887Schin break; 447*4887Schin } 448*4887Schin break; 449*4887Schin case T_GE: 450*4887Schin switch (un) 451*4887Schin { 452*4887Schin case 01: 453*4887Schin n = n >= (unsigned long)x; 454*4887Schin break; 455*4887Schin case 02: 456*4887Schin n = (unsigned long)n >= x; 457*4887Schin break; 458*4887Schin case 03: 459*4887Schin n = (unsigned long)n >= (unsigned long)x; 460*4887Schin break; 461*4887Schin default: 462*4887Schin n = n >= x; 463*4887Schin break; 464*4887Schin } 465*4887Schin break; 466*4887Schin case '>': 467*4887Schin switch (un) 468*4887Schin { 469*4887Schin case 01: 470*4887Schin n = n > (unsigned long)x; 471*4887Schin break; 472*4887Schin case 02: 473*4887Schin n = (unsigned long)n > x; 474*4887Schin break; 475*4887Schin case 03: 476*4887Schin n = (unsigned long)n > (unsigned long)x; 477*4887Schin break; 478*4887Schin default: 479*4887Schin n = n > x; 480*4887Schin break; 481*4887Schin } 482*4887Schin break; 483*4887Schin } 484*4887Schin un = 0; 485*4887Schin break; 486*4887Schin case T_LSHIFT: 487*4887Schin case T_RSHIFT: 488*4887Schin if (precedence > 9) goto done; 489*4887Schin x = subexpr(10, &un); 490*4887Schin if (c == T_LSHIFT) n <<= x; 491*4887Schin else n >>= x; 492*4887Schin un >>= 1; 493*4887Schin break; 494*4887Schin case '+': 495*4887Schin case '-': 496*4887Schin if (precedence > 10) goto done; 497*4887Schin x = subexpr(11, &un); 498*4887Schin if (c == '+') n += x; 499*4887Schin else n -= x; 500*4887Schin break; 501*4887Schin case '*': 502*4887Schin case '/': 503*4887Schin case '%': 504*4887Schin if (precedence > 11) goto done; 505*4887Schin x = subexpr(12, &un); 506*4887Schin if (c == '*') n *= x; 507*4887Schin else if (x == 0) 508*4887Schin { 509*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero"; 510*4887Schin return 0; 511*4887Schin } 512*4887Schin else if (c == '/') n /= x; 513*4887Schin else n %= x; 514*4887Schin break; 515*4887Schin case '#': 516*4887Schin pp.state |= DISABLE; 517*4887Schin c = pplex(); 518*4887Schin pp.state &= ~DISABLE; 519*4887Schin if (c != T_ID) 520*4887Schin { 521*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier"; 522*4887Schin return 0; 523*4887Schin } 524*4887Schin n = predicate(0); 525*4887Schin goto gotoperand; 526*4887Schin case T_ID: 527*4887Schin n = predicate(1); 528*4887Schin goto gotoperand; 529*4887Schin case T_CHARCONST: 530*4887Schin c = *(pp.toknxt - 1); 531*4887Schin *(pp.toknxt - 1) = 0; 532*4887Schin n = chrtoi(pp.token + 1); 533*4887Schin *(pp.toknxt - 1) = c; 534*4887Schin if (n & ~((1<<CHAR_BIT)-1)) 535*4887Schin { 536*4887Schin if (!(pp.mode & HOSTED)) 537*4887Schin error(1, "'%s': multi-character character constants are not portable", pp.token); 538*4887Schin } 539*4887Schin #if CHAR_MIN < 0 540*4887Schin else n = (char)n; 541*4887Schin #endif 542*4887Schin goto gotoperand; 543*4887Schin case T_DECIMAL_U: 544*4887Schin case T_DECIMAL_UL: 545*4887Schin case T_OCTAL_U: 546*4887Schin case T_OCTAL_UL: 547*4887Schin case T_HEXADECIMAL_U: 548*4887Schin case T_HEXADECIMAL_UL: 549*4887Schin un |= 01; 550*4887Schin /*FALLTHROUGH*/ 551*4887Schin case T_DECIMAL: 552*4887Schin case T_DECIMAL_L: 553*4887Schin case T_OCTAL: 554*4887Schin case T_OCTAL_L: 555*4887Schin case T_HEXADECIMAL: 556*4887Schin case T_HEXADECIMAL_L: 557*4887Schin n = strtoul(pp.token, NiL, 0); 558*4887Schin if ((unsigned long)n > LONG_MAX) un |= 01; 559*4887Schin goto gotoperand; 560*4887Schin case T_WCHARCONST: 561*4887Schin n = chrtoi(pp.token); 562*4887Schin goto gotoperand; 563*4887Schin default: 564*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token"; 565*4887Schin return 0; 566*4887Schin } 567*4887Schin if (errmsg) return 0; 568*4887Schin if (!operand) goto nooperand; 569*4887Schin } 570*4887Schin done: 571*4887Schin unlex(c); 572*4887Schin if (!operand) 573*4887Schin { 574*4887Schin nooperand: 575*4887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected"; 576*4887Schin return 0; 577*4887Schin } 578*4887Schin if (un) *pun |= 01; 579*4887Schin return n; 580*4887Schin } 581*4887Schin 582*4887Schin /* 583*4887Schin * preprocessor expression evaluator using modified streval(3) 584*4887Schin * *pun!=0 if result is unsigned 585*4887Schin */ 586*4887Schin 587*4887Schin long 588*4887Schin ppexpr(int* pun) 589*4887Schin { 590*4887Schin long n; 591*4887Schin int opeektoken; 592*4887Schin long ppstate; 593*4887Schin 594*4887Schin ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP)); 595*4887Schin pp.state &= ~(DISABLE|STRIP); 596*4887Schin pp.state |= CONDITIONAL|NOSPACE; 597*4887Schin opeektoken = peektoken; 598*4887Schin peektoken = -1; 599*4887Schin *pun = 0; 600*4887Schin n = subexpr(0, pun); 601*4887Schin if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :"; 602*4887Schin if (errmsg) 603*4887Schin { 604*4887Schin error(2, "%s in expression", errmsg); 605*4887Schin errmsg = 0; 606*4887Schin n = 0; 607*4887Schin } 608*4887Schin peektoken = opeektoken; 609*4887Schin pp.state &= ~(CONDITIONAL|NOSPACE); 610*4887Schin pp.state |= ppstate; 611*4887Schin if (*pun) debug((-4, "ppexpr() = %luU", n)); 612*4887Schin else debug((-4, "ppexpr() = %ld", n)); 613*4887Schin return n; 614*4887Schin } 615*4887Schin 616*4887Schin /* 617*4887Schin * return non-zero if option s is set 618*4887Schin */ 619*4887Schin 620*4887Schin int 621*4887Schin ppoption(char* s) 622*4887Schin { 623*4887Schin switch ((int)hashget(pp.strtab, s)) 624*4887Schin { 625*4887Schin case X_ALLMULTIPLE: 626*4887Schin return pp.mode & ALLMULTIPLE; 627*4887Schin case X_BUILTIN: 628*4887Schin return pp.mode & BUILTIN; 629*4887Schin case X_CATLITERAL: 630*4887Schin return pp.mode & CATLITERAL; 631*4887Schin case X_COMPATIBILITY: 632*4887Schin return pp.state & COMPATIBILITY; 633*4887Schin case X_DEBUG: 634*4887Schin return -error_info.trace; 635*4887Schin case X_ELSEIF: 636*4887Schin return pp.option & ELSEIF; 637*4887Schin case X_FINAL: 638*4887Schin return pp.option & FINAL; 639*4887Schin case X_HOSTDIR: 640*4887Schin return pp.mode & HOSTED; 641*4887Schin case X_HOSTED: 642*4887Schin return pp.flags & PP_hosted; 643*4887Schin case X_INITIAL: 644*4887Schin return pp.option & INITIAL; 645*4887Schin case X_KEYARGS: 646*4887Schin return pp.option & KEYARGS; 647*4887Schin case X_LINEBASE: 648*4887Schin return pp.flags & PP_linebase; 649*4887Schin case X_LINEFILE: 650*4887Schin return pp.flags & PP_linefile; 651*4887Schin case X_LINETYPE: 652*4887Schin return pp.flags & PP_linetype; 653*4887Schin case X_PLUSCOMMENT: 654*4887Schin return pp.option & PLUSCOMMENT; 655*4887Schin case X_PLUSPLUS: 656*4887Schin return pp.option & PLUSPLUS; 657*4887Schin case X_PLUSSPLICE: 658*4887Schin return pp.option & PLUSSPLICE; 659*4887Schin case X_PRAGMAEXPAND: 660*4887Schin return pp.option & PRAGMAEXPAND; 661*4887Schin case X_PREDEFINED: 662*4887Schin return pp.option & PREDEFINED; 663*4887Schin case X_PREFIX: 664*4887Schin return pp.option & PREFIX; 665*4887Schin case X_PROTOTYPED: 666*4887Schin return pp.option & PROTOTYPED; 667*4887Schin case X_READONLY: 668*4887Schin return pp.mode & READONLY; 669*4887Schin case X_REGUARD: 670*4887Schin return pp.option & REGUARD; 671*4887Schin case X_SPACEOUT: 672*4887Schin return pp.state & SPACEOUT; 673*4887Schin case X_SPLICECAT: 674*4887Schin return pp.option & SPLICECAT; 675*4887Schin case X_SPLICESPACE: 676*4887Schin return pp.option & SPLICESPACE; 677*4887Schin case X_STRICT: 678*4887Schin return pp.state & STRICT; 679*4887Schin case X_STRINGSPAN: 680*4887Schin return pp.option & STRINGSPAN; 681*4887Schin case X_STRINGSPLIT: 682*4887Schin return pp.option & STRINGSPLIT; 683*4887Schin case X_TEST: 684*4887Schin return pp.test; 685*4887Schin case X_TEXT: 686*4887Schin return !(pp.state & NOTEXT); 687*4887Schin case X_TRANSITION: 688*4887Schin return pp.state & TRANSITION; 689*4887Schin case X_TRUNCATE: 690*4887Schin return pp.truncate; 691*4887Schin case X_WARN: 692*4887Schin return pp.state & WARN; 693*4887Schin default: 694*4887Schin if (pp.state & WARN) error(1, "%s: unknown option name", s); 695*4887Schin return 0; 696*4887Schin } 697*4887Schin } 698