OSDN Git Service

(call patterns): Use %. in cror.
[pf3gnuchains/gcc-fork.git] / gcc / cexp.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