1 /* Parse C expressions for CCCP.
2 Copyright (C) 1987, 1992 Free Software Foundation.
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
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.
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.
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!
22 Adapted from expread.y of GDB by Paul Rubin, July 1986. */
24 /* Parse a C expression from text in a string */
29 /* #define YYDEBUG 1 */
31 #ifdef MULTIBYTE_CHARS
38 typedef unsigned char U_CHAR;
40 /* This is used for communicating lists of keywords with cccp.c. */
48 /* Define a generic NULL if one hasn't already been defined. */
55 #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
56 #define GENERIC_PTR void *
58 #define GENERIC_PTR char *
63 #define NULL_PTR ((GENERIC_PTR)0)
70 static jmp_buf parse_return_error;
72 /* Nonzero means count most punctuation as part of a name. */
73 static int keyword_parsing = 0;
75 /* some external tables of character types */
76 extern unsigned char is_idstart[], is_idchar[], is_hor_space[];
78 extern char *xmalloc ();
80 /* Flag for -pedantic. */
83 /* Flag for -traditional. */
84 extern int traditional;
86 #ifndef CHAR_TYPE_SIZE
87 #define CHAR_TYPE_SIZE BITS_PER_UNIT
91 #define INT_TYPE_SIZE BITS_PER_WORD
94 #ifndef LONG_TYPE_SIZE
95 #define LONG_TYPE_SIZE BITS_PER_WORD
98 #ifndef WCHAR_TYPE_SIZE
99 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
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)
106 static void integer_overflow ();
107 static long left_shift ();
108 static long right_shift ();
112 struct constant {long value; int unsignedp;} integer;
113 struct name {U_CHAR *address; int length;} name;
114 struct arglist *keywords;
119 %type <integer> exp exp1 start
120 %type <keywords> keywords
121 %token <integer> INT CHAR
123 %token <integer> ERROR
133 %left '<' '>' LEQ GEQ
144 { expression_value = $1.value; }
147 /* Expressions, including the comma operator. */
151 pedwarn ("comma operator in operand of `#if'");
155 /* Expressions, not including the comma operator. */
156 exp : '-' exp %prec UNARY
157 { $$.value = - $2.value;
158 if (($$.value & $2.value) < 0 && ! $2.unsignedp)
160 $$.unsignedp = $2.unsignedp; }
161 | '!' exp %prec UNARY
162 { $$.value = ! $2.value;
164 | '+' exp %prec UNARY
166 | '~' exp %prec UNARY
167 { $$.value = ~ $2.value;
168 $$.unsignedp = $2.unsignedp; }
170 { $$.value = check_assertion ($2.address, $2.length,
174 { keyword_parsing = 1; }
176 { $$.value = check_assertion ($2.address, $2.length,
184 /* Binary operators in order of decreasing precedence. */
186 { $$.unsignedp = $1.unsignedp || $3.unsignedp;
188 $$.value = (unsigned long) $1.value * $3.value;
191 $$.value = $1.value * $3.value;
193 && ($$.value / $1.value != $3.value
194 || ($$.value & $1.value & $3.value) < 0))
200 error ("division by zero in #if");
203 $$.unsignedp = $1.unsignedp || $3.unsignedp;
205 $$.value = (unsigned long) $1.value / $3.value;
208 $$.value = $1.value / $3.value;
209 if (($$.value & $1.value & $3.value) < 0)
215 error ("division by zero in #if");
218 $$.unsignedp = $1.unsignedp || $3.unsignedp;
220 $$.value = (unsigned long) $1.value % $3.value;
222 $$.value = $1.value % $3.value; }
224 { $$.value = $1.value + $3.value;
225 $$.unsignedp = $1.unsignedp || $3.unsignedp;
227 && ! possible_sum_sign ($1.value, $3.value,
229 integer_overflow (); }
231 { $$.value = $1.value - $3.value;
232 $$.unsignedp = $1.unsignedp || $3.unsignedp;
234 && ! possible_sum_sign ($$.value, $3.value,
236 integer_overflow (); }
238 { $$.unsignedp = $1.unsignedp;
239 if ($3.value < 0 && ! $3.unsignedp)
240 $$.value = right_shift (&$1, -$3.value);
242 $$.value = left_shift (&$1, $3.value); }
244 { $$.unsignedp = $1.unsignedp;
245 if ($3.value < 0 && ! $3.unsignedp)
246 $$.value = left_shift (&$1, -$3.value);
248 $$.value = right_shift (&$1, $3.value); }
250 { $$.value = ($1.value == $3.value);
253 { $$.value = ($1.value != $3.value);
257 if ($1.unsignedp || $3.unsignedp)
258 $$.value = (unsigned long) $1.value <= $3.value;
260 $$.value = $1.value <= $3.value; }
263 if ($1.unsignedp || $3.unsignedp)
264 $$.value = (unsigned long) $1.value >= $3.value;
266 $$.value = $1.value >= $3.value; }
269 if ($1.unsignedp || $3.unsignedp)
270 $$.value = (unsigned long) $1.value < $3.value;
272 $$.value = $1.value < $3.value; }
275 if ($1.unsignedp || $3.unsignedp)
276 $$.value = (unsigned long) $1.value > $3.value;
278 $$.value = $1.value > $3.value; }
280 { $$.value = $1.value & $3.value;
281 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
283 { $$.value = $1.value ^ $3.value;
284 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
286 { $$.value = $1.value | $3.value;
287 $$.unsignedp = $1.unsignedp || $3.unsignedp; }
289 { $$.value = ($1.value && $3.value);
292 { $$.value = ($1.value || $3.value);
294 | exp '?' exp ':' exp
295 { $$.value = $1.value ? $3.value : $5.value;
296 $$.unsignedp = $3.unsignedp || $5.unsignedp; }
298 { $$ = yylval.integer; }
300 { $$ = yylval.integer; }
308 | '(' keywords ')' keywords
309 { struct arglist *temp;
310 $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
312 $$->name = (U_CHAR *) "(";
315 while (temp != 0 && temp->next != 0)
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; }
322 { $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
323 $$->name = $1.address;
324 $$->length = $1.length;
329 /* During parsing of a C expression, the pointer to the next character
330 is in this variable. */
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. */
338 /* maybe needs to actually deal with floating point numbers */
344 register char *p = lexptr;
346 register unsigned long n = 0, nd, ULONG_MAX_over_base;
347 register int base = 10;
348 register int len = olen;
349 register int overflow = 0;
350 register int digit, largest_digit = 0;
353 for (c = 0; c < len; c++)
355 /* It's a float since it contains a point. */
356 yyerror ("floating point numbers not allowed in #if expressions");
360 yylval.integer.unsignedp = 0;
362 if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
370 ULONG_MAX_over_base = (unsigned long) -1 / base;
372 for (; len > 0; len--) {
375 if (c >= '0' && c <= '9')
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;
382 /* `l' means long, and `u' means unsigned. */
384 if (c == 'l' || c == 'L')
387 yyerror ("two `l's in integer constant");
390 else if (c == 'u' || c == 'U')
392 if (yylval.integer.unsignedp)
393 yyerror ("two `u's in integer constant");
394 yylval.integer.unsignedp = 1;
403 /* Don't look for any more digits after the suffixes. */
406 if (largest_digit < digit)
407 largest_digit = digit;
408 nd = n * base + digit;
409 overflow |= ULONG_MAX_over_base < n | nd < n;
414 yyerror ("Invalid number in #if expression");
418 if (base <= largest_digit)
419 warning ("integer constant contains digits beyond the radix");
422 warning ("integer constant out of range");
424 /* If too big to be signed, consider it unsigned. */
425 if ((long) n < 0 && ! yylval.integer.unsignedp)
428 warning ("integer constant is so large that it is unsigned");
429 yylval.integer.unsignedp = 1;
433 yylval.integer.value = n;
442 static struct token tokentab2[] = {
456 /* Read one token, getting characters through lexptr. */
462 register int namelen;
463 register unsigned char *tokstart;
464 register struct token *toktab;
469 tokstart = (unsigned char *) lexptr;
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]) {
476 if (toktab->token == ERROR)
478 char *buf = (char *) alloca (40);
479 sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator);
482 return toktab->token;
497 /* Capital L may start a wide-string or wide-character constant. */
498 if (lexptr[1] == '\'')
504 if (lexptr[1] == '"')
508 goto string_constant;
516 if (keyword_parsing) {
517 char *start_ptr = lexptr - 1;
521 c = parse_escape (&lexptr);
525 yylval.name.address = tokstart;
526 yylval.name.length = lexptr - start_ptr;
530 /* This code for reading a character constant
531 handles multicharacter constants and wide characters.
532 It is mostly copied from c-lex.c. */
534 register int result = 0;
535 register num_chars = 0;
536 unsigned width = CHAR_TYPE_SIZE;
542 width = WCHAR_TYPE_SIZE;
543 #ifdef MULTIBYTE_CHARS
544 max_chars = MB_CUR_MAX;
550 max_chars = LONG_TYPE_SIZE / width;
552 token_buffer = (char *) alloca (max_chars + 1);
558 if (c == '\'' || c == EOF)
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");
571 /* Merge character into result; ignore excess chars. */
572 if (num_chars < max_chars + 1)
574 if (width < HOST_BITS_PER_INT)
575 result = (result << width) | (c & ((1 << width) - 1));
578 token_buffer[num_chars - 1] = c;
582 token_buffer[num_chars] = 0;
585 error ("malformatted character constant");
586 else if (num_chars == 0)
587 error ("empty character constant");
588 else if (num_chars > max_chars)
590 num_chars = max_chars;
591 error ("character constant too long");
593 else if (num_chars != 1 && ! traditional)
594 warning ("multi-character character constant");
596 /* If char type is signed, sign-extend the constant. */
599 int num_bits = num_chars * width;
601 if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1)
602 || ((result >> (num_bits - 1)) & 1) == 0)
604 = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
607 = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
611 #ifdef MULTIBYTE_CHARS
612 /* Set the initial shift state and convert the next sequence. */
614 /* In all locales L'\0' is zero and mbtowc will return zero,
617 || (num_chars == 1 && token_buffer[0] != '\0'))
620 (void) mbtowc (NULL_PTR, NULL_PTR, 0);
621 if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
624 warning ("Ignoring invalid multibyte character");
627 yylval.integer.value = result;
631 /* This is always a signed type. */
632 yylval.integer.unsignedp = 0;
636 /* some of these chars are invalid in constant expressions;
637 maybe do something about them later */
670 if (keyword_parsing) {
671 char *start_ptr = lexptr;
676 c = parse_escape (&lexptr);
680 yylval.name.address = tokstart;
681 yylval.name.length = lexptr - start_ptr;
684 yyerror ("string constants not allowed in #if expressions");
688 if (c >= '0' && c <= '9' && !keyword_parsing) {
691 c = tokstart[namelen], is_idchar[c] || c == '.';
694 return parse_number (namelen);
697 /* It is a name. See how long it is. */
699 if (keyword_parsing) {
700 for (namelen = 0;; namelen++) {
701 if (is_hor_space[tokstart[namelen]])
703 if (tokstart[namelen] == '(' || tokstart[namelen] == ')')
705 if (tokstart[namelen] == '"' || tokstart[namelen] == '\'')
709 if (!is_idstart[c]) {
710 yyerror ("Invalid token in expression");
714 for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
719 yylval.name.address = tokstart;
720 yylval.name.length = namelen;
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.
730 A negative value means the sequence \ newline was seen,
731 which is supposed to be equivalent to nothing at all.
733 If \ is followed by a null character, we return a negative
734 value and leave the string pointer pointing at the null character.
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. */
740 parse_escape (string_ptr)
743 register int c = *(*string_ptr)++;
753 pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
758 return TARGET_NEWLINE;
780 register int i = c - '0';
781 register int count = 0;
784 c = *(*string_ptr)++;
785 if (c >= '0' && c <= '7')
786 i = (i << 3) + c - '0';
793 if ((i & ~((1 << CHAR_TYPE_SIZE) - 1)) != 0)
795 i &= (1 << CHAR_TYPE_SIZE) - 1;
796 warning ("octal character constant does not fit in a byte");
802 register unsigned i = 0, overflow = 0, digits_found = 0, digit;
805 c = *(*string_ptr)++;
806 if (c >= '0' && c <= '9')
808 else if (c >= 'a' && c <= 'f')
809 digit = c - 'a' + 10;
810 else if (c >= 'A' && c <= 'F')
811 digit = c - 'A' + 10;
817 overflow |= i ^ (i << 4 >> 4);
818 i = (i << 4) + digit;
822 yyerror ("\\x used with no following hex digits");
823 if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
825 i &= (1 << BITS_PER_UNIT) - 1;
826 warning ("hex character constant does not fit in a byte");
840 longjmp (parse_return_error, 1);
847 pedwarn ("integer overflow in preprocessor expression");
855 if (b >= HOST_BITS_PER_LONG)
857 if (! a->unsignedp && a->value != 0)
861 else if (a->unsignedp)
862 return (unsigned long) a->value << b;
865 long l = a->value << b;
866 if (l >> b != a->value)
877 if (b >= HOST_BITS_PER_LONG)
878 return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1);
879 else if (a->unsignedp)
880 return (unsigned long) a->value >> b;
882 return a->value >> b;
885 /* This page contains the entry point to this file. */
887 /* Parse STRING as an expression, and complain if this fails
888 to use up all of the contents of STRING. */
889 /* We do not support C comments. They should be removed before
890 this function is called. */
893 parse_c_expression (string)
898 if (lexptr == 0 || *lexptr == 0) {
899 error ("empty #if expression");
900 return 0; /* don't include the #if group */
903 /* if there is some sort of scanning error, just return 0 and assume
904 the parsing routine has printed an error message somewhere.
905 there is surely a better thing to do than this. */
906 if (setjmp (parse_return_error))
910 return 0; /* actually this is never reached
911 the way things stand. */
913 error ("Junk after end of expression.");
915 return expression_value; /* set by yyparse () */
918 #ifdef TEST_EXP_READER
921 /* Main program for testing purposes. */
931 initialize_random_junk ();
934 printf ("enter expression: ");
936 while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF)
941 printf ("parser returned %d\n", parse_c_expression (buf));
947 /* table to tell if char can be part of a C identifier. */
948 unsigned char is_idchar[256];
949 /* table to tell if char can be first char of a c identifier. */
950 unsigned char is_idstart[256];
951 /* table to tell if c is horizontal space. isspace () thinks that
952 newline is space; this is not a good idea for this program. */
953 char is_hor_space[256];
956 * initialize random junk in the hash table and maybe other places
958 initialize_random_junk ()
963 * Set up is_idchar and is_idstart tables. These should be
964 * faster than saying (is_alpha (c) || c == '_'), etc.
965 * Must do set up these things before calling any routines tthat
968 for (i = 'a'; i <= 'z'; i++) {
969 ++is_idchar[i - 'a' + 'A'];
971 ++is_idstart[i - 'a' + 'A'];
974 for (i = '0'; i <= '9'; i++)
978 #if DOLLARS_IN_IDENTIFIERS
983 /* horizontal space table */
985 ++is_hor_space['\t'];
990 printf ("error: %s\n", msg);
995 printf ("warning: %s\n", msg);
999 lookup (name, len, hash)
1004 return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);