]> gcc.gnu.org Git - gcc.git/blob - gcc/cexp.y
* cppinit.c: Fix thinko in previous patch.
[gcc.git] / gcc / cexp.y
1 /* Parse C expressions for CCCP.
2 Copyright (C) 1987, 1992, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000 Free Software Foundation.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23
24 Adapted from expread.y of GDB by Paul Rubin, July 1986. */
25
26 /* Parse a C expression from text in a string */
27
28 %{
29 #include "config.h"
30
31 #include "system.h"
32 #include "intl.h"
33 #include <setjmp.h>
34 /* #define YYDEBUG 1 */
35
36 #ifdef MULTIBYTE_CHARS
37 #include "mbchar.h"
38 #include <locale.h>
39 #endif /* MULTIBYTE_CHARS */
40
41 typedef unsigned char U_CHAR;
42
43 /* This is used for communicating lists of keywords with cccp.c. */
44 struct arglist {
45 struct arglist *next;
46 U_CHAR *name;
47 int length;
48 int argno;
49 };
50
51 HOST_WIDEST_INT parse_c_expression PARAMS ((char *, int));
52
53 static int yylex PARAMS ((void));
54 static void yyerror PARAMS ((const char *, ...))
55 ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
56 static HOST_WIDEST_INT expression_value;
57 #ifdef TEST_EXP_READER
58 static int expression_signedp;
59 #endif
60
61 static jmp_buf parse_return_error;
62
63 /* Nonzero means count most punctuation as part of a name. */
64 static int keyword_parsing = 0;
65
66 /* Nonzero means do not evaluate this expression.
67 This is a count, since unevaluated expressions can nest. */
68 static int skip_evaluation;
69
70 /* Nonzero means warn if undefined identifiers are evaluated. */
71 static int warn_undef;
72
73 /* some external tables of character types */
74 extern unsigned char is_idstart[], is_idchar[], is_space[];
75
76 /* Flag for -pedantic. */
77 extern int pedantic;
78
79 /* Flag for -traditional. */
80 extern int traditional;
81
82 /* Flag for -lang-c89. */
83 extern int c89;
84
85 #ifndef CHAR_TYPE_SIZE
86 #define CHAR_TYPE_SIZE BITS_PER_UNIT
87 #endif
88
89 #ifndef INT_TYPE_SIZE
90 #define INT_TYPE_SIZE BITS_PER_WORD
91 #endif
92
93 #ifndef LONG_TYPE_SIZE
94 #define LONG_TYPE_SIZE BITS_PER_WORD
95 #endif
96
97 #ifndef WCHAR_TYPE_SIZE
98 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
99 #endif
100
101 #ifndef MAX_CHAR_TYPE_SIZE
102 #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
103 #endif
104
105 #ifndef MAX_INT_TYPE_SIZE
106 #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE
107 #endif
108
109 #ifndef MAX_LONG_TYPE_SIZE
110 #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
111 #endif
112
113 #ifndef MAX_WCHAR_TYPE_SIZE
114 #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
115 #endif
116
117 #define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
118 ? (~ (~ (HOST_WIDEST_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
119 : ~ (HOST_WIDEST_INT) 0)
120
121 #define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
122 ? ~ (~ (HOST_WIDEST_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
123 : ~ (HOST_WIDEST_INT) 0)
124
125 /* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
126 Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
127 Suppose SIGNEDP is negative if the result is signed, zero if unsigned.
128 Then this yields nonzero if overflow occurred during the addition.
129 Overflow occurs if A and B have the same sign, but A and SUM differ in sign,
130 and SIGNEDP is negative.
131 Use `^' to test whether signs differ, and `< 0' to isolate the sign. */
132 #define overflow_sum_sign(a, b, sum, signedp) \
133 ((~((a) ^ (b)) & ((a) ^ (sum)) & (signedp)) < 0)
134
135 struct constant;
136
137 HOST_WIDEST_INT parse_escape PARAMS ((char **, HOST_WIDEST_INT));
138 int check_assertion PARAMS ((U_CHAR *, int, int, struct arglist *));
139 struct hashnode *lookup PARAMS ((U_CHAR *, int, int));
140 void error PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
141 void verror PARAMS ((const char *, va_list));
142 void pedwarn PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
143 void warning PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
144
145 static int parse_number PARAMS ((int));
146 static HOST_WIDEST_INT left_shift PARAMS ((struct constant *, unsigned HOST_WIDEST_INT));
147 static HOST_WIDEST_INT right_shift PARAMS ((struct constant *, unsigned HOST_WIDEST_INT));
148 static void integer_overflow PARAMS ((void));
149
150 /* `signedp' values */
151 #define SIGNED (~0)
152 #define UNSIGNED 0
153 %}
154
155 %union {
156 struct constant {HOST_WIDEST_INT value; int signedp;} integer;
157 struct name {U_CHAR *address; int length;} name;
158 struct arglist *keywords;
159 }
160
161 %type <integer> exp exp1 start
162 %type <keywords> keywords
163 %token <integer> INT CHAR
164 %token <name> NAME
165 %token <integer> ERROR
166
167 %right '?' ':'
168 %left ','
169 %left OR
170 %left AND
171 %left '|'
172 %left '^'
173 %left '&'
174 %left EQUAL NOTEQUAL
175 %left '<' '>' LEQ GEQ
176 %left LSH RSH
177 %left '+' '-'
178 %left '*' '/' '%'
179 %right UNARY
180
181 /* %expect 40 */
182 \f
183 %%
184
185 start : exp1
186 {
187 expression_value = $1.value;
188 #ifdef TEST_EXP_READER
189 expression_signedp = $1.signedp;
190 #endif
191 }
192 ;
193
194 /* Expressions, including the comma operator. */
195 exp1 : exp
196 | exp1 ',' exp
197 { if (pedantic)
198 pedwarn ("comma operator in operand of `#if'");
199 $$ = $3; }
200 ;
201
202 /* Expressions, not including the comma operator. */
203 exp : '-' exp %prec UNARY
204 { $$.value = - $2.value;
205 $$.signedp = $2.signedp;
206 if (($$.value & $2.value & $$.signedp) < 0)
207 integer_overflow (); }
208 | '!' exp %prec UNARY
209 { $$.value = ! $2.value;
210 $$.signedp = SIGNED; }
211 | '+' exp %prec UNARY
212 { $$ = $2; }
213 | '~' exp %prec UNARY
214 { $$.value = ~ $2.value;
215 $$.signedp = $2.signedp; }
216 | '#' NAME
217 { $$.value = check_assertion ($2.address, $2.length,
218 0, NULL_PTR);
219 $$.signedp = SIGNED; }
220 | '#' NAME
221 { keyword_parsing = 1; }
222 '(' keywords ')'
223 { $$.value = check_assertion ($2.address, $2.length,
224 1, $5);
225 keyword_parsing = 0;
226 $$.signedp = SIGNED; }
227 | '(' exp1 ')'
228 { $$ = $2; }
229 ;
230
231 /* Binary operators in order of decreasing precedence. */
232 exp : exp '*' exp
233 { $$.signedp = $1.signedp & $3.signedp;
234 if ($$.signedp)
235 {
236 $$.value = $1.value * $3.value;
237 if ($1.value
238 && ($$.value / $1.value != $3.value
239 || ($$.value & $1.value & $3.value) < 0))
240 integer_overflow ();
241 }
242 else
243 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
244 * $3.value); }
245 | exp '/' exp
246 { if ($3.value == 0)
247 {
248 if (!skip_evaluation)
249 error ("division by zero in #if");
250 $3.value = 1;
251 }
252 $$.signedp = $1.signedp & $3.signedp;
253 if ($$.signedp)
254 {
255 $$.value = $1.value / $3.value;
256 if (($$.value & $1.value & $3.value) < 0)
257 integer_overflow ();
258 }
259 else
260 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
261 / $3.value); }
262 | exp '%' exp
263 { if ($3.value == 0)
264 {
265 if (!skip_evaluation)
266 error ("division by zero in #if");
267 $3.value = 1;
268 }
269 $$.signedp = $1.signedp & $3.signedp;
270 if ($$.signedp)
271 $$.value = $1.value % $3.value;
272 else
273 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
274 % $3.value); }
275 | exp '+' exp
276 { $$.value = $1.value + $3.value;
277 $$.signedp = $1.signedp & $3.signedp;
278 if (overflow_sum_sign ($1.value, $3.value,
279 $$.value, $$.signedp))
280 integer_overflow (); }
281 | exp '-' exp
282 { $$.value = $1.value - $3.value;
283 $$.signedp = $1.signedp & $3.signedp;
284 if (overflow_sum_sign ($$.value, $3.value,
285 $1.value, $$.signedp))
286 integer_overflow (); }
287 | exp LSH exp
288 { $$.signedp = $1.signedp;
289 if (($3.value & $3.signedp) < 0)
290 $$.value = right_shift (&$1, -$3.value);
291 else
292 $$.value = left_shift (&$1, $3.value); }
293 | exp RSH exp
294 { $$.signedp = $1.signedp;
295 if (($3.value & $3.signedp) < 0)
296 $$.value = left_shift (&$1, -$3.value);
297 else
298 $$.value = right_shift (&$1, $3.value); }
299 | exp EQUAL exp
300 { $$.value = ($1.value == $3.value);
301 $$.signedp = SIGNED; }
302 | exp NOTEQUAL exp
303 { $$.value = ($1.value != $3.value);
304 $$.signedp = SIGNED; }
305 | exp LEQ exp
306 { $$.signedp = SIGNED;
307 if ($1.signedp & $3.signedp)
308 $$.value = $1.value <= $3.value;
309 else
310 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
311 <= $3.value); }
312 | exp GEQ exp
313 { $$.signedp = SIGNED;
314 if ($1.signedp & $3.signedp)
315 $$.value = $1.value >= $3.value;
316 else
317 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
318 >= $3.value); }
319 | exp '<' exp
320 { $$.signedp = SIGNED;
321 if ($1.signedp & $3.signedp)
322 $$.value = $1.value < $3.value;
323 else
324 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
325 < $3.value); }
326 | exp '>' exp
327 { $$.signedp = SIGNED;
328 if ($1.signedp & $3.signedp)
329 $$.value = $1.value > $3.value;
330 else
331 $$.value = ((unsigned HOST_WIDEST_INT) $1.value
332 > $3.value); }
333 | exp '&' exp
334 { $$.value = $1.value & $3.value;
335 $$.signedp = $1.signedp & $3.signedp; }
336 | exp '^' exp
337 { $$.value = $1.value ^ $3.value;
338 $$.signedp = $1.signedp & $3.signedp; }
339 | exp '|' exp
340 { $$.value = $1.value | $3.value;
341 $$.signedp = $1.signedp & $3.signedp; }
342 | exp AND
343 { skip_evaluation += !$1.value; }
344 exp
345 { skip_evaluation -= !$1.value;
346 $$.value = ($1.value && $4.value);
347 $$.signedp = SIGNED; }
348 | exp OR
349 { skip_evaluation += !!$1.value; }
350 exp
351 { skip_evaluation -= !!$1.value;
352 $$.value = ($1.value || $4.value);
353 $$.signedp = SIGNED; }
354 | exp '?'
355 { skip_evaluation += !$1.value; }
356 exp ':'
357 { skip_evaluation += !!$1.value - !$1.value; }
358 exp
359 { skip_evaluation -= !!$1.value;
360 $$.value = $1.value ? $4.value : $7.value;
361 $$.signedp = $4.signedp & $7.signedp; }
362 | INT
363 { $$ = yylval.integer; }
364 | CHAR
365 { $$ = yylval.integer; }
366 | NAME
367 { if (warn_undef && !skip_evaluation)
368 warning ("`%.*s' is not defined",
369 $1.length, $1.address);
370 $$.value = 0;
371 $$.signedp = SIGNED; }
372 ;
373
374 keywords :
375 { $$ = 0; }
376 | '(' keywords ')' keywords
377 { struct arglist *temp;
378 $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
379 $$->next = $2;
380 $$->name = (U_CHAR *) "(";
381 $$->length = 1;
382 temp = $$;
383 while (temp != 0 && temp->next != 0)
384 temp = temp->next;
385 temp->next = (struct arglist *) xmalloc (sizeof (struct arglist));
386 temp->next->next = $4;
387 temp->next->name = (U_CHAR *) ")";
388 temp->next->length = 1; }
389 | NAME keywords
390 { $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
391 $$->name = $1.address;
392 $$->length = $1.length;
393 $$->next = $2; }
394 ;
395 %%
396 \f
397 /* During parsing of a C expression, the pointer to the next character
398 is in this variable. */
399
400 static char *lexptr;
401
402 /* Take care of parsing a number (anything that starts with a digit).
403 Set yylval and return the token type; update lexptr.
404 LEN is the number of characters in it. */
405
406 /* maybe needs to actually deal with floating point numbers */
407
408 static int
409 parse_number (olen)
410 int olen;
411 {
412 register char *p = lexptr;
413 register int c;
414 register unsigned HOST_WIDEST_INT n = 0, nd, max_over_base;
415 register int base = 10;
416 register int len = olen;
417 register int overflow = 0;
418 register int digit, largest_digit = 0;
419 int spec_long = 0;
420
421 yylval.integer.signedp = SIGNED;
422
423 if (*p == '0') {
424 base = 8;
425 if (len >= 3 && (p[1] == 'x' || p[1] == 'X')) {
426 p += 2;
427 base = 16;
428 len -= 2;
429 }
430 }
431
432 max_over_base = (unsigned HOST_WIDEST_INT) -1 / base;
433
434 for (; len > 0; len--) {
435 c = *p++;
436
437 if (c >= '0' && c <= '9')
438 digit = c - '0';
439 else if (base == 16 && c >= 'a' && c <= 'f')
440 digit = c - 'a' + 10;
441 else if (base == 16 && c >= 'A' && c <= 'F')
442 digit = c - 'A' + 10;
443 else {
444 /* `l' means long, and `u' means unsigned. */
445 while (1) {
446 if (c == 'l' || c == 'L')
447 {
448 if (!pedantic < spec_long)
449 yyerror ("too many `l's in integer constant");
450 spec_long++;
451 }
452 else if (c == 'u' || c == 'U')
453 {
454 if (! yylval.integer.signedp)
455 yyerror ("two `u's in integer constant");
456 yylval.integer.signedp = UNSIGNED;
457 }
458 else {
459 if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P')
460 yyerror ("Floating point numbers not allowed in #if expressions");
461 else
462 yyerror ("missing white space after number `%.*s'",
463 (int) (p - lexptr - 1), lexptr);
464 }
465
466 if (--len == 0)
467 break;
468 c = *p++;
469 }
470 /* Don't look for any more digits after the suffixes. */
471 break;
472 }
473 if (largest_digit < digit)
474 largest_digit = digit;
475 nd = n * base + digit;
476 overflow |= (max_over_base < n) | (nd < n);
477 n = nd;
478 }
479
480 if (base <= largest_digit)
481 pedwarn ("integer constant contains digits beyond the radix");
482
483 if (overflow)
484 pedwarn ("integer constant out of range");
485
486 /* If too big to be signed, consider it unsigned. */
487 if (((HOST_WIDEST_INT) n & yylval.integer.signedp) < 0)
488 {
489 if (base == 10)
490 warning ("integer constant is so large that it is unsigned");
491 yylval.integer.signedp = UNSIGNED;
492 }
493
494 lexptr = p;
495 yylval.integer.value = n;
496 return INT;
497 }
498
499 struct token {
500 const char *operator;
501 int token;
502 };
503
504 static struct token tokentab2[] = {
505 {"&&", AND},
506 {"||", OR},
507 {"<<", LSH},
508 {">>", RSH},
509 {"==", EQUAL},
510 {"!=", NOTEQUAL},
511 {"<=", LEQ},
512 {">=", GEQ},
513 {"++", ERROR},
514 {"--", ERROR},
515 {NULL, ERROR}
516 };
517
518 /* Read one token, getting characters through lexptr. */
519
520 static int
521 yylex ()
522 {
523 register int c;
524 register int namelen;
525 register unsigned char *tokstart;
526 register struct token *toktab;
527 int wide_flag;
528 HOST_WIDEST_INT mask;
529
530 retry:
531
532 tokstart = (unsigned char *) lexptr;
533 c = *tokstart;
534 /* See if it is a special token of length 2. */
535 if (! keyword_parsing)
536 for (toktab = tokentab2; toktab->operator != NULL; toktab++)
537 if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
538 lexptr += 2;
539 if (toktab->token == ERROR)
540 yyerror ("`%s' not allowed in operand of `#if'", toktab->operator);
541 return toktab->token;
542 }
543
544 switch (c) {
545 case '\n':
546 return 0;
547
548 case ' ':
549 case '\t':
550 case '\r':
551 lexptr++;
552 goto retry;
553
554 case 'L':
555 /* Capital L may start a wide-string or wide-character constant. */
556 if (lexptr[1] == '\'')
557 {
558 lexptr++;
559 wide_flag = 1;
560 mask = MAX_WCHAR_TYPE_MASK;
561 goto char_constant;
562 }
563 if (lexptr[1] == '"')
564 {
565 lexptr++;
566 wide_flag = 1;
567 mask = MAX_WCHAR_TYPE_MASK;
568 goto string_constant;
569 }
570 break;
571
572 case '\'':
573 wide_flag = 0;
574 mask = MAX_CHAR_TYPE_MASK;
575 char_constant:
576 lexptr++;
577 if (keyword_parsing) {
578 char *start_ptr = lexptr - 1;
579 while (1) {
580 c = *lexptr++;
581 if (c == '\\')
582 c = parse_escape (&lexptr, mask);
583 else if (c == '\'')
584 break;
585 }
586 yylval.name.address = tokstart;
587 yylval.name.length = lexptr - start_ptr;
588 return NAME;
589 }
590
591 /* This code for reading a character constant
592 handles multicharacter constants and wide characters.
593 It is mostly copied from c-lex.c. */
594 {
595 register HOST_WIDEST_INT result = 0;
596 register int num_chars = 0;
597 int chars_seen = 0;
598 unsigned width = MAX_CHAR_TYPE_SIZE;
599 int max_chars;
600 #ifdef MULTIBYTE_CHARS
601 int longest_char = local_mb_cur_max ();
602 char *token_buffer = (char *) alloca (longest_char);
603 (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
604 #endif
605
606 max_chars = MAX_LONG_TYPE_SIZE / width;
607 if (wide_flag)
608 width = MAX_WCHAR_TYPE_SIZE;
609
610 while (1)
611 {
612 c = *lexptr++;
613
614 if (c == '\'' || c == EOF)
615 break;
616
617 ++chars_seen;
618 if (c == '\\')
619 {
620 c = parse_escape (&lexptr, mask);
621 }
622 else
623 {
624 #ifdef MULTIBYTE_CHARS
625 wchar_t wc;
626 int i;
627 int char_len = -1;
628 for (i = 1; i <= longest_char; ++i)
629 {
630 token_buffer[i - 1] = c;
631 char_len = local_mbtowc (& wc, token_buffer, i);
632 if (char_len != -1)
633 break;
634 c = *lexptr++;
635 }
636 if (char_len > 1)
637 {
638 /* mbtowc sometimes needs an extra char before accepting */
639 if (char_len < i)
640 lexptr--;
641 if (! wide_flag)
642 {
643 /* Merge character into result; ignore excess chars. */
644 for (i = 1; i <= char_len; ++i)
645 {
646 if (i > max_chars)
647 break;
648 if (width < HOST_BITS_PER_INT)
649 result = (result << width)
650 | (token_buffer[i - 1]
651 & ((1 << width) - 1));
652 else
653 result = token_buffer[i - 1];
654 }
655 num_chars += char_len;
656 continue;
657 }
658 }
659 else
660 {
661 if (char_len == -1)
662 warning ("Ignoring invalid multibyte character");
663 }
664 if (wide_flag)
665 c = wc;
666 #endif /* ! MULTIBYTE_CHARS */
667 }
668
669 if (wide_flag)
670 {
671 if (chars_seen == 1) /* only keep the first one */
672 result = c;
673 continue;
674 }
675
676 /* Merge character into result; ignore excess chars. */
677 num_chars++;
678 if (num_chars <= max_chars)
679 {
680 if (width < HOST_BITS_PER_INT)
681 result = (result << width) | (c & ((1 << width) - 1));
682 else
683 result = c;
684 }
685 }
686
687 if (c != '\'')
688 error ("malformatted character constant");
689 else if (chars_seen == 0)
690 error ("empty character constant");
691 else if (num_chars > max_chars)
692 {
693 num_chars = max_chars;
694 error ("character constant too long");
695 }
696 else if (chars_seen != 1 && ! traditional)
697 warning ("multi-character character constant");
698
699 /* If char type is signed, sign-extend the constant. */
700 if (! wide_flag)
701 {
702 int num_bits = num_chars * width;
703 if (num_bits == 0)
704 /* We already got an error; avoid invalid shift. */
705 yylval.integer.value = 0;
706 else if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
707 sizeof ("__CHAR_UNSIGNED__") - 1, -1)
708 || ((result >> (num_bits - 1)) & 1) == 0)
709 yylval.integer.value
710 = result & (~ (unsigned HOST_WIDEST_INT) 0
711 >> (HOST_BITS_PER_WIDEST_INT - num_bits));
712 else
713 yylval.integer.value
714 = result | ~(~ (unsigned HOST_WIDEST_INT) 0
715 >> (HOST_BITS_PER_WIDEST_INT - num_bits));
716 }
717 else
718 {
719 yylval.integer.value = result;
720 }
721 }
722
723 /* This is always a signed type. */
724 yylval.integer.signedp = SIGNED;
725
726 return CHAR;
727
728 /* some of these chars are invalid in constant expressions;
729 maybe do something about them later */
730 case '/':
731 case '+':
732 case '-':
733 case '*':
734 case '%':
735 case '|':
736 case '&':
737 case '^':
738 case '~':
739 case '!':
740 case '@':
741 case '<':
742 case '>':
743 case '[':
744 case ']':
745 case '.':
746 case '?':
747 case ':':
748 case '=':
749 case '{':
750 case '}':
751 case ',':
752 case '#':
753 if (keyword_parsing)
754 break;
755 case '(':
756 case ')':
757 lexptr++;
758 return c;
759
760 case '"':
761 mask = MAX_CHAR_TYPE_MASK;
762 string_constant:
763 if (keyword_parsing) {
764 char *start_ptr = lexptr;
765 lexptr++;
766 while (1) {
767 c = *lexptr++;
768 if (c == '\\')
769 c = parse_escape (&lexptr, mask);
770 else if (c == '"')
771 break;
772 }
773 yylval.name.address = tokstart;
774 yylval.name.length = lexptr - start_ptr;
775 return NAME;
776 }
777 yyerror ("string constants not allowed in #if expressions");
778 return ERROR;
779 }
780
781 if (c >= '0' && c <= '9' && !keyword_parsing) {
782 /* It's a number */
783 for (namelen = 1; ; namelen++) {
784 int d = tokstart[namelen];
785 if (! ((is_idchar[d] || d == '.')
786 || ((d == '-' || d == '+')
787 && (c == 'e' || c == 'E'
788 || ((c == 'p' || c == 'P') && ! c89))
789 && ! traditional)))
790 break;
791 c = d;
792 }
793 return parse_number (namelen);
794 }
795
796 /* It is a name. See how long it is. */
797
798 if (keyword_parsing) {
799 for (namelen = 0;; namelen++) {
800 if (is_space[tokstart[namelen]])
801 break;
802 if (tokstart[namelen] == '(' || tokstart[namelen] == ')')
803 break;
804 if (tokstart[namelen] == '"' || tokstart[namelen] == '\'')
805 break;
806 }
807 } else {
808 if (!is_idstart[c]) {
809 yyerror ("Invalid token in expression");
810 return ERROR;
811 }
812
813 for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
814 ;
815 }
816
817 lexptr += namelen;
818 yylval.name.address = tokstart;
819 yylval.name.length = namelen;
820 return NAME;
821 }
822
823
824 /* Parse a C escape sequence. STRING_PTR points to a variable
825 containing a pointer to the string to parse. That pointer
826 is updated past the characters we use. The value of the
827 escape sequence is returned.
828
829 RESULT_MASK is used to mask out the result;
830 an error is reported if bits are lost thereby.
831
832 A negative value means the sequence \ newline was seen,
833 which is supposed to be equivalent to nothing at all.
834
835 If \ is followed by a null character, we return a negative
836 value and leave the string pointer pointing at the null character.
837
838 If \ is followed by 000, we return 0 and leave the string pointer
839 after the zeros. A value of 0 does not mean end of string. */
840
841 HOST_WIDEST_INT
842 parse_escape (string_ptr, result_mask)
843 char **string_ptr;
844 HOST_WIDEST_INT result_mask;
845 {
846 register int c = *(*string_ptr)++;
847 switch (c)
848 {
849 case 'a':
850 return TARGET_BELL;
851 case 'b':
852 return TARGET_BS;
853 case 'e':
854 case 'E':
855 if (pedantic)
856 pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
857 return TARGET_ESC;
858 case 'f':
859 return TARGET_FF;
860 case 'n':
861 return TARGET_NEWLINE;
862 case 'r':
863 return TARGET_CR;
864 case 't':
865 return TARGET_TAB;
866 case 'v':
867 return TARGET_VT;
868 case '\n':
869 return -2;
870 case 0:
871 (*string_ptr)--;
872 return 0;
873
874 case '0':
875 case '1':
876 case '2':
877 case '3':
878 case '4':
879 case '5':
880 case '6':
881 case '7':
882 {
883 register HOST_WIDEST_INT i = c - '0';
884 register int count = 0;
885 while (++count < 3)
886 {
887 c = *(*string_ptr)++;
888 if (c >= '0' && c <= '7')
889 i = (i << 3) + c - '0';
890 else
891 {
892 (*string_ptr)--;
893 break;
894 }
895 }
896 if (i != (i & result_mask))
897 {
898 i &= result_mask;
899 pedwarn ("octal escape sequence out of range");
900 }
901 return i;
902 }
903 case 'x':
904 {
905 register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
906 register int digits_found = 0, digit;
907 for (;;)
908 {
909 c = *(*string_ptr)++;
910 if (c >= '0' && c <= '9')
911 digit = c - '0';
912 else if (c >= 'a' && c <= 'f')
913 digit = c - 'a' + 10;
914 else if (c >= 'A' && c <= 'F')
915 digit = c - 'A' + 10;
916 else
917 {
918 (*string_ptr)--;
919 break;
920 }
921 overflow |= i ^ (i << 4 >> 4);
922 i = (i << 4) + digit;
923 digits_found = 1;
924 }
925 if (!digits_found)
926 yyerror ("\\x used with no following hex digits");
927 if (overflow | (i != (i & result_mask)))
928 {
929 i &= result_mask;
930 pedwarn ("hex escape sequence out of range");
931 }
932 return i;
933 }
934 default:
935 return c;
936 }
937 }
938
939 static void
940 integer_overflow ()
941 {
942 if (!skip_evaluation && pedantic)
943 pedwarn ("integer overflow in preprocessor expression");
944 }
945
946 static HOST_WIDEST_INT
947 left_shift (a, b)
948 struct constant *a;
949 unsigned HOST_WIDEST_INT b;
950 {
951 /* It's unclear from the C standard whether shifts can overflow.
952 The following code ignores overflow; perhaps a C standard
953 interpretation ruling is needed. */
954 if (b >= HOST_BITS_PER_WIDEST_INT)
955 return 0;
956 else
957 return (unsigned HOST_WIDEST_INT) a->value << b;
958 }
959
960 static HOST_WIDEST_INT
961 right_shift (a, b)
962 struct constant *a;
963 unsigned HOST_WIDEST_INT b;
964 {
965 if (b >= HOST_BITS_PER_WIDEST_INT)
966 return a->signedp ? a->value >> (HOST_BITS_PER_WIDEST_INT - 1) : 0;
967 else if (a->signedp)
968 return a->value >> b;
969 else
970 return (unsigned HOST_WIDEST_INT) a->value >> b;
971 }
972 \f
973 /* This page contains the entry point to this file. */
974
975 /* Parse STRING as an expression, and complain if this fails
976 to use up all of the contents of STRING.
977 STRING may contain '\0' bytes; it is terminated by the first '\n'
978 outside a string constant, so that we can diagnose '\0' properly.
979 If WARN_UNDEFINED is nonzero, warn if undefined identifiers are evaluated.
980 We do not support C comments. They should be removed before
981 this function is called. */
982
983 HOST_WIDEST_INT
984 parse_c_expression (string, warn_undefined)
985 char *string;
986 int warn_undefined;
987 {
988 lexptr = string;
989 warn_undef = warn_undefined;
990
991 /* if there is some sort of scanning error, just return 0 and assume
992 the parsing routine has printed an error message somewhere.
993 there is surely a better thing to do than this. */
994 if (setjmp (parse_return_error))
995 return 0;
996
997 if (yyparse () != 0)
998 abort ();
999
1000 if (*lexptr != '\n')
1001 error ("Junk after end of expression.");
1002
1003 return expression_value; /* set by yyparse () */
1004 }
1005
1006 static void
1007 yyerror VPARAMS ((const char * msgid, ...))
1008 {
1009 #ifndef ANSI_PROTOTYPES
1010 const char * msgid;
1011 #endif
1012 va_list args;
1013
1014 VA_START (args, msgid);
1015
1016 #ifndef ANSI_PROTOTYPES
1017 msgid = va_arg (args, const char *);
1018 #endif
1019
1020 verror (msgid, args);
1021 va_end (args);
1022 skip_evaluation = 0;
1023 longjmp (parse_return_error, 1);
1024 }
1025
1026 \f
1027 #ifdef TEST_EXP_READER
1028
1029 #if YYDEBUG
1030 extern int yydebug;
1031 #endif
1032
1033 int pedantic;
1034 int traditional;
1035 int c89;
1036
1037 int main PARAMS ((int, char **));
1038 static void initialize_random_junk PARAMS ((void));
1039 static void print_unsigned_host_widest_int PARAMS ((unsigned HOST_WIDEST_INT));
1040
1041 /* Main program for testing purposes. */
1042 int
1043 main (argc, argv)
1044 int argc;
1045 char **argv;
1046 {
1047 int n, c;
1048 char buf[1024];
1049 unsigned HOST_WIDEST_INT u;
1050
1051 pedantic = 1 < argc;
1052 traditional = 2 < argc;
1053 c89 = 3 < argc;
1054 #if YYDEBUG
1055 yydebug = 4 < argc;
1056 #endif
1057 initialize_random_junk ();
1058
1059 for (;;) {
1060 printf ("enter expression: ");
1061 n = 0;
1062 while ((buf[n] = c = getchar ()) != '\n' && c != EOF)
1063 n++;
1064 if (c == EOF)
1065 break;
1066 parse_c_expression (buf, 1);
1067 printf ("parser returned ");
1068 u = (unsigned HOST_WIDEST_INT) expression_value;
1069 if (expression_value < 0 && expression_signedp) {
1070 u = -u;
1071 printf ("-");
1072 }
1073 if (u == 0)
1074 printf ("0");
1075 else
1076 print_unsigned_host_widest_int (u);
1077 if (! expression_signedp)
1078 printf("u");
1079 printf ("\n");
1080 }
1081
1082 return 0;
1083 }
1084
1085 static void
1086 print_unsigned_host_widest_int (u)
1087 unsigned HOST_WIDEST_INT u;
1088 {
1089 if (u) {
1090 print_unsigned_host_widest_int (u / 10);
1091 putchar ('0' + (int) (u % 10));
1092 }
1093 }
1094
1095 /* table to tell if char can be part of a C identifier. */
1096 unsigned char is_idchar[256];
1097 /* table to tell if char can be first char of a c identifier. */
1098 unsigned char is_idstart[256];
1099 /* table to tell if c is horizontal or vertical space. */
1100 unsigned char is_space[256];
1101
1102 /*
1103 * initialize random junk in the hash table and maybe other places
1104 */
1105 static void
1106 initialize_random_junk ()
1107 {
1108 register int i;
1109
1110 /*
1111 * Set up is_idchar and is_idstart tables. These should be
1112 * faster than saying (is_alpha (c) || c == '_'), etc.
1113 * Must do set up these things before calling any routines tthat
1114 * refer to them.
1115 */
1116 for (i = 'a'; i <= 'z'; i++) {
1117 ++is_idchar[TOUPPER(i)];
1118 ++is_idchar[i];
1119 ++is_idstart[TOUPPER(i)];
1120 ++is_idstart[i];
1121 }
1122 for (i = '0'; i <= '9'; i++)
1123 ++is_idchar[i];
1124 ++is_idchar['_'];
1125 ++is_idstart['_'];
1126 ++is_idchar['$'];
1127 ++is_idstart['$'];
1128
1129 ++is_space[' '];
1130 ++is_space['\t'];
1131 ++is_space['\v'];
1132 ++is_space['\f'];
1133 ++is_space['\n'];
1134 ++is_space['\r'];
1135 }
1136
1137 void
1138 error VPARAMS ((char * msgid, ...))
1139 {
1140 #ifndef ANSI_PROTOTYPES
1141 char * msgid;
1142 #endif
1143 va_list args;
1144
1145 VA_START (args, msgid);
1146
1147 #ifndef ANSI_PROTOTYPES
1148 msgid = va_arg (args, char *);
1149 #endif
1150
1151 fprintf (stderr, "error: ");
1152 vfprintf (stderr, _(msgid), args);
1153 fprintf (stderr, "\n");
1154 va_end (args);
1155 }
1156
1157 void
1158 pedwarn VPARAMS ((char * msgid, ...))
1159 {
1160 #ifndef ANSI_PROTOTYPES
1161 char * msgid;
1162 #endif
1163 va_list args;
1164
1165 VA_START (args, msgid);
1166
1167 #ifndef ANSI_PROTOTYPES
1168 msgid = va_arg (args, char *);
1169 #endif
1170
1171 fprintf (stderr, "pedwarn: ");
1172 vfprintf (stderr, _(msgid), args);
1173 fprintf (stderr, "\n");
1174 va_end (args);
1175 }
1176
1177 void
1178 warning VPARAMS ((char * msgid, ...))
1179 {
1180 #ifndef ANSI_PROTOTYPES
1181 char * msgid;
1182 #endif
1183 va_list args;
1184
1185 VA_START (args, msgid);
1186
1187 #ifndef ANSI_PROTOTYPES
1188 msgid = va_arg (args, char *);
1189 #endif
1190
1191 fprintf (stderr, "warning: ");
1192 vfprintf (stderr, _(msgid), args);
1193 fprintf (stderr, "\n");
1194 va_end (args);
1195 }
1196
1197
1198 int
1199 check_assertion (name, sym_length, tokens_specified, tokens)
1200 U_CHAR *name;
1201 int sym_length;
1202 int tokens_specified;
1203 struct arglist *tokens;
1204 {
1205 return 0;
1206 }
1207
1208 struct hashnode *
1209 lookup (name, len, hash)
1210 U_CHAR *name;
1211 int len;
1212 int hash;
1213 {
1214 return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
1215 }
1216
1217 PTR
1218 xmalloc (size)
1219 size_t size;
1220 {
1221 return (PTR) malloc (size);
1222 }
1223 #endif
This page took 0.090234 seconds and 5 git commands to generate.