|
|
1.1 root 1: /* Parse C expressions for CCCP. 1.1.1.6 ! root 2: Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation. 1.1 root 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 1.1.1.6 ! root 16: Foundation, 59 Temple Place - Suite 330, ! 17: Boston, MA 02111-1307, USA. 1.1 root 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: 1.1.1.2 root 23: Adapted from expread.y of GDB by Paul Rubin, July 1986. */ 1.1 root 24: 25: /* Parse a C expression from text in a string */ 26: 27: %{ 28: #include "config.h" 29: #include <setjmp.h> 30: /* #define YYDEBUG 1 */ 31: 32: #ifdef MULTIBYTE_CHARS 33: #include <stdlib.h> 34: #include <locale.h> 35: #endif 36: 1.1.1.2 root 37: #include <stdio.h> 38: 1.1 root 39: typedef unsigned char U_CHAR; 40: 41: /* This is used for communicating lists of keywords with cccp.c. */ 42: struct arglist { 43: struct arglist *next; 44: U_CHAR *name; 45: int length; 46: int argno; 47: }; 48: 1.1.1.2 root 49: /* Define a generic NULL if one hasn't already been defined. */ 50: 51: #ifndef NULL 52: #define NULL 0 53: #endif 54: 55: #ifndef GENERIC_PTR 56: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 57: #define GENERIC_PTR void * 58: #else 59: #define GENERIC_PTR char * 60: #endif 61: #endif 62: 1.1.1.5 root 63: /* Find the largest host integer type and set its size and type. */ 64: 65: #ifndef HOST_BITS_PER_WIDE_INT 66: 67: #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT 68: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG 69: #define HOST_WIDE_INT long 70: #else 71: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT 72: #define HOST_WIDE_INT int 73: #endif 74: 75: #endif 76: 1.1.1.2 root 77: #ifndef NULL_PTR 78: #define NULL_PTR ((GENERIC_PTR)0) 79: #endif 80: 1.1 root 81: int yylex (); 82: void yyerror (); 1.1.1.5 root 83: HOST_WIDE_INT expression_value; 1.1 root 84: 85: static jmp_buf parse_return_error; 86: 87: /* Nonzero means count most punctuation as part of a name. */ 88: static int keyword_parsing = 0; 89: 1.1.1.6 ! root 90: /* Nonzero means do not evaluate this expression. ! 91: This is a count, since unevaluated expressions can nest. */ ! 92: static int skip_evaluation; ! 93: 1.1 root 94: /* some external tables of character types */ 95: extern unsigned char is_idstart[], is_idchar[], is_hor_space[]; 96: 1.1.1.2 root 97: extern char *xmalloc (); 98: 1.1 root 99: /* Flag for -pedantic. */ 100: extern int pedantic; 101: 102: /* Flag for -traditional. */ 103: extern int traditional; 104: 105: #ifndef CHAR_TYPE_SIZE 106: #define CHAR_TYPE_SIZE BITS_PER_UNIT 107: #endif 108: 109: #ifndef INT_TYPE_SIZE 110: #define INT_TYPE_SIZE BITS_PER_WORD 111: #endif 112: 113: #ifndef LONG_TYPE_SIZE 114: #define LONG_TYPE_SIZE BITS_PER_WORD 115: #endif 116: 117: #ifndef WCHAR_TYPE_SIZE 118: #define WCHAR_TYPE_SIZE INT_TYPE_SIZE 119: #endif 1.1.1.2 root 120: 1.1.1.4 root 121: #ifndef MAX_CHAR_TYPE_SIZE 122: #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE 123: #endif 124: 125: #ifndef MAX_INT_TYPE_SIZE 126: #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE 127: #endif 128: 129: #ifndef MAX_LONG_TYPE_SIZE 130: #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE 131: #endif 132: 133: #ifndef MAX_WCHAR_TYPE_SIZE 134: #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE 135: #endif 136: 1.1.1.2 root 137: /* Yield nonzero if adding two numbers with A's and B's signs can yield a 138: number with SUM's sign, where A, B, and SUM are all C integers. */ 139: #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) 140: 141: static void integer_overflow (); 142: static long left_shift (); 143: static long right_shift (); 1.1 root 144: %} 145: 146: %union { 147: struct constant {long value; int unsignedp;} integer; 148: struct name {U_CHAR *address; int length;} name; 149: struct arglist *keywords; 150: } 151: 152: %type <integer> exp exp1 start 153: %type <keywords> keywords 154: %token <integer> INT CHAR 155: %token <name> NAME 156: %token <integer> ERROR 157: 158: %right '?' ':' 159: %left ',' 160: %left OR 161: %left AND 162: %left '|' 163: %left '^' 164: %left '&' 165: %left EQUAL NOTEQUAL 166: %left '<' '>' LEQ GEQ 167: %left LSH RSH 168: %left '+' '-' 169: %left '*' '/' '%' 170: %right UNARY 171: 172: /* %expect 40 */ 173: 174: %% 175: 176: start : exp1 177: { expression_value = $1.value; } 178: ; 179: 180: /* Expressions, including the comma operator. */ 181: exp1 : exp 182: | exp1 ',' exp 183: { if (pedantic) 184: pedwarn ("comma operator in operand of `#if'"); 185: $$ = $3; } 186: ; 187: 188: /* Expressions, not including the comma operator. */ 189: exp : '-' exp %prec UNARY 190: { $$.value = - $2.value; 1.1.1.2 root 191: if (($$.value & $2.value) < 0 && ! $2.unsignedp) 192: integer_overflow (); 1.1 root 193: $$.unsignedp = $2.unsignedp; } 194: | '!' exp %prec UNARY 195: { $$.value = ! $2.value; 196: $$.unsignedp = 0; } 197: | '+' exp %prec UNARY 198: { $$ = $2; } 199: | '~' exp %prec UNARY 200: { $$.value = ~ $2.value; 201: $$.unsignedp = $2.unsignedp; } 202: | '#' NAME 203: { $$.value = check_assertion ($2.address, $2.length, 1.1.1.2 root 204: 0, NULL_PTR); 1.1 root 205: $$.unsignedp = 0; } 206: | '#' NAME 207: { keyword_parsing = 1; } 208: '(' keywords ')' 209: { $$.value = check_assertion ($2.address, $2.length, 210: 1, $5); 211: keyword_parsing = 0; 212: $$.unsignedp = 0; } 213: | '(' exp1 ')' 214: { $$ = $2; } 215: ; 216: 217: /* Binary operators in order of decreasing precedence. */ 218: exp : exp '*' exp 219: { $$.unsignedp = $1.unsignedp || $3.unsignedp; 220: if ($$.unsignedp) 1.1.1.2 root 221: $$.value = (unsigned long) $1.value * $3.value; 1.1 root 222: else 1.1.1.2 root 223: { 224: $$.value = $1.value * $3.value; 225: if ($1.value 226: && ($$.value / $1.value != $3.value 227: || ($$.value & $1.value & $3.value) < 0)) 228: integer_overflow (); 229: } } 1.1 root 230: | exp '/' exp 231: { if ($3.value == 0) 232: { 1.1.1.6 ! root 233: if (!skip_evaluation) ! 234: error ("division by zero in #if"); 1.1 root 235: $3.value = 1; 236: } 237: $$.unsignedp = $1.unsignedp || $3.unsignedp; 238: if ($$.unsignedp) 1.1.1.2 root 239: $$.value = (unsigned long) $1.value / $3.value; 1.1 root 240: else 1.1.1.2 root 241: { 242: $$.value = $1.value / $3.value; 243: if (($$.value & $1.value & $3.value) < 0) 244: integer_overflow (); 245: } } 1.1 root 246: | exp '%' exp 247: { if ($3.value == 0) 248: { 1.1.1.6 ! root 249: if (!skip_evaluation) ! 250: error ("division by zero in #if"); 1.1 root 251: $3.value = 1; 252: } 253: $$.unsignedp = $1.unsignedp || $3.unsignedp; 254: if ($$.unsignedp) 1.1.1.2 root 255: $$.value = (unsigned long) $1.value % $3.value; 1.1 root 256: else 257: $$.value = $1.value % $3.value; } 258: | exp '+' exp 259: { $$.value = $1.value + $3.value; 1.1.1.2 root 260: $$.unsignedp = $1.unsignedp || $3.unsignedp; 261: if (! $$.unsignedp 262: && ! possible_sum_sign ($1.value, $3.value, 263: $$.value)) 264: integer_overflow (); } 1.1 root 265: | exp '-' exp 266: { $$.value = $1.value - $3.value; 1.1.1.2 root 267: $$.unsignedp = $1.unsignedp || $3.unsignedp; 268: if (! $$.unsignedp 269: && ! possible_sum_sign ($$.value, $3.value, 270: $1.value)) 271: integer_overflow (); } 1.1 root 272: | exp LSH exp 273: { $$.unsignedp = $1.unsignedp; 1.1.1.2 root 274: if ($3.value < 0 && ! $3.unsignedp) 275: $$.value = right_shift (&$1, -$3.value); 1.1 root 276: else 1.1.1.2 root 277: $$.value = left_shift (&$1, $3.value); } 1.1 root 278: | exp RSH exp 279: { $$.unsignedp = $1.unsignedp; 1.1.1.2 root 280: if ($3.value < 0 && ! $3.unsignedp) 281: $$.value = left_shift (&$1, -$3.value); 1.1 root 282: else 1.1.1.2 root 283: $$.value = right_shift (&$1, $3.value); } 1.1 root 284: | exp EQUAL exp 285: { $$.value = ($1.value == $3.value); 286: $$.unsignedp = 0; } 287: | exp NOTEQUAL exp 288: { $$.value = ($1.value != $3.value); 289: $$.unsignedp = 0; } 290: | exp LEQ exp 291: { $$.unsignedp = 0; 292: if ($1.unsignedp || $3.unsignedp) 1.1.1.2 root 293: $$.value = (unsigned long) $1.value <= $3.value; 1.1 root 294: else 295: $$.value = $1.value <= $3.value; } 296: | exp GEQ exp 297: { $$.unsignedp = 0; 298: if ($1.unsignedp || $3.unsignedp) 1.1.1.2 root 299: $$.value = (unsigned long) $1.value >= $3.value; 1.1 root 300: else 301: $$.value = $1.value >= $3.value; } 302: | exp '<' exp 303: { $$.unsignedp = 0; 304: if ($1.unsignedp || $3.unsignedp) 1.1.1.2 root 305: $$.value = (unsigned long) $1.value < $3.value; 1.1 root 306: else 307: $$.value = $1.value < $3.value; } 308: | exp '>' exp 309: { $$.unsignedp = 0; 310: if ($1.unsignedp || $3.unsignedp) 1.1.1.2 root 311: $$.value = (unsigned long) $1.value > $3.value; 1.1 root 312: else 313: $$.value = $1.value > $3.value; } 314: | exp '&' exp 315: { $$.value = $1.value & $3.value; 316: $$.unsignedp = $1.unsignedp || $3.unsignedp; } 317: | exp '^' exp 318: { $$.value = $1.value ^ $3.value; 319: $$.unsignedp = $1.unsignedp || $3.unsignedp; } 320: | exp '|' exp 321: { $$.value = $1.value | $3.value; 322: $$.unsignedp = $1.unsignedp || $3.unsignedp; } 1.1.1.6 ! root 323: | exp AND ! 324: { skip_evaluation += !$1.value; } ! 325: exp ! 326: { skip_evaluation -= !$1.value; ! 327: $$.value = ($1.value && $4.value); 1.1 root 328: $$.unsignedp = 0; } 1.1.1.6 ! root 329: | exp OR ! 330: { skip_evaluation += !!$1.value; } ! 331: exp ! 332: { skip_evaluation -= !!$1.value; ! 333: $$.value = ($1.value || $4.value); 1.1 root 334: $$.unsignedp = 0; } 1.1.1.6 ! root 335: | exp '?' ! 336: { skip_evaluation += !$1.value; } ! 337: exp ':' ! 338: { skip_evaluation += !!$1.value - !$1.value; } ! 339: exp ! 340: { skip_evaluation -= !!$1.value; ! 341: $$.value = $1.value ? $4.value : $7.value; ! 342: $$.unsignedp = $4.unsignedp || $7.unsignedp; } 1.1 root 343: | INT 344: { $$ = yylval.integer; } 345: | CHAR 346: { $$ = yylval.integer; } 347: | NAME 348: { $$.value = 0; 349: $$.unsignedp = 0; } 350: ; 351: 352: keywords : 353: { $$ = 0; } 354: | '(' keywords ')' keywords 355: { struct arglist *temp; 356: $$ = (struct arglist *) xmalloc (sizeof (struct arglist)); 357: $$->next = $2; 358: $$->name = (U_CHAR *) "("; 359: $$->length = 1; 360: temp = $$; 361: while (temp != 0 && temp->next != 0) 362: temp = temp->next; 363: temp->next = (struct arglist *) xmalloc (sizeof (struct arglist)); 364: temp->next->next = $4; 365: temp->next->name = (U_CHAR *) ")"; 366: temp->next->length = 1; } 367: | NAME keywords 368: { $$ = (struct arglist *) xmalloc (sizeof (struct arglist)); 369: $$->name = $1.address; 370: $$->length = $1.length; 371: $$->next = $2; } 372: ; 373: %% 374: 375: /* During parsing of a C expression, the pointer to the next character 376: is in this variable. */ 377: 378: static char *lexptr; 379: 380: /* Take care of parsing a number (anything that starts with a digit). 381: Set yylval and return the token type; update lexptr. 382: LEN is the number of characters in it. */ 383: 384: /* maybe needs to actually deal with floating point numbers */ 385: 386: int 387: parse_number (olen) 388: int olen; 389: { 390: register char *p = lexptr; 391: register int c; 1.1.1.2 root 392: register unsigned long n = 0, nd, ULONG_MAX_over_base; 1.1 root 393: register int base = 10; 394: register int len = olen; 1.1.1.2 root 395: register int overflow = 0; 396: register int digit, largest_digit = 0; 397: int spec_long = 0; 1.1 root 398: 399: for (c = 0; c < len; c++) 400: if (p[c] == '.') { 401: /* It's a float since it contains a point. */ 402: yyerror ("floating point numbers not allowed in #if expressions"); 403: return ERROR; 404: } 405: 406: yylval.integer.unsignedp = 0; 407: 408: if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) { 409: p += 2; 410: base = 16; 411: len -= 2; 412: } 413: else if (*p == '0') 414: base = 8; 415: 1.1.1.2 root 416: ULONG_MAX_over_base = (unsigned long) -1 / base; 417: 418: for (; len > 0; len--) { 1.1 root 419: c = *p++; 420: 1.1.1.2 root 421: if (c >= '0' && c <= '9') 422: digit = c - '0'; 423: else if (base == 16 && c >= 'a' && c <= 'f') 424: digit = c - 'a' + 10; 425: else if (base == 16 && c >= 'A' && c <= 'F') 426: digit = c - 'A' + 10; 427: else { 1.1 root 428: /* `l' means long, and `u' means unsigned. */ 429: while (1) { 430: if (c == 'l' || c == 'L') 1.1.1.2 root 431: { 432: if (spec_long) 433: yyerror ("two `l's in integer constant"); 434: spec_long = 1; 435: } 1.1 root 436: else if (c == 'u' || c == 'U') 1.1.1.2 root 437: { 438: if (yylval.integer.unsignedp) 439: yyerror ("two `u's in integer constant"); 440: yylval.integer.unsignedp = 1; 441: } 1.1 root 442: else 443: break; 444: 1.1.1.2 root 445: if (--len == 0) 1.1 root 446: break; 447: c = *p++; 448: } 449: /* Don't look for any more digits after the suffixes. */ 450: break; 451: } 1.1.1.2 root 452: if (largest_digit < digit) 453: largest_digit = digit; 454: nd = n * base + digit; 455: overflow |= ULONG_MAX_over_base < n | nd < n; 456: n = nd; 1.1 root 457: } 458: 459: if (len != 0) { 460: yyerror ("Invalid number in #if expression"); 461: return ERROR; 462: } 463: 1.1.1.2 root 464: if (base <= largest_digit) 465: warning ("integer constant contains digits beyond the radix"); 466: 467: if (overflow) 468: warning ("integer constant out of range"); 469: 1.1 root 470: /* If too big to be signed, consider it unsigned. */ 1.1.1.2 root 471: if ((long) n < 0 && ! yylval.integer.unsignedp) 472: { 473: if (base == 10) 474: warning ("integer constant is so large that it is unsigned"); 475: yylval.integer.unsignedp = 1; 476: } 1.1 root 477: 478: lexptr = p; 479: yylval.integer.value = n; 480: return INT; 481: } 482: 483: struct token { 484: char *operator; 485: int token; 486: }; 487: 488: static struct token tokentab2[] = { 489: {"&&", AND}, 490: {"||", OR}, 491: {"<<", LSH}, 492: {">>", RSH}, 493: {"==", EQUAL}, 494: {"!=", NOTEQUAL}, 495: {"<=", LEQ}, 496: {">=", GEQ}, 497: {"++", ERROR}, 498: {"--", ERROR}, 499: {NULL, ERROR} 500: }; 501: 502: /* Read one token, getting characters through lexptr. */ 503: 504: int 505: yylex () 506: { 507: register int c; 508: register int namelen; 1.1.1.3 root 509: register unsigned char *tokstart; 1.1 root 510: register struct token *toktab; 511: int wide_flag; 512: 513: retry: 514: 1.1.1.3 root 515: tokstart = (unsigned char *) lexptr; 1.1 root 516: c = *tokstart; 517: /* See if it is a special token of length 2. */ 518: if (! keyword_parsing) 519: for (toktab = tokentab2; toktab->operator != NULL; toktab++) 520: if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) { 521: lexptr += 2; 522: if (toktab->token == ERROR) 523: { 524: char *buf = (char *) alloca (40); 525: sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator); 526: yyerror (buf); 527: } 528: return toktab->token; 529: } 530: 531: switch (c) { 532: case 0: 533: return 0; 534: 535: case ' ': 536: case '\t': 537: case '\r': 538: case '\n': 539: lexptr++; 540: goto retry; 541: 542: case 'L': 543: /* Capital L may start a wide-string or wide-character constant. */ 544: if (lexptr[1] == '\'') 545: { 546: lexptr++; 547: wide_flag = 1; 548: goto char_constant; 549: } 550: if (lexptr[1] == '"') 551: { 552: lexptr++; 553: wide_flag = 1; 554: goto string_constant; 555: } 556: break; 557: 558: case '\'': 559: wide_flag = 0; 560: char_constant: 561: lexptr++; 562: if (keyword_parsing) { 563: char *start_ptr = lexptr - 1; 564: while (1) { 565: c = *lexptr++; 566: if (c == '\\') 567: c = parse_escape (&lexptr); 568: else if (c == '\'') 569: break; 570: } 1.1.1.3 root 571: yylval.name.address = tokstart; 1.1 root 572: yylval.name.length = lexptr - start_ptr; 573: return NAME; 574: } 575: 576: /* This code for reading a character constant 577: handles multicharacter constants and wide characters. 578: It is mostly copied from c-lex.c. */ 579: { 580: register int result = 0; 581: register num_chars = 0; 1.1.1.4 root 582: unsigned width = MAX_CHAR_TYPE_SIZE; 1.1 root 583: int max_chars; 584: char *token_buffer; 585: 586: if (wide_flag) 587: { 1.1.1.4 root 588: width = MAX_WCHAR_TYPE_SIZE; 1.1 root 589: #ifdef MULTIBYTE_CHARS 590: max_chars = MB_CUR_MAX; 591: #else 592: max_chars = 1; 593: #endif 594: } 595: else 1.1.1.4 root 596: max_chars = MAX_LONG_TYPE_SIZE / width; 1.1 root 597: 598: token_buffer = (char *) alloca (max_chars + 1); 599: 600: while (1) 601: { 602: c = *lexptr++; 603: 604: if (c == '\'' || c == EOF) 605: break; 606: 607: if (c == '\\') 608: { 609: c = parse_escape (&lexptr); 610: if (width < HOST_BITS_PER_INT 611: && (unsigned) c >= (1 << width)) 612: pedwarn ("escape sequence out of range for character"); 613: } 614: 615: num_chars++; 616: 617: /* Merge character into result; ignore excess chars. */ 618: if (num_chars < max_chars + 1) 619: { 620: if (width < HOST_BITS_PER_INT) 621: result = (result << width) | (c & ((1 << width) - 1)); 622: else 623: result = c; 624: token_buffer[num_chars - 1] = c; 625: } 626: } 627: 628: token_buffer[num_chars] = 0; 629: 630: if (c != '\'') 631: error ("malformatted character constant"); 632: else if (num_chars == 0) 633: error ("empty character constant"); 634: else if (num_chars > max_chars) 635: { 636: num_chars = max_chars; 637: error ("character constant too long"); 638: } 639: else if (num_chars != 1 && ! traditional) 640: warning ("multi-character character constant"); 641: 642: /* If char type is signed, sign-extend the constant. */ 643: if (! wide_flag) 644: { 645: int num_bits = num_chars * width; 646: 647: if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1) 648: || ((result >> (num_bits - 1)) & 1) == 0) 649: yylval.integer.value 1.1.1.2 root 650: = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); 1.1 root 651: else 652: yylval.integer.value 1.1.1.2 root 653: = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); 1.1 root 654: } 655: else 656: { 657: #ifdef MULTIBYTE_CHARS 658: /* Set the initial shift state and convert the next sequence. */ 659: result = 0; 660: /* In all locales L'\0' is zero and mbtowc will return zero, 661: so don't use it. */ 662: if (num_chars > 1 663: || (num_chars == 1 && token_buffer[0] != '\0')) 664: { 665: wchar_t wc; 1.1.1.2 root 666: (void) mbtowc (NULL_PTR, NULL_PTR, 0); 1.1 root 667: if (mbtowc (& wc, token_buffer, num_chars) == num_chars) 668: result = wc; 669: else 670: warning ("Ignoring invalid multibyte character"); 671: } 672: #endif 673: yylval.integer.value = result; 674: } 675: } 676: 677: /* This is always a signed type. */ 678: yylval.integer.unsignedp = 0; 679: 680: return CHAR; 681: 682: /* some of these chars are invalid in constant expressions; 683: maybe do something about them later */ 684: case '/': 685: case '+': 686: case '-': 687: case '*': 688: case '%': 689: case '|': 690: case '&': 691: case '^': 692: case '~': 693: case '!': 694: case '@': 695: case '<': 696: case '>': 697: case '[': 698: case ']': 699: case '.': 700: case '?': 701: case ':': 702: case '=': 703: case '{': 704: case '}': 705: case ',': 706: case '#': 707: if (keyword_parsing) 708: break; 709: case '(': 710: case ')': 711: lexptr++; 712: return c; 713: 714: case '"': 715: string_constant: 716: if (keyword_parsing) { 717: char *start_ptr = lexptr; 718: lexptr++; 719: while (1) { 720: c = *lexptr++; 721: if (c == '\\') 722: c = parse_escape (&lexptr); 723: else if (c == '"') 724: break; 725: } 1.1.1.3 root 726: yylval.name.address = tokstart; 1.1 root 727: yylval.name.length = lexptr - start_ptr; 728: return NAME; 729: } 730: yyerror ("string constants not allowed in #if expressions"); 731: return ERROR; 732: } 733: 734: if (c >= '0' && c <= '9' && !keyword_parsing) { 735: /* It's a number */ 736: for (namelen = 0; 737: c = tokstart[namelen], is_idchar[c] || c == '.'; 738: namelen++) 739: ; 740: return parse_number (namelen); 741: } 742: 743: /* It is a name. See how long it is. */ 744: 745: if (keyword_parsing) { 746: for (namelen = 0;; namelen++) { 747: if (is_hor_space[tokstart[namelen]]) 748: break; 749: if (tokstart[namelen] == '(' || tokstart[namelen] == ')') 750: break; 751: if (tokstart[namelen] == '"' || tokstart[namelen] == '\'') 752: break; 753: } 754: } else { 755: if (!is_idstart[c]) { 756: yyerror ("Invalid token in expression"); 757: return ERROR; 758: } 759: 760: for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++) 761: ; 762: } 763: 764: lexptr += namelen; 1.1.1.3 root 765: yylval.name.address = tokstart; 1.1 root 766: yylval.name.length = namelen; 767: return NAME; 768: } 769: 770: 771: /* Parse a C escape sequence. STRING_PTR points to a variable 772: containing a pointer to the string to parse. That pointer 773: is updated past the characters we use. The value of the 774: escape sequence is returned. 775: 776: A negative value means the sequence \ newline was seen, 777: which is supposed to be equivalent to nothing at all. 778: 779: If \ is followed by a null character, we return a negative 780: value and leave the string pointer pointing at the null character. 781: 782: If \ is followed by 000, we return 0 and leave the string pointer 783: after the zeros. A value of 0 does not mean end of string. */ 784: 785: int 786: parse_escape (string_ptr) 787: char **string_ptr; 788: { 789: register int c = *(*string_ptr)++; 790: switch (c) 791: { 792: case 'a': 793: return TARGET_BELL; 794: case 'b': 795: return TARGET_BS; 796: case 'e': 1.1.1.3 root 797: case 'E': 798: if (pedantic) 799: pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c); 1.1 root 800: return 033; 801: case 'f': 802: return TARGET_FF; 803: case 'n': 804: return TARGET_NEWLINE; 805: case 'r': 806: return TARGET_CR; 807: case 't': 808: return TARGET_TAB; 809: case 'v': 810: return TARGET_VT; 811: case '\n': 812: return -2; 813: case 0: 814: (*string_ptr)--; 815: return 0; 816: 817: case '0': 818: case '1': 819: case '2': 820: case '3': 821: case '4': 822: case '5': 823: case '6': 824: case '7': 825: { 826: register int i = c - '0'; 827: register int count = 0; 828: while (++count < 3) 829: { 830: c = *(*string_ptr)++; 831: if (c >= '0' && c <= '7') 832: i = (i << 3) + c - '0'; 833: else 834: { 835: (*string_ptr)--; 836: break; 837: } 838: } 1.1.1.4 root 839: if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) 1.1 root 840: { 1.1.1.4 root 841: i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; 1.1 root 842: warning ("octal character constant does not fit in a byte"); 843: } 844: return i; 845: } 846: case 'x': 847: { 1.1.1.2 root 848: register unsigned i = 0, overflow = 0, digits_found = 0, digit; 1.1 root 849: for (;;) 850: { 851: c = *(*string_ptr)++; 852: if (c >= '0' && c <= '9') 1.1.1.2 root 853: digit = c - '0'; 1.1 root 854: else if (c >= 'a' && c <= 'f') 1.1.1.2 root 855: digit = c - 'a' + 10; 1.1 root 856: else if (c >= 'A' && c <= 'F') 1.1.1.2 root 857: digit = c - 'A' + 10; 1.1 root 858: else 859: { 860: (*string_ptr)--; 861: break; 862: } 1.1.1.2 root 863: overflow |= i ^ (i << 4 >> 4); 864: i = (i << 4) + digit; 865: digits_found = 1; 1.1 root 866: } 1.1.1.2 root 867: if (!digits_found) 868: yyerror ("\\x used with no following hex digits"); 869: if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) 1.1 root 870: { 871: i &= (1 << BITS_PER_UNIT) - 1; 872: warning ("hex character constant does not fit in a byte"); 873: } 874: return i; 875: } 876: default: 877: return c; 878: } 879: } 880: 881: void 882: yyerror (s) 883: char *s; 884: { 885: error (s); 1.1.1.6 ! root 886: skip_evaluation = 0; 1.1 root 887: longjmp (parse_return_error, 1); 888: } 1.1.1.2 root 889: 890: static void 891: integer_overflow () 892: { 1.1.1.6 ! root 893: if (!skip_evaluation && pedantic) 1.1.1.2 root 894: pedwarn ("integer overflow in preprocessor expression"); 895: } 896: 897: static long 898: left_shift (a, b) 899: struct constant *a; 900: unsigned long b; 901: { 1.1.1.6 ! root 902: /* It's unclear from the C standard whether shifts can overflow. ! 903: The following code ignores overflow; perhaps a C standard ! 904: interpretation ruling is needed. */ 1.1.1.2 root 905: if (b >= HOST_BITS_PER_LONG) 1.1.1.6 ! root 906: return 0; 1.1.1.2 root 907: else if (a->unsignedp) 908: return (unsigned long) a->value << b; 909: else 1.1.1.6 ! root 910: return a->value << b; 1.1.1.2 root 911: } 912: 913: static long 914: right_shift (a, b) 915: struct constant *a; 916: unsigned long b; 917: { 918: if (b >= HOST_BITS_PER_LONG) 919: return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1); 920: else if (a->unsignedp) 921: return (unsigned long) a->value >> b; 922: else 923: return a->value >> b; 924: } 1.1 root 925: 926: /* This page contains the entry point to this file. */ 927: 928: /* Parse STRING as an expression, and complain if this fails 929: to use up all of the contents of STRING. */ 930: /* We do not support C comments. They should be removed before 931: this function is called. */ 932: 1.1.1.5 root 933: HOST_WIDE_INT 1.1 root 934: parse_c_expression (string) 935: char *string; 936: { 937: lexptr = string; 938: 939: if (lexptr == 0 || *lexptr == 0) { 940: error ("empty #if expression"); 941: return 0; /* don't include the #if group */ 942: } 943: 944: /* if there is some sort of scanning error, just return 0 and assume 945: the parsing routine has printed an error message somewhere. 946: there is surely a better thing to do than this. */ 947: if (setjmp (parse_return_error)) 948: return 0; 949: 950: if (yyparse ()) 951: return 0; /* actually this is never reached 952: the way things stand. */ 953: if (*lexptr) 954: error ("Junk after end of expression."); 955: 956: return expression_value; /* set by yyparse () */ 957: } 958: 959: #ifdef TEST_EXP_READER 960: extern int yydebug; 961: 962: /* Main program for testing purposes. */ 963: int 964: main () 965: { 966: int n, c; 967: char buf[1024]; 968: 969: /* 970: yydebug = 1; 971: */ 972: initialize_random_junk (); 973: 974: for (;;) { 975: printf ("enter expression: "); 976: n = 0; 977: while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF) 978: n++; 979: if (buf[n] == EOF) 980: break; 981: buf[n] = '\0'; 1.1.1.5 root 982: printf ("parser returned %ld\n", parse_c_expression (buf)); 1.1 root 983: } 984: 985: return 0; 986: } 987: 988: /* table to tell if char can be part of a C identifier. */ 989: unsigned char is_idchar[256]; 990: /* table to tell if char can be first char of a c identifier. */ 991: unsigned char is_idstart[256]; 992: /* table to tell if c is horizontal space. isspace () thinks that 993: newline is space; this is not a good idea for this program. */ 994: char is_hor_space[256]; 995: 996: /* 997: * initialize random junk in the hash table and maybe other places 998: */ 999: initialize_random_junk () 1000: { 1001: register int i; 1002: 1003: /* 1004: * Set up is_idchar and is_idstart tables. These should be 1005: * faster than saying (is_alpha (c) || c == '_'), etc. 1006: * Must do set up these things before calling any routines tthat 1007: * refer to them. 1008: */ 1009: for (i = 'a'; i <= 'z'; i++) { 1010: ++is_idchar[i - 'a' + 'A']; 1011: ++is_idchar[i]; 1012: ++is_idstart[i - 'a' + 'A']; 1013: ++is_idstart[i]; 1014: } 1015: for (i = '0'; i <= '9'; i++) 1016: ++is_idchar[i]; 1017: ++is_idchar['_']; 1018: ++is_idstart['_']; 1019: #if DOLLARS_IN_IDENTIFIERS 1020: ++is_idchar['$']; 1021: ++is_idstart['$']; 1022: #endif 1023: 1024: /* horizontal space table */ 1025: ++is_hor_space[' ']; 1026: ++is_hor_space['\t']; 1027: } 1028: 1029: error (msg) 1030: { 1031: printf ("error: %s\n", msg); 1032: } 1033: 1034: warning (msg) 1035: { 1036: printf ("warning: %s\n", msg); 1037: } 1038: 1039: struct hashnode * 1040: lookup (name, len, hash) 1041: char *name; 1042: int len; 1043: int hash; 1044: { 1045: return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1); 1046: } 1047: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.