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