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