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