14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1986-2009 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * Glenn Fowler 234887Schin * AT&T Research 244887Schin * 254887Schin * preprocessor expression evaluation support 264887Schin */ 274887Schin 284887Schin #include "pplib.h" 294887Schin 304887Schin #include <regex.h> 314887Schin 324887Schin #define lex(c) ((((c)=peektoken)>=0?(peektoken=(-1)):((c)=pplex())),(c)) 334887Schin #define unlex(c) (peektoken=(c)) 344887Schin 354887Schin static int peektoken; /* expression lookahead token */ 364887Schin static char* errmsg; /* subexpr() error message */ 374887Schin 384887Schin /* 394887Schin * exists predicate evaluation 404887Schin */ 414887Schin 424887Schin static int 434887Schin exists(int op, char* pred, register char* args) 444887Schin { 454887Schin register int c; 464887Schin register int type; 474887Schin char* pptoken; 484887Schin long state; 494887Schin char file[MAXTOKEN + 1]; 504887Schin 514887Schin state = (pp.state & ~DISABLE); 524887Schin PUSH_STRING(args); 534887Schin pptoken = pp.token; 544887Schin pp.token = file; 554887Schin pp.state |= HEADER|PASSEOF; 564887Schin type = pplex(); 574887Schin pp.state &= ~HEADER; 584887Schin pp.token = pptoken; 594887Schin switch (type) 604887Schin { 614887Schin case T_STRING: 624887Schin case T_HEADER: 634887Schin break; 644887Schin default: 654887Schin error(1, "%s: \"...\" or <...> argument expected", pred); 664887Schin c = 0; 674887Schin goto done; 684887Schin } 694887Schin if (op == X_EXISTS) 704887Schin { 714887Schin if ((c = pplex()) == ',') 724887Schin { 734887Schin while ((c = pplex()) == T_STRING) 744887Schin { 754887Schin if (pathaccess(pp.path, pp.token, file, NiL, 0)) 764887Schin { 774887Schin pathcanon(pp.path, 0); 784887Schin message((-2, "%s: %s found", pred, pp.path)); 794887Schin c = 1; 804887Schin goto done; 814887Schin } 824887Schin if ((c = pplex()) != ',') break; 834887Schin } 844887Schin if (c) error(1, "%s: \"...\" arguments expected", pred); 854887Schin strcpy(pp.path, file); 864887Schin message((-2, "%s: %s not found", pred, file)); 874887Schin c = 0; 884887Schin } 894887Schin else c = ppsearch(file, type, SEARCH_EXISTS) >= 0; 904887Schin } 914887Schin else 924887Schin { 934887Schin register struct ppfile* fp; 944887Schin 954887Schin fp = ppsetfile(file); 964887Schin c = fp->flags || fp->guard == INC_IGNORE; 974887Schin } 984887Schin done: 994887Schin while (pplex()); 1004887Schin pp.state = state; 1014887Schin return c; 1024887Schin } 1034887Schin 1044887Schin /* 1054887Schin * strcmp/match predicate evaluation 1064887Schin */ 1074887Schin 1084887Schin static int 1094887Schin compare(char* pred, char* args, int match) 1104887Schin { 1114887Schin register int c; 1124887Schin char* pptoken; 1134887Schin long state; 1144887Schin regex_t re; 1154887Schin char tmp[MAXTOKEN + 1]; 1164887Schin 1174887Schin state = (pp.state & ~DISABLE); 1184887Schin PUSH_STRING(args); 1194887Schin pp.state |= PASSEOF; 1204887Schin pptoken = pp.token; 1214887Schin pp.token = tmp; 1224887Schin if (!pplex()) 1234887Schin goto bad; 1244887Schin pp.token = pptoken; 1254887Schin if (pplex() != ',' || !pplex()) 1264887Schin goto bad; 1274887Schin if (!match) 1284887Schin c = strcmp(tmp, pp.token); 1294887Schin else if ((c = regcomp(&re, pp.token, REG_AUGMENTED|REG_LENIENT|REG_NULL)) || (c = regexec(&re, tmp, NiL, 0, 0)) && c != REG_NOMATCH) 1304887Schin regfatal(&re, 3, c); 1314887Schin else 1324887Schin { 1334887Schin c = !c; 1344887Schin regfree(&re); 1354887Schin } 1364887Schin if ((pp.state & PASSEOF) && pplex()) 1374887Schin goto bad; 1384887Schin pp.state = state; 1394887Schin return c; 1404887Schin bad: 1414887Schin pp.token = pptoken; 1424887Schin error(2, "%s: 2 arguments expected", pred); 1434887Schin while (pplex()); 1444887Schin pp.state = state; 1454887Schin return 0; 1464887Schin } 1474887Schin 1484887Schin /* 1494887Schin * #if predicate parse and evaluation 1504887Schin */ 1514887Schin 1524887Schin static int 1534887Schin predicate(int warn) 1544887Schin { 1554887Schin register char* args; 1564887Schin register struct pplist* p; 1574887Schin register struct ppsymbol* sym; 1584887Schin register int type; 1594887Schin int index; 1604887Schin 1614887Schin static char pred[MAXID + 1]; 1624887Schin 1634887Schin /* 1644887Schin * first gather the args 1654887Schin */ 1664887Schin 1674887Schin index = (int)hashref(pp.strtab, pp.token); 1684887Schin if (warn && peekchr() != '(') switch (index) 1694887Schin { 1704887Schin case X_DEFINED: 1714887Schin case X_EXISTS: 1724887Schin case X_INCLUDED: 1734887Schin case X_MATCH: 1744887Schin case X_NOTICED: 1754887Schin case X_OPTION: 1764887Schin case X_SIZEOF: 1774887Schin case X_STRCMP: 1784887Schin break; 1794887Schin default: 1804887Schin if (pp.macref) pprefmac(pp.token, REF_IF); 1814887Schin return 0; 1824887Schin } 1834887Schin strcpy(pred, pp.token); 1844887Schin pp.state |= DISABLE; 1854887Schin type = pppredargs(); 1864887Schin pp.state &= ~DISABLE; 1874887Schin switch (type) 1884887Schin { 1894887Schin case T_ID: 1904887Schin case T_STRING: 1914887Schin break; 1924887Schin default: 1934887Schin unlex(type); 1944887Schin /*FALLTHROUGH*/ 1954887Schin case 0: 1964887Schin if (index && !(pp.state & STRICT)) 1974887Schin error(1, "%s: predicate argument expected", pred); 1984887Schin if (pp.macref) pprefmac(pred, REF_IF); 1994887Schin return 0; 2004887Schin } 2014887Schin args = pp.args; 2024887Schin 2034887Schin /* 2044887Schin * now evaluate 2054887Schin */ 2064887Schin 2074887Schin debug((-6, "pred=%s args=%s", pred, args)); 2084887Schin if ((pp.state & STRICT) && !(pp.mode & HOSTED)) switch (index) 2094887Schin { 2104887Schin case X_DEFINED: 2114887Schin case X_SIZEOF: 2124887Schin break; 2134887Schin default: 2144887Schin error(1, "%s(%s): non-standard predicate test", pred, args); 2154887Schin return 0; 2164887Schin } 2174887Schin switch (index) 2184887Schin { 2194887Schin case X_DEFINED: 2204887Schin if (type != T_ID) error(1, "%s: identifier argument expected", pred); 2214887Schin else if ((sym = pprefmac(args, REF_IF)) && sym->macro) return 1; 2224887Schin else if (args[0] == '_' && args[1] == '_' && !strncmp(args, "__STDPP__", 9)) 2234887Schin { 2244887Schin if (pp.hosted == 1 && pp.in->prev->type == IN_FILE) 2254887Schin { 2264887Schin pp.mode |= HOSTED; 2274887Schin pp.flags |= PP_hosted; 2284887Schin } 2294887Schin return *(args + 9) ? (int)hashref(pp.strtab, args + 9) : 1; 2304887Schin } 2314887Schin break; 2324887Schin case X_EXISTS: 2334887Schin case X_INCLUDED: 2344887Schin return exists(index, pred, args); 2354887Schin case X_MATCH: 2364887Schin case X_STRCMP: 2374887Schin return compare(pred, args, index == X_MATCH); 2384887Schin case X_NOTICED: 2394887Schin if (type != T_ID) error(1, "%s: identifier argument expected", pred); 2404887Schin else if (((sym = pprefmac(args, REF_IF)) || (sym = ppsymref(pp.symtab, args))) && (sym->flags & SYM_NOTICED)) return 1; 2414887Schin break; 2424887Schin case X_OPTION: 2434887Schin return ppoption(args); 2444887Schin case X_SIZEOF: 2454887Schin error(2, "%s invalid in #%s expressions", pred, dirname(IF)); 2464887Schin break; 2474887Schin default: 2484887Schin if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE)) 2494887Schin error(1, "use #%s(%s) to disambiguate", pred, args); 2504887Schin if (p = (struct pplist*)hashget(pp.prdtab, pred)) 2514887Schin { 2524887Schin if (!*args) return 1; 2534887Schin while (p) 2544887Schin { 2554887Schin if (streq(p->value, args)) return 1; 2564887Schin p = p->next; 2574887Schin } 2584887Schin } 2594887Schin break; 2604887Schin } 2614887Schin return 0; 2624887Schin } 2634887Schin 2644887Schin /* 2654887Schin * evaluate a long integer subexpression with precedence 2664887Schin * taken from the library routine streval() 2674887Schin * may be called recursively 2684887Schin * 2694887Schin * NOTE: all operands are evaluated as both the parse 2704887Schin * and evaluation are done on the fly 2714887Schin */ 2724887Schin 2734887Schin static long 2744887Schin subexpr(register int precedence, int* pun) 2754887Schin { 2764887Schin register int c; 2774887Schin register long n; 2784887Schin register long x; 2794887Schin register int operand = 1; 2804887Schin int un = 0; 2814887Schin int xn; 2824887Schin 2834887Schin switch (lex(c)) 2844887Schin { 2854887Schin case 0: 2864887Schin case '\n': 2874887Schin unlex(c); 2884887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected"; 2894887Schin return 0; 2904887Schin case '-': 2914887Schin n = -subexpr(13, &un); 2924887Schin break; 2934887Schin case '+': 2944887Schin n = subexpr(13, &un); 2954887Schin break; 2964887Schin case '!': 2974887Schin n = !subexpr(13, &un); 2984887Schin break; 2994887Schin case '~': 3004887Schin n = ~subexpr(13, &un); 3014887Schin break; 3024887Schin default: 3034887Schin unlex(c); 3044887Schin n = 0; 3054887Schin operand = 0; 3064887Schin break; 3074887Schin } 3084887Schin un <<= 1; 3094887Schin for (;;) 3104887Schin { 3114887Schin switch (lex(c)) 3124887Schin { 3134887Schin case 0: 3144887Schin case '\n': 3154887Schin goto done; 3164887Schin case ')': 3174887Schin if (!precedence) 3184887Schin { 3194887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s"; 3204887Schin return 0; 3214887Schin } 3224887Schin goto done; 3234887Schin case '(': 3244887Schin n = subexpr(1, &un); 3254887Schin if (lex(c) != ')') 3264887Schin { 3274887Schin unlex(c); 3284887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected"; 3294887Schin return 0; 3304887Schin } 3314887Schin gotoperand: 3324887Schin if (operand) 3334887Schin { 3344887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected"; 3354887Schin return 0; 3364887Schin } 3374887Schin operand = 1; 3384887Schin un <<= 1; 3394887Schin continue; 3404887Schin case '?': 3414887Schin if (precedence > 1) goto done; 3424887Schin un = 0; 3434887Schin if (lex(c) == ':') 3444887Schin { 3454887Schin if (!n) n = subexpr(2, &un); 3464887Schin else 3474887Schin { 3484887Schin x = pp.mode; 3494887Schin pp.mode |= INACTIVE; 3504887Schin subexpr(2, &xn); 3514887Schin pp.mode = x; 3524887Schin } 3534887Schin } 3544887Schin else 3554887Schin { 3564887Schin unlex(c); 3574887Schin x = subexpr(2, &xn); 3584887Schin if (lex(c) != ':') 3594887Schin { 3604887Schin unlex(c); 3614887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator"; 3624887Schin return 0; 3634887Schin } 3644887Schin if (n) 3654887Schin { 3664887Schin n = x; 3674887Schin un = xn; 3684887Schin subexpr(2, &xn); 3694887Schin } 3704887Schin else n = subexpr(2, &un); 3714887Schin } 3724887Schin break; 3734887Schin case ':': 3744887Schin goto done; 3754887Schin case T_ANDAND: 3764887Schin case T_OROR: 3774887Schin xn = (c == T_ANDAND) ? 4 : 3; 3784887Schin if (precedence >= xn) goto done; 3794887Schin if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0; 3804887Schin else 3814887Schin { 3824887Schin x = pp.mode; 3834887Schin pp.mode |= INACTIVE; 3844887Schin subexpr(xn, &un); 3854887Schin pp.mode = x; 3864887Schin } 3874887Schin un = 0; 3884887Schin break; 3894887Schin case '|': 3904887Schin if (precedence > 4) goto done; 3914887Schin n |= subexpr(5, &un); 3924887Schin break; 3934887Schin case '^': 3944887Schin if (precedence > 5) goto done; 3954887Schin n ^= subexpr(6, &un); 3964887Schin break; 3974887Schin case '&': 3984887Schin if (precedence > 6) goto done; 3994887Schin n &= subexpr(7, &un); 4004887Schin break; 4014887Schin case T_EQ: 4024887Schin case T_NE: 4034887Schin if (precedence > 7) goto done; 4044887Schin n = (n == subexpr(8, &un)) == (c == T_EQ); 4054887Schin un = 0; 4064887Schin break; 4074887Schin case '<': 4084887Schin case T_LE: 4094887Schin case T_GE: 4104887Schin case '>': 4114887Schin if (precedence > 8) goto done; 4124887Schin x = subexpr(9, &un); 4134887Schin switch (c) 4144887Schin { 4154887Schin case '<': 4164887Schin switch (un) 4174887Schin { 4184887Schin case 01: 4194887Schin n = n < (unsigned long)x; 4204887Schin break; 4214887Schin case 02: 4224887Schin n = (unsigned long)n < x; 4234887Schin break; 4244887Schin case 03: 4254887Schin n = (unsigned long)n < (unsigned long)x; 4264887Schin break; 4274887Schin default: 4284887Schin n = n < x; 4294887Schin break; 4304887Schin } 4314887Schin break; 4324887Schin case T_LE: 4334887Schin switch (un) 4344887Schin { 4354887Schin case 01: 4364887Schin n = n <= (unsigned long)x; 4374887Schin break; 4384887Schin case 02: 4394887Schin n = (unsigned long)n <= x; 4404887Schin break; 4414887Schin case 03: 4424887Schin n = (unsigned long)n <= (unsigned long)x; 4434887Schin break; 4444887Schin default: 4454887Schin n = n <= x; 4464887Schin break; 4474887Schin } 4484887Schin break; 4494887Schin case T_GE: 4504887Schin switch (un) 4514887Schin { 4524887Schin case 01: 4534887Schin n = n >= (unsigned long)x; 4544887Schin break; 4554887Schin case 02: 4564887Schin n = (unsigned long)n >= x; 4574887Schin break; 4584887Schin case 03: 4594887Schin n = (unsigned long)n >= (unsigned long)x; 4604887Schin break; 4614887Schin default: 4624887Schin n = n >= x; 4634887Schin break; 4644887Schin } 4654887Schin break; 4664887Schin case '>': 4674887Schin switch (un) 4684887Schin { 4694887Schin case 01: 4704887Schin n = n > (unsigned long)x; 4714887Schin break; 4724887Schin case 02: 4734887Schin n = (unsigned long)n > x; 4744887Schin break; 4754887Schin case 03: 4764887Schin n = (unsigned long)n > (unsigned long)x; 4774887Schin break; 4784887Schin default: 4794887Schin n = n > x; 4804887Schin break; 4814887Schin } 4824887Schin break; 4834887Schin } 4844887Schin un = 0; 4854887Schin break; 4864887Schin case T_LSHIFT: 4874887Schin case T_RSHIFT: 4884887Schin if (precedence > 9) goto done; 4894887Schin x = subexpr(10, &un); 4904887Schin if (c == T_LSHIFT) n <<= x; 4914887Schin else n >>= x; 4924887Schin un >>= 1; 4934887Schin break; 4944887Schin case '+': 4954887Schin case '-': 4964887Schin if (precedence > 10) goto done; 4974887Schin x = subexpr(11, &un); 4984887Schin if (c == '+') n += x; 4994887Schin else n -= x; 5004887Schin break; 5014887Schin case '*': 5024887Schin case '/': 5034887Schin case '%': 5044887Schin if (precedence > 11) goto done; 5054887Schin x = subexpr(12, &un); 5064887Schin if (c == '*') n *= x; 5074887Schin else if (x == 0) 5084887Schin { 5094887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero"; 5104887Schin return 0; 5114887Schin } 5124887Schin else if (c == '/') n /= x; 5134887Schin else n %= x; 5144887Schin break; 5154887Schin case '#': 5164887Schin pp.state |= DISABLE; 5174887Schin c = pplex(); 5184887Schin pp.state &= ~DISABLE; 5194887Schin if (c != T_ID) 5204887Schin { 5214887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier"; 5224887Schin return 0; 5234887Schin } 5244887Schin n = predicate(0); 5254887Schin goto gotoperand; 5264887Schin case T_ID: 5274887Schin n = predicate(1); 5284887Schin goto gotoperand; 5294887Schin case T_CHARCONST: 5304887Schin c = *(pp.toknxt - 1); 5314887Schin *(pp.toknxt - 1) = 0; 5324887Schin n = chrtoi(pp.token + 1); 5334887Schin *(pp.toknxt - 1) = c; 5344887Schin if (n & ~((1<<CHAR_BIT)-1)) 5354887Schin { 5364887Schin if (!(pp.mode & HOSTED)) 5374887Schin error(1, "'%s': multi-character character constants are not portable", pp.token); 5384887Schin } 5394887Schin #if CHAR_MIN < 0 5404887Schin else n = (char)n; 5414887Schin #endif 5424887Schin goto gotoperand; 5434887Schin case T_DECIMAL_U: 5444887Schin case T_DECIMAL_UL: 5454887Schin case T_OCTAL_U: 5464887Schin case T_OCTAL_UL: 5474887Schin case T_HEXADECIMAL_U: 5484887Schin case T_HEXADECIMAL_UL: 5494887Schin un |= 01; 5504887Schin /*FALLTHROUGH*/ 5514887Schin case T_DECIMAL: 5524887Schin case T_DECIMAL_L: 5534887Schin case T_OCTAL: 5544887Schin case T_OCTAL_L: 5554887Schin case T_HEXADECIMAL: 5564887Schin case T_HEXADECIMAL_L: 5574887Schin n = strtoul(pp.token, NiL, 0); 5584887Schin if ((unsigned long)n > LONG_MAX) un |= 01; 5594887Schin goto gotoperand; 5604887Schin case T_WCHARCONST: 5614887Schin n = chrtoi(pp.token); 5624887Schin goto gotoperand; 5634887Schin default: 5644887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token"; 5654887Schin return 0; 5664887Schin } 5674887Schin if (errmsg) return 0; 5684887Schin if (!operand) goto nooperand; 5694887Schin } 5704887Schin done: 5714887Schin unlex(c); 5724887Schin if (!operand) 5734887Schin { 5744887Schin nooperand: 5754887Schin if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected"; 5764887Schin return 0; 5774887Schin } 5784887Schin if (un) *pun |= 01; 5794887Schin return n; 5804887Schin } 5814887Schin 5824887Schin /* 5834887Schin * preprocessor expression evaluator using modified streval(3) 5844887Schin * *pun!=0 if result is unsigned 5854887Schin */ 5864887Schin 5874887Schin long 5884887Schin ppexpr(int* pun) 5894887Schin { 5904887Schin long n; 5914887Schin int opeektoken; 5924887Schin long ppstate; 5934887Schin 5944887Schin ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP)); 5954887Schin pp.state &= ~(DISABLE|STRIP); 5964887Schin pp.state |= CONDITIONAL|NOSPACE; 5974887Schin opeektoken = peektoken; 5984887Schin peektoken = -1; 5994887Schin *pun = 0; 6004887Schin n = subexpr(0, pun); 6014887Schin if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :"; 6024887Schin if (errmsg) 6034887Schin { 6044887Schin error(2, "%s in expression", errmsg); 6054887Schin errmsg = 0; 6064887Schin n = 0; 6074887Schin } 6084887Schin peektoken = opeektoken; 6094887Schin pp.state &= ~(CONDITIONAL|NOSPACE); 6104887Schin pp.state |= ppstate; 6114887Schin if (*pun) debug((-4, "ppexpr() = %luU", n)); 6124887Schin else debug((-4, "ppexpr() = %ld", n)); 6134887Schin return n; 6144887Schin } 6154887Schin 6164887Schin /* 6174887Schin * return non-zero if option s is set 6184887Schin */ 6194887Schin 6204887Schin int 6214887Schin ppoption(char* s) 6224887Schin { 6234887Schin switch ((int)hashget(pp.strtab, s)) 6244887Schin { 6254887Schin case X_ALLMULTIPLE: 6264887Schin return pp.mode & ALLMULTIPLE; 6274887Schin case X_BUILTIN: 6284887Schin return pp.mode & BUILTIN; 6294887Schin case X_CATLITERAL: 6304887Schin return pp.mode & CATLITERAL; 6314887Schin case X_COMPATIBILITY: 6324887Schin return pp.state & COMPATIBILITY; 6334887Schin case X_DEBUG: 6344887Schin return -error_info.trace; 6354887Schin case X_ELSEIF: 6364887Schin return pp.option & ELSEIF; 6374887Schin case X_FINAL: 6384887Schin return pp.option & FINAL; 6394887Schin case X_HOSTDIR: 6404887Schin return pp.mode & HOSTED; 6414887Schin case X_HOSTED: 6424887Schin return pp.flags & PP_hosted; 6434887Schin case X_INITIAL: 6444887Schin return pp.option & INITIAL; 6454887Schin case X_KEYARGS: 6464887Schin return pp.option & KEYARGS; 6474887Schin case X_LINEBASE: 6484887Schin return pp.flags & PP_linebase; 6494887Schin case X_LINEFILE: 6504887Schin return pp.flags & PP_linefile; 6514887Schin case X_LINETYPE: 6524887Schin return pp.flags & PP_linetype; 6534887Schin case X_PLUSCOMMENT: 6544887Schin return pp.option & PLUSCOMMENT; 6554887Schin case X_PLUSPLUS: 6564887Schin return pp.option & PLUSPLUS; 6574887Schin case X_PLUSSPLICE: 6584887Schin return pp.option & PLUSSPLICE; 6594887Schin case X_PRAGMAEXPAND: 6604887Schin return pp.option & PRAGMAEXPAND; 6614887Schin case X_PREDEFINED: 6624887Schin return pp.option & PREDEFINED; 6634887Schin case X_PREFIX: 6644887Schin return pp.option & PREFIX; 6654887Schin case X_PROTOTYPED: 6664887Schin return pp.option & PROTOTYPED; 6674887Schin case X_READONLY: 6684887Schin return pp.mode & READONLY; 6694887Schin case X_REGUARD: 6704887Schin return pp.option & REGUARD; 6714887Schin case X_SPACEOUT: 6724887Schin return pp.state & SPACEOUT; 6734887Schin case X_SPLICECAT: 6744887Schin return pp.option & SPLICECAT; 6754887Schin case X_SPLICESPACE: 6764887Schin return pp.option & SPLICESPACE; 6774887Schin case X_STRICT: 6784887Schin return pp.state & STRICT; 6794887Schin case X_STRINGSPAN: 6804887Schin return pp.option & STRINGSPAN; 6814887Schin case X_STRINGSPLIT: 6824887Schin return pp.option & STRINGSPLIT; 6834887Schin case X_TEST: 6844887Schin return pp.test; 6854887Schin case X_TEXT: 6864887Schin return !(pp.state & NOTEXT); 6874887Schin case X_TRANSITION: 6884887Schin return pp.state & TRANSITION; 6894887Schin case X_TRUNCATE: 6904887Schin return pp.truncate; 6914887Schin case X_WARN: 6924887Schin return pp.state & WARN; 6934887Schin default: 6944887Schin if (pp.state & WARN) error(1, "%s: unknown option name", s); 6954887Schin return 0; 6964887Schin } 6974887Schin } 698