13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include "cpp.h" 43e12c5d1SDavid du Colombier 53e12c5d1SDavid du Colombier #define NSTAK 32 63e12c5d1SDavid du Colombier #define SGN 0 73e12c5d1SDavid du Colombier #define UNS 1 83e12c5d1SDavid du Colombier #define UND 2 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier #define UNSMARK 0x1000 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier struct value { 133e12c5d1SDavid du Colombier long val; 143e12c5d1SDavid du Colombier int type; 153e12c5d1SDavid du Colombier }; 163e12c5d1SDavid du Colombier 173e12c5d1SDavid du Colombier /* conversion types */ 183e12c5d1SDavid du Colombier #define RELAT 1 193e12c5d1SDavid du Colombier #define ARITH 2 203e12c5d1SDavid du Colombier #define LOGIC 3 213e12c5d1SDavid du Colombier #define SPCL 4 223e12c5d1SDavid du Colombier #define SHIFT 5 233e12c5d1SDavid du Colombier #define UNARY 6 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier /* operator priority, arity, and conversion type, indexed by tokentype */ 263e12c5d1SDavid du Colombier const struct pri { 273e12c5d1SDavid du Colombier char pri; 283e12c5d1SDavid du Colombier char arity; 293e12c5d1SDavid du Colombier char ctype; 303e12c5d1SDavid du Colombier } priority[] = { 313e12c5d1SDavid du Colombier { 0, 0, 0 }, /* END */ 323e12c5d1SDavid du Colombier { 0, 0, 0 }, /* UNCLASS */ 333e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NAME */ 343e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NUMBER */ 353e12c5d1SDavid du Colombier { 0, 0, 0 }, /* STRING */ 363e12c5d1SDavid du Colombier { 0, 0, 0 }, /* CCON */ 373e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NL */ 383e12c5d1SDavid du Colombier { 0, 0, 0 }, /* WS */ 393e12c5d1SDavid du Colombier { 0, 0, 0 }, /* DSHARP */ 403e12c5d1SDavid du Colombier { 11, 2, RELAT }, /* EQ */ 413e12c5d1SDavid du Colombier { 11, 2, RELAT }, /* NEQ */ 423e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* LEQ */ 433e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* GEQ */ 443e12c5d1SDavid du Colombier { 13, 2, SHIFT }, /* LSH */ 453e12c5d1SDavid du Colombier { 13, 2, SHIFT }, /* RSH */ 463e12c5d1SDavid du Colombier { 7, 2, LOGIC }, /* LAND */ 473e12c5d1SDavid du Colombier { 6, 2, LOGIC }, /* LOR */ 483e12c5d1SDavid du Colombier { 0, 0, 0 }, /* PPLUS */ 493e12c5d1SDavid du Colombier { 0, 0, 0 }, /* MMINUS */ 503e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ARROW */ 513e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SBRA */ 523e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SKET */ 533e12c5d1SDavid du Colombier { 3, 0, 0 }, /* LP */ 543e12c5d1SDavid du Colombier { 3, 0, 0 }, /* RP */ 553e12c5d1SDavid du Colombier { 0, 0, 0 }, /* DOT */ 563e12c5d1SDavid du Colombier { 10, 2, ARITH }, /* AND */ 573e12c5d1SDavid du Colombier { 15, 2, ARITH }, /* STAR */ 583e12c5d1SDavid du Colombier { 14, 2, ARITH }, /* PLUS */ 593e12c5d1SDavid du Colombier { 14, 2, ARITH }, /* MINUS */ 603e12c5d1SDavid du Colombier { 16, 1, UNARY }, /* TILDE */ 613e12c5d1SDavid du Colombier { 16, 1, UNARY }, /* NOT */ 623e12c5d1SDavid du Colombier { 15, 2, ARITH }, /* SLASH */ 633e12c5d1SDavid du Colombier { 15, 2, ARITH }, /* PCT */ 643e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* LT */ 653e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* GT */ 663e12c5d1SDavid du Colombier { 9, 2, ARITH }, /* CIRC */ 673e12c5d1SDavid du Colombier { 8, 2, ARITH }, /* OR */ 683e12c5d1SDavid du Colombier { 5, 2, SPCL }, /* QUEST */ 693e12c5d1SDavid du Colombier { 5, 2, SPCL }, /* COLON */ 703e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASGN */ 713e12c5d1SDavid du Colombier { 4, 2, 0 }, /* COMMA */ 723e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SHARP */ 733e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SEMIC */ 743e12c5d1SDavid du Colombier { 0, 0, 0 }, /* CBRA */ 753e12c5d1SDavid du Colombier { 0, 0, 0 }, /* CKET */ 763e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASPLUS */ 773e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASMINUS */ 783e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASSTAR */ 793e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASSLASH */ 803e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASPCT */ 813e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASCIRC */ 823e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASLSH */ 833e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASRSH */ 843e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASOR */ 853e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASAND */ 863e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ELLIPS */ 873e12c5d1SDavid du Colombier { 0, 0, 0 }, /* DSHARP1 */ 883e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NAME1 */ 893e12c5d1SDavid du Colombier { 16, 1, UNARY }, /* DEFINED */ 903e12c5d1SDavid du Colombier { 16, 0, UNARY }, /* UMINUS */ 913e12c5d1SDavid du Colombier }; 923e12c5d1SDavid du Colombier 933e12c5d1SDavid du Colombier int evalop(struct pri); 943e12c5d1SDavid du Colombier struct value tokval(Token *); 953e12c5d1SDavid du Colombier struct value vals[NSTAK], *vp; 963e12c5d1SDavid du Colombier enum toktype ops[NSTAK], *op; 973e12c5d1SDavid du Colombier 983e12c5d1SDavid du Colombier /* 993e12c5d1SDavid du Colombier * Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword. 1003e12c5d1SDavid du Colombier */ 1013e12c5d1SDavid du Colombier long 1023e12c5d1SDavid du Colombier eval(Tokenrow *trp, int kw) 1033e12c5d1SDavid du Colombier { 1043e12c5d1SDavid du Colombier Token *tp; 1053e12c5d1SDavid du Colombier Nlist *np; 1063e12c5d1SDavid du Colombier int ntok, rand; 1073e12c5d1SDavid du Colombier 1083e12c5d1SDavid du Colombier trp->tp++; 1093e12c5d1SDavid du Colombier if (kw==KIFDEF || kw==KIFNDEF) { 1103e12c5d1SDavid du Colombier if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) { 1113e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #ifdef/#ifndef"); 1123e12c5d1SDavid du Colombier return 0; 1133e12c5d1SDavid du Colombier } 1143e12c5d1SDavid du Colombier np = lookup(trp->tp, 0); 115*219b2ee8SDavid du Colombier return (kw==KIFDEF) == (np && np->flag&(ISDEFINED|ISMAC)); 1163e12c5d1SDavid du Colombier } 117bd389b36SDavid du Colombier ntok = trp->tp - trp->bp; 118bd389b36SDavid du Colombier kwdefined->val = KDEFINED; /* activate special meaning of defined */ 1193e12c5d1SDavid du Colombier expandrow(trp, "<if>"); 120bd389b36SDavid du Colombier kwdefined->val = NAME; 1213e12c5d1SDavid du Colombier vp = vals; 1223e12c5d1SDavid du Colombier op = ops; 1233e12c5d1SDavid du Colombier *op++ = END; 1243e12c5d1SDavid du Colombier for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) { 1253e12c5d1SDavid du Colombier switch(tp->type) { 1263e12c5d1SDavid du Colombier case WS: 1273e12c5d1SDavid du Colombier case NL: 1283e12c5d1SDavid du Colombier continue; 1293e12c5d1SDavid du Colombier 1303e12c5d1SDavid du Colombier /* nilary */ 1313e12c5d1SDavid du Colombier case NAME: 1323e12c5d1SDavid du Colombier case NAME1: 1333e12c5d1SDavid du Colombier case NUMBER: 1343e12c5d1SDavid du Colombier case CCON: 1353e12c5d1SDavid du Colombier case STRING: 1363e12c5d1SDavid du Colombier if (rand) 1373e12c5d1SDavid du Colombier goto syntax; 1383e12c5d1SDavid du Colombier *vp++ = tokval(tp); 1393e12c5d1SDavid du Colombier rand = 1; 1403e12c5d1SDavid du Colombier continue; 1413e12c5d1SDavid du Colombier 1423e12c5d1SDavid du Colombier /* unary */ 1433e12c5d1SDavid du Colombier case DEFINED: 1443e12c5d1SDavid du Colombier case TILDE: 1453e12c5d1SDavid du Colombier case NOT: 1463e12c5d1SDavid du Colombier if (rand) 1473e12c5d1SDavid du Colombier goto syntax; 1483e12c5d1SDavid du Colombier *op++ = tp->type; 1493e12c5d1SDavid du Colombier continue; 1503e12c5d1SDavid du Colombier 1513e12c5d1SDavid du Colombier /* unary-binary */ 1523e12c5d1SDavid du Colombier case PLUS: case MINUS: case STAR: case AND: 1533e12c5d1SDavid du Colombier if (rand==0) { 1543e12c5d1SDavid du Colombier if (tp->type==MINUS) 1553e12c5d1SDavid du Colombier *op++ = UMINUS; 1563e12c5d1SDavid du Colombier if (tp->type==STAR || tp->type==AND) { 1573e12c5d1SDavid du Colombier error(ERROR, "Illegal operator * or & in #if/#elsif"); 1583e12c5d1SDavid du Colombier return 0; 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier continue; 1613e12c5d1SDavid du Colombier } 1623e12c5d1SDavid du Colombier /* flow through */ 1633e12c5d1SDavid du Colombier 1643e12c5d1SDavid du Colombier /* plain binary */ 1653e12c5d1SDavid du Colombier case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH: 1663e12c5d1SDavid du Colombier case LAND: case LOR: case SLASH: case PCT: 1673e12c5d1SDavid du Colombier case LT: case GT: case CIRC: case OR: case QUEST: 1683e12c5d1SDavid du Colombier case COLON: case COMMA: 1693e12c5d1SDavid du Colombier if (rand==0) 1703e12c5d1SDavid du Colombier goto syntax; 1713e12c5d1SDavid du Colombier if (evalop(priority[tp->type])!=0) 1723e12c5d1SDavid du Colombier return 0; 1733e12c5d1SDavid du Colombier *op++ = tp->type; 1743e12c5d1SDavid du Colombier rand = 0; 1753e12c5d1SDavid du Colombier continue; 1763e12c5d1SDavid du Colombier 1773e12c5d1SDavid du Colombier case LP: 1783e12c5d1SDavid du Colombier if (rand) 1793e12c5d1SDavid du Colombier goto syntax; 1803e12c5d1SDavid du Colombier *op++ = LP; 1813e12c5d1SDavid du Colombier continue; 1823e12c5d1SDavid du Colombier 1833e12c5d1SDavid du Colombier case RP: 1843e12c5d1SDavid du Colombier if (!rand) 1853e12c5d1SDavid du Colombier goto syntax; 1863e12c5d1SDavid du Colombier if (evalop(priority[RP])!=0) 1873e12c5d1SDavid du Colombier return 0; 1883e12c5d1SDavid du Colombier if (op<=ops || op[-1]!=LP) { 1893e12c5d1SDavid du Colombier goto syntax; 1903e12c5d1SDavid du Colombier } 1913e12c5d1SDavid du Colombier op--; 1923e12c5d1SDavid du Colombier continue; 1933e12c5d1SDavid du Colombier 1943e12c5d1SDavid du Colombier default: 1953e12c5d1SDavid du Colombier error(ERROR,"Bad operator (%t) in #if/#elsif", tp); 1963e12c5d1SDavid du Colombier return 0; 1973e12c5d1SDavid du Colombier } 1983e12c5d1SDavid du Colombier } 1993e12c5d1SDavid du Colombier if (rand==0) 2003e12c5d1SDavid du Colombier goto syntax; 2013e12c5d1SDavid du Colombier if (evalop(priority[END])!=0) 2023e12c5d1SDavid du Colombier return 0; 2033e12c5d1SDavid du Colombier if (op!=&ops[1] || vp!=&vals[1]) { 2043e12c5d1SDavid du Colombier error(ERROR, "Botch in #if/#elsif"); 2053e12c5d1SDavid du Colombier return 0; 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier if (vals[0].type==UND) 2083e12c5d1SDavid du Colombier error(ERROR, "Undefined expression value"); 2093e12c5d1SDavid du Colombier return vals[0].val; 2103e12c5d1SDavid du Colombier syntax: 2113e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #if/#elsif"); 2123e12c5d1SDavid du Colombier return 0; 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier int 2163e12c5d1SDavid du Colombier evalop(struct pri pri) 2173e12c5d1SDavid du Colombier { 2183e12c5d1SDavid du Colombier struct value v1, v2; 2193e12c5d1SDavid du Colombier long rv1, rv2; 2203e12c5d1SDavid du Colombier int rtype, oper; 2213e12c5d1SDavid du Colombier 2223e12c5d1SDavid du Colombier rv2=0; 2233e12c5d1SDavid du Colombier rtype=0; 2243e12c5d1SDavid du Colombier while (pri.pri < priority[op[-1]].pri) { 2253e12c5d1SDavid du Colombier oper = *--op; 2263e12c5d1SDavid du Colombier if (priority[oper].arity==2) { 2273e12c5d1SDavid du Colombier v2 = *--vp; 2283e12c5d1SDavid du Colombier rv2 = v2.val; 2293e12c5d1SDavid du Colombier } 2303e12c5d1SDavid du Colombier v1 = *--vp; 2313e12c5d1SDavid du Colombier rv1 = v1.val; 2323e12c5d1SDavid du Colombier switch (priority[oper].ctype) { 2333e12c5d1SDavid du Colombier case 0: 2343e12c5d1SDavid du Colombier default: 2353e12c5d1SDavid du Colombier error(WARNING, "Syntax error in #if/#endif"); 2363e12c5d1SDavid du Colombier return 1; 2373e12c5d1SDavid du Colombier case ARITH: 2383e12c5d1SDavid du Colombier case RELAT: 2393e12c5d1SDavid du Colombier if (v1.type==UNS || v2.type==UNS) 2403e12c5d1SDavid du Colombier rtype = UNS; 2413e12c5d1SDavid du Colombier else 2423e12c5d1SDavid du Colombier rtype = SGN; 2433e12c5d1SDavid du Colombier if (v1.type==UND || v2.type==UND) 2443e12c5d1SDavid du Colombier rtype = UND; 2453e12c5d1SDavid du Colombier if (priority[oper].ctype==RELAT && rtype==UNS) { 2463e12c5d1SDavid du Colombier oper |= UNSMARK; 2473e12c5d1SDavid du Colombier rtype = SGN; 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier break; 2503e12c5d1SDavid du Colombier case SHIFT: 2513e12c5d1SDavid du Colombier if (v1.type==UND || v2.type==UND) 2523e12c5d1SDavid du Colombier rtype = UND; 2533e12c5d1SDavid du Colombier else 2543e12c5d1SDavid du Colombier rtype = v1.type; 2553e12c5d1SDavid du Colombier if (rtype==UNS) 2563e12c5d1SDavid du Colombier oper |= UNSMARK; 2573e12c5d1SDavid du Colombier break; 2583e12c5d1SDavid du Colombier case UNARY: 2593e12c5d1SDavid du Colombier rtype = v1.type; 2603e12c5d1SDavid du Colombier break; 2613e12c5d1SDavid du Colombier case LOGIC: 2623e12c5d1SDavid du Colombier case SPCL: 2633e12c5d1SDavid du Colombier break; 2643e12c5d1SDavid du Colombier } 2653e12c5d1SDavid du Colombier switch (oper) { 2663e12c5d1SDavid du Colombier case EQ: case EQ|UNSMARK: 2673e12c5d1SDavid du Colombier rv1 = rv1==rv2; break; 2683e12c5d1SDavid du Colombier case NEQ: case NEQ|UNSMARK: 2693e12c5d1SDavid du Colombier rv1 = rv1!=rv2; break; 2703e12c5d1SDavid du Colombier case LEQ: 2713e12c5d1SDavid du Colombier rv1 = rv1<=rv2; break; 2723e12c5d1SDavid du Colombier case GEQ: 2733e12c5d1SDavid du Colombier rv1 = rv1>=rv2; break; 2743e12c5d1SDavid du Colombier case LT: 2753e12c5d1SDavid du Colombier rv1 = rv1<rv2; break; 2763e12c5d1SDavid du Colombier case GT: 2773e12c5d1SDavid du Colombier rv1 = rv1>rv2; break; 2783e12c5d1SDavid du Colombier case LEQ|UNSMARK: 2793e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1<=rv2; break; 2803e12c5d1SDavid du Colombier case GEQ|UNSMARK: 2813e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1>=rv2; break; 2823e12c5d1SDavid du Colombier case LT|UNSMARK: 2833e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1<rv2; break; 2843e12c5d1SDavid du Colombier case GT|UNSMARK: 2853e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1>rv2; break; 2863e12c5d1SDavid du Colombier case LSH: 2873e12c5d1SDavid du Colombier rv1 <<= rv2; break; 2883e12c5d1SDavid du Colombier case LSH|UNSMARK: 2893e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1<<rv2; break; 2903e12c5d1SDavid du Colombier case RSH: 2913e12c5d1SDavid du Colombier rv1 >>= rv2; break; 2923e12c5d1SDavid du Colombier case RSH|UNSMARK: 2933e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1>>rv2; break; 2943e12c5d1SDavid du Colombier case LAND: 2953e12c5d1SDavid du Colombier rtype = UND; 2963e12c5d1SDavid du Colombier if (v1.type==UND) 2973e12c5d1SDavid du Colombier break; 2983e12c5d1SDavid du Colombier if (rv1!=0) { 2993e12c5d1SDavid du Colombier if (v2.type==UND) 3003e12c5d1SDavid du Colombier break; 3013e12c5d1SDavid du Colombier rv1 = rv2!=0; 3023e12c5d1SDavid du Colombier } else 3033e12c5d1SDavid du Colombier rv1 = 0; 3043e12c5d1SDavid du Colombier rtype = SGN; 3053e12c5d1SDavid du Colombier break; 3063e12c5d1SDavid du Colombier case LOR: 3073e12c5d1SDavid du Colombier rtype = UND; 3083e12c5d1SDavid du Colombier if (v1.type==UND) 3093e12c5d1SDavid du Colombier break; 3103e12c5d1SDavid du Colombier if (rv1==0) { 3113e12c5d1SDavid du Colombier if (v2.type==UND) 3123e12c5d1SDavid du Colombier break; 3133e12c5d1SDavid du Colombier rv1 = rv2!=0; 3143e12c5d1SDavid du Colombier } else 3153e12c5d1SDavid du Colombier rv1 = 1; 3163e12c5d1SDavid du Colombier rtype = SGN; 3173e12c5d1SDavid du Colombier break; 3183e12c5d1SDavid du Colombier case AND: 3193e12c5d1SDavid du Colombier rv1 &= rv2; break; 3203e12c5d1SDavid du Colombier case STAR: 3213e12c5d1SDavid du Colombier rv1 *= rv2; break; 3223e12c5d1SDavid du Colombier case PLUS: 3233e12c5d1SDavid du Colombier rv1 += rv2; break; 3243e12c5d1SDavid du Colombier case MINUS: 3253e12c5d1SDavid du Colombier rv1 -= rv2; break; 3263e12c5d1SDavid du Colombier case UMINUS: 3273e12c5d1SDavid du Colombier if (v1.type==UND) 3283e12c5d1SDavid du Colombier rtype = UND; 3293e12c5d1SDavid du Colombier rv1 = -rv1; break; 3303e12c5d1SDavid du Colombier case OR: 3313e12c5d1SDavid du Colombier rv1 |= rv2; break; 3323e12c5d1SDavid du Colombier case CIRC: 3333e12c5d1SDavid du Colombier rv1 ^= rv2; break; 3343e12c5d1SDavid du Colombier case TILDE: 3353e12c5d1SDavid du Colombier rv1 = ~rv1; break; 3363e12c5d1SDavid du Colombier case NOT: 3373e12c5d1SDavid du Colombier rv1 = !rv1; if (rtype!=UND) rtype = SGN; break; 3383e12c5d1SDavid du Colombier case SLASH: 3393e12c5d1SDavid du Colombier if (rv2==0) { 3403e12c5d1SDavid du Colombier rtype = UND; 3413e12c5d1SDavid du Colombier break; 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier if (rtype==UNS) 3443e12c5d1SDavid du Colombier rv1 /= (unsigned long)rv2; 3453e12c5d1SDavid du Colombier else 3463e12c5d1SDavid du Colombier rv1 /= rv2; 3473e12c5d1SDavid du Colombier break; 3483e12c5d1SDavid du Colombier case PCT: 3493e12c5d1SDavid du Colombier if (rv2==0) { 3503e12c5d1SDavid du Colombier rtype = UND; 3513e12c5d1SDavid du Colombier break; 3523e12c5d1SDavid du Colombier } 3533e12c5d1SDavid du Colombier if (rtype==UNS) 3543e12c5d1SDavid du Colombier rv1 %= (unsigned long)rv2; 3553e12c5d1SDavid du Colombier else 3563e12c5d1SDavid du Colombier rv1 %= rv2; 3573e12c5d1SDavid du Colombier break; 3583e12c5d1SDavid du Colombier case COLON: 3593e12c5d1SDavid du Colombier if (op[-1] != QUEST) 3603e12c5d1SDavid du Colombier error(ERROR, "Bad ?: in #if/endif"); 3613e12c5d1SDavid du Colombier else { 3623e12c5d1SDavid du Colombier op--; 3633e12c5d1SDavid du Colombier if ((--vp)->val==0) 3643e12c5d1SDavid du Colombier v1 = v2; 3653e12c5d1SDavid du Colombier rtype = v1.type; 3663e12c5d1SDavid du Colombier rv1 = v1.val; 3673e12c5d1SDavid du Colombier } 3683e12c5d1SDavid du Colombier break; 3693e12c5d1SDavid du Colombier case DEFINED: 3703e12c5d1SDavid du Colombier break; 3713e12c5d1SDavid du Colombier default: 3723e12c5d1SDavid du Colombier error(ERROR, "Eval botch (unknown operator)"); 3733e12c5d1SDavid du Colombier return 1; 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier v1.val = rv1; 3763e12c5d1SDavid du Colombier v1.type = rtype; 3773e12c5d1SDavid du Colombier *vp++ = v1; 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier return 0; 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier 3823e12c5d1SDavid du Colombier struct value 3833e12c5d1SDavid du Colombier tokval(Token *tp) 3843e12c5d1SDavid du Colombier { 3853e12c5d1SDavid du Colombier struct value v; 3863e12c5d1SDavid du Colombier Nlist *np; 3873e12c5d1SDavid du Colombier int i, base, c, longcc; 3883e12c5d1SDavid du Colombier unsigned long n; 3893e12c5d1SDavid du Colombier Rune r; 3903e12c5d1SDavid du Colombier uchar *p; 3913e12c5d1SDavid du Colombier 3923e12c5d1SDavid du Colombier v.type = SGN; 3933e12c5d1SDavid du Colombier v.val = 0; 3943e12c5d1SDavid du Colombier switch (tp->type) { 3953e12c5d1SDavid du Colombier 3963e12c5d1SDavid du Colombier case NAME: 3973e12c5d1SDavid du Colombier v.val = 0; 3983e12c5d1SDavid du Colombier break; 3993e12c5d1SDavid du Colombier 4003e12c5d1SDavid du Colombier case NAME1: 401*219b2ee8SDavid du Colombier if ((np = lookup(tp, 0)) && np->flag&(ISDEFINED|ISMAC)) 4023e12c5d1SDavid du Colombier v.val = 1; 4033e12c5d1SDavid du Colombier break; 4043e12c5d1SDavid du Colombier 4053e12c5d1SDavid du Colombier case NUMBER: 4063e12c5d1SDavid du Colombier n = 0; 4073e12c5d1SDavid du Colombier base = 10; 4083e12c5d1SDavid du Colombier p = tp->t; 4093e12c5d1SDavid du Colombier c = p[tp->len]; 4103e12c5d1SDavid du Colombier p[tp->len] = '\0'; 4113e12c5d1SDavid du Colombier if (*p=='0') { 4123e12c5d1SDavid du Colombier base = 8; 4133e12c5d1SDavid du Colombier if (p[1]=='x' || p[1]=='X') { 4143e12c5d1SDavid du Colombier base = 16; 4153e12c5d1SDavid du Colombier p++; 4163e12c5d1SDavid du Colombier } 4173e12c5d1SDavid du Colombier p++; 4183e12c5d1SDavid du Colombier } 4193e12c5d1SDavid du Colombier for (;; p++) { 4203e12c5d1SDavid du Colombier if ((i = digit(*p)) < 0) 4213e12c5d1SDavid du Colombier break; 4223e12c5d1SDavid du Colombier if (i>=base) 4233e12c5d1SDavid du Colombier error(WARNING, 4243e12c5d1SDavid du Colombier "Bad digit in number %t", tp); 4253e12c5d1SDavid du Colombier n *= base; 4263e12c5d1SDavid du Colombier n += i; 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier if (n>=0x80000000 && base!=10) 4293e12c5d1SDavid du Colombier v.type = UNS; 4303e12c5d1SDavid du Colombier for (; *p; p++) { 4313e12c5d1SDavid du Colombier if (*p=='u' || *p=='U') 4323e12c5d1SDavid du Colombier v.type = UNS; 4333e12c5d1SDavid du Colombier else if (*p=='l' || *p=='L') 4343e12c5d1SDavid du Colombier ; 4353e12c5d1SDavid du Colombier else { 4363e12c5d1SDavid du Colombier error(ERROR, 4373e12c5d1SDavid du Colombier "Bad number %t in #if/#elsif", tp); 4383e12c5d1SDavid du Colombier break; 4393e12c5d1SDavid du Colombier } 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier v.val = n; 4423e12c5d1SDavid du Colombier tp->t[tp->len] = c; 4433e12c5d1SDavid du Colombier break; 4443e12c5d1SDavid du Colombier 4453e12c5d1SDavid du Colombier case CCON: 4463e12c5d1SDavid du Colombier n = 0; 4473e12c5d1SDavid du Colombier p = tp->t; 4483e12c5d1SDavid du Colombier longcc = 0; 4493e12c5d1SDavid du Colombier if (*p=='L') { 4503e12c5d1SDavid du Colombier p += 1; 4513e12c5d1SDavid du Colombier longcc = 1; 4523e12c5d1SDavid du Colombier } 4533e12c5d1SDavid du Colombier p += 1; 4543e12c5d1SDavid du Colombier if (*p=='\\') { 4553e12c5d1SDavid du Colombier p += 1; 4563e12c5d1SDavid du Colombier if ((i = digit(*p))>=0 && i<=7) { 4573e12c5d1SDavid du Colombier n = i; 4583e12c5d1SDavid du Colombier p += 1; 4593e12c5d1SDavid du Colombier if ((i = digit(*p))>=0 && i<=7) { 4603e12c5d1SDavid du Colombier p += 1; 4613e12c5d1SDavid du Colombier n <<= 3; 4623e12c5d1SDavid du Colombier n += i; 4633e12c5d1SDavid du Colombier if ((i = digit(*p))>=0 && i<=7) { 4643e12c5d1SDavid du Colombier p += 1; 4653e12c5d1SDavid du Colombier n <<= 3; 4663e12c5d1SDavid du Colombier n += i; 4673e12c5d1SDavid du Colombier } 4683e12c5d1SDavid du Colombier } 4693e12c5d1SDavid du Colombier } else if (*p=='x') { 4703e12c5d1SDavid du Colombier p += 1; 4713e12c5d1SDavid du Colombier while ((i = digit(*p))>=0 && i<=15) { 4723e12c5d1SDavid du Colombier p += 1; 4733e12c5d1SDavid du Colombier n <<= 4; 4743e12c5d1SDavid du Colombier n += i; 4753e12c5d1SDavid du Colombier } 4763e12c5d1SDavid du Colombier } else { 4773e12c5d1SDavid du Colombier static char cvcon[] 4783e12c5d1SDavid du Colombier = "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\"; 4793e12c5d1SDavid du Colombier for (i=0; i<sizeof(cvcon); i+=2) { 4803e12c5d1SDavid du Colombier if (*p == cvcon[i]) { 4813e12c5d1SDavid du Colombier n = cvcon[i+1]; 4823e12c5d1SDavid du Colombier break; 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier } 4853e12c5d1SDavid du Colombier p += 1; 4863e12c5d1SDavid du Colombier if (i>=sizeof(cvcon)) 4873e12c5d1SDavid du Colombier error(WARNING, 4883e12c5d1SDavid du Colombier "Undefined escape in character constant"); 4893e12c5d1SDavid du Colombier } 4903e12c5d1SDavid du Colombier } else if (*p=='\'') 4913e12c5d1SDavid du Colombier error(ERROR, "Empty character constant"); 4923e12c5d1SDavid du Colombier else { 4933e12c5d1SDavid du Colombier i = chartorune(&r, (char*)p); 4943e12c5d1SDavid du Colombier n = r; 4953e12c5d1SDavid du Colombier p += i; 4963e12c5d1SDavid du Colombier if (i>1 && longcc==0) 4973e12c5d1SDavid du Colombier error(WARNING, "Undefined character constant"); 4983e12c5d1SDavid du Colombier } 4993e12c5d1SDavid du Colombier if (*p!='\'') 5003e12c5d1SDavid du Colombier error(WARNING, "Multibyte character constant undefined"); 5013e12c5d1SDavid du Colombier else if (n>127 && longcc==0) 5023e12c5d1SDavid du Colombier error(WARNING, "Character constant taken as not signed"); 5033e12c5d1SDavid du Colombier v.val = n; 5043e12c5d1SDavid du Colombier break; 5053e12c5d1SDavid du Colombier 5063e12c5d1SDavid du Colombier case STRING: 5073e12c5d1SDavid du Colombier error(ERROR, "String in #if/#elsif"); 5083e12c5d1SDavid du Colombier break; 5093e12c5d1SDavid du Colombier } 5103e12c5d1SDavid du Colombier return v; 5113e12c5d1SDavid du Colombier } 5123e12c5d1SDavid du Colombier 5133e12c5d1SDavid du Colombier int 5143e12c5d1SDavid du Colombier digit(int i) 5153e12c5d1SDavid du Colombier { 5163e12c5d1SDavid du Colombier if ('0'<=i && i<='9') 5173e12c5d1SDavid du Colombier i -= '0'; 5183e12c5d1SDavid du Colombier else if ('a'<=i && i<='f') 5193e12c5d1SDavid du Colombier i -= 'a'-10; 5203e12c5d1SDavid du Colombier else if ('A'<=i && i<='F') 5213e12c5d1SDavid du Colombier i -= 'A'-10; 5223e12c5d1SDavid du Colombier else 5233e12c5d1SDavid du Colombier i = -1; 5243e12c5d1SDavid du Colombier return i; 5253e12c5d1SDavid du Colombier } 526