1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #include <stdio.h> 29*cdf0e10cSrcweir #include <ctype.h> 30*cdf0e10cSrcweir #include "cppdef.h" 31*cdf0e10cSrcweir #include "cpp.h" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir /* 34*cdf0e10cSrcweir * Evaluate an #if expression. 35*cdf0e10cSrcweir */ 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir static char *opname[] = { /* For debug and error messages */ 38*cdf0e10cSrcweir "end of expression", "val", "id", 39*cdf0e10cSrcweir "+", "-", "*", "/", "%", 40*cdf0e10cSrcweir "<<", ">>", "&", "|", "^", 41*cdf0e10cSrcweir "==", "!=", "<", "<=", ">=", ">", 42*cdf0e10cSrcweir "&&", "||", "?", ":", ",", 43*cdf0e10cSrcweir "unary +", "unary -", "~", "!", "(", ")", "(none)", 44*cdf0e10cSrcweir }; 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir /* 47*cdf0e10cSrcweir * opdope[] has the operator precedence: 48*cdf0e10cSrcweir * Bits 49*cdf0e10cSrcweir * 7 Unused (so the value is always positive) 50*cdf0e10cSrcweir * 6-2 Precedence (000x .. 017x) 51*cdf0e10cSrcweir * 1-0 Binary op. flags: 52*cdf0e10cSrcweir * 01 The binop flag should be set/cleared when this op is seen. 53*cdf0e10cSrcweir * 10 The new value of the binop flag. 54*cdf0e10cSrcweir * Note: Expected, New binop 55*cdf0e10cSrcweir * constant 0 1 Binop, end, or ) should follow constants 56*cdf0e10cSrcweir * End of line 1 0 End may not be preceeded by an operator 57*cdf0e10cSrcweir * binary 1 0 Binary op follows a value, value follows. 58*cdf0e10cSrcweir * unary 0 0 Unary op doesn't follow a value, value follows 59*cdf0e10cSrcweir * ( 0 0 Doesn't follow value, value or unop follows 60*cdf0e10cSrcweir * ) 1 1 Follows value. Op follows. 61*cdf0e10cSrcweir */ 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir static char opdope[OP_MAX] = { 64*cdf0e10cSrcweir 0001, /* End of expression */ 65*cdf0e10cSrcweir 0002, /* Digit */ 66*cdf0e10cSrcweir 0000, /* Letter (identifier) */ 67*cdf0e10cSrcweir 0141, 0141, 0151, 0151, 0151, /* ADD, SUB, MUL, DIV, MOD */ 68*cdf0e10cSrcweir 0131, 0131, 0101, 0071, 0071, /* ASL, ASR, AND, OR, XOR */ 69*cdf0e10cSrcweir 0111, 0111, 0121, 0121, 0121, 0121, /* EQ, NE, LT, LE, GE, GT */ 70*cdf0e10cSrcweir 0061, 0051, 0041, 0041, 0031, /* ANA, ORO, QUE, COL, CMA */ 71*cdf0e10cSrcweir /* 72*cdf0e10cSrcweir * Unary op's follow 73*cdf0e10cSrcweir */ 74*cdf0e10cSrcweir 0160, 0160, 0160, 0160, /* NEG, PLU, COM, NOT */ 75*cdf0e10cSrcweir 0170, 0013, 0023, /* LPA, RPA, END */ 76*cdf0e10cSrcweir }; 77*cdf0e10cSrcweir /* 78*cdf0e10cSrcweir * OP_QUE and OP_RPA have alternate precedences: 79*cdf0e10cSrcweir */ 80*cdf0e10cSrcweir #define OP_RPA_PREC 0013 81*cdf0e10cSrcweir #define OP_QUE_PREC 0034 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir /* 84*cdf0e10cSrcweir * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that 85*cdf0e10cSrcweir * #if FOO != 0 && 10 / FOO ... 86*cdf0e10cSrcweir * doesn't generate an error message. They are stored in optab.skip. 87*cdf0e10cSrcweir */ 88*cdf0e10cSrcweir #define S_ANDOR 2 89*cdf0e10cSrcweir #define S_QUEST 1 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir typedef struct optab { 92*cdf0e10cSrcweir char op; /* Operator */ 93*cdf0e10cSrcweir char prec; /* Its precedence */ 94*cdf0e10cSrcweir char skip; /* Short-circuit: TRUE to skip */ 95*cdf0e10cSrcweir } OPTAB; 96*cdf0e10cSrcweir static int evalue; /* Current value from evallex() */ 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir #ifdef nomacargs 99*cdf0e10cSrcweir FILE_LOCAL int 100*cdf0e10cSrcweir isbinary(op) 101*cdf0e10cSrcweir register int op; 102*cdf0e10cSrcweir { 103*cdf0e10cSrcweir return (op >= FIRST_BINOP && op <= LAST_BINOP); 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir FILE_LOCAL int 107*cdf0e10cSrcweir isunary(op) 108*cdf0e10cSrcweir register int op; 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir return (op >= FIRST_UNOP && op <= LAST_UNOP); 111*cdf0e10cSrcweir } 112*cdf0e10cSrcweir #else 113*cdf0e10cSrcweir #define isbinary(op) (op >= FIRST_BINOP && op <= LAST_BINOP) 114*cdf0e10cSrcweir #define isunary(op) (op >= FIRST_UNOP && op <= LAST_UNOP) 115*cdf0e10cSrcweir #endif 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir /* 118*cdf0e10cSrcweir * The following definitions are used to specify basic variable sizes. 119*cdf0e10cSrcweir */ 120*cdf0e10cSrcweir 121*cdf0e10cSrcweir #ifndef S_CHAR 122*cdf0e10cSrcweir #define S_CHAR (sizeof (char)) 123*cdf0e10cSrcweir #endif 124*cdf0e10cSrcweir #ifndef S_SINT 125*cdf0e10cSrcweir #define S_SINT (sizeof (short int)) 126*cdf0e10cSrcweir #endif 127*cdf0e10cSrcweir #ifndef S_INT 128*cdf0e10cSrcweir #define S_INT (sizeof (int)) 129*cdf0e10cSrcweir #endif 130*cdf0e10cSrcweir #ifndef S_LINT 131*cdf0e10cSrcweir #define S_LINT (sizeof (long int)) 132*cdf0e10cSrcweir #endif 133*cdf0e10cSrcweir #ifndef S_FLOAT 134*cdf0e10cSrcweir #define S_FLOAT (sizeof (float)) 135*cdf0e10cSrcweir #endif 136*cdf0e10cSrcweir #ifndef S_DOUBLE 137*cdf0e10cSrcweir #define S_DOUBLE (sizeof (double)) 138*cdf0e10cSrcweir #endif 139*cdf0e10cSrcweir #ifndef S_PCHAR 140*cdf0e10cSrcweir #define S_PCHAR (sizeof (char *)) 141*cdf0e10cSrcweir #endif 142*cdf0e10cSrcweir #ifndef S_PSINT 143*cdf0e10cSrcweir #define S_PSINT (sizeof (short int *)) 144*cdf0e10cSrcweir #endif 145*cdf0e10cSrcweir #ifndef S_PINT 146*cdf0e10cSrcweir #define S_PINT (sizeof (int *)) 147*cdf0e10cSrcweir #endif 148*cdf0e10cSrcweir #ifndef S_PLINT 149*cdf0e10cSrcweir #define S_PLINT (sizeof (long int *)) 150*cdf0e10cSrcweir #endif 151*cdf0e10cSrcweir #ifndef S_PFLOAT 152*cdf0e10cSrcweir #define S_PFLOAT (sizeof (float *)) 153*cdf0e10cSrcweir #endif 154*cdf0e10cSrcweir #ifndef S_PDOUBLE 155*cdf0e10cSrcweir #define S_PDOUBLE (sizeof (double *)) 156*cdf0e10cSrcweir #endif 157*cdf0e10cSrcweir #ifndef S_PFPTR 158*cdf0e10cSrcweir #define S_PFPTR (sizeof (int (*)())) 159*cdf0e10cSrcweir #endif 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir typedef struct types { 162*cdf0e10cSrcweir short type; /* This is the bit if */ 163*cdf0e10cSrcweir char *name; /* this is the token word */ 164*cdf0e10cSrcweir } TYPES; 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir static TYPES basic_types[] = { 167*cdf0e10cSrcweir { T_CHAR, "char", }, 168*cdf0e10cSrcweir { T_INT, "int", }, 169*cdf0e10cSrcweir { T_FLOAT, "float", }, 170*cdf0e10cSrcweir { T_DOUBLE, "double", }, 171*cdf0e10cSrcweir { T_SHORT, "short", }, 172*cdf0e10cSrcweir { T_LONG, "long", }, 173*cdf0e10cSrcweir { T_SIGNED, "signed", }, 174*cdf0e10cSrcweir { T_UNSIGNED, "unsigned", }, 175*cdf0e10cSrcweir { 0, NULL, }, /* Signal end */ 176*cdf0e10cSrcweir }; 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir /* 179*cdf0e10cSrcweir * Test_table[] is used to test for illegal combinations. 180*cdf0e10cSrcweir */ 181*cdf0e10cSrcweir static short test_table[] = { 182*cdf0e10cSrcweir T_FLOAT | T_DOUBLE | T_LONG | T_SHORT, 183*cdf0e10cSrcweir T_FLOAT | T_DOUBLE | T_CHAR | T_INT, 184*cdf0e10cSrcweir T_FLOAT | T_DOUBLE | T_SIGNED | T_UNSIGNED, 185*cdf0e10cSrcweir T_LONG | T_SHORT | T_CHAR, 186*cdf0e10cSrcweir 0 /* end marker */ 187*cdf0e10cSrcweir }; 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir /* 190*cdf0e10cSrcweir * The order of this table is important -- it is also referenced by 191*cdf0e10cSrcweir * the command line processor to allow run-time overriding of the 192*cdf0e10cSrcweir * built-in size values. The order must not be changed: 193*cdf0e10cSrcweir * char, short, int, long, float, double (func pointer) 194*cdf0e10cSrcweir */ 195*cdf0e10cSrcweir SIZES size_table[] = { 196*cdf0e10cSrcweir { T_CHAR, S_CHAR, S_PCHAR }, /* char */ 197*cdf0e10cSrcweir { T_SHORT, S_SINT, S_PSINT }, /* short int */ 198*cdf0e10cSrcweir { T_INT, S_INT, S_PINT }, /* int */ 199*cdf0e10cSrcweir { T_LONG, S_LINT, S_PLINT }, /* long */ 200*cdf0e10cSrcweir { T_FLOAT, S_FLOAT, S_PFLOAT }, /* float */ 201*cdf0e10cSrcweir { T_DOUBLE, S_DOUBLE, S_PDOUBLE }, /* double */ 202*cdf0e10cSrcweir { T_FPTR, 0, S_PFPTR }, /* int (*()) */ 203*cdf0e10cSrcweir { 0, 0, 0 }, /* End of table */ 204*cdf0e10cSrcweir }; 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir void InitCpp5() 208*cdf0e10cSrcweir { 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir int 215*cdf0e10cSrcweir eval() 216*cdf0e10cSrcweir /* 217*cdf0e10cSrcweir * Evaluate an expression. Straight-forward operator precedence. 218*cdf0e10cSrcweir * This is called from control() on encountering an #if statement. 219*cdf0e10cSrcweir * It calls the following routines: 220*cdf0e10cSrcweir * evallex Lexical analyser -- returns the type and value of 221*cdf0e10cSrcweir * the next input token. 222*cdf0e10cSrcweir * evaleval Evaluate the current operator, given the values on 223*cdf0e10cSrcweir * the value stack. Returns a pointer to the (new) 224*cdf0e10cSrcweir * value stack. 225*cdf0e10cSrcweir * For compatiblity with older cpp's, this return returns 1 (TRUE) 226*cdf0e10cSrcweir * if a syntax error is detected. 227*cdf0e10cSrcweir */ 228*cdf0e10cSrcweir { 229*cdf0e10cSrcweir register int op; /* Current operator */ 230*cdf0e10cSrcweir register int *valp; /* -> value vector */ 231*cdf0e10cSrcweir register OPTAB *opp; /* Operator stack */ 232*cdf0e10cSrcweir int prec; /* Op precedence */ 233*cdf0e10cSrcweir int binop; /* Set if binary op. needed */ 234*cdf0e10cSrcweir int op1; /* Operand from stack */ 235*cdf0e10cSrcweir int skip; /* For short-circuit testing */ 236*cdf0e10cSrcweir int value[NEXP]; /* Value stack */ 237*cdf0e10cSrcweir OPTAB opstack[NEXP]; /* Operand stack */ 238*cdf0e10cSrcweir #ifndef ZTC /* BP */ 239*cdf0e10cSrcweir extern int *evaleval(); /* Does actual evaluation */ 240*cdf0e10cSrcweir #endif 241*cdf0e10cSrcweir valp = value; 242*cdf0e10cSrcweir opp = opstack; 243*cdf0e10cSrcweir opp->op = OP_END; /* Mark bottom of stack */ 244*cdf0e10cSrcweir opp->prec = opdope[OP_END]; /* And its precedence */ 245*cdf0e10cSrcweir opp->skip = 0; /* Not skipping now */ 246*cdf0e10cSrcweir binop = 0; 247*cdf0e10cSrcweir again: ; 248*cdf0e10cSrcweir #ifdef DEBUG_EVAL 249*cdf0e10cSrcweir fprintf( pCppOut, "In #if at again: skip = %d, binop = %d, line is: %s", 250*cdf0e10cSrcweir opp->skip, binop, infile->bptr); 251*cdf0e10cSrcweir #endif 252*cdf0e10cSrcweir if ((op = evallex(opp->skip)) == OP_SUB && binop == 0) 253*cdf0e10cSrcweir op = OP_NEG; /* Unary minus */ 254*cdf0e10cSrcweir else if (op == OP_ADD && binop == 0) 255*cdf0e10cSrcweir op = OP_PLU; /* Unary plus */ 256*cdf0e10cSrcweir else if (op == OP_FAIL) 257*cdf0e10cSrcweir return (1); /* Error in evallex */ 258*cdf0e10cSrcweir #ifdef DEBUG_EVAL 259*cdf0e10cSrcweir fprintf( pCppOut, "op = %s, opdope = %03o, binop = %d, skip = %d\n", 260*cdf0e10cSrcweir opname[op], opdope[op], binop, opp->skip); 261*cdf0e10cSrcweir #endif 262*cdf0e10cSrcweir if (op == DIG) { /* Value? */ 263*cdf0e10cSrcweir if (binop != 0) { 264*cdf0e10cSrcweir cerror("misplaced constant in #if", NULLST); 265*cdf0e10cSrcweir return (1); 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir else if (valp >= &value[NEXP-1]) { 268*cdf0e10cSrcweir cerror("#if value stack overflow", NULLST); 269*cdf0e10cSrcweir return (1); 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir else { 272*cdf0e10cSrcweir #ifdef DEBUG_EVAL 273*cdf0e10cSrcweir fprintf( pCppOut, "pushing %d onto value stack[%d]\n", 274*cdf0e10cSrcweir evalue, valp - value); 275*cdf0e10cSrcweir #endif 276*cdf0e10cSrcweir *valp++ = evalue; 277*cdf0e10cSrcweir binop = 1; 278*cdf0e10cSrcweir } 279*cdf0e10cSrcweir goto again; 280*cdf0e10cSrcweir } 281*cdf0e10cSrcweir else if (op > OP_END) { 282*cdf0e10cSrcweir cerror("Illegal #if line", NULLST); 283*cdf0e10cSrcweir return (1); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir prec = opdope[op]; 286*cdf0e10cSrcweir if (binop != (prec & 1)) { 287*cdf0e10cSrcweir cerror("Operator %s in incorrect context", opname[op]); 288*cdf0e10cSrcweir return (1); 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir binop = (prec & 2) >> 1; 291*cdf0e10cSrcweir for (;;) { 292*cdf0e10cSrcweir #ifdef DEBUG_EVAL 293*cdf0e10cSrcweir fprintf( pCppOut, "op %s, prec %d., stacked op %s, prec %d, skip %d\n", 294*cdf0e10cSrcweir opname[op], prec, opname[opp->op], opp->prec, opp->skip); 295*cdf0e10cSrcweir #endif 296*cdf0e10cSrcweir if (prec > opp->prec) { 297*cdf0e10cSrcweir if (op == OP_LPA) 298*cdf0e10cSrcweir prec = OP_RPA_PREC; 299*cdf0e10cSrcweir else if (op == OP_QUE) 300*cdf0e10cSrcweir prec = OP_QUE_PREC; 301*cdf0e10cSrcweir op1 = opp->skip; /* Save skip for test */ 302*cdf0e10cSrcweir /* 303*cdf0e10cSrcweir * Push operator onto op. stack. 304*cdf0e10cSrcweir */ 305*cdf0e10cSrcweir opp++; 306*cdf0e10cSrcweir if (opp >= &opstack[NEXP]) { 307*cdf0e10cSrcweir cerror("expression stack overflow at op \"%s\"", 308*cdf0e10cSrcweir opname[op]); 309*cdf0e10cSrcweir return (1); 310*cdf0e10cSrcweir } 311*cdf0e10cSrcweir opp->op = (char)op; 312*cdf0e10cSrcweir opp->prec = (char)prec; 313*cdf0e10cSrcweir skip = (valp[-1] != 0); /* Short-circuit tester */ 314*cdf0e10cSrcweir /* 315*cdf0e10cSrcweir * Do the short-circuit stuff here. Short-circuiting 316*cdf0e10cSrcweir * stops automagically when operators are evaluated. 317*cdf0e10cSrcweir */ 318*cdf0e10cSrcweir if ((op == OP_ANA && !skip) 319*cdf0e10cSrcweir || (op == OP_ORO && skip)) 320*cdf0e10cSrcweir opp->skip = S_ANDOR; /* And/or skip starts */ 321*cdf0e10cSrcweir else if (op == OP_QUE) /* Start of ?: operator */ 322*cdf0e10cSrcweir opp->skip = (char)((op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0)); 323*cdf0e10cSrcweir else if (op == OP_COL) { /* : inverts S_QUEST */ 324*cdf0e10cSrcweir opp->skip = (char)((op1 & S_ANDOR) 325*cdf0e10cSrcweir | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST)); 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir else { /* Other ops leave */ 328*cdf0e10cSrcweir opp->skip = (char)op1; /* skipping unchanged. */ 329*cdf0e10cSrcweir } 330*cdf0e10cSrcweir #ifdef DEBUG_EVAL 331*cdf0e10cSrcweir fprintf( pCppOut, "stacking %s, valp[-1] == %d at %s", 332*cdf0e10cSrcweir opname[op], valp[-1], infile->bptr); 333*cdf0e10cSrcweir dumpstack(opstack, opp, value, valp); 334*cdf0e10cSrcweir #endif 335*cdf0e10cSrcweir goto again; 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir /* 338*cdf0e10cSrcweir * Pop operator from op. stack and evaluate it. 339*cdf0e10cSrcweir * End of stack and '(' are specials. 340*cdf0e10cSrcweir */ 341*cdf0e10cSrcweir skip = opp->skip; /* Remember skip value */ 342*cdf0e10cSrcweir switch ((op1 = opp->op)) { /* Look at stacked op */ 343*cdf0e10cSrcweir case OP_END: /* Stack end marker */ 344*cdf0e10cSrcweir if (op == OP_EOE) 345*cdf0e10cSrcweir return (valp[-1]); /* Finished ok. */ 346*cdf0e10cSrcweir goto again; /* Read another op. */ 347*cdf0e10cSrcweir 348*cdf0e10cSrcweir case OP_LPA: /* ( on stack */ 349*cdf0e10cSrcweir if (op != OP_RPA) { /* Matches ) on input */ 350*cdf0e10cSrcweir cerror("unbalanced paren's, op is \"%s\"", opname[op]); 351*cdf0e10cSrcweir return (1); 352*cdf0e10cSrcweir } 353*cdf0e10cSrcweir opp--; /* Unstack it */ 354*cdf0e10cSrcweir /* goto again; -- Fall through */ 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir case OP_QUE: 357*cdf0e10cSrcweir goto again; /* Evaluate true expr. */ 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir case OP_COL: /* : on stack. */ 360*cdf0e10cSrcweir opp--; /* Unstack : */ 361*cdf0e10cSrcweir if (opp->op != OP_QUE) { /* Matches ? on stack? */ 362*cdf0e10cSrcweir cerror("Misplaced '?' or ':', previous operator is %s", 363*cdf0e10cSrcweir opname[(int)opp->op]); 364*cdf0e10cSrcweir return (1); 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir /* 367*cdf0e10cSrcweir * Evaluate op1. 368*cdf0e10cSrcweir */ 369*cdf0e10cSrcweir default: /* Others: */ 370*cdf0e10cSrcweir opp--; /* Unstack the operator */ 371*cdf0e10cSrcweir #ifdef DEBUG_EVAL 372*cdf0e10cSrcweir fprintf( pCppOut, "Stack before evaluation of %s\n", opname[op1]); 373*cdf0e10cSrcweir dumpstack(opstack, opp, value, valp); 374*cdf0e10cSrcweir #endif 375*cdf0e10cSrcweir valp = evaleval(valp, op1, skip); 376*cdf0e10cSrcweir #ifdef DEBUG_EVAL 377*cdf0e10cSrcweir fprintf( pCppOut, "Stack after evaluation\n"); 378*cdf0e10cSrcweir dumpstack(opstack, opp, value, valp); 379*cdf0e10cSrcweir #endif 380*cdf0e10cSrcweir } /* op1 switch end */ 381*cdf0e10cSrcweir } /* Stack unwind loop */ 382*cdf0e10cSrcweir } 383*cdf0e10cSrcweir 384*cdf0e10cSrcweir FILE_LOCAL int 385*cdf0e10cSrcweir evallex(int skip) 386*cdf0e10cSrcweir /* 387*cdf0e10cSrcweir * Return next eval operator or value. Called from eval(). It 388*cdf0e10cSrcweir * calls a special-purpose routines for 'char' strings and 389*cdf0e10cSrcweir * numeric values: 390*cdf0e10cSrcweir * evalchar called to evaluate 'x' 391*cdf0e10cSrcweir * evalnum called to evaluate numbers. 392*cdf0e10cSrcweir */ 393*cdf0e10cSrcweir { 394*cdf0e10cSrcweir register int c, c1, t; 395*cdf0e10cSrcweir 396*cdf0e10cSrcweir again: do { /* Collect the token */ 397*cdf0e10cSrcweir c = skipws(); 398*cdf0e10cSrcweir if ((c = macroid(c)) == EOF_CHAR || c == '\n') { 399*cdf0e10cSrcweir unget(); 400*cdf0e10cSrcweir return (OP_EOE); /* End of expression */ 401*cdf0e10cSrcweir } 402*cdf0e10cSrcweir } while ((t = type[c]) == LET && catenate()); 403*cdf0e10cSrcweir if (t == INV) { /* Total nonsense */ 404*cdf0e10cSrcweir if (!skip) { 405*cdf0e10cSrcweir if (isascii(c) && isprint(c)) 406*cdf0e10cSrcweir cierror("illegal character '%c' in #if", c); 407*cdf0e10cSrcweir else 408*cdf0e10cSrcweir cierror("illegal character (%d decimal) in #if", c); 409*cdf0e10cSrcweir } 410*cdf0e10cSrcweir return (OP_FAIL); 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir else if (t == QUO) { /* ' or " */ 413*cdf0e10cSrcweir if (c == '\'') { /* Character constant */ 414*cdf0e10cSrcweir evalue = evalchar(skip); /* Somewhat messy */ 415*cdf0e10cSrcweir #ifdef DEBUG_EVAL 416*cdf0e10cSrcweir fprintf( pCppOut, "evalchar returns %d.\n", evalue); 417*cdf0e10cSrcweir #endif 418*cdf0e10cSrcweir return (DIG); /* Return a value */ 419*cdf0e10cSrcweir } 420*cdf0e10cSrcweir cerror("Can't use a string in an #if", NULLST); 421*cdf0e10cSrcweir return (OP_FAIL); 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir else if (t == LET) { /* ID must be a macro */ 424*cdf0e10cSrcweir if (streq(token, "defined")) { /* Or defined name */ 425*cdf0e10cSrcweir c1 = c = skipws(); 426*cdf0e10cSrcweir if (c == '(') /* Allow defined(name) */ 427*cdf0e10cSrcweir c = skipws(); 428*cdf0e10cSrcweir if (type[c] == LET) { 429*cdf0e10cSrcweir evalue = (lookid(c) != NULL); 430*cdf0e10cSrcweir if (c1 != '(' /* Need to balance */ 431*cdf0e10cSrcweir || skipws() == ')') /* Did we balance? */ 432*cdf0e10cSrcweir return (DIG); /* Parsed ok */ 433*cdf0e10cSrcweir } 434*cdf0e10cSrcweir cerror("Bad #if ... defined() syntax", NULLST); 435*cdf0e10cSrcweir return (OP_FAIL); 436*cdf0e10cSrcweir } 437*cdf0e10cSrcweir else if (streq(token, "sizeof")) /* New sizeof hackery */ 438*cdf0e10cSrcweir return (dosizeof()); /* Gets own routine */ 439*cdf0e10cSrcweir /* 440*cdf0e10cSrcweir * The Draft ANSI C Standard says that an undefined symbol 441*cdf0e10cSrcweir * in an #if has the value zero. We are a bit pickier, 442*cdf0e10cSrcweir * warning except where the programmer was careful to write 443*cdf0e10cSrcweir * #if defined(foo) ? foo : 0 444*cdf0e10cSrcweir */ 445*cdf0e10cSrcweir #ifdef STRICT_UNDEF 446*cdf0e10cSrcweir if (!skip) 447*cdf0e10cSrcweir cwarn("undefined symbol \"%s\" in #if, 0 used", token); 448*cdf0e10cSrcweir #endif 449*cdf0e10cSrcweir evalue = 0; 450*cdf0e10cSrcweir return (DIG); 451*cdf0e10cSrcweir } 452*cdf0e10cSrcweir else if (t == DIG) { /* Numbers are harder */ 453*cdf0e10cSrcweir evalue = evalnum(c); 454*cdf0e10cSrcweir #ifdef DEBUG_EVAL 455*cdf0e10cSrcweir fprintf( pCppOut, "evalnum returns %d.\n", evalue); 456*cdf0e10cSrcweir #endif 457*cdf0e10cSrcweir } 458*cdf0e10cSrcweir else if (strchr("!=<>&|\\", c) != NULL) { 459*cdf0e10cSrcweir /* 460*cdf0e10cSrcweir * Process a possible multi-byte lexeme. 461*cdf0e10cSrcweir */ 462*cdf0e10cSrcweir c1 = cget(); /* Peek at next char */ 463*cdf0e10cSrcweir switch (c) { 464*cdf0e10cSrcweir case '!': 465*cdf0e10cSrcweir if (c1 == '=') 466*cdf0e10cSrcweir return (OP_NE); 467*cdf0e10cSrcweir break; 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir case '=': 470*cdf0e10cSrcweir if (c1 != '=') { /* Can't say a=b in #if */ 471*cdf0e10cSrcweir unget(); 472*cdf0e10cSrcweir cerror("= not allowed in #if", NULLST); 473*cdf0e10cSrcweir return (OP_FAIL); 474*cdf0e10cSrcweir } 475*cdf0e10cSrcweir return (OP_EQ); 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir case '>': 478*cdf0e10cSrcweir case '<': 479*cdf0e10cSrcweir if (c1 == c) 480*cdf0e10cSrcweir return ((c == '<') ? OP_ASL : OP_ASR); 481*cdf0e10cSrcweir else if (c1 == '=') 482*cdf0e10cSrcweir return ((c == '<') ? OP_LE : OP_GE); 483*cdf0e10cSrcweir break; 484*cdf0e10cSrcweir 485*cdf0e10cSrcweir case '|': 486*cdf0e10cSrcweir case '&': 487*cdf0e10cSrcweir if (c1 == c) 488*cdf0e10cSrcweir return ((c == '|') ? OP_ORO : OP_ANA); 489*cdf0e10cSrcweir break; 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir case '\\': 492*cdf0e10cSrcweir if (c1 == '\n') /* Multi-line if */ 493*cdf0e10cSrcweir goto again; 494*cdf0e10cSrcweir cerror("Unexpected \\ in #if", NULLST); 495*cdf0e10cSrcweir return (OP_FAIL); 496*cdf0e10cSrcweir } 497*cdf0e10cSrcweir unget(); 498*cdf0e10cSrcweir } 499*cdf0e10cSrcweir return (t); 500*cdf0e10cSrcweir } 501*cdf0e10cSrcweir 502*cdf0e10cSrcweir FILE_LOCAL int 503*cdf0e10cSrcweir dosizeof() 504*cdf0e10cSrcweir /* 505*cdf0e10cSrcweir * Process the sizeof (basic type) operation in an #if string. 506*cdf0e10cSrcweir * Sets evalue to the size and returns 507*cdf0e10cSrcweir * DIG success 508*cdf0e10cSrcweir * OP_FAIL bad parse or something. 509*cdf0e10cSrcweir */ 510*cdf0e10cSrcweir { 511*cdf0e10cSrcweir register int c; 512*cdf0e10cSrcweir register TYPES *tp; 513*cdf0e10cSrcweir register SIZES *sizp; 514*cdf0e10cSrcweir register short *testp; 515*cdf0e10cSrcweir short typecode; 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir if ((c = skipws()) != '(') 518*cdf0e10cSrcweir goto nogood; 519*cdf0e10cSrcweir /* 520*cdf0e10cSrcweir * Scan off the tokens. 521*cdf0e10cSrcweir */ 522*cdf0e10cSrcweir typecode = 0; 523*cdf0e10cSrcweir while (0 != (c = skipws())) { 524*cdf0e10cSrcweir if ((c = macroid(c)) == EOF_CHAR || c == '\n') 525*cdf0e10cSrcweir goto nogood; /* End of line is a bug */ 526*cdf0e10cSrcweir else if (c == '(') { /* thing (*)() func ptr */ 527*cdf0e10cSrcweir if (skipws() == '*' 528*cdf0e10cSrcweir && skipws() == ')') { /* We found (*) */ 529*cdf0e10cSrcweir if (skipws() != '(') /* Let () be optional */ 530*cdf0e10cSrcweir unget(); 531*cdf0e10cSrcweir else if (skipws() != ')') 532*cdf0e10cSrcweir goto nogood; 533*cdf0e10cSrcweir typecode |= T_FPTR; /* Function pointer */ 534*cdf0e10cSrcweir } 535*cdf0e10cSrcweir else { /* Junk is a bug */ 536*cdf0e10cSrcweir goto nogood; 537*cdf0e10cSrcweir } 538*cdf0e10cSrcweir } 539*cdf0e10cSrcweir else if (type[c] != LET) /* Exit if not a type */ 540*cdf0e10cSrcweir break; 541*cdf0e10cSrcweir else if (!catenate()) { /* Maybe combine tokens */ 542*cdf0e10cSrcweir /* 543*cdf0e10cSrcweir * Look for this unexpandable token in basic_types. 544*cdf0e10cSrcweir * The code accepts "int long" as well as "long int" 545*cdf0e10cSrcweir * which is a minor bug as bugs go (and one shared with 546*cdf0e10cSrcweir * a lot of C compilers). 547*cdf0e10cSrcweir */ 548*cdf0e10cSrcweir for (tp = basic_types; tp->name != NULLST; tp++) { 549*cdf0e10cSrcweir if (streq(token, tp->name)) 550*cdf0e10cSrcweir break; 551*cdf0e10cSrcweir } 552*cdf0e10cSrcweir if (tp->name == NULLST) { 553*cdf0e10cSrcweir cerror("#if sizeof, unknown type \"%s\"", token); 554*cdf0e10cSrcweir return (OP_FAIL); 555*cdf0e10cSrcweir } 556*cdf0e10cSrcweir typecode |= tp->type; /* Or in the type bit */ 557*cdf0e10cSrcweir } 558*cdf0e10cSrcweir } 559*cdf0e10cSrcweir /* 560*cdf0e10cSrcweir * We are at the end of the type scan. Chew off '*' if necessary. 561*cdf0e10cSrcweir */ 562*cdf0e10cSrcweir if (c == '*') { 563*cdf0e10cSrcweir typecode |= T_PTR; 564*cdf0e10cSrcweir c = skipws(); 565*cdf0e10cSrcweir } 566*cdf0e10cSrcweir if (c == ')') { /* Last syntax check */ 567*cdf0e10cSrcweir for (testp = test_table; *testp != 0; testp++) { 568*cdf0e10cSrcweir if (!bittest(typecode & *testp)) { 569*cdf0e10cSrcweir cerror("#if ... sizeof: illegal type combination", NULLST); 570*cdf0e10cSrcweir return (OP_FAIL); 571*cdf0e10cSrcweir } 572*cdf0e10cSrcweir } 573*cdf0e10cSrcweir /* 574*cdf0e10cSrcweir * We assume that all function pointers are the same size: 575*cdf0e10cSrcweir * sizeof (int (*)()) == sizeof (float (*)()) 576*cdf0e10cSrcweir * We assume that signed and unsigned don't change the size: 577*cdf0e10cSrcweir * sizeof (signed int) == (sizeof unsigned int) 578*cdf0e10cSrcweir */ 579*cdf0e10cSrcweir if ((typecode & T_FPTR) != 0) /* Function pointer */ 580*cdf0e10cSrcweir typecode = T_FPTR | T_PTR; 581*cdf0e10cSrcweir else { /* Var or var * datum */ 582*cdf0e10cSrcweir typecode &= ~(T_SIGNED | T_UNSIGNED); 583*cdf0e10cSrcweir if ((typecode & (T_SHORT | T_LONG)) != 0) 584*cdf0e10cSrcweir typecode &= ~T_INT; 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir if ((typecode & ~T_PTR) == 0) { 587*cdf0e10cSrcweir cerror("#if sizeof() error, no type specified", NULLST); 588*cdf0e10cSrcweir return (OP_FAIL); 589*cdf0e10cSrcweir } 590*cdf0e10cSrcweir /* 591*cdf0e10cSrcweir * Exactly one bit (and possibly T_PTR) may be set. 592*cdf0e10cSrcweir */ 593*cdf0e10cSrcweir for (sizp = size_table; sizp->bits != 0; sizp++) { 594*cdf0e10cSrcweir if ((typecode & ~T_PTR) == sizp->bits) { 595*cdf0e10cSrcweir evalue = ((typecode & T_PTR) != 0) 596*cdf0e10cSrcweir ? sizp->psize : sizp->size; 597*cdf0e10cSrcweir return (DIG); 598*cdf0e10cSrcweir } 599*cdf0e10cSrcweir } /* We shouldn't fail */ 600*cdf0e10cSrcweir cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode); 601*cdf0e10cSrcweir return (OP_FAIL); 602*cdf0e10cSrcweir } 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir nogood: unget(); 605*cdf0e10cSrcweir cerror("#if ... sizeof() syntax error", NULLST); 606*cdf0e10cSrcweir return (OP_FAIL); 607*cdf0e10cSrcweir } 608*cdf0e10cSrcweir 609*cdf0e10cSrcweir FILE_LOCAL int 610*cdf0e10cSrcweir bittest(int value) 611*cdf0e10cSrcweir /* 612*cdf0e10cSrcweir * TRUE if value is zero or exactly one bit is set in value. 613*cdf0e10cSrcweir */ 614*cdf0e10cSrcweir { 615*cdf0e10cSrcweir #if (4096 & ~(-4096)) == 0 616*cdf0e10cSrcweir return ((value & ~(-value)) == 0); 617*cdf0e10cSrcweir #else 618*cdf0e10cSrcweir /* 619*cdf0e10cSrcweir * Do it the hard way (for non 2's complement machines) 620*cdf0e10cSrcweir */ 621*cdf0e10cSrcweir return (value == 0 || value ^ (value - 1) == (value * 2 - 1)); 622*cdf0e10cSrcweir #endif 623*cdf0e10cSrcweir } 624*cdf0e10cSrcweir 625*cdf0e10cSrcweir FILE_LOCAL int 626*cdf0e10cSrcweir evalnum(int c) 627*cdf0e10cSrcweir /* 628*cdf0e10cSrcweir * Expand number for #if lexical analysis. Note: evalnum recognizes 629*cdf0e10cSrcweir * the unsigned suffix, but only returns a signed int value. 630*cdf0e10cSrcweir */ 631*cdf0e10cSrcweir { 632*cdf0e10cSrcweir register int value; 633*cdf0e10cSrcweir register int base; 634*cdf0e10cSrcweir register int c1; 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir if (c != '0') 637*cdf0e10cSrcweir base = 10; 638*cdf0e10cSrcweir else if ((c = cget()) == 'x' || c == 'X') { 639*cdf0e10cSrcweir base = 16; 640*cdf0e10cSrcweir c = cget(); 641*cdf0e10cSrcweir } 642*cdf0e10cSrcweir else base = 8; 643*cdf0e10cSrcweir value = 0; 644*cdf0e10cSrcweir for (;;) { 645*cdf0e10cSrcweir c1 = c; 646*cdf0e10cSrcweir if (isascii(c) && isupper(c1)) 647*cdf0e10cSrcweir c1 = tolower(c1); 648*cdf0e10cSrcweir #ifdef EBCDIC 649*cdf0e10cSrcweir if (c1 <= 'f') 650*cdf0e10cSrcweir #else 651*cdf0e10cSrcweir if (c1 >= 'a') 652*cdf0e10cSrcweir #endif 653*cdf0e10cSrcweir c1 -= ('a' - 10); 654*cdf0e10cSrcweir else c1 -= '0'; 655*cdf0e10cSrcweir if (c1 < 0 || c1 >= base) 656*cdf0e10cSrcweir break; 657*cdf0e10cSrcweir value *= base; 658*cdf0e10cSrcweir value += c1; 659*cdf0e10cSrcweir c = cget(); 660*cdf0e10cSrcweir } 661*cdf0e10cSrcweir if (c == 'u' || c == 'U') /* Unsigned nonsense */ 662*cdf0e10cSrcweir c = cget(); 663*cdf0e10cSrcweir unget(); 664*cdf0e10cSrcweir return (value); 665*cdf0e10cSrcweir } 666*cdf0e10cSrcweir 667*cdf0e10cSrcweir FILE_LOCAL int 668*cdf0e10cSrcweir evalchar(int skip) 669*cdf0e10cSrcweir /* 670*cdf0e10cSrcweir * Get a character constant 671*cdf0e10cSrcweir */ 672*cdf0e10cSrcweir { 673*cdf0e10cSrcweir register int c; 674*cdf0e10cSrcweir register int value; 675*cdf0e10cSrcweir register int count; 676*cdf0e10cSrcweir 677*cdf0e10cSrcweir instring = TRUE; 678*cdf0e10cSrcweir if ((c = cget()) == '\\') { 679*cdf0e10cSrcweir switch ((c = cget())) { 680*cdf0e10cSrcweir case 'a': /* New in Standard */ 681*cdf0e10cSrcweir #if ('a' == '\a' || '\a' == ALERT) 682*cdf0e10cSrcweir value = ALERT; /* Use predefined value */ 683*cdf0e10cSrcweir #else 684*cdf0e10cSrcweir value = '\a'; /* Use compiler's value */ 685*cdf0e10cSrcweir #endif 686*cdf0e10cSrcweir break; 687*cdf0e10cSrcweir 688*cdf0e10cSrcweir case 'b': 689*cdf0e10cSrcweir value = '\b'; 690*cdf0e10cSrcweir break; 691*cdf0e10cSrcweir 692*cdf0e10cSrcweir case 'f': 693*cdf0e10cSrcweir value = '\f'; 694*cdf0e10cSrcweir break; 695*cdf0e10cSrcweir 696*cdf0e10cSrcweir case 'n': 697*cdf0e10cSrcweir value = '\n'; 698*cdf0e10cSrcweir break; 699*cdf0e10cSrcweir 700*cdf0e10cSrcweir case 'r': 701*cdf0e10cSrcweir value = '\r'; 702*cdf0e10cSrcweir break; 703*cdf0e10cSrcweir 704*cdf0e10cSrcweir case 't': 705*cdf0e10cSrcweir value = '\t'; 706*cdf0e10cSrcweir break; 707*cdf0e10cSrcweir 708*cdf0e10cSrcweir case 'v': /* New in Standard */ 709*cdf0e10cSrcweir #if ('v' == '\v' || '\v' == VT) 710*cdf0e10cSrcweir value = VT; /* Use predefined value */ 711*cdf0e10cSrcweir #else 712*cdf0e10cSrcweir value = '\v'; /* Use compiler's value */ 713*cdf0e10cSrcweir #endif 714*cdf0e10cSrcweir break; 715*cdf0e10cSrcweir 716*cdf0e10cSrcweir case 'x': /* '\xFF' */ 717*cdf0e10cSrcweir count = 3; 718*cdf0e10cSrcweir value = 0; 719*cdf0e10cSrcweir while ((((c = get()) >= '0' && c <= '9') 720*cdf0e10cSrcweir || (c >= 'a' && c <= 'f') 721*cdf0e10cSrcweir || (c >= 'A' && c <= 'F')) 722*cdf0e10cSrcweir && (--count >= 0)) { 723*cdf0e10cSrcweir value *= 16; 724*cdf0e10cSrcweir #ifdef EBCDIC 725*cdf0e10cSrcweir value += (c <= '9') ? (c - '0') : ((c & 0xF) + 9); 726*cdf0e10cSrcweir #else 727*cdf0e10cSrcweir value += (c >= '0') ? (c - '0') : ((c & 0xF) + 9); 728*cdf0e10cSrcweir #endif 729*cdf0e10cSrcweir } 730*cdf0e10cSrcweir unget(); 731*cdf0e10cSrcweir break; 732*cdf0e10cSrcweir 733*cdf0e10cSrcweir default: 734*cdf0e10cSrcweir if (c >= '0' && c <= '7') { 735*cdf0e10cSrcweir count = 3; 736*cdf0e10cSrcweir value = 0; 737*cdf0e10cSrcweir while (c >= '0' && c <= '7' && --count >= 0) { 738*cdf0e10cSrcweir value *= 8; 739*cdf0e10cSrcweir value += (c - '0'); 740*cdf0e10cSrcweir c = get(); 741*cdf0e10cSrcweir } 742*cdf0e10cSrcweir unget(); 743*cdf0e10cSrcweir } 744*cdf0e10cSrcweir else value = c; 745*cdf0e10cSrcweir break; 746*cdf0e10cSrcweir } 747*cdf0e10cSrcweir } 748*cdf0e10cSrcweir else if (c == '\'') 749*cdf0e10cSrcweir value = 0; 750*cdf0e10cSrcweir else value = c; 751*cdf0e10cSrcweir /* 752*cdf0e10cSrcweir * We warn on multi-byte constants and try to hack 753*cdf0e10cSrcweir * (big|little)endian machines. 754*cdf0e10cSrcweir */ 755*cdf0e10cSrcweir #if BIG_ENDIAN 756*cdf0e10cSrcweir count = 0; 757*cdf0e10cSrcweir #endif 758*cdf0e10cSrcweir while ((c = get()) != '\'' && c != EOF_CHAR && c != '\n') { 759*cdf0e10cSrcweir if (!skip) 760*cdf0e10cSrcweir ciwarn("multi-byte constant '%c' isn't portable", c); 761*cdf0e10cSrcweir #if BIG_ENDIAN 762*cdf0e10cSrcweir count += BITS_CHAR; 763*cdf0e10cSrcweir value += (c << count); 764*cdf0e10cSrcweir #else 765*cdf0e10cSrcweir value <<= BITS_CHAR; 766*cdf0e10cSrcweir value += c; 767*cdf0e10cSrcweir #endif 768*cdf0e10cSrcweir } 769*cdf0e10cSrcweir instring = FALSE; 770*cdf0e10cSrcweir return (value); 771*cdf0e10cSrcweir } 772*cdf0e10cSrcweir 773*cdf0e10cSrcweir FILE_LOCAL int * 774*cdf0e10cSrcweir evaleval(int* valp, int op, int skip) 775*cdf0e10cSrcweir /* 776*cdf0e10cSrcweir * Apply the argument operator to the data on the value stack. 777*cdf0e10cSrcweir * One or two values are popped from the value stack and the result 778*cdf0e10cSrcweir * is pushed onto the value stack. 779*cdf0e10cSrcweir * 780*cdf0e10cSrcweir * OP_COL is a special case. 781*cdf0e10cSrcweir * 782*cdf0e10cSrcweir * evaleval() returns the new pointer to the top of the value stack. 783*cdf0e10cSrcweir */ 784*cdf0e10cSrcweir { 785*cdf0e10cSrcweir register int v1, v2 = 0; 786*cdf0e10cSrcweir 787*cdf0e10cSrcweir if (isbinary(op)) 788*cdf0e10cSrcweir v2 = *--valp; 789*cdf0e10cSrcweir v1 = *--valp; 790*cdf0e10cSrcweir #ifdef DEBUG_EVAL 791*cdf0e10cSrcweir fprintf( pCppOut, "%s op %s", (isbinary(op)) ? "binary" : "unary", 792*cdf0e10cSrcweir opname[op]); 793*cdf0e10cSrcweir if (isbinary(op)) 794*cdf0e10cSrcweir fprintf( pCppOut, ", v2 = %d.", v2); 795*cdf0e10cSrcweir fprintf( pCppOut, ", v1 = %d.\n", v1); 796*cdf0e10cSrcweir #endif 797*cdf0e10cSrcweir switch (op) { 798*cdf0e10cSrcweir case OP_EOE: 799*cdf0e10cSrcweir break; 800*cdf0e10cSrcweir 801*cdf0e10cSrcweir case OP_ADD: 802*cdf0e10cSrcweir v1 += v2; 803*cdf0e10cSrcweir break; 804*cdf0e10cSrcweir 805*cdf0e10cSrcweir case OP_SUB: 806*cdf0e10cSrcweir v1 -= v2; 807*cdf0e10cSrcweir break; 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir case OP_MUL: 810*cdf0e10cSrcweir v1 *= v2; 811*cdf0e10cSrcweir break; 812*cdf0e10cSrcweir 813*cdf0e10cSrcweir case OP_DIV: 814*cdf0e10cSrcweir case OP_MOD: 815*cdf0e10cSrcweir if (v2 == 0) { 816*cdf0e10cSrcweir if (!skip) { 817*cdf0e10cSrcweir cwarn("%s by zero in #if, zero result assumed", 818*cdf0e10cSrcweir (op == OP_DIV) ? "divide" : "mod"); 819*cdf0e10cSrcweir } 820*cdf0e10cSrcweir v1 = 0; 821*cdf0e10cSrcweir } 822*cdf0e10cSrcweir else if (op == OP_DIV) 823*cdf0e10cSrcweir v1 /= v2; 824*cdf0e10cSrcweir else 825*cdf0e10cSrcweir v1 %= v2; 826*cdf0e10cSrcweir break; 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir case OP_ASL: 829*cdf0e10cSrcweir v1 <<= v2; 830*cdf0e10cSrcweir break; 831*cdf0e10cSrcweir 832*cdf0e10cSrcweir case OP_ASR: 833*cdf0e10cSrcweir v1 >>= v2; 834*cdf0e10cSrcweir break; 835*cdf0e10cSrcweir 836*cdf0e10cSrcweir case OP_AND: 837*cdf0e10cSrcweir v1 &= v2; 838*cdf0e10cSrcweir break; 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir case OP_OR: 841*cdf0e10cSrcweir v1 |= v2; 842*cdf0e10cSrcweir break; 843*cdf0e10cSrcweir 844*cdf0e10cSrcweir case OP_XOR: 845*cdf0e10cSrcweir v1 ^= v2; 846*cdf0e10cSrcweir break; 847*cdf0e10cSrcweir 848*cdf0e10cSrcweir case OP_EQ: 849*cdf0e10cSrcweir v1 = (v1 == v2); 850*cdf0e10cSrcweir break; 851*cdf0e10cSrcweir 852*cdf0e10cSrcweir case OP_NE: 853*cdf0e10cSrcweir v1 = (v1 != v2); 854*cdf0e10cSrcweir break; 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir case OP_LT: 857*cdf0e10cSrcweir v1 = (v1 < v2); 858*cdf0e10cSrcweir break; 859*cdf0e10cSrcweir 860*cdf0e10cSrcweir case OP_LE: 861*cdf0e10cSrcweir v1 = (v1 <= v2); 862*cdf0e10cSrcweir break; 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir case OP_GE: 865*cdf0e10cSrcweir v1 = (v1 >= v2); 866*cdf0e10cSrcweir break; 867*cdf0e10cSrcweir 868*cdf0e10cSrcweir case OP_GT: 869*cdf0e10cSrcweir v1 = (v1 > v2); 870*cdf0e10cSrcweir break; 871*cdf0e10cSrcweir 872*cdf0e10cSrcweir case OP_ANA: 873*cdf0e10cSrcweir v1 = (v1 && v2); 874*cdf0e10cSrcweir break; 875*cdf0e10cSrcweir 876*cdf0e10cSrcweir case OP_ORO: 877*cdf0e10cSrcweir v1 = (v1 || v2); 878*cdf0e10cSrcweir break; 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir case OP_COL: 881*cdf0e10cSrcweir /* 882*cdf0e10cSrcweir * v1 has the "true" value, v2 the "false" value. 883*cdf0e10cSrcweir * The top of the value stack has the test. 884*cdf0e10cSrcweir */ 885*cdf0e10cSrcweir v1 = (*--valp) ? v1 : v2; 886*cdf0e10cSrcweir break; 887*cdf0e10cSrcweir 888*cdf0e10cSrcweir case OP_NEG: 889*cdf0e10cSrcweir v1 = (-v1); 890*cdf0e10cSrcweir break; 891*cdf0e10cSrcweir 892*cdf0e10cSrcweir case OP_PLU: 893*cdf0e10cSrcweir break; 894*cdf0e10cSrcweir 895*cdf0e10cSrcweir case OP_COM: 896*cdf0e10cSrcweir v1 = ~v1; 897*cdf0e10cSrcweir break; 898*cdf0e10cSrcweir 899*cdf0e10cSrcweir case OP_NOT: 900*cdf0e10cSrcweir v1 = !v1; 901*cdf0e10cSrcweir break; 902*cdf0e10cSrcweir 903*cdf0e10cSrcweir default: 904*cdf0e10cSrcweir cierror("#if bug, operand = %d.", op); 905*cdf0e10cSrcweir v1 = 0; 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir *valp++ = v1; 908*cdf0e10cSrcweir return (valp); 909*cdf0e10cSrcweir } 910*cdf0e10cSrcweir 911*cdf0e10cSrcweir #ifdef DEBUG_EVAL 912*cdf0e10cSrcweir dumpstack(opstack, opp, value, valp) 913*cdf0e10cSrcweir OPTAB opstack[NEXP]; /* Operand stack */ 914*cdf0e10cSrcweir register OPTAB *opp; /* Operator stack */ 915*cdf0e10cSrcweir int value[NEXP]; /* Value stack */ 916*cdf0e10cSrcweir register int *valp; /* -> value vector */ 917*cdf0e10cSrcweir { 918*cdf0e10cSrcweir fprintf( pCppOut, "index op prec skip name -- op stack at %s", infile->bptr); 919*cdf0e10cSrcweir while (opp > opstack) { 920*cdf0e10cSrcweir fprintf( pCppOut, " [%2d] %2d %03o %d %s\n", opp - opstack, 921*cdf0e10cSrcweir opp->op, opp->prec, opp->skip, opname[opp->op]); 922*cdf0e10cSrcweir opp--; 923*cdf0e10cSrcweir } 924*cdf0e10cSrcweir while (--valp >= value) { 925*cdf0e10cSrcweir fprintf( pCppOut, "value[%d] = %d\n", (valp - value), *valp); 926*cdf0e10cSrcweir } 927*cdf0e10cSrcweir } 928*cdf0e10cSrcweir #endif 929*cdf0e10cSrcweir 930