|
|
1.1 ! root 1: /* Parse C expressions for CCCP. ! 2: Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation. ! 3: ! 4: This program is free software; you can redistribute it and/or modify it ! 5: under the terms of the GNU General Public License as published by the ! 6: Free Software Foundation; either version 2, or (at your option) any ! 7: later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 12: GNU General Public License for more details. ! 13: ! 14: You should have received a copy of the GNU General Public License ! 15: along with this program; if not, write to the Free Software ! 16: Foundation, 59 Temple Place - Suite 330, ! 17: Boston, MA 02111-1307, USA. ! 18: ! 19: In other words, you are welcome to use, share and improve this program. ! 20: You are forbidden to forbid anyone else to use, share and improve ! 21: what you give them. Help stamp out software-hoarding! ! 22: ! 23: Written by Per Bothner 1994. */ ! 24: ! 25: /* Parse a C expression from text in a string */ ! 26: ! 27: #include "config.h" ! 28: #include "cpplib.h" ! 29: ! 30: extern char *xmalloc PARAMS ((unsigned)); ! 31: extern char *xrealloc PARAMS ((char *, unsigned)); ! 32: ! 33: #ifdef MULTIBYTE_CHARS ! 34: #include <stdlib.h> ! 35: #include <locale.h> ! 36: #endif ! 37: ! 38: #include <stdio.h> ! 39: ! 40: /* This is used for communicating lists of keywords with cccp.c. */ ! 41: struct arglist { ! 42: struct arglist *next; ! 43: U_CHAR *name; ! 44: int length; ! 45: int argno; ! 46: }; ! 47: ! 48: /* Define a generic NULL if one hasn't already been defined. */ ! 49: ! 50: #ifndef NULL ! 51: #define NULL 0 ! 52: #endif ! 53: ! 54: #ifndef GENERIC_PTR ! 55: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) ! 56: #define GENERIC_PTR void * ! 57: #else ! 58: #define GENERIC_PTR char * ! 59: #endif ! 60: #endif ! 61: ! 62: #ifndef NULL_PTR ! 63: #define NULL_PTR ((GENERIC_PTR)0) ! 64: #endif ! 65: ! 66: extern char *xmalloc (); ! 67: ! 68: #ifndef CHAR_TYPE_SIZE ! 69: #define CHAR_TYPE_SIZE BITS_PER_UNIT ! 70: #endif ! 71: ! 72: #ifndef INT_TYPE_SIZE ! 73: #define INT_TYPE_SIZE BITS_PER_WORD ! 74: #endif ! 75: ! 76: #ifndef LONG_TYPE_SIZE ! 77: #define LONG_TYPE_SIZE BITS_PER_WORD ! 78: #endif ! 79: ! 80: #ifndef WCHAR_TYPE_SIZE ! 81: #define WCHAR_TYPE_SIZE INT_TYPE_SIZE ! 82: #endif ! 83: ! 84: #ifndef MAX_CHAR_TYPE_SIZE ! 85: #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE ! 86: #endif ! 87: ! 88: #ifndef MAX_INT_TYPE_SIZE ! 89: #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE ! 90: #endif ! 91: ! 92: #ifndef MAX_LONG_TYPE_SIZE ! 93: #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE ! 94: #endif ! 95: ! 96: #ifndef MAX_WCHAR_TYPE_SIZE ! 97: #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE ! 98: #endif ! 99: ! 100: /* Yield nonzero if adding two numbers with A's and B's signs can yield a ! 101: number with SUM's sign, where A, B, and SUM are all C integers. */ ! 102: #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) ! 103: ! 104: static void integer_overflow (); ! 105: static long left_shift (); ! 106: static long right_shift (); ! 107: ! 108: #define ERROR 299 ! 109: #define OROR 300 ! 110: #define ANDAND 301 ! 111: #define EQUAL 302 ! 112: #define NOTEQUAL 303 ! 113: #define LEQ 304 ! 114: #define GEQ 305 ! 115: #define LSH 306 ! 116: #define RSH 307 ! 117: #define NAME 308 ! 118: #define INT 309 ! 119: #define CHAR 310 ! 120: ! 121: #define LEFT_OPERAND_REQUIRED 1 ! 122: #define RIGHT_OPERAND_REQUIRED 2 ! 123: #define HAVE_VALUE 4 ! 124: /*#define UNSIGNEDP 8*/ ! 125: ! 126: #ifndef HOST_BITS_PER_WIDE_INT ! 127: ! 128: #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT ! 129: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG ! 130: #define HOST_WIDE_INT long ! 131: #else ! 132: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT ! 133: #define HOST_WIDE_INT int ! 134: #endif ! 135: ! 136: #endif ! 137: ! 138: struct operation { ! 139: short op; ! 140: char rprio; /* Priority of op (relative to it right operand). */ ! 141: char flags; ! 142: char unsignedp; /* true if value should be treated as unsigned */ ! 143: HOST_WIDE_INT value; /* The value logically "right" of op. */ ! 144: }; ! 145: ! 146: /* Take care of parsing a number (anything that starts with a digit). ! 147: LEN is the number of characters in it. */ ! 148: ! 149: /* maybe needs to actually deal with floating point numbers */ ! 150: ! 151: struct operation ! 152: parse_number (pfile, start, olen) ! 153: cpp_reader *pfile; ! 154: char *start; ! 155: int olen; ! 156: { ! 157: struct operation op; ! 158: register char *p = start; ! 159: register int c; ! 160: register unsigned long n = 0, nd, ULONG_MAX_over_base; ! 161: register int base = 10; ! 162: register int len = olen; ! 163: register int overflow = 0; ! 164: register int digit, largest_digit = 0; ! 165: int spec_long = 0; ! 166: ! 167: op.unsignedp = 0; ! 168: ! 169: for (c = 0; c < len; c++) ! 170: if (p[c] == '.') { ! 171: /* It's a float since it contains a point. */ ! 172: cpp_error (pfile, ! 173: "floating point numbers not allowed in #if expressions"); ! 174: op.op = ERROR; ! 175: return op; ! 176: } ! 177: ! 178: if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) { ! 179: p += 2; ! 180: base = 16; ! 181: len -= 2; ! 182: } ! 183: else if (*p == '0') ! 184: base = 8; ! 185: ! 186: /* Some buggy compilers (e.g. MPW C) seem to need both casts. */ ! 187: ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base); ! 188: ! 189: for (; len > 0; len--) { ! 190: c = *p++; ! 191: ! 192: if (c >= '0' && c <= '9') ! 193: digit = c - '0'; ! 194: else if (base == 16 && c >= 'a' && c <= 'f') ! 195: digit = c - 'a' + 10; ! 196: else if (base == 16 && c >= 'A' && c <= 'F') ! 197: digit = c - 'A' + 10; ! 198: else { ! 199: /* `l' means long, and `u' means unsigned. */ ! 200: while (1) { ! 201: if (c == 'l' || c == 'L') ! 202: { ! 203: if (spec_long) ! 204: cpp_error (pfile, "two `l's in integer constant"); ! 205: spec_long = 1; ! 206: } ! 207: else if (c == 'u' || c == 'U') ! 208: { ! 209: if (op.unsignedp) ! 210: cpp_error (pfile, "two `u's in integer constant"); ! 211: op.unsignedp = 1; ! 212: } ! 213: else ! 214: break; ! 215: ! 216: if (--len == 0) ! 217: break; ! 218: c = *p++; ! 219: } ! 220: /* Don't look for any more digits after the suffixes. */ ! 221: break; ! 222: } ! 223: if (largest_digit < digit) ! 224: largest_digit = digit; ! 225: nd = n * base + digit; ! 226: overflow |= ULONG_MAX_over_base < n | nd < n; ! 227: n = nd; ! 228: } ! 229: ! 230: if (len != 0) ! 231: { ! 232: cpp_error (pfile, "Invalid number in #if expression"); ! 233: op.op = ERROR; ! 234: return op; ! 235: } ! 236: ! 237: if (base <= largest_digit) ! 238: cpp_warning (pfile, "integer constant contains digits beyond the radix"); ! 239: ! 240: if (overflow) ! 241: cpp_warning (pfile, "integer constant out of range"); ! 242: ! 243: /* If too big to be signed, consider it unsigned. */ ! 244: if ((long) n < 0 && ! op.unsignedp) ! 245: { ! 246: if (base == 10) ! 247: cpp_warning (pfile, "integer constant is so large that it is unsigned"); ! 248: op.unsignedp = 1; ! 249: } ! 250: ! 251: op.value = n; ! 252: op.op = INT; ! 253: return op; ! 254: } ! 255: ! 256: struct token { ! 257: char *operator; ! 258: int token; ! 259: }; ! 260: ! 261: static struct token tokentab2[] = { ! 262: {"&&", ANDAND}, ! 263: {"||", OROR}, ! 264: {"<<", LSH}, ! 265: {">>", RSH}, ! 266: {"==", EQUAL}, ! 267: {"!=", NOTEQUAL}, ! 268: {"<=", LEQ}, ! 269: {">=", GEQ}, ! 270: {"++", ERROR}, ! 271: {"--", ERROR}, ! 272: {NULL, ERROR} ! 273: }; ! 274: ! 275: /* Read one token. */ ! 276: ! 277: struct operation ! 278: cpp_lex (pfile) ! 279: cpp_reader *pfile; ! 280: { ! 281: register int c; ! 282: register int namelen; ! 283: register struct token *toktab; ! 284: enum cpp_token token; ! 285: struct operation op; ! 286: U_CHAR *tok_start, *tok_end; ! 287: int old_written; ! 288: ! 289: retry: ! 290: ! 291: old_written = CPP_WRITTEN (pfile); ! 292: cpp_skip_hspace (pfile); ! 293: c = CPP_BUF_PEEK (CPP_BUFFER (pfile)); ! 294: if (c == '#') ! 295: return parse_number (pfile, ! 296: cpp_read_check_assertion (pfile) ? "1" : "0", 1); ! 297: ! 298: if (c == '\n') ! 299: { ! 300: op.op = 0; ! 301: return op; ! 302: } ! 303: ! 304: token = cpp_get_token (pfile); ! 305: tok_start = pfile->token_buffer + old_written; ! 306: tok_end = CPP_PWRITTEN (pfile); ! 307: pfile->limit = tok_start; ! 308: switch (token) ! 309: { ! 310: case CPP_EOF: /* Should not happen ... */ ! 311: op.op = 0; ! 312: return op; ! 313: case CPP_VSPACE: ! 314: case CPP_POP: ! 315: if (CPP_BUFFER (pfile)->fname != NULL) ! 316: { ! 317: op.op = 0; ! 318: return op; ! 319: } ! 320: goto retry; ! 321: case CPP_HSPACE: case CPP_COMMENT: ! 322: goto retry; ! 323: case CPP_NUMBER: ! 324: return parse_number (pfile, tok_start, tok_end - tok_start); ! 325: case CPP_STRING: ! 326: cpp_error (pfile, "string constants not allowed in #if expressions"); ! 327: op.op = ERROR; ! 328: return op; ! 329: case CPP_CHAR: ! 330: /* This code for reading a character constant ! 331: handles multicharacter constants and wide characters. ! 332: It is mostly copied from c-lex.c. */ ! 333: { ! 334: register int result = 0; ! 335: register num_chars = 0; ! 336: unsigned width = MAX_CHAR_TYPE_SIZE; ! 337: int wide_flag = 0; ! 338: int max_chars; ! 339: U_CHAR *ptr = tok_start; ! 340: #ifdef MULTIBYTE_CHARS ! 341: char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX]; ! 342: #else ! 343: char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1]; ! 344: #endif ! 345: ! 346: if (*ptr == 'L') ! 347: { ! 348: ptr++; ! 349: wide_flag = 1; ! 350: width = MAX_WCHAR_TYPE_SIZE; ! 351: #ifdef MULTIBYTE_CHARS ! 352: max_chars = MB_CUR_MAX; ! 353: #else ! 354: max_chars = 1; ! 355: #endif ! 356: } ! 357: else ! 358: max_chars = MAX_LONG_TYPE_SIZE / width; ! 359: ! 360: ++ptr; ! 361: while (ptr < tok_end && ((c = *ptr++) != '\'')) ! 362: { ! 363: if (c == '\\') ! 364: { ! 365: c = cpp_parse_escape (pfile, &ptr); ! 366: if (width < HOST_BITS_PER_INT ! 367: && (unsigned) c >= (1 << width)) ! 368: cpp_pedwarn (pfile, ! 369: "escape sequence out of range for character"); ! 370: } ! 371: ! 372: num_chars++; ! 373: ! 374: /* Merge character into result; ignore excess chars. */ ! 375: if (num_chars < max_chars + 1) ! 376: { ! 377: if (width < HOST_BITS_PER_INT) ! 378: result = (result << width) | (c & ((1 << width) - 1)); ! 379: else ! 380: result = c; ! 381: token_buffer[num_chars - 1] = c; ! 382: } ! 383: } ! 384: ! 385: token_buffer[num_chars] = 0; ! 386: ! 387: if (c != '\'') ! 388: cpp_error (pfile, "malformatted character constant"); ! 389: else if (num_chars == 0) ! 390: cpp_error (pfile, "empty character constant"); ! 391: else if (num_chars > max_chars) ! 392: { ! 393: num_chars = max_chars; ! 394: cpp_error (pfile, "character constant too long"); ! 395: } ! 396: else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile)) ! 397: cpp_warning (pfile, "multi-character character constant"); ! 398: ! 399: /* If char type is signed, sign-extend the constant. */ ! 400: if (! wide_flag) ! 401: { ! 402: int num_bits = num_chars * width; ! 403: ! 404: if (cpp_lookup (pfile, "__CHAR_UNSIGNED__", ! 405: sizeof ("__CHAR_UNSIGNED__")-1, -1) ! 406: || ((result >> (num_bits - 1)) & 1) == 0) ! 407: op.value ! 408: = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); ! 409: else ! 410: op.value ! 411: = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); ! 412: } ! 413: else ! 414: { ! 415: #ifdef MULTIBYTE_CHARS ! 416: /* Set the initial shift state and convert the next sequence. */ ! 417: result = 0; ! 418: /* In all locales L'\0' is zero and mbtowc will return zero, ! 419: so don't use it. */ ! 420: if (num_chars > 1 ! 421: || (num_chars == 1 && token_buffer[0] != '\0')) ! 422: { ! 423: wchar_t wc; ! 424: (void) mbtowc (NULL_PTR, NULL_PTR, 0); ! 425: if (mbtowc (& wc, token_buffer, num_chars) == num_chars) ! 426: result = wc; ! 427: else ! 428: cpp_warning (pfile,"Ignoring invalid multibyte character"); ! 429: } ! 430: #endif ! 431: op.value = result; ! 432: } ! 433: } ! 434: ! 435: /* This is always a signed type. */ ! 436: op.unsignedp = 0; ! 437: op.op = CHAR; ! 438: ! 439: return op; ! 440: ! 441: case CPP_NAME: ! 442: return parse_number (pfile, "0", 0); ! 443: ! 444: case CPP_OTHER: ! 445: /* See if it is a special token of length 2. */ ! 446: if (tok_start + 2 == tok_end) ! 447: { ! 448: for (toktab = tokentab2; toktab->operator != NULL; toktab++) ! 449: if (tok_start[0] == toktab->operator[0] ! 450: && tok_start[1] == toktab->operator[1]) ! 451: break; ! 452: if (toktab->token == ERROR) ! 453: { ! 454: char *buf = (char *) alloca (40); ! 455: sprintf (buf, "`%s' not allowed in operand of `#if'", tok_start); ! 456: cpp_error (pfile, buf); ! 457: } ! 458: op.op = toktab->token; ! 459: return op; ! 460: } ! 461: /* fall through */ ! 462: default: ! 463: op.op = *tok_start; ! 464: return op; ! 465: } ! 466: } ! 467: ! 468: ! 469: /* Parse a C escape sequence. STRING_PTR points to a variable ! 470: containing a pointer to the string to parse. That pointer ! 471: is updated past the characters we use. The value of the ! 472: escape sequence is returned. ! 473: ! 474: A negative value means the sequence \ newline was seen, ! 475: which is supposed to be equivalent to nothing at all. ! 476: ! 477: If \ is followed by a null character, we return a negative ! 478: value and leave the string pointer pointing at the null character. ! 479: ! 480: If \ is followed by 000, we return 0 and leave the string pointer ! 481: after the zeros. A value of 0 does not mean end of string. */ ! 482: ! 483: int ! 484: cpp_parse_escape (pfile, string_ptr) ! 485: cpp_reader *pfile; ! 486: char **string_ptr; ! 487: { ! 488: register int c = *(*string_ptr)++; ! 489: switch (c) ! 490: { ! 491: case 'a': ! 492: return TARGET_BELL; ! 493: case 'b': ! 494: return TARGET_BS; ! 495: case 'e': ! 496: case 'E': ! 497: if (CPP_PEDANTIC (pfile)) ! 498: cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c); ! 499: return 033; ! 500: case 'f': ! 501: return TARGET_FF; ! 502: case 'n': ! 503: return TARGET_NEWLINE; ! 504: case 'r': ! 505: return TARGET_CR; ! 506: case 't': ! 507: return TARGET_TAB; ! 508: case 'v': ! 509: return TARGET_VT; ! 510: case '\n': ! 511: return -2; ! 512: case 0: ! 513: (*string_ptr)--; ! 514: return 0; ! 515: ! 516: case '0': ! 517: case '1': ! 518: case '2': ! 519: case '3': ! 520: case '4': ! 521: case '5': ! 522: case '6': ! 523: case '7': ! 524: { ! 525: register int i = c - '0'; ! 526: register int count = 0; ! 527: while (++count < 3) ! 528: { ! 529: c = *(*string_ptr)++; ! 530: if (c >= '0' && c <= '7') ! 531: i = (i << 3) + c - '0'; ! 532: else ! 533: { ! 534: (*string_ptr)--; ! 535: break; ! 536: } ! 537: } ! 538: if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) ! 539: { ! 540: i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; ! 541: cpp_warning (pfile, ! 542: "octal character constant does not fit in a byte"); ! 543: } ! 544: return i; ! 545: } ! 546: case 'x': ! 547: { ! 548: register unsigned i = 0, overflow = 0, digits_found = 0, digit; ! 549: for (;;) ! 550: { ! 551: c = *(*string_ptr)++; ! 552: if (c >= '0' && c <= '9') ! 553: digit = c - '0'; ! 554: else if (c >= 'a' && c <= 'f') ! 555: digit = c - 'a' + 10; ! 556: else if (c >= 'A' && c <= 'F') ! 557: digit = c - 'A' + 10; ! 558: else ! 559: { ! 560: (*string_ptr)--; ! 561: break; ! 562: } ! 563: overflow |= i ^ (i << 4 >> 4); ! 564: i = (i << 4) + digit; ! 565: digits_found = 1; ! 566: } ! 567: if (!digits_found) ! 568: cpp_error (pfile, "\\x used with no following hex digits"); ! 569: if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) ! 570: { ! 571: i &= (1 << BITS_PER_UNIT) - 1; ! 572: cpp_warning (pfile, ! 573: "hex character constant does not fit in a byte"); ! 574: } ! 575: return i; ! 576: } ! 577: default: ! 578: return c; ! 579: } ! 580: } ! 581: ! 582: static void ! 583: integer_overflow (pfile) ! 584: cpp_reader *pfile; ! 585: { ! 586: if (CPP_PEDANTIC (pfile)) ! 587: cpp_pedwarn (pfile, "integer overflow in preprocessor expression"); ! 588: } ! 589: ! 590: static long ! 591: left_shift (pfile, a, unsignedp, b) ! 592: cpp_reader *pfile; ! 593: long a; ! 594: int unsignedp; ! 595: unsigned long b; ! 596: { ! 597: if (b >= HOST_BITS_PER_LONG) ! 598: { ! 599: if (! unsignedp && a != 0) ! 600: integer_overflow (pfile); ! 601: return 0; ! 602: } ! 603: else if (unsignedp) ! 604: return (unsigned long) a << b; ! 605: else ! 606: { ! 607: long l = a << b; ! 608: if (l >> b != a) ! 609: integer_overflow (pfile); ! 610: return l; ! 611: } ! 612: } ! 613: ! 614: static long ! 615: right_shift (pfile, a, unsignedp, b) ! 616: cpp_reader *pfile; ! 617: long a; ! 618: int unsignedp; ! 619: unsigned long b; ! 620: { ! 621: if (b >= HOST_BITS_PER_LONG) ! 622: return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1); ! 623: else if (unsignedp) ! 624: return (unsigned long) a >> b; ! 625: else ! 626: return a >> b; ! 627: } ! 628: ! 629: /* These priorities are all even, so we can handle associatively. */ ! 630: #define PAREN_INNER_PRIO 0 ! 631: #define COMMA_PRIO 4 ! 632: #define COND_PRIO (COMMA_PRIO+2) ! 633: #define OROR_PRIO (COND_PRIO+2) ! 634: #define ANDAND_PRIO (OROR_PRIO+2) ! 635: #define OR_PRIO (ANDAND_PRIO+2) ! 636: #define XOR_PRIO (OR_PRIO+2) ! 637: #define AND_PRIO (XOR_PRIO+2) ! 638: #define EQUAL_PRIO (AND_PRIO+2) ! 639: #define LESS_PRIO (EQUAL_PRIO+2) ! 640: #define SHIFT_PRIO (LESS_PRIO+2) ! 641: #define PLUS_PRIO (SHIFT_PRIO+2) ! 642: #define MUL_PRIO (PLUS_PRIO+2) ! 643: #define UNARY_PRIO (MUL_PRIO+2) ! 644: #define PAREN_OUTER_PRIO (UNARY_PRIO+2) ! 645: ! 646: #define COMPARE(OP) \ ! 647: top->unsignedp = 0;\ ! 648: top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP v2 : (v1 OP v2) ! 649: ! 650: /* Parse and evaluate a C expression, reading from PFILE. ! 651: Returns the value of the expression. */ ! 652: ! 653: HOST_WIDE_INT ! 654: cpp_parse_expr (pfile) ! 655: cpp_reader *pfile; ! 656: { ! 657: /* The implementation is an operator precedence parser, ! 658: i.e. a bottom-up parser, using a stack for not-yet-reduced tokens. ! 659: ! 660: The stack base is 'stack', and the current stack pointer is 'top'. ! 661: There is a stack element for each operator (only), ! 662: and the most recently pushed operator is 'top->op'. ! 663: An operand (value) is stored in the 'value' field of the stack ! 664: element of the operator that precedes it. ! 665: In that case the 'flags' field has the HAVE_VALUE flag set. */ ! 666: ! 667: #define INIT_STACK_SIZE 20 ! 668: struct operation init_stack[INIT_STACK_SIZE]; ! 669: struct operation *stack = init_stack; ! 670: struct operation *limit = stack + INIT_STACK_SIZE; ! 671: register struct operation *top = stack; ! 672: int lprio, rprio; ! 673: ! 674: top->rprio = 0; ! 675: top->flags = 0; ! 676: for (;;) ! 677: { ! 678: struct operation op; ! 679: char flags = 0; ! 680: ! 681: /* Read a token */ ! 682: op = cpp_lex (pfile); ! 683: ! 684: /* See if the token is an operand, in which case go to set_value. ! 685: If the token is an operator, figure out its left and right ! 686: priorities, and then goto maybe_reduce. */ ! 687: ! 688: switch (op.op) ! 689: { ! 690: case NAME: ! 691: top->value = 0, top->unsignedp = 0; ! 692: goto set_value; ! 693: case INT: case CHAR: ! 694: top->value = op.value; ! 695: top->unsignedp = op.unsignedp; ! 696: goto set_value; ! 697: case 0: ! 698: lprio = 0; goto maybe_reduce; ! 699: case '+': case '-': ! 700: /* Is this correct if unary ? FIXME */ ! 701: flags = RIGHT_OPERAND_REQUIRED; ! 702: lprio = PLUS_PRIO; rprio = lprio + 1; goto maybe_reduce; ! 703: case '!': case '~': ! 704: flags = RIGHT_OPERAND_REQUIRED; ! 705: rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce; ! 706: case '*': case '/': case '%': ! 707: lprio = MUL_PRIO; goto binop; ! 708: case '<': case '>': case LEQ: case GEQ: ! 709: lprio = LESS_PRIO; goto binop; ! 710: case EQUAL: case NOTEQUAL: ! 711: lprio = EQUAL_PRIO; goto binop; ! 712: case LSH: case RSH: ! 713: lprio = SHIFT_PRIO; goto binop; ! 714: case '&': lprio = AND_PRIO; goto binop; ! 715: case '^': lprio = XOR_PRIO; goto binop; ! 716: case '|': lprio = OR_PRIO; goto binop; ! 717: case ANDAND: lprio = ANDAND_PRIO; goto binop; ! 718: case OROR: lprio = OROR_PRIO; goto binop; ! 719: case ',': ! 720: lprio = COMMA_PRIO; goto binop; ! 721: case '(': ! 722: lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO; ! 723: goto maybe_reduce; ! 724: case ')': ! 725: lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO; ! 726: goto maybe_reduce; ! 727: case ':': ! 728: lprio = COND_PRIO; rprio = COND_PRIO; ! 729: goto maybe_reduce; ! 730: case '?': ! 731: lprio = COND_PRIO + 1; rprio = COND_PRIO; ! 732: goto maybe_reduce; ! 733: binop: ! 734: flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED; ! 735: rprio = lprio + 1; ! 736: goto maybe_reduce; ! 737: default: ! 738: cpp_error (pfile, "invalid character in #if"); ! 739: goto syntax_error; ! 740: } ! 741: ! 742: set_value: ! 743: /* Push a value onto the stack. */ ! 744: if (top->flags & HAVE_VALUE) ! 745: { ! 746: cpp_error (pfile, "syntax error in #if"); ! 747: goto syntax_error; ! 748: } ! 749: top->flags |= HAVE_VALUE; ! 750: continue; ! 751: ! 752: maybe_reduce: ! 753: /* Push an operator, and check if we can reduce now. */ ! 754: while (top->rprio > lprio) ! 755: { ! 756: long v1 = top[-1].value, v2 = top[0].value; ! 757: int unsigned1 = top[-1].unsignedp, unsigned2 = top[0].unsignedp; ! 758: top--; ! 759: if ((top[1].flags & LEFT_OPERAND_REQUIRED) ! 760: && ! (top[0].flags & HAVE_VALUE)) ! 761: { ! 762: cpp_error (pfile, "syntax error - missing left operand"); ! 763: goto syntax_error; ! 764: } ! 765: if ((top[1].flags & RIGHT_OPERAND_REQUIRED) ! 766: && ! (top[1].flags & HAVE_VALUE)) ! 767: { ! 768: cpp_error (pfile, "syntax error - missing right operand"); ! 769: goto syntax_error; ! 770: } ! 771: /* top[0].value = (top[1].op)(v1, v2);*/ ! 772: switch (top[1].op) ! 773: { ! 774: case '+': ! 775: if (!(top->flags & HAVE_VALUE)) ! 776: { /* Unary '+' */ ! 777: top->value = v2; ! 778: top->unsignedp = unsigned2; ! 779: top->flags |= HAVE_VALUE; ! 780: } ! 781: else ! 782: { ! 783: top->value = v1 + v2; ! 784: top->unsignedp = unsigned1 || unsigned2; ! 785: if (! top->unsignedp ! 786: && ! possible_sum_sign (v1, v2, top->value)) ! 787: integer_overflow (pfile); ! 788: } ! 789: break; ! 790: case '-': ! 791: if (!(top->flags & HAVE_VALUE)) ! 792: { /* Unary '-' */ ! 793: top->value = - v2; ! 794: if ((top->value & v2) < 0 && ! unsigned2) ! 795: integer_overflow (pfile); ! 796: top->unsignedp = unsigned2; ! 797: top->flags |= HAVE_VALUE; ! 798: } ! 799: else ! 800: { /* Binary '-' */ ! 801: top->value = v1 - v2; ! 802: top->unsignedp = unsigned1 || unsigned2; ! 803: if (! top->unsignedp ! 804: && ! possible_sum_sign (top->value, v2, v1)) ! 805: integer_overflow (pfile); ! 806: } ! 807: break; ! 808: case '*': ! 809: top->unsignedp = unsigned1 || unsigned2; ! 810: if (top->unsignedp) ! 811: top->value = (unsigned long) v1 * v2; ! 812: else ! 813: { ! 814: top->value = v1 * v2; ! 815: if (v1 ! 816: && (top->value / v1 != v2 ! 817: || (top->value & v1 & v2) < 0)) ! 818: integer_overflow (pfile); ! 819: } ! 820: break; ! 821: case '/': ! 822: if (v2 == 0) ! 823: { ! 824: cpp_error (pfile, "division by zero in #if"); ! 825: v2 = 1; ! 826: } ! 827: top->unsignedp = unsigned1 || unsigned2; ! 828: if (top->unsignedp) ! 829: top->value = (unsigned long) v1 / v2; ! 830: else ! 831: { ! 832: top->value = v1 / v2; ! 833: if ((top->value & v1 & v2) < 0) ! 834: integer_overflow (pfile); ! 835: } ! 836: break; ! 837: case '%': ! 838: if (v2 == 0) ! 839: { ! 840: cpp_error (pfile, "division by zero in #if"); ! 841: v2 = 1; ! 842: } ! 843: top->unsignedp = unsigned1 || unsigned2; ! 844: if (top->unsignedp) ! 845: top->value = (unsigned long) v1 % v2; ! 846: else ! 847: top->value = v1 % v2; ! 848: break; ! 849: case '!': ! 850: if (top->flags & HAVE_VALUE) ! 851: { ! 852: cpp_error (pfile, "syntax error"); ! 853: goto syntax_error; ! 854: } ! 855: top->value = ! v2; ! 856: top->unsignedp = 0; ! 857: top->flags |= HAVE_VALUE; ! 858: break; ! 859: case '~': ! 860: if (top->flags & HAVE_VALUE) ! 861: { ! 862: cpp_error (pfile, "syntax error"); ! 863: goto syntax_error; ! 864: } ! 865: top->value = ~ v2; ! 866: top->unsignedp = unsigned2; ! 867: top->flags |= HAVE_VALUE; ! 868: break; ! 869: case '<': COMPARE(<); break; ! 870: case '>': COMPARE(>); break; ! 871: case LEQ: COMPARE(<=); break; ! 872: case GEQ: COMPARE(>=); break; ! 873: case EQUAL: ! 874: top->value = (v1 == v2); ! 875: top->unsignedp = 0; ! 876: break; ! 877: case NOTEQUAL: ! 878: top->value = (v1 != v2); ! 879: top->unsignedp = 0; ! 880: break; ! 881: case LSH: ! 882: top->unsignedp = unsigned1; ! 883: if (v2 < 0 && ! unsigned2) ! 884: top->value = right_shift (pfile, v1, unsigned1, -v2); ! 885: else ! 886: top->value = left_shift (pfile, v1, unsigned1, v2); ! 887: break; ! 888: case RSH: ! 889: top->unsignedp = unsigned1; ! 890: if (v2 < 0 && ! unsigned2) ! 891: top->value = left_shift (pfile, v1, unsigned1, -v2); ! 892: else ! 893: top->value = right_shift (pfile, v1, unsigned1, v2); ! 894: break; ! 895: #define LOGICAL(OP) \ ! 896: top->value = v1 OP v2;\ ! 897: top->unsignedp = unsigned1 || unsigned2; ! 898: case '&': LOGICAL(&); break; ! 899: case '^': LOGICAL(^); break; ! 900: case '|': LOGICAL(|); break; ! 901: case ANDAND: ! 902: top->value = v1 && v2; top->unsignedp = 0; break; ! 903: case OROR: ! 904: top->value = v1 || v2; top->unsignedp = 0; break; ! 905: case ',': ! 906: if (CPP_PEDANTIC (pfile)) ! 907: cpp_pedwarn (pfile, "comma operator in operand of `#if'"); ! 908: top->value = v2; ! 909: top->unsignedp = unsigned2; ! 910: break; ! 911: case '(': case '?': ! 912: cpp_error (pfile, "syntax error in #if"); ! 913: goto syntax_error; ! 914: case ':': ! 915: if (top[0].op != '?') ! 916: { ! 917: cpp_error (pfile, ! 918: "syntax error ':' without preceding '?'"); ! 919: goto syntax_error; ! 920: } ! 921: else if (! (top[1].flags & HAVE_VALUE) ! 922: || !(top[-1].flags & HAVE_VALUE) ! 923: || !(top[0].flags & HAVE_VALUE)) ! 924: { ! 925: cpp_error (pfile, "bad syntax for ?: operator"); ! 926: goto syntax_error; ! 927: } ! 928: else ! 929: { ! 930: top--; ! 931: top->value = top->value ? v1 : v2; ! 932: top->unsignedp = unsigned1 || unsigned2; ! 933: } ! 934: break; ! 935: case ')': ! 936: if ((top[1].flags & HAVE_VALUE) ! 937: || ! (top[0].flags & HAVE_VALUE) ! 938: || top[0].op != '(' ! 939: || (top[-1].flags & HAVE_VALUE)) ! 940: { ! 941: cpp_error (pfile, "mismatched parentheses in #if"); ! 942: goto syntax_error; ! 943: } ! 944: else ! 945: { ! 946: top--; ! 947: top->value = v1; ! 948: top->unsignedp = unsigned1; ! 949: top->flags |= HAVE_VALUE; ! 950: } ! 951: break; ! 952: default: ! 953: fprintf (stderr, ! 954: top[1].op >= ' ' && top[1].op <= '~' ! 955: ? "unimplemented operator '%c'\n" ! 956: : "unimplemented operator '\\%03o'\n", ! 957: top[1].op); ! 958: } ! 959: } ! 960: if (op.op == 0) ! 961: { ! 962: if (top != stack) ! 963: cpp_error (pfile, "internal error in #if expression"); ! 964: if (stack != init_stack) ! 965: free (stack); ! 966: return top->value; ! 967: } ! 968: top++; ! 969: ! 970: /* Check for and handle stack overflow. */ ! 971: if (top == limit) ! 972: { ! 973: struct operation *new_stack; ! 974: int old_size = (char*)limit - (char*)stack; ! 975: int new_size = 2 * old_size; ! 976: if (stack != init_stack) ! 977: new_stack = (struct operation*) xrealloc (stack, new_size); ! 978: else ! 979: { ! 980: new_stack = (struct operation*) xmalloc (new_size); ! 981: bcopy ((char *) stack, (char *) new_stack, old_size); ! 982: } ! 983: stack = new_stack; ! 984: top = (struct operation*)((char*) new_stack + old_size); ! 985: limit = (struct operation*)((char*) new_stack + new_size); ! 986: } ! 987: ! 988: top->flags = flags; ! 989: top->rprio = rprio; ! 990: top->op = op.op; ! 991: } ! 992: syntax_error: ! 993: if (stack != init_stack) ! 994: free (stack); ! 995: skip_rest_of_line (pfile); ! 996: return 0; ! 997: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.