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