OSDN Git Service

* pt.c (do_type_instantiation): Add complain parm; don't complain
[pf3gnuchains/gcc-fork.git] / gcc / tradcif.y
1 /* Parse C expressions for CCCP.
2    Copyright (C) 1987 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 1, 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 "system.h"
29 #include <setjmp.h>
30
31   int yylex PARAMS ((void));
32   void yyerror PARAMS ((const char *msgid));
33   extern void error   PARAMS ((const char *msgid, ...));
34   extern void warning PARAMS ((const char *msgid, ...));
35   extern struct hashnode *lookup PARAMS ((const unsigned char *, int, int));
36
37   int parse_number PARAMS ((int));
38   int parse_escape PARAMS ((char **));
39   int parse_c_expression PARAMS ((char *));
40
41   int expression_value;
42   static jmp_buf parse_return_error;
43
44   /* some external tables of character types */
45   extern unsigned char is_idstart[], is_idchar[];
46
47 #ifndef CHAR_TYPE_SIZE
48 #define CHAR_TYPE_SIZE BITS_PER_UNIT
49 #endif
50 %}
51
52 %union {
53   struct constant {long value; int unsignedp;} integer;
54   int voidval;
55   char *sval;
56 }
57
58 %type <integer> exp exp1 start
59 %token <integer> INT CHAR
60 %token <sval> NAME
61 %token <integer> ERROR
62
63 %right '?' ':'
64 %left ','
65 %left OR
66 %left AND
67 %left '|'
68 %left '^'
69 %left '&'
70 %left EQUAL NOTEQUAL
71 %left '<' '>' LEQ GEQ
72 %left LSH RSH
73 %left '+' '-'
74 %left '*' '/' '%'
75 %right UNARY
76
77 /* %expect 40 */
78 \f
79 %%
80
81 start   :       exp1
82                 { expression_value = $1.value; }
83         ;
84
85 /* Expressions, including the comma operator.  */
86 exp1    :       exp
87         |       exp1 ',' exp
88                         { $$ = $3; }
89         ;
90
91 /* Expressions, not including the comma operator.  */
92 exp     :       '-' exp    %prec UNARY
93                         { $$.value = - $2.value;
94                           $$.unsignedp = $2.unsignedp; }
95         |       '!' exp    %prec UNARY
96                         { $$.value = ! $2.value;
97                           $$.unsignedp = 0; }
98         |       '+' exp    %prec UNARY
99                         { $$ = $2; }
100         |       '~' exp    %prec UNARY
101                         { $$.value = ~ $2.value;
102                           $$.unsignedp = $2.unsignedp; }
103         |       '(' exp1 ')'
104                         { $$ = $2; }
105         ;
106
107 /* Binary operators in order of decreasing precedence.  */
108 exp     :       exp '*' exp
109                         { $$.unsignedp = $1.unsignedp || $3.unsignedp;
110                           if ($$.unsignedp)
111                             $$.value = (unsigned) $1.value * $3.value;
112                           else
113                             $$.value = $1.value * $3.value; }
114         |       exp '/' exp
115                         { if ($3.value == 0)
116                             {
117                               error ("division by zero in #if");
118                               $3.value = 1;
119                             }
120                           $$.unsignedp = $1.unsignedp || $3.unsignedp;
121                           if ($$.unsignedp)
122                             $$.value = (unsigned) $1.value / $3.value;
123                           else
124                             $$.value = $1.value / $3.value; }
125         |       exp '%' exp
126                         { if ($3.value == 0)
127                             {
128                               error ("division by zero in #if");
129                               $3.value = 1;
130                             }
131                           $$.unsignedp = $1.unsignedp || $3.unsignedp;
132                           if ($$.unsignedp)
133                             $$.value = (unsigned) $1.value % $3.value;
134                           else
135                             $$.value = $1.value % $3.value; }
136         |       exp '+' exp
137                         { $$.value = $1.value + $3.value;
138                           $$.unsignedp = $1.unsignedp || $3.unsignedp; }
139         |       exp '-' exp
140                         { $$.value = $1.value - $3.value;
141                           $$.unsignedp = $1.unsignedp || $3.unsignedp; }
142         |       exp LSH exp
143                         { $$.unsignedp = $1.unsignedp;
144                           if ($$.unsignedp)
145                             $$.value = (unsigned) $1.value << $3.value;
146                           else
147                             $$.value = $1.value << $3.value; }
148         |       exp RSH exp
149                         { $$.unsignedp = $1.unsignedp;
150                           if ($$.unsignedp)
151                             $$.value = (unsigned) $1.value >> $3.value;
152                           else
153                             $$.value = $1.value >> $3.value; }
154         |       exp EQUAL exp
155                         { $$.value = ($1.value == $3.value);
156                           $$.unsignedp = 0; }
157         |       exp NOTEQUAL exp
158                         { $$.value = ($1.value != $3.value);
159                           $$.unsignedp = 0; }
160         |       exp LEQ exp
161                         { $$.unsignedp = 0;
162                           if ($1.unsignedp || $3.unsignedp)
163                             $$.value =
164                               (unsigned) $1.value <= (unsigned) $3.value;
165                           else
166                             $$.value = $1.value <= $3.value; }
167         |       exp GEQ exp
168                         { $$.unsignedp = 0;
169                           if ($1.unsignedp || $3.unsignedp)
170                             $$.value =
171                               (unsigned) $1.value >= (unsigned) $3.value;
172                           else
173                             $$.value = $1.value >= $3.value; }
174         |       exp '<' exp
175                         { $$.unsignedp = 0;
176                           if ($1.unsignedp || $3.unsignedp)
177                             $$.value =
178                               (unsigned) $1.value < (unsigned) $3.value;
179                           else
180                             $$.value = $1.value < $3.value; }
181         |       exp '>' exp
182                         { $$.unsignedp = 0;
183                           if ($1.unsignedp || $3.unsignedp)
184                             $$.value =
185                               (unsigned) $1.value > (unsigned) $3.value;
186                           else
187                             $$.value = $1.value > $3.value; }
188         |       exp '&' exp
189                         { $$.value = $1.value & $3.value;
190                           $$.unsignedp = $1.unsignedp || $3.unsignedp; }
191         |       exp '^' exp
192                         { $$.value = $1.value ^ $3.value;
193                           $$.unsignedp = $1.unsignedp || $3.unsignedp; }
194         |       exp '|' exp
195                         { $$.value = $1.value | $3.value;
196                           $$.unsignedp = $1.unsignedp || $3.unsignedp; }
197         |       exp AND exp
198                         { $$.value = ($1.value && $3.value);
199                           $$.unsignedp = 0; }
200         |       exp OR exp
201                         { $$.value = ($1.value || $3.value);
202                           $$.unsignedp = 0; }
203         |       exp '?' exp ':' exp
204                         { $$.value = $1.value ? $3.value : $5.value;
205                           $$.unsignedp = $3.unsignedp || $5.unsignedp; }
206         |       INT
207                         { $$ = yylval.integer; }
208         |       CHAR
209                         { $$ = yylval.integer; }
210         |       NAME
211                         { $$.value = 0;
212                           $$.unsignedp = 0; }
213         ;
214 %%
215 \f
216 /* During parsing of a C expression, the pointer to the next character
217    is in this variable.  */
218
219 static char *lexptr;
220
221 /* Take care of parsing a number (anything that starts with a digit).
222    Set yylval and return the token type; update lexptr.
223    LEN is the number of characters in it.  */
224
225 /* maybe needs to actually deal with floating point numbers */
226
227 int
228 parse_number (olen)
229      int olen;
230 {
231   register char *p = lexptr;
232   register long n = 0;
233   register int c;
234   register int base = 10;
235   register int len = olen;
236
237   for (c = 0; c < len; c++)
238     if (p[c] == '.') {
239       /* It's a float since it contains a point.  */
240       yyerror ("floating point numbers not allowed in #if expressions");
241       return ERROR;
242     }
243
244   yylval.integer.unsignedp = 0;
245
246   if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
247     p += 2;
248     base = 16;
249     len -= 2;
250   }
251   else if (*p == '0')
252     base = 8;
253
254   while (len > 0) {
255     c = *p++;
256     len--;
257     if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
258
259     if (c >= '0' && c <= '9') {
260       n *= base;
261       n += c - '0';
262     } else if (base == 16 && c >= 'a' && c <= 'f') {
263       n *= base;
264       n += c - 'a' + 10;
265     } else {
266       /* `l' means long, and `u' means unsigned.  */
267       while (1) {
268         if (c == 'l' || c == 'L')
269           ;
270         else if (c == 'u' || c == 'U')
271           yylval.integer.unsignedp = 1;
272         else
273           break;
274
275         if (len == 0)
276           break;
277         c = *p++;
278         len--;
279       }
280       /* Don't look for any more digits after the suffixes.  */
281       break;
282     }
283   }
284
285   if (len != 0) {
286     yyerror ("Invalid number in #if expression");
287     return ERROR;
288   }
289
290   /* If too big to be signed, consider it unsigned.  */
291   if (n < 0)
292     yylval.integer.unsignedp = 1;
293
294   lexptr = p;
295   yylval.integer.value = n;
296   return INT;
297 }
298
299 struct token {
300   const char *operator;
301   int token;
302 };
303
304 #ifndef NULL
305 #define NULL 0
306 #endif
307
308 static struct token tokentab2[] = {
309   {"&&", AND},
310   {"||", OR},
311   {"<<", LSH},
312   {">>", RSH},
313   {"==", EQUAL},
314   {"!=", NOTEQUAL},
315   {"<=", LEQ},
316   {">=", GEQ},
317   {NULL, ERROR}
318 };
319
320 /* Read one token, getting characters through lexptr.  */
321
322 int
323 yylex ()
324 {
325   register int c;
326   register int namelen;
327   register char *tokstart;
328   register struct token *toktab;
329
330  retry:
331
332   tokstart = lexptr;
333   c = *tokstart;
334   /* See if it is a special token of length 2.  */
335   for (toktab = tokentab2; toktab->operator != NULL; toktab++)
336     if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
337       lexptr += 2;
338       return toktab->token;
339     }
340
341   switch (c) {
342   case 0:
343     return 0;
344     
345   case ' ':
346   case '\t':
347   case '\r':
348   case '\n':
349     lexptr++;
350     goto retry;
351     
352   case '\'':
353     lexptr++;
354     c = *lexptr++;
355     if (c == '\\')
356       c = parse_escape (&lexptr);
357
358     /* Sign-extend the constant if chars are signed on target machine.  */
359     {
360       if (lookup ((const unsigned char *)"__CHAR_UNSIGNED__",
361                    sizeof ("__CHAR_UNSIGNED__")-1, -1)
362           || ((c >> (CHAR_TYPE_SIZE - 1)) & 1) == 0)
363         yylval.integer.value = c & ((1 << CHAR_TYPE_SIZE) - 1);
364       else
365         yylval.integer.value = c | ~((1 << CHAR_TYPE_SIZE) - 1);
366     }
367
368     yylval.integer.unsignedp = 0;
369     c = *lexptr++;
370     if (c != '\'') {
371       yyerror ("Invalid character constant in #if");
372       return ERROR;
373     }
374     
375     return CHAR;
376
377     /* some of these chars are invalid in constant expressions;
378        maybe do something about them later */
379   case '/':
380   case '+':
381   case '-':
382   case '*':
383   case '%':
384   case '|':
385   case '&':
386   case '^':
387   case '~':
388   case '!':
389   case '@':
390   case '<':
391   case '>':
392   case '(':
393   case ')':
394   case '[':
395   case ']':
396   case '.':
397   case '?':
398   case ':':
399   case '=':
400   case '{':
401   case '}':
402   case ',':
403     lexptr++;
404     return c;
405     
406   case '"':
407     yyerror ("double quoted strings not allowed in #if expressions");
408     return ERROR;
409   }
410   if (c >= '0' && c <= '9') {
411     /* It's a number */
412     for (namelen = 0;
413          c = tokstart[namelen], is_idchar[c] || c == '.'; 
414          namelen++)
415       ;
416     return parse_number (namelen);
417   }
418   
419   if (!is_idstart[c]) {
420     yyerror ("Invalid token in expression");
421     return ERROR;
422   }
423   
424   /* It is a name.  See how long it is.  */
425   
426   for (namelen = 0;
427        is_idchar[(int)(unsigned char)tokstart[namelen]];
428        namelen++)
429     ;
430   
431   lexptr += namelen;
432   return NAME;
433 }
434
435
436 /* Parse a C escape sequence.  STRING_PTR points to a variable
437    containing a pointer to the string to parse.  That pointer
438    is updated past the characters we use.  The value of the
439    escape sequence is returned.
440
441    A negative value means the sequence \ newline was seen,
442    which is supposed to be equivalent to nothing at all.
443
444    If \ is followed by a null character, we return a negative
445    value and leave the string pointer pointing at the null character.
446
447    If \ is followed by 000, we return 0 and leave the string pointer
448    after the zeros.  A value of 0 does not mean end of string.  */
449
450 int
451 parse_escape (string_ptr)
452      char **string_ptr;
453 {
454   register int c = *(*string_ptr)++;
455   switch (c)
456     {
457     case 'a':
458       return TARGET_BELL;
459     case 'b':
460       return TARGET_BS;
461     case 'e':
462       return 033;
463     case 'f':
464       return TARGET_FF;
465     case 'n':
466       return TARGET_NEWLINE;
467     case 'r':
468       return TARGET_CR;
469     case 't':
470       return TARGET_TAB;
471     case 'v':
472       return TARGET_VT;
473     case '\n':
474       return -2;
475     case 0:
476       (*string_ptr)--;
477       return 0;
478     case '^':
479       c = *(*string_ptr)++;
480       if (c == '\\')
481         c = parse_escape (string_ptr);
482       if (c == '?')
483         return 0177;
484       return (c & 0200) | (c & 037);
485       
486     case '0':
487     case '1':
488     case '2':
489     case '3':
490     case '4':
491     case '5':
492     case '6':
493     case '7':
494       {
495         register int i = c - '0';
496         register int count = 0;
497         while (++count < 3)
498           {
499             c = *(*string_ptr)++;
500             if (c >= '0' && c <= '7')
501               i = (i << 3) + c - '0';
502             else
503               {
504                 (*string_ptr)--;
505                 break;
506               }
507           }
508         if ((i & ~((1 << CHAR_TYPE_SIZE) - 1)) != 0)
509           {
510             i &= (1 << CHAR_TYPE_SIZE) - 1;
511             warning ("octal character constant does not fit in a byte");
512           }
513         return i;
514       }
515     case 'x':
516       {
517         register int i = 0;
518         for (;;)
519           {
520             c = *(*string_ptr)++;
521             if (c >= '0' && c <= '9')
522               i = (i << 4) + c - '0';
523             else if (c >= 'a' && c <= 'f')
524               i = (i << 4) + c - 'a' + 10;
525             else if (c >= 'A' && c <= 'F')
526               i = (i << 4) + c - 'A' + 10;
527             else
528               {
529                 (*string_ptr)--;
530                 break;
531               }
532           }
533         if ((i & ~((1 << BITS_PER_UNIT) - 1)) != 0)
534           {
535             i &= (1 << BITS_PER_UNIT) - 1;
536             warning ("hex character constant does not fit in a byte");
537           }
538         return i;
539       }
540     default:
541       return c;
542     }
543 }
544
545 void
546 yyerror (s)
547      const char *s;
548 {
549   error (s);
550   longjmp (parse_return_error, 1);
551 }
552 \f
553 /* This page contains the entry point to this file.  */
554
555 /* Parse STRING as an expression, and complain if this fails
556    to use up all of the contents of STRING.  */
557 /* We do not support C comments.  They should be removed before
558    this function is called.  */
559
560 int
561 parse_c_expression (string)
562      char *string;
563 {
564   lexptr = string;
565   
566   if (lexptr == 0 || *lexptr == 0) {
567     error ("empty #if expression");
568     return 0;                   /* don't include the #if group */
569   }
570
571   /* if there is some sort of scanning error, just return 0 and assume
572      the parsing routine has printed an error message somewhere.
573      there is surely a better thing to do than this.     */
574   if (setjmp (parse_return_error))
575     return 0;
576
577   if (yyparse ())
578     return 0;                   /* actually this is never reached
579                                    the way things stand. */
580   if (*lexptr)
581     error ("Junk after end of expression.");
582
583   return expression_value;      /* set by yyparse () */
584 }