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