1*3e12c5d1SDavid du Colombier #include <u.h> 2*3e12c5d1SDavid du Colombier #include <libc.h> 3*3e12c5d1SDavid du Colombier #include "cpp.h" 4*3e12c5d1SDavid du Colombier 5*3e12c5d1SDavid du Colombier #define NSTAK 32 6*3e12c5d1SDavid du Colombier #define SGN 0 7*3e12c5d1SDavid du Colombier #define UNS 1 8*3e12c5d1SDavid du Colombier #define UND 2 9*3e12c5d1SDavid du Colombier 10*3e12c5d1SDavid du Colombier #define UNSMARK 0x1000 11*3e12c5d1SDavid du Colombier 12*3e12c5d1SDavid du Colombier struct value { 13*3e12c5d1SDavid du Colombier long val; 14*3e12c5d1SDavid du Colombier int type; 15*3e12c5d1SDavid du Colombier }; 16*3e12c5d1SDavid du Colombier 17*3e12c5d1SDavid du Colombier /* conversion types */ 18*3e12c5d1SDavid du Colombier #define RELAT 1 19*3e12c5d1SDavid du Colombier #define ARITH 2 20*3e12c5d1SDavid du Colombier #define LOGIC 3 21*3e12c5d1SDavid du Colombier #define SPCL 4 22*3e12c5d1SDavid du Colombier #define SHIFT 5 23*3e12c5d1SDavid du Colombier #define UNARY 6 24*3e12c5d1SDavid du Colombier 25*3e12c5d1SDavid du Colombier /* operator priority, arity, and conversion type, indexed by tokentype */ 26*3e12c5d1SDavid du Colombier const struct pri { 27*3e12c5d1SDavid du Colombier char pri; 28*3e12c5d1SDavid du Colombier char arity; 29*3e12c5d1SDavid du Colombier char ctype; 30*3e12c5d1SDavid du Colombier } priority[] = { 31*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* END */ 32*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* UNCLASS */ 33*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NAME */ 34*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NUMBER */ 35*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* STRING */ 36*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* CCON */ 37*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NL */ 38*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* WS */ 39*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* DSHARP */ 40*3e12c5d1SDavid du Colombier { 11, 2, RELAT }, /* EQ */ 41*3e12c5d1SDavid du Colombier { 11, 2, RELAT }, /* NEQ */ 42*3e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* LEQ */ 43*3e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* GEQ */ 44*3e12c5d1SDavid du Colombier { 13, 2, SHIFT }, /* LSH */ 45*3e12c5d1SDavid du Colombier { 13, 2, SHIFT }, /* RSH */ 46*3e12c5d1SDavid du Colombier { 7, 2, LOGIC }, /* LAND */ 47*3e12c5d1SDavid du Colombier { 6, 2, LOGIC }, /* LOR */ 48*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* PPLUS */ 49*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* MMINUS */ 50*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ARROW */ 51*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SBRA */ 52*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SKET */ 53*3e12c5d1SDavid du Colombier { 3, 0, 0 }, /* LP */ 54*3e12c5d1SDavid du Colombier { 3, 0, 0 }, /* RP */ 55*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* DOT */ 56*3e12c5d1SDavid du Colombier { 10, 2, ARITH }, /* AND */ 57*3e12c5d1SDavid du Colombier { 15, 2, ARITH }, /* STAR */ 58*3e12c5d1SDavid du Colombier { 14, 2, ARITH }, /* PLUS */ 59*3e12c5d1SDavid du Colombier { 14, 2, ARITH }, /* MINUS */ 60*3e12c5d1SDavid du Colombier { 16, 1, UNARY }, /* TILDE */ 61*3e12c5d1SDavid du Colombier { 16, 1, UNARY }, /* NOT */ 62*3e12c5d1SDavid du Colombier { 15, 2, ARITH }, /* SLASH */ 63*3e12c5d1SDavid du Colombier { 15, 2, ARITH }, /* PCT */ 64*3e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* LT */ 65*3e12c5d1SDavid du Colombier { 12, 2, RELAT }, /* GT */ 66*3e12c5d1SDavid du Colombier { 9, 2, ARITH }, /* CIRC */ 67*3e12c5d1SDavid du Colombier { 8, 2, ARITH }, /* OR */ 68*3e12c5d1SDavid du Colombier { 5, 2, SPCL }, /* QUEST */ 69*3e12c5d1SDavid du Colombier { 5, 2, SPCL }, /* COLON */ 70*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASGN */ 71*3e12c5d1SDavid du Colombier { 4, 2, 0 }, /* COMMA */ 72*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SHARP */ 73*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* SEMIC */ 74*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* CBRA */ 75*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* CKET */ 76*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASPLUS */ 77*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASMINUS */ 78*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASSTAR */ 79*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASSLASH */ 80*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASPCT */ 81*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASCIRC */ 82*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASLSH */ 83*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASRSH */ 84*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASOR */ 85*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ASAND */ 86*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* ELLIPS */ 87*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* DSHARP1 */ 88*3e12c5d1SDavid du Colombier { 0, 0, 0 }, /* NAME1 */ 89*3e12c5d1SDavid du Colombier { 16, 1, UNARY }, /* DEFINED */ 90*3e12c5d1SDavid du Colombier { 16, 0, UNARY }, /* UMINUS */ 91*3e12c5d1SDavid du Colombier }; 92*3e12c5d1SDavid du Colombier 93*3e12c5d1SDavid du Colombier int evalop(struct pri); 94*3e12c5d1SDavid du Colombier struct value tokval(Token *); 95*3e12c5d1SDavid du Colombier struct value vals[NSTAK], *vp; 96*3e12c5d1SDavid du Colombier enum toktype ops[NSTAK], *op; 97*3e12c5d1SDavid du Colombier 98*3e12c5d1SDavid du Colombier /* 99*3e12c5d1SDavid du Colombier * Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword. 100*3e12c5d1SDavid du Colombier */ 101*3e12c5d1SDavid du Colombier long 102*3e12c5d1SDavid du Colombier eval(Tokenrow *trp, int kw) 103*3e12c5d1SDavid du Colombier { 104*3e12c5d1SDavid du Colombier Token *tp; 105*3e12c5d1SDavid du Colombier Nlist *np; 106*3e12c5d1SDavid du Colombier int ntok, rand; 107*3e12c5d1SDavid du Colombier 108*3e12c5d1SDavid du Colombier trp->tp++; 109*3e12c5d1SDavid du Colombier if (kw==KIFDEF || kw==KIFNDEF) { 110*3e12c5d1SDavid du Colombier if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) { 111*3e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #ifdef/#ifndef"); 112*3e12c5d1SDavid du Colombier return 0; 113*3e12c5d1SDavid du Colombier } 114*3e12c5d1SDavid du Colombier np = lookup(trp->tp, 0); 115*3e12c5d1SDavid du Colombier return (kw==KIFDEF) == (np && np->flag&ISDEFINED); 116*3e12c5d1SDavid du Colombier } 117*3e12c5d1SDavid du Colombier /* replace 'defined name', 'defined(name)' to prevent evaluation */ 118*3e12c5d1SDavid du Colombier for (tp=trp->tp, ntok=tp-trp->bp; tp < trp->lp; tp++) { 119*3e12c5d1SDavid du Colombier if (tp->type!=NAME) 120*3e12c5d1SDavid du Colombier continue; 121*3e12c5d1SDavid du Colombier if ((np=lookup(tp, 0))!=NULL && np->val==KDEFINED) { 122*3e12c5d1SDavid du Colombier tp->type = DEFINED; 123*3e12c5d1SDavid du Colombier if ((tp+1)<trp->lp && (tp+1)->type==NAME) 124*3e12c5d1SDavid du Colombier (tp+1)->type = NAME1; 125*3e12c5d1SDavid du Colombier else if ((tp+3)<trp->lp && (tp+1)->type==LP 126*3e12c5d1SDavid du Colombier && (tp+2)->type==NAME && (tp+3)->type==RP) 127*3e12c5d1SDavid du Colombier (tp+2)->type = NAME1; 128*3e12c5d1SDavid du Colombier else 129*3e12c5d1SDavid du Colombier error(ERROR, "Incorrect syntax for `defined'"); 130*3e12c5d1SDavid du Colombier } 131*3e12c5d1SDavid du Colombier } 132*3e12c5d1SDavid du Colombier expandrow(trp, "<if>"); 133*3e12c5d1SDavid du Colombier vp = vals; 134*3e12c5d1SDavid du Colombier op = ops; 135*3e12c5d1SDavid du Colombier *op++ = END; 136*3e12c5d1SDavid du Colombier for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) { 137*3e12c5d1SDavid du Colombier switch(tp->type) { 138*3e12c5d1SDavid du Colombier case WS: 139*3e12c5d1SDavid du Colombier case NL: 140*3e12c5d1SDavid du Colombier continue; 141*3e12c5d1SDavid du Colombier 142*3e12c5d1SDavid du Colombier /* nilary */ 143*3e12c5d1SDavid du Colombier case NAME: 144*3e12c5d1SDavid du Colombier case NAME1: 145*3e12c5d1SDavid du Colombier case NUMBER: 146*3e12c5d1SDavid du Colombier case CCON: 147*3e12c5d1SDavid du Colombier case STRING: 148*3e12c5d1SDavid du Colombier if (rand) 149*3e12c5d1SDavid du Colombier goto syntax; 150*3e12c5d1SDavid du Colombier *vp++ = tokval(tp); 151*3e12c5d1SDavid du Colombier rand = 1; 152*3e12c5d1SDavid du Colombier continue; 153*3e12c5d1SDavid du Colombier 154*3e12c5d1SDavid du Colombier /* unary */ 155*3e12c5d1SDavid du Colombier case DEFINED: 156*3e12c5d1SDavid du Colombier case TILDE: 157*3e12c5d1SDavid du Colombier case NOT: 158*3e12c5d1SDavid du Colombier if (rand) 159*3e12c5d1SDavid du Colombier goto syntax; 160*3e12c5d1SDavid du Colombier *op++ = tp->type; 161*3e12c5d1SDavid du Colombier continue; 162*3e12c5d1SDavid du Colombier 163*3e12c5d1SDavid du Colombier /* unary-binary */ 164*3e12c5d1SDavid du Colombier case PLUS: case MINUS: case STAR: case AND: 165*3e12c5d1SDavid du Colombier if (rand==0) { 166*3e12c5d1SDavid du Colombier if (tp->type==MINUS) 167*3e12c5d1SDavid du Colombier *op++ = UMINUS; 168*3e12c5d1SDavid du Colombier if (tp->type==STAR || tp->type==AND) { 169*3e12c5d1SDavid du Colombier error(ERROR, "Illegal operator * or & in #if/#elsif"); 170*3e12c5d1SDavid du Colombier return 0; 171*3e12c5d1SDavid du Colombier } 172*3e12c5d1SDavid du Colombier continue; 173*3e12c5d1SDavid du Colombier } 174*3e12c5d1SDavid du Colombier /* flow through */ 175*3e12c5d1SDavid du Colombier 176*3e12c5d1SDavid du Colombier /* plain binary */ 177*3e12c5d1SDavid du Colombier case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH: 178*3e12c5d1SDavid du Colombier case LAND: case LOR: case SLASH: case PCT: 179*3e12c5d1SDavid du Colombier case LT: case GT: case CIRC: case OR: case QUEST: 180*3e12c5d1SDavid du Colombier case COLON: case COMMA: 181*3e12c5d1SDavid du Colombier if (rand==0) 182*3e12c5d1SDavid du Colombier goto syntax; 183*3e12c5d1SDavid du Colombier if (evalop(priority[tp->type])!=0) 184*3e12c5d1SDavid du Colombier return 0; 185*3e12c5d1SDavid du Colombier *op++ = tp->type; 186*3e12c5d1SDavid du Colombier rand = 0; 187*3e12c5d1SDavid du Colombier continue; 188*3e12c5d1SDavid du Colombier 189*3e12c5d1SDavid du Colombier case LP: 190*3e12c5d1SDavid du Colombier if (rand) 191*3e12c5d1SDavid du Colombier goto syntax; 192*3e12c5d1SDavid du Colombier *op++ = LP; 193*3e12c5d1SDavid du Colombier continue; 194*3e12c5d1SDavid du Colombier 195*3e12c5d1SDavid du Colombier case RP: 196*3e12c5d1SDavid du Colombier if (!rand) 197*3e12c5d1SDavid du Colombier goto syntax; 198*3e12c5d1SDavid du Colombier if (evalop(priority[RP])!=0) 199*3e12c5d1SDavid du Colombier return 0; 200*3e12c5d1SDavid du Colombier if (op<=ops || op[-1]!=LP) { 201*3e12c5d1SDavid du Colombier goto syntax; 202*3e12c5d1SDavid du Colombier } 203*3e12c5d1SDavid du Colombier op--; 204*3e12c5d1SDavid du Colombier continue; 205*3e12c5d1SDavid du Colombier 206*3e12c5d1SDavid du Colombier default: 207*3e12c5d1SDavid du Colombier error(ERROR,"Bad operator (%t) in #if/#elsif", tp); 208*3e12c5d1SDavid du Colombier return 0; 209*3e12c5d1SDavid du Colombier } 210*3e12c5d1SDavid du Colombier } 211*3e12c5d1SDavid du Colombier if (rand==0) 212*3e12c5d1SDavid du Colombier goto syntax; 213*3e12c5d1SDavid du Colombier if (evalop(priority[END])!=0) 214*3e12c5d1SDavid du Colombier return 0; 215*3e12c5d1SDavid du Colombier if (op!=&ops[1] || vp!=&vals[1]) { 216*3e12c5d1SDavid du Colombier error(ERROR, "Botch in #if/#elsif"); 217*3e12c5d1SDavid du Colombier return 0; 218*3e12c5d1SDavid du Colombier } 219*3e12c5d1SDavid du Colombier if (vals[0].type==UND) 220*3e12c5d1SDavid du Colombier error(ERROR, "Undefined expression value"); 221*3e12c5d1SDavid du Colombier return vals[0].val; 222*3e12c5d1SDavid du Colombier syntax: 223*3e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #if/#elsif"); 224*3e12c5d1SDavid du Colombier return 0; 225*3e12c5d1SDavid du Colombier } 226*3e12c5d1SDavid du Colombier 227*3e12c5d1SDavid du Colombier int 228*3e12c5d1SDavid du Colombier evalop(struct pri pri) 229*3e12c5d1SDavid du Colombier { 230*3e12c5d1SDavid du Colombier struct value v1, v2; 231*3e12c5d1SDavid du Colombier long rv1, rv2; 232*3e12c5d1SDavid du Colombier int rtype, oper; 233*3e12c5d1SDavid du Colombier 234*3e12c5d1SDavid du Colombier rv2=0; 235*3e12c5d1SDavid du Colombier rtype=0; 236*3e12c5d1SDavid du Colombier while (pri.pri < priority[op[-1]].pri) { 237*3e12c5d1SDavid du Colombier oper = *--op; 238*3e12c5d1SDavid du Colombier if (priority[oper].arity==2) { 239*3e12c5d1SDavid du Colombier v2 = *--vp; 240*3e12c5d1SDavid du Colombier rv2 = v2.val; 241*3e12c5d1SDavid du Colombier } 242*3e12c5d1SDavid du Colombier v1 = *--vp; 243*3e12c5d1SDavid du Colombier rv1 = v1.val; 244*3e12c5d1SDavid du Colombier switch (priority[oper].ctype) { 245*3e12c5d1SDavid du Colombier case 0: 246*3e12c5d1SDavid du Colombier default: 247*3e12c5d1SDavid du Colombier error(WARNING, "Syntax error in #if/#endif"); 248*3e12c5d1SDavid du Colombier return 1; 249*3e12c5d1SDavid du Colombier case ARITH: 250*3e12c5d1SDavid du Colombier case RELAT: 251*3e12c5d1SDavid du Colombier if (v1.type==UNS || v2.type==UNS) 252*3e12c5d1SDavid du Colombier rtype = UNS; 253*3e12c5d1SDavid du Colombier else 254*3e12c5d1SDavid du Colombier rtype = SGN; 255*3e12c5d1SDavid du Colombier if (v1.type==UND || v2.type==UND) 256*3e12c5d1SDavid du Colombier rtype = UND; 257*3e12c5d1SDavid du Colombier if (priority[oper].ctype==RELAT && rtype==UNS) { 258*3e12c5d1SDavid du Colombier oper |= UNSMARK; 259*3e12c5d1SDavid du Colombier rtype = SGN; 260*3e12c5d1SDavid du Colombier } 261*3e12c5d1SDavid du Colombier break; 262*3e12c5d1SDavid du Colombier case SHIFT: 263*3e12c5d1SDavid du Colombier if (v1.type==UND || v2.type==UND) 264*3e12c5d1SDavid du Colombier rtype = UND; 265*3e12c5d1SDavid du Colombier else 266*3e12c5d1SDavid du Colombier rtype = v1.type; 267*3e12c5d1SDavid du Colombier if (rtype==UNS) 268*3e12c5d1SDavid du Colombier oper |= UNSMARK; 269*3e12c5d1SDavid du Colombier break; 270*3e12c5d1SDavid du Colombier case UNARY: 271*3e12c5d1SDavid du Colombier rtype = v1.type; 272*3e12c5d1SDavid du Colombier break; 273*3e12c5d1SDavid du Colombier case LOGIC: 274*3e12c5d1SDavid du Colombier case SPCL: 275*3e12c5d1SDavid du Colombier break; 276*3e12c5d1SDavid du Colombier } 277*3e12c5d1SDavid du Colombier switch (oper) { 278*3e12c5d1SDavid du Colombier case EQ: case EQ|UNSMARK: 279*3e12c5d1SDavid du Colombier rv1 = rv1==rv2; break; 280*3e12c5d1SDavid du Colombier case NEQ: case NEQ|UNSMARK: 281*3e12c5d1SDavid du Colombier rv1 = rv1!=rv2; break; 282*3e12c5d1SDavid du Colombier case LEQ: 283*3e12c5d1SDavid du Colombier rv1 = rv1<=rv2; break; 284*3e12c5d1SDavid du Colombier case GEQ: 285*3e12c5d1SDavid du Colombier rv1 = rv1>=rv2; break; 286*3e12c5d1SDavid du Colombier case LT: 287*3e12c5d1SDavid du Colombier rv1 = rv1<rv2; break; 288*3e12c5d1SDavid du Colombier case GT: 289*3e12c5d1SDavid du Colombier rv1 = rv1>rv2; break; 290*3e12c5d1SDavid du Colombier case LEQ|UNSMARK: 291*3e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1<=rv2; break; 292*3e12c5d1SDavid du Colombier case GEQ|UNSMARK: 293*3e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1>=rv2; break; 294*3e12c5d1SDavid du Colombier case LT|UNSMARK: 295*3e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1<rv2; break; 296*3e12c5d1SDavid du Colombier case GT|UNSMARK: 297*3e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1>rv2; break; 298*3e12c5d1SDavid du Colombier case LSH: 299*3e12c5d1SDavid du Colombier rv1 <<= rv2; break; 300*3e12c5d1SDavid du Colombier case LSH|UNSMARK: 301*3e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1<<rv2; break; 302*3e12c5d1SDavid du Colombier case RSH: 303*3e12c5d1SDavid du Colombier rv1 >>= rv2; break; 304*3e12c5d1SDavid du Colombier case RSH|UNSMARK: 305*3e12c5d1SDavid du Colombier rv1 = (unsigned long)rv1>>rv2; break; 306*3e12c5d1SDavid du Colombier case LAND: 307*3e12c5d1SDavid du Colombier rtype = UND; 308*3e12c5d1SDavid du Colombier if (v1.type==UND) 309*3e12c5d1SDavid du Colombier break; 310*3e12c5d1SDavid du Colombier if (rv1!=0) { 311*3e12c5d1SDavid du Colombier if (v2.type==UND) 312*3e12c5d1SDavid du Colombier break; 313*3e12c5d1SDavid du Colombier rv1 = rv2!=0; 314*3e12c5d1SDavid du Colombier } else 315*3e12c5d1SDavid du Colombier rv1 = 0; 316*3e12c5d1SDavid du Colombier rtype = SGN; 317*3e12c5d1SDavid du Colombier break; 318*3e12c5d1SDavid du Colombier case LOR: 319*3e12c5d1SDavid du Colombier rtype = UND; 320*3e12c5d1SDavid du Colombier if (v1.type==UND) 321*3e12c5d1SDavid du Colombier break; 322*3e12c5d1SDavid du Colombier if (rv1==0) { 323*3e12c5d1SDavid du Colombier if (v2.type==UND) 324*3e12c5d1SDavid du Colombier break; 325*3e12c5d1SDavid du Colombier rv1 = rv2!=0; 326*3e12c5d1SDavid du Colombier } else 327*3e12c5d1SDavid du Colombier rv1 = 1; 328*3e12c5d1SDavid du Colombier rtype = SGN; 329*3e12c5d1SDavid du Colombier break; 330*3e12c5d1SDavid du Colombier case AND: 331*3e12c5d1SDavid du Colombier rv1 &= rv2; break; 332*3e12c5d1SDavid du Colombier case STAR: 333*3e12c5d1SDavid du Colombier rv1 *= rv2; break; 334*3e12c5d1SDavid du Colombier case PLUS: 335*3e12c5d1SDavid du Colombier rv1 += rv2; break; 336*3e12c5d1SDavid du Colombier case MINUS: 337*3e12c5d1SDavid du Colombier rv1 -= rv2; break; 338*3e12c5d1SDavid du Colombier case UMINUS: 339*3e12c5d1SDavid du Colombier if (v1.type==UND) 340*3e12c5d1SDavid du Colombier rtype = UND; 341*3e12c5d1SDavid du Colombier rv1 = -rv1; break; 342*3e12c5d1SDavid du Colombier case OR: 343*3e12c5d1SDavid du Colombier rv1 |= rv2; break; 344*3e12c5d1SDavid du Colombier case CIRC: 345*3e12c5d1SDavid du Colombier rv1 ^= rv2; break; 346*3e12c5d1SDavid du Colombier case TILDE: 347*3e12c5d1SDavid du Colombier rv1 = ~rv1; break; 348*3e12c5d1SDavid du Colombier case NOT: 349*3e12c5d1SDavid du Colombier rv1 = !rv1; if (rtype!=UND) rtype = SGN; break; 350*3e12c5d1SDavid du Colombier case SLASH: 351*3e12c5d1SDavid du Colombier if (rv2==0) { 352*3e12c5d1SDavid du Colombier rtype = UND; 353*3e12c5d1SDavid du Colombier break; 354*3e12c5d1SDavid du Colombier } 355*3e12c5d1SDavid du Colombier if (rtype==UNS) 356*3e12c5d1SDavid du Colombier rv1 /= (unsigned long)rv2; 357*3e12c5d1SDavid du Colombier else 358*3e12c5d1SDavid du Colombier rv1 /= rv2; 359*3e12c5d1SDavid du Colombier break; 360*3e12c5d1SDavid du Colombier case PCT: 361*3e12c5d1SDavid du Colombier if (rv2==0) { 362*3e12c5d1SDavid du Colombier rtype = UND; 363*3e12c5d1SDavid du Colombier break; 364*3e12c5d1SDavid du Colombier } 365*3e12c5d1SDavid du Colombier if (rtype==UNS) 366*3e12c5d1SDavid du Colombier rv1 %= (unsigned long)rv2; 367*3e12c5d1SDavid du Colombier else 368*3e12c5d1SDavid du Colombier rv1 %= rv2; 369*3e12c5d1SDavid du Colombier break; 370*3e12c5d1SDavid du Colombier case COLON: 371*3e12c5d1SDavid du Colombier if (op[-1] != QUEST) 372*3e12c5d1SDavid du Colombier error(ERROR, "Bad ?: in #if/endif"); 373*3e12c5d1SDavid du Colombier else { 374*3e12c5d1SDavid du Colombier op--; 375*3e12c5d1SDavid du Colombier if ((--vp)->val==0) 376*3e12c5d1SDavid du Colombier v1 = v2; 377*3e12c5d1SDavid du Colombier rtype = v1.type; 378*3e12c5d1SDavid du Colombier rv1 = v1.val; 379*3e12c5d1SDavid du Colombier } 380*3e12c5d1SDavid du Colombier break; 381*3e12c5d1SDavid du Colombier case DEFINED: 382*3e12c5d1SDavid du Colombier break; 383*3e12c5d1SDavid du Colombier default: 384*3e12c5d1SDavid du Colombier error(ERROR, "Eval botch (unknown operator)"); 385*3e12c5d1SDavid du Colombier return 1; 386*3e12c5d1SDavid du Colombier } 387*3e12c5d1SDavid du Colombier v1.val = rv1; 388*3e12c5d1SDavid du Colombier v1.type = rtype; 389*3e12c5d1SDavid du Colombier *vp++ = v1; 390*3e12c5d1SDavid du Colombier } 391*3e12c5d1SDavid du Colombier return 0; 392*3e12c5d1SDavid du Colombier } 393*3e12c5d1SDavid du Colombier 394*3e12c5d1SDavid du Colombier struct value 395*3e12c5d1SDavid du Colombier tokval(Token *tp) 396*3e12c5d1SDavid du Colombier { 397*3e12c5d1SDavid du Colombier struct value v; 398*3e12c5d1SDavid du Colombier Nlist *np; 399*3e12c5d1SDavid du Colombier int i, base, c, longcc; 400*3e12c5d1SDavid du Colombier unsigned long n; 401*3e12c5d1SDavid du Colombier Rune r; 402*3e12c5d1SDavid du Colombier uchar *p; 403*3e12c5d1SDavid du Colombier 404*3e12c5d1SDavid du Colombier v.type = SGN; 405*3e12c5d1SDavid du Colombier v.val = 0; 406*3e12c5d1SDavid du Colombier switch (tp->type) { 407*3e12c5d1SDavid du Colombier 408*3e12c5d1SDavid du Colombier case NAME: 409*3e12c5d1SDavid du Colombier v.val = 0; 410*3e12c5d1SDavid du Colombier break; 411*3e12c5d1SDavid du Colombier 412*3e12c5d1SDavid du Colombier case NAME1: 413*3e12c5d1SDavid du Colombier if ((np = lookup(tp, 0)) && np->flag&ISDEFINED) 414*3e12c5d1SDavid du Colombier v.val = 1; 415*3e12c5d1SDavid du Colombier break; 416*3e12c5d1SDavid du Colombier 417*3e12c5d1SDavid du Colombier case NUMBER: 418*3e12c5d1SDavid du Colombier n = 0; 419*3e12c5d1SDavid du Colombier base = 10; 420*3e12c5d1SDavid du Colombier p = tp->t; 421*3e12c5d1SDavid du Colombier c = p[tp->len]; 422*3e12c5d1SDavid du Colombier p[tp->len] = '\0'; 423*3e12c5d1SDavid du Colombier if (*p=='0') { 424*3e12c5d1SDavid du Colombier base = 8; 425*3e12c5d1SDavid du Colombier if (p[1]=='x' || p[1]=='X') { 426*3e12c5d1SDavid du Colombier base = 16; 427*3e12c5d1SDavid du Colombier p++; 428*3e12c5d1SDavid du Colombier } 429*3e12c5d1SDavid du Colombier p++; 430*3e12c5d1SDavid du Colombier } 431*3e12c5d1SDavid du Colombier for (;; p++) { 432*3e12c5d1SDavid du Colombier if ((i = digit(*p)) < 0) 433*3e12c5d1SDavid du Colombier break; 434*3e12c5d1SDavid du Colombier if (i>=base) 435*3e12c5d1SDavid du Colombier error(WARNING, 436*3e12c5d1SDavid du Colombier "Bad digit in number %t", tp); 437*3e12c5d1SDavid du Colombier n *= base; 438*3e12c5d1SDavid du Colombier n += i; 439*3e12c5d1SDavid du Colombier } 440*3e12c5d1SDavid du Colombier if (n>=0x80000000 && base!=10) 441*3e12c5d1SDavid du Colombier v.type = UNS; 442*3e12c5d1SDavid du Colombier for (; *p; p++) { 443*3e12c5d1SDavid du Colombier if (*p=='u' || *p=='U') 444*3e12c5d1SDavid du Colombier v.type = UNS; 445*3e12c5d1SDavid du Colombier else if (*p=='l' || *p=='L') 446*3e12c5d1SDavid du Colombier ; 447*3e12c5d1SDavid du Colombier else { 448*3e12c5d1SDavid du Colombier error(ERROR, 449*3e12c5d1SDavid du Colombier "Bad number %t in #if/#elsif", tp); 450*3e12c5d1SDavid du Colombier break; 451*3e12c5d1SDavid du Colombier } 452*3e12c5d1SDavid du Colombier } 453*3e12c5d1SDavid du Colombier v.val = n; 454*3e12c5d1SDavid du Colombier tp->t[tp->len] = c; 455*3e12c5d1SDavid du Colombier break; 456*3e12c5d1SDavid du Colombier 457*3e12c5d1SDavid du Colombier case CCON: 458*3e12c5d1SDavid du Colombier n = 0; 459*3e12c5d1SDavid du Colombier p = tp->t; 460*3e12c5d1SDavid du Colombier longcc = 0; 461*3e12c5d1SDavid du Colombier if (*p=='L') { 462*3e12c5d1SDavid du Colombier p += 1; 463*3e12c5d1SDavid du Colombier longcc = 1; 464*3e12c5d1SDavid du Colombier } 465*3e12c5d1SDavid du Colombier p += 1; 466*3e12c5d1SDavid du Colombier if (*p=='\\') { 467*3e12c5d1SDavid du Colombier p += 1; 468*3e12c5d1SDavid du Colombier if ((i = digit(*p))>=0 && i<=7) { 469*3e12c5d1SDavid du Colombier n = i; 470*3e12c5d1SDavid du Colombier p += 1; 471*3e12c5d1SDavid du Colombier if ((i = digit(*p))>=0 && i<=7) { 472*3e12c5d1SDavid du Colombier p += 1; 473*3e12c5d1SDavid du Colombier n <<= 3; 474*3e12c5d1SDavid du Colombier n += i; 475*3e12c5d1SDavid du Colombier if ((i = digit(*p))>=0 && i<=7) { 476*3e12c5d1SDavid du Colombier p += 1; 477*3e12c5d1SDavid du Colombier n <<= 3; 478*3e12c5d1SDavid du Colombier n += i; 479*3e12c5d1SDavid du Colombier } 480*3e12c5d1SDavid du Colombier } 481*3e12c5d1SDavid du Colombier } else if (*p=='x') { 482*3e12c5d1SDavid du Colombier p += 1; 483*3e12c5d1SDavid du Colombier while ((i = digit(*p))>=0 && i<=15) { 484*3e12c5d1SDavid du Colombier p += 1; 485*3e12c5d1SDavid du Colombier n <<= 4; 486*3e12c5d1SDavid du Colombier n += i; 487*3e12c5d1SDavid du Colombier } 488*3e12c5d1SDavid du Colombier } else { 489*3e12c5d1SDavid du Colombier static char cvcon[] 490*3e12c5d1SDavid du Colombier = "a\ab\bf\fn\nr\rt\tv\v''\"\"??\\\\"; 491*3e12c5d1SDavid du Colombier for (i=0; i<sizeof(cvcon); i+=2) { 492*3e12c5d1SDavid du Colombier if (*p == cvcon[i]) { 493*3e12c5d1SDavid du Colombier n = cvcon[i+1]; 494*3e12c5d1SDavid du Colombier break; 495*3e12c5d1SDavid du Colombier } 496*3e12c5d1SDavid du Colombier } 497*3e12c5d1SDavid du Colombier p += 1; 498*3e12c5d1SDavid du Colombier if (i>=sizeof(cvcon)) 499*3e12c5d1SDavid du Colombier error(WARNING, 500*3e12c5d1SDavid du Colombier "Undefined escape in character constant"); 501*3e12c5d1SDavid du Colombier } 502*3e12c5d1SDavid du Colombier } else if (*p=='\'') 503*3e12c5d1SDavid du Colombier error(ERROR, "Empty character constant"); 504*3e12c5d1SDavid du Colombier else { 505*3e12c5d1SDavid du Colombier i = chartorune(&r, (char*)p); 506*3e12c5d1SDavid du Colombier n = r; 507*3e12c5d1SDavid du Colombier p += i; 508*3e12c5d1SDavid du Colombier if (i>1 && longcc==0) 509*3e12c5d1SDavid du Colombier error(WARNING, "Undefined character constant"); 510*3e12c5d1SDavid du Colombier } 511*3e12c5d1SDavid du Colombier if (*p!='\'') 512*3e12c5d1SDavid du Colombier error(WARNING, "Multibyte character constant undefined"); 513*3e12c5d1SDavid du Colombier else if (n>127 && longcc==0) 514*3e12c5d1SDavid du Colombier error(WARNING, "Character constant taken as not signed"); 515*3e12c5d1SDavid du Colombier v.val = n; 516*3e12c5d1SDavid du Colombier break; 517*3e12c5d1SDavid du Colombier 518*3e12c5d1SDavid du Colombier case STRING: 519*3e12c5d1SDavid du Colombier error(ERROR, "String in #if/#elsif"); 520*3e12c5d1SDavid du Colombier break; 521*3e12c5d1SDavid du Colombier } 522*3e12c5d1SDavid du Colombier return v; 523*3e12c5d1SDavid du Colombier } 524*3e12c5d1SDavid du Colombier 525*3e12c5d1SDavid du Colombier int 526*3e12c5d1SDavid du Colombier digit(int i) 527*3e12c5d1SDavid du Colombier { 528*3e12c5d1SDavid du Colombier if ('0'<=i && i<='9') 529*3e12c5d1SDavid du Colombier i -= '0'; 530*3e12c5d1SDavid du Colombier else if ('a'<=i && i<='f') 531*3e12c5d1SDavid du Colombier i -= 'a'-10; 532*3e12c5d1SDavid du Colombier else if ('A'<=i && i<='F') 533*3e12c5d1SDavid du Colombier i -= 'A'-10; 534*3e12c5d1SDavid du Colombier else 535*3e12c5d1SDavid du Colombier i = -1; 536*3e12c5d1SDavid du Colombier return i; 537*3e12c5d1SDavid du Colombier } 538