source: trunk/third/gcc/cexp.y @ 11288

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