OSDN Git Service

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