]> code.delx.au - gnu-emacs/blob - test/manual/etags/y-src/cccp.y
; Merge from origin/emacs-25
[gnu-emacs] / test / manual / etags / y-src / cccp.y
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
22 Adapted from expread.y of GDB by Paul Rubin, July 1986. */
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
36 #include <stdio.h>
37
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
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
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
78 extern char *xmalloc ();
79
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
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 ();
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 \f
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;
158 if (($$.value & $2.value) < 0 && ! $2.unsignedp)
159 integer_overflow ();
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,
171 0, NULL_PTR);
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)
188 $$.value = (unsigned long) $1.value * $3.value;
189 else
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 } }
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)
205 $$.value = (unsigned long) $1.value / $3.value;
206 else
207 {
208 $$.value = $1.value / $3.value;
209 if (($$.value & $1.value & $3.value) < 0)
210 integer_overflow ();
211 } }
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)
220 $$.value = (unsigned long) $1.value % $3.value;
221 else
222 $$.value = $1.value % $3.value; }
223 | exp '+' exp
224 { $$.value = $1.value + $3.value;
225 $$.unsignedp = $1.unsignedp || $3.unsignedp;
226 if (! $$.unsignedp
227 && ! possible_sum_sign ($1.value, $3.value,
228 $$.value))
229 integer_overflow (); }
230 | exp '-' exp
231 { $$.value = $1.value - $3.value;
232 $$.unsignedp = $1.unsignedp || $3.unsignedp;
233 if (! $$.unsignedp
234 && ! possible_sum_sign ($$.value, $3.value,
235 $1.value))
236 integer_overflow (); }
237 | exp LSH exp
238 { $$.unsignedp = $1.unsignedp;
239 if ($3.value < 0 && ! $3.unsignedp)
240 $$.value = right_shift (&$1, -$3.value);
241 else
242 $$.value = left_shift (&$1, $3.value); }
243 | exp RSH exp
244 { $$.unsignedp = $1.unsignedp;
245 if ($3.value < 0 && ! $3.unsignedp)
246 $$.value = left_shift (&$1, -$3.value);
247 else
248 $$.value = right_shift (&$1, $3.value); }
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)
258 $$.value = (unsigned long) $1.value <= $3.value;
259 else
260 $$.value = $1.value <= $3.value; }
261 | exp GEQ exp
262 { $$.unsignedp = 0;
263 if ($1.unsignedp || $3.unsignedp)
264 $$.value = (unsigned long) $1.value >= $3.value;
265 else
266 $$.value = $1.value >= $3.value; }
267 | exp '<' exp
268 { $$.unsignedp = 0;
269 if ($1.unsignedp || $3.unsignedp)
270 $$.value = (unsigned long) $1.value < $3.value;
271 else
272 $$.value = $1.value < $3.value; }
273 | exp '>' exp
274 { $$.unsignedp = 0;
275 if ($1.unsignedp || $3.unsignedp)
276 $$.value = (unsigned long) $1.value > $3.value;
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 \f
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;
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;
351 int spec_long = 0;
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
370 ULONG_MAX_over_base = (unsigned long) -1 / base;
371
372 for (; len > 0; len--) {
373 c = *p++;
374
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 {
382 /* `l' means long, and `u' means unsigned. */
383 while (1) {
384 if (c == 'l' || c == 'L')
385 {
386 if (spec_long)
387 yyerror ("two `l's in integer constant");
388 spec_long = 1;
389 }
390 else if (c == 'u' || c == 'U')
391 {
392 if (yylval.integer.unsignedp)
393 yyerror ("two `u's in integer constant");
394 yylval.integer.unsignedp = 1;
395 }
396 else
397 break;
398
399 if (--len == 0)
400 break;
401 c = *p++;
402 }
403 /* Don't look for any more digits after the suffixes. */
404 break;
405 }
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;
411 }
412
413 if (len != 0) {
414 yyerror ("Invalid number in #if expression");
415 return ERROR;
416 }
417
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
424 /* If too big to be signed, consider it unsigned. */
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 }
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 unsigned char *tokstart;
464 register struct token *toktab;
465 int wide_flag;
466
467 retry:
468
469 tokstart = (unsigned char *) 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 = 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
604 = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
605 else
606 yylval.integer.value
607 = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
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;
620 (void) mbtowc (NULL_PTR, NULL_PTR, 0);
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 = 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 = 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 case 'E':
752 if (pedantic)
753 pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
754 return 033;
755 case 'f':
756 return TARGET_FF;
757 case 'n':
758 return TARGET_NEWLINE;
759 case 'r':
760 return TARGET_CR;
761 case 't':
762 return TARGET_TAB;
763 case 'v':
764 return TARGET_VT;
765 case '\n':
766 return -2;
767 case 0:
768 (*string_ptr)--;
769 return 0;
770
771 case '0':
772 case '1':
773 case '2':
774 case '3':
775 case '4':
776 case '5':
777 case '6':
778 case '7':
779 {
780 register int i = c - '0';
781 register int count = 0;
782 while (++count < 3)
783 {
784 c = *(*string_ptr)++;
785 if (c >= '0' && c <= '7')
786 i = (i << 3) + c - '0';
787 else
788 {
789 (*string_ptr)--;
790 break;
791 }
792 }
793 if ((i & ~((1 << CHAR_TYPE_SIZE) - 1)) != 0)
794 {
795 i &= (1 << CHAR_TYPE_SIZE) - 1;
796 warning ("octal character constant does not fit in a byte");
797 }
798 return i;
799 }
800 case 'x':
801 {
802 register unsigned i = 0, overflow = 0, digits_found = 0, digit;
803 for (;;)
804 {
805 c = *(*string_ptr)++;
806 if (c >= '0' && c <= '9')
807 digit = c - '0';
808 else if (c >= 'a' && c <= 'f')
809 digit = c - 'a' + 10;
810 else if (c >= 'A' && c <= 'F')
811 digit = c - 'A' + 10;
812 else
813 {
814 (*string_ptr)--;
815 break;
816 }
817 overflow |= i ^ (i << 4 >> 4);
818 i = (i << 4) + digit;
819 digits_found = 1;
820 }
821 if (!digits_found)
822 yyerror ("\\x used with no following hex digits");
823 if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
824 {
825 i &= (1 << BITS_PER_UNIT) - 1;
826 warning ("hex character constant does not fit in a byte");
827 }
828 return i;
829 }
830 default:
831 return c;
832 }
833 }
834
835 void
836 yyerror (s)
837 char *s;
838 {
839 error (s);
840 longjmp (parse_return_error, 1);
841 }
842
843 static void
844 integer_overflow ()
845 {
846 if (pedantic)
847 pedwarn ("integer overflow in preprocessor expression");
848 }
849
850 static long
851 left_shift (a, b)
852 struct constant *a;
853 unsigned long b;
854 {
855 if (b >= HOST_BITS_PER_LONG)
856 {
857 if (! a->unsignedp && a->value != 0)
858 integer_overflow ();
859 return 0;
860 }
861 else if (a->unsignedp)
862 return (unsigned long) a->value << b;
863 else
864 {
865 long l = a->value << b;
866 if (l >> b != a->value)
867 integer_overflow ();
868 return l;
869 }
870 }
871
872 static long
873 right_shift (a, b)
874 struct constant *a;
875 unsigned long b;
876 {
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;
881 else
882 return a->value >> b;
883 }
884 \f
885 /* This page contains the entry point to this file. */
886
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. */
891
892 int
893 parse_c_expression (string)
894 char *string;
895 {
896 lexptr = string;
897
898 if (lexptr == 0 || *lexptr == 0) {
899 error ("empty #if expression");
900 return 0; /* don't include the #if group */
901 }
902
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))
907 return 0;
908
909 if (yyparse ())
910 return 0; /* actually this is never reached
911 the way things stand. */
912 if (*lexptr)
913 error ("Junk after end of expression.");
914
915 return expression_value; /* set by yyparse () */
916 }
917 \f
918 #ifdef TEST_EXP_READER
919 extern int yydebug;
920
921 /* Main program for testing purposes. */
922 int
923 main ()
924 {
925 int n, c;
926 char buf[1024];
927
928 /*
929 yydebug = 1;
930 */
931 initialize_random_junk ();
932
933 for (;;) {
934 printf ("enter expression: ");
935 n = 0;
936 while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF)
937 n++;
938 if (buf[n] == EOF)
939 break;
940 buf[n] = '\0';
941 printf ("parser returned %d\n", parse_c_expression (buf));
942 }
943
944 return 0;
945 }
946
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];
954
955 /*
956 * initialize random junk in the hash table and maybe other places
957 */
958 initialize_random_junk ()
959 {
960 register int i;
961
962 /*
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
966 * refer to them.
967 */
968 for (i = 'a'; i <= 'z'; i++) {
969 ++is_idchar[i - 'a' + 'A'];
970 ++is_idchar[i];
971 ++is_idstart[i - 'a' + 'A'];
972 ++is_idstart[i];
973 }
974 for (i = '0'; i <= '9'; i++)
975 ++is_idchar[i];
976 ++is_idchar['_'];
977 ++is_idstart['_'];
978 #if DOLLARS_IN_IDENTIFIERS
979 ++is_idchar['$'];
980 ++is_idstart['$'];
981 #endif
982
983 /* horizontal space table */
984 ++is_hor_space[' '];
985 ++is_hor_space['\t'];
986 }
987
988 error (msg)
989 {
990 printf ("error: %s\n", msg);
991 }
992
993 warning (msg)
994 {
995 printf ("warning: %s\n", msg);
996 }
997
998 struct hashnode *
999 lookup (name, len, hash)
1000 char *name;
1001 int len;
1002 int hash;
1003 {
1004 return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
1005 }
1006 #endif