source: trunk/third/gcc/cppexp.c @ 11288

Revision 11288, 25.7 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, 1997, 1998 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
23Written by Per Bothner 1994.  */
24
25/* Parse a C expression from text in a string  */
26   
27#include "config.h"
28#include "cpplib.h"
29#include "gansidecl.h"
30
31extern char *xmalloc PARAMS ((unsigned));
32extern char *xrealloc PARAMS ((void *, unsigned));
33
34#ifdef MULTIBYTE_CHARS
35#include <stdlib.h>
36#include <locale.h>
37#endif
38
39#if HAVE_LIMITS_H
40# include <limits.h>
41#endif
42
43#include <stdio.h>
44
45/* This is used for communicating lists of keywords with cccp.c.  */
46struct arglist {
47  struct arglist *next;
48  U_CHAR *name;
49  int length;
50  int argno;
51};
52
53/* Define a generic NULL if one hasn't already been defined.  */
54
55#ifndef NULL
56#define NULL 0
57#endif
58
59#ifndef GENERIC_PTR
60#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
61#define GENERIC_PTR void *
62#else
63#define GENERIC_PTR char *
64#endif
65#endif
66
67#ifndef NULL_PTR
68#define NULL_PTR ((GENERIC_PTR) 0)
69#endif
70
71extern char *xmalloc ();
72
73#ifndef CHAR_TYPE_SIZE
74#define CHAR_TYPE_SIZE BITS_PER_UNIT
75#endif
76
77#ifndef INT_TYPE_SIZE
78#define INT_TYPE_SIZE BITS_PER_WORD
79#endif
80
81#ifndef LONG_TYPE_SIZE
82#define LONG_TYPE_SIZE BITS_PER_WORD
83#endif
84
85#ifndef WCHAR_TYPE_SIZE
86#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
87#endif
88
89#ifndef MAX_CHAR_TYPE_SIZE
90#define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
91#endif
92
93#ifndef MAX_INT_TYPE_SIZE
94#define MAX_INT_TYPE_SIZE INT_TYPE_SIZE
95#endif
96
97#ifndef MAX_LONG_TYPE_SIZE
98#define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
99#endif
100
101#ifndef MAX_WCHAR_TYPE_SIZE
102#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
103#endif
104
105/* Yield nonzero if adding two numbers with A's and B's signs can yield a
106   number with SUM's sign, where A, B, and SUM are all C integers.  */
107#define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
108
109static void integer_overflow ();
110static long left_shift ();
111static long right_shift ();
112
113#define ERROR 299
114#define OROR 300
115#define ANDAND 301
116#define EQUAL 302
117#define NOTEQUAL 303
118#define LEQ 304
119#define GEQ 305
120#define LSH 306
121#define RSH 307
122#define NAME 308
123#define INT 309
124#define CHAR 310
125
126#define LEFT_OPERAND_REQUIRED 1
127#define RIGHT_OPERAND_REQUIRED 2
128#define HAVE_VALUE 4
129/* SKIP_OPERAND is set for '&&' '||' '?' and ':' when the
130   following operand should be short-circuited instead of evaluated.  */
131#define SKIP_OPERAND 8
132/*#define UNSIGNEDP 16*/
133
134/* Find the largest host integer type and set its size and type.
135   Watch out: on some crazy hosts `long' is shorter than `int'.  */
136
137#ifndef HOST_WIDE_INT
138# if HAVE_INTTYPES_H
139#  include <inttypes.h>
140#  define HOST_WIDE_INT intmax_t
141# else
142#  if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
143       && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
144#   define HOST_WIDE_INT int
145#  else
146#  if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
147       || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
148#   define HOST_WIDE_INT long
149#  else
150#   define HOST_WIDE_INT long long
151#  endif
152#  endif
153# endif
154#endif
155
156#ifndef CHAR_BIT
157#define CHAR_BIT 8
158#endif
159
160#ifndef HOST_BITS_PER_WIDE_INT
161#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
162#endif
163
164struct operation {
165    short op;
166    char rprio; /* Priority of op (relative to it right operand).  */
167    char flags;
168    char unsignedp;    /* true if value should be treated as unsigned */
169    HOST_WIDE_INT value;        /* The value logically "right" of op.  */
170};
171
172/* Take care of parsing a number (anything that starts with a digit).
173   LEN is the number of characters in it.  */
174
175/* maybe needs to actually deal with floating point numbers */
176
177struct operation
178parse_number (pfile, start, olen)
179     cpp_reader *pfile;
180     char *start;
181     int olen;
182{
183  struct operation op;
184  register char *p = start;
185  register int c;
186  register unsigned long n = 0, nd, ULONG_MAX_over_base;
187  register int base = 10;
188  register int len = olen;
189  register int overflow = 0;
190  register int digit, largest_digit = 0;
191  int spec_long = 0;
192
193  op.unsignedp = 0;
194
195  for (c = 0; c < len; c++)
196    if (p[c] == '.') {
197      /* It's a float since it contains a point.  */
198      cpp_error (pfile,
199                 "floating point numbers not allowed in #if expressions");
200      op.op = ERROR;
201      return op;
202    }
203
204  if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
205    p += 2;
206    base = 16;
207    len -= 2;
208  }
209  else if (*p == '0')
210    base = 8;
211
212  /* Some buggy compilers (e.g. MPW C) seem to need both casts.  */
213  ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
214
215  for (; len > 0; len--) {
216    c = *p++;
217
218    if (c >= '0' && c <= '9')
219      digit = c - '0';
220    else if (base == 16 && c >= 'a' && c <= 'f')
221      digit = c - 'a' + 10;
222    else if (base == 16 && c >= 'A' && c <= 'F')
223      digit = c - 'A' + 10;
224    else {
225      /* `l' means long, and `u' means unsigned.  */
226      while (1) {
227        if (c == 'l' || c == 'L')
228          {
229            if (spec_long)
230              cpp_error (pfile, "two `l's in integer constant");
231            spec_long = 1;
232          }
233        else if (c == 'u' || c == 'U')
234          {
235            if (op.unsignedp)
236              cpp_error (pfile, "two `u's in integer constant");
237            op.unsignedp = 1;
238          }
239        else
240          break;
241
242        if (--len == 0)
243          break;
244        c = *p++;
245      }
246      /* Don't look for any more digits after the suffixes.  */
247      break;
248    }
249    if (largest_digit < digit)
250      largest_digit = digit;
251    nd = n * base + digit;
252    overflow |= ULONG_MAX_over_base < n | nd < n;
253    n = nd;
254  }
255
256  if (len != 0)
257    {
258      cpp_error (pfile, "Invalid number in #if expression");
259      op.op = ERROR;
260      return op;
261    }
262
263  if (base <= largest_digit)
264    cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
265
266  if (overflow)
267    cpp_pedwarn (pfile, "integer constant out of range");
268
269  /* If too big to be signed, consider it unsigned.  */
270  if ((long) n < 0 && ! op.unsignedp)
271    {
272      if (base == 10)
273        cpp_warning (pfile, "integer constant is so large that it is unsigned");
274      op.unsignedp = 1;
275    }
276
277  op.value = n;
278  op.op = INT;
279  return op;
280}
281
282struct token {
283  char *operator;
284  int token;
285};
286
287static struct token tokentab2[] = {
288  {"&&", ANDAND},
289  {"||", OROR},
290  {"<<", LSH},
291  {">>", RSH},
292  {"==", EQUAL},
293  {"!=", NOTEQUAL},
294  {"<=", LEQ},
295  {">=", GEQ},
296  {"++", ERROR},
297  {"--", ERROR},
298  {NULL, ERROR}
299};
300
301/* Read one token.  */
302
303struct operation
304cpp_lex (pfile, skip_evaluation)
305     cpp_reader *pfile;
306     int skip_evaluation;
307{
308  register int c;
309  register int namelen;
310  register struct token *toktab;
311  enum cpp_token token;
312  struct operation op;
313  U_CHAR *tok_start, *tok_end;
314  int old_written;
315
316 retry:
317
318  old_written = CPP_WRITTEN (pfile);
319  cpp_skip_hspace (pfile);
320  c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
321  if (c == '#')
322    return parse_number (pfile,
323                         cpp_read_check_assertion (pfile) ? "1" : "0", 1);
324
325  if (c == '\n')
326    {
327      op.op = 0;
328      return op;
329    }
330
331  token = cpp_get_token (pfile);
332  tok_start = pfile->token_buffer + old_written;
333  tok_end = CPP_PWRITTEN (pfile);
334  pfile->limit = tok_start;
335  switch (token)
336  {
337    case CPP_EOF: /* Should not happen ...  */
338    case CPP_VSPACE:
339      op.op = 0;
340      return op;
341    case CPP_POP:
342      if (CPP_BUFFER (pfile)->fname != NULL)
343        {
344          op.op = 0;
345          return op;
346        }
347      cpp_pop_buffer (pfile);
348      goto retry;
349    case CPP_HSPACE:   case CPP_COMMENT:
350      goto retry;
351    case CPP_NUMBER:
352      return parse_number (pfile, tok_start, tok_end - tok_start);
353    case CPP_STRING:
354      cpp_error (pfile, "string constants not allowed in #if expressions");
355      op.op = ERROR;
356      return op;
357    case CPP_CHAR:
358      /* This code for reading a character constant
359         handles multicharacter constants and wide characters.
360         It is mostly copied from c-lex.c.  */
361      {
362        register int result = 0;
363        register num_chars = 0;
364        unsigned width = MAX_CHAR_TYPE_SIZE;
365        int wide_flag = 0;
366        int max_chars;
367        U_CHAR *ptr = tok_start;
368#ifdef MULTIBYTE_CHARS
369        char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
370#else
371        char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
372#endif
373
374        if (*ptr == 'L')
375          {
376            ptr++;
377            wide_flag = 1;
378            width = MAX_WCHAR_TYPE_SIZE;
379#ifdef MULTIBYTE_CHARS
380            max_chars = MB_CUR_MAX;
381#else
382            max_chars = 1;
383#endif
384          }
385        else
386            max_chars = MAX_LONG_TYPE_SIZE / width;
387
388        ++ptr;
389        while (ptr < tok_end && ((c = *ptr++) != '\''))
390          {
391            if (c == '\\')
392              {
393                c = cpp_parse_escape (pfile, (char **) &ptr);
394                if (width < HOST_BITS_PER_INT
395                  && (unsigned) c >= (1 << width))
396                    cpp_pedwarn (pfile,
397                                 "escape sequence out of range for character");
398              }
399
400            num_chars++;
401
402            /* Merge character into result; ignore excess chars.  */
403            if (num_chars < max_chars + 1)
404              {
405                if (width < HOST_BITS_PER_INT)
406                  result = (result << width) | (c & ((1 << width) - 1));
407                else
408                  result = c;
409                token_buffer[num_chars - 1] = c;
410              }
411          }
412
413        token_buffer[num_chars] = 0;
414
415        if (c != '\'')
416          cpp_error (pfile, "malformatted character constant");
417        else if (num_chars == 0)
418          cpp_error (pfile, "empty character constant");
419        else if (num_chars > max_chars)
420          {
421            num_chars = max_chars;
422            cpp_error (pfile, "character constant too long");
423          }
424        else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
425          cpp_warning (pfile, "multi-character character constant");
426
427        /* If char type is signed, sign-extend the constant.  */
428        if (! wide_flag)
429          {
430            int num_bits = num_chars * width;
431
432            if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__",
433                            sizeof ("__CHAR_UNSIGNED__")-1, -1)
434                || ((result >> (num_bits - 1)) & 1) == 0)
435                op.value
436                    = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
437            else
438                op.value
439                    = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
440          }
441        else
442          {
443#ifdef MULTIBYTE_CHARS
444            /* Set the initial shift state and convert the next sequence.  */
445              result = 0;
446              /* In all locales L'\0' is zero and mbtowc will return zero,
447                 so don't use it.  */
448              if (num_chars > 1
449                  || (num_chars == 1 && token_buffer[0] != '\0'))
450                {
451                  wchar_t wc;
452                  (void) mbtowc (NULL_PTR, NULL_PTR, 0);
453                  if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
454                    result = wc;
455                  else
456                    cpp_pedwarn (pfile,"Ignoring invalid multibyte character");
457                }
458#endif
459              op.value = result;
460            }
461        }
462
463      /* This is always a signed type.  */
464      op.unsignedp = 0;
465      op.op = CHAR;
466   
467      return op;
468
469    case CPP_NAME:
470      if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
471        cpp_warning (pfile, "`%.*s' is not defined",
472                     (int) (tok_end - tok_start), tok_start);
473      return parse_number (pfile, "0", 0);
474
475    case CPP_OTHER:
476      /* See if it is a special token of length 2.  */
477      if (tok_start + 2 == tok_end)
478        {
479          for (toktab = tokentab2; toktab->operator != NULL; toktab++)
480            if (tok_start[0] == toktab->operator[0]
481                && tok_start[1] == toktab->operator[1])
482                break;
483          if (toktab->token == ERROR)
484            {
485              char *buf = (char *) alloca (40);
486              sprintf (buf, "`%s' not allowed in operand of `#if'", tok_start);
487              cpp_error (pfile, buf);
488            }
489          op.op = toktab->token;
490          return op;
491        }
492      /* fall through */
493    default:
494      op.op = *tok_start;
495      return op;
496  }
497}
498
499
500/* Parse a C escape sequence.  STRING_PTR points to a variable
501   containing a pointer to the string to parse.  That pointer
502   is updated past the characters we use.  The value of the
503   escape sequence is returned.
504
505   A negative value means the sequence \ newline was seen,
506   which is supposed to be equivalent to nothing at all.
507
508   If \ is followed by a null character, we return a negative
509   value and leave the string pointer pointing at the null character.
510
511   If \ is followed by 000, we return 0 and leave the string pointer
512   after the zeros.  A value of 0 does not mean end of string.  */
513
514int
515cpp_parse_escape (pfile, string_ptr)
516     cpp_reader *pfile;
517     char **string_ptr;
518{
519  register int c = *(*string_ptr)++;
520  switch (c)
521    {
522    case 'a':
523      return TARGET_BELL;
524    case 'b':
525      return TARGET_BS;
526    case 'e':
527    case 'E':
528      if (CPP_PEDANTIC (pfile))
529        cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c);
530      return 033;
531    case 'f':
532      return TARGET_FF;
533    case 'n':
534      return TARGET_NEWLINE;
535    case 'r':
536      return TARGET_CR;
537    case 't':
538      return TARGET_TAB;
539    case 'v':
540      return TARGET_VT;
541    case '\n':
542      return -2;
543    case 0:
544      (*string_ptr)--;
545      return 0;
546     
547    case '0':
548    case '1':
549    case '2':
550    case '3':
551    case '4':
552    case '5':
553    case '6':
554    case '7':
555      {
556        register int i = c - '0';
557        register int count = 0;
558        while (++count < 3)
559          {
560            c = *(*string_ptr)++;
561            if (c >= '0' && c <= '7')
562              i = (i << 3) + c - '0';
563            else
564              {
565                (*string_ptr)--;
566                break;
567              }
568          }
569        if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
570          {
571            i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
572            cpp_pedwarn (pfile,
573                          "octal character constant does not fit in a byte");
574          }
575        return i;
576      }
577    case 'x':
578      {
579        register unsigned i = 0, overflow = 0, digits_found = 0, digit;
580        for (;;)
581          {
582            c = *(*string_ptr)++;
583            if (c >= '0' && c <= '9')
584              digit = c - '0';
585            else if (c >= 'a' && c <= 'f')
586              digit = c - 'a' + 10;
587            else if (c >= 'A' && c <= 'F')
588              digit = c - 'A' + 10;
589            else
590              {
591                (*string_ptr)--;
592                break;
593              }
594            overflow |= i ^ (i << 4 >> 4);
595            i = (i << 4) + digit;
596            digits_found = 1;
597          }
598        if (!digits_found)
599          cpp_error (pfile, "\\x used with no following hex digits");
600        if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
601          {
602            i &= (1 << BITS_PER_UNIT) - 1;
603            cpp_pedwarn (pfile,
604                         "hex character constant does not fit in a byte");
605          }
606        return i;
607      }
608    default:
609      return c;
610    }
611}
612
613static void
614integer_overflow (pfile)
615     cpp_reader *pfile;
616{
617  if (CPP_PEDANTIC (pfile))
618    cpp_pedwarn (pfile, "integer overflow in preprocessor expression");
619}
620
621static long
622left_shift (pfile, a, unsignedp, b)
623     cpp_reader *pfile;
624     long a;
625     int unsignedp;
626     unsigned long b;
627{
628  if (b >= HOST_BITS_PER_LONG)
629    {
630      if (! unsignedp && a != 0)
631        integer_overflow (pfile);
632      return 0;
633    }
634  else if (unsignedp)
635    return (unsigned long) a << b;
636  else
637    {
638      long l = a << b;
639      if (l >> b != a)
640        integer_overflow (pfile);
641      return l;
642    }
643}
644
645static long
646right_shift (pfile, a, unsignedp, b)
647     cpp_reader *pfile;
648     long a;
649     int unsignedp;
650     unsigned long b;
651{
652  if (b >= HOST_BITS_PER_LONG)
653    return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1);
654  else if (unsignedp)
655    return (unsigned long) a >> b;
656  else
657    return a >> b;
658}
659
660/* These priorities are all even, so we can handle associatively.  */
661#define PAREN_INNER_PRIO 0
662#define COMMA_PRIO 4
663#define COND_PRIO (COMMA_PRIO+2)
664#define OROR_PRIO (COND_PRIO+2)
665#define ANDAND_PRIO (OROR_PRIO+2)
666#define OR_PRIO (ANDAND_PRIO+2)
667#define XOR_PRIO (OR_PRIO+2)
668#define AND_PRIO (XOR_PRIO+2)
669#define EQUAL_PRIO (AND_PRIO+2)
670#define LESS_PRIO (EQUAL_PRIO+2)
671#define SHIFT_PRIO (LESS_PRIO+2)
672#define PLUS_PRIO (SHIFT_PRIO+2)
673#define MUL_PRIO (PLUS_PRIO+2)
674#define UNARY_PRIO (MUL_PRIO+2)
675#define PAREN_OUTER_PRIO (UNARY_PRIO+2)
676
677#define COMPARE(OP) \
678  top->unsignedp = 0;\
679  top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP v2 : (v1 OP v2)
680
681/* Parse and evaluate a C expression, reading from PFILE.
682   Returns the value of the expression.  */
683
684HOST_WIDE_INT
685cpp_parse_expr (pfile)
686     cpp_reader *pfile;
687{
688  /* The implementation is an operator precedence parser,
689     i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
690
691     The stack base is 'stack', and the current stack pointer is 'top'.
692     There is a stack element for each operator (only),
693     and the most recently pushed operator is 'top->op'.
694     An operand (value) is stored in the 'value' field of the stack
695     element of the operator that precedes it.
696     In that case the 'flags' field has the HAVE_VALUE flag set.  */
697
698#define INIT_STACK_SIZE 20
699  struct operation init_stack[INIT_STACK_SIZE];
700  struct operation *stack = init_stack;
701  struct operation *limit = stack + INIT_STACK_SIZE;
702  register struct operation *top = stack;
703  int lprio, rprio;
704  int skip_evaluation = 0;
705
706  top->rprio = 0;
707  top->flags = 0;
708  for (;;)
709    {
710      struct operation op;
711      char flags = 0;
712
713      /* Read a token */
714      op =  cpp_lex (pfile, skip_evaluation);
715
716      /* See if the token is an operand, in which case go to set_value.
717         If the token is an operator, figure out its left and right
718         priorities, and then goto maybe_reduce.  */
719
720      switch (op.op)
721        {
722        case NAME:
723          abort ();
724        case INT:  case CHAR:
725          top->value = op.value;
726          top->unsignedp = op.unsignedp;
727          goto set_value;
728        case 0:
729          lprio = 0;  goto maybe_reduce;
730        case '+':  case '-':
731          /* Is this correct if unary ? FIXME */
732          flags = RIGHT_OPERAND_REQUIRED;
733          lprio = PLUS_PRIO;  rprio = lprio + 1;  goto maybe_reduce;
734        case '!':  case '~':
735          flags = RIGHT_OPERAND_REQUIRED;
736          rprio = UNARY_PRIO;  lprio = rprio + 1;  goto maybe_reduce;
737        case '*':  case '/':  case '%':
738          lprio = MUL_PRIO;  goto binop;
739        case '<':  case '>':  case LEQ:  case GEQ:
740          lprio = LESS_PRIO;  goto binop;
741        case EQUAL:  case NOTEQUAL:
742          lprio = EQUAL_PRIO;  goto binop;
743        case LSH:  case RSH:
744          lprio = SHIFT_PRIO;  goto binop;
745        case '&':  lprio = AND_PRIO;  goto binop;
746        case '^':  lprio = XOR_PRIO;  goto binop;
747        case '|':  lprio = OR_PRIO;  goto binop;
748        case ANDAND:  lprio = ANDAND_PRIO;  goto binop;
749        case OROR:  lprio = OROR_PRIO;  goto binop;
750        case ',':
751          lprio = COMMA_PRIO;  goto binop;
752        case '(':
753          lprio = PAREN_OUTER_PRIO;  rprio = PAREN_INNER_PRIO;
754          goto maybe_reduce;
755        case ')':
756          lprio = PAREN_INNER_PRIO;  rprio = PAREN_OUTER_PRIO;
757          goto maybe_reduce;
758        case ':':
759          lprio = COND_PRIO;  rprio = COND_PRIO;
760          goto maybe_reduce;
761        case '?':
762          lprio = COND_PRIO + 1;  rprio = COND_PRIO;
763          goto maybe_reduce;
764        binop:
765          flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED;
766          rprio = lprio + 1;
767          goto maybe_reduce;
768        default:
769          cpp_error (pfile, "invalid character in #if");
770          goto syntax_error;
771        }
772
773    set_value:
774      /* Push a value onto the stack.  */
775      if (top->flags & HAVE_VALUE)
776        {
777          cpp_error (pfile, "syntax error in #if");
778          goto syntax_error;
779        }
780      top->flags |= HAVE_VALUE;
781      continue;
782
783    maybe_reduce:
784      /* Push an operator, and check if we can reduce now.  */
785      while (top->rprio > lprio)
786        {
787          long v1 = top[-1].value, v2 = top[0].value;
788          int unsigned1 = top[-1].unsignedp, unsigned2 = top[0].unsignedp;
789          top--;
790          if ((top[1].flags & LEFT_OPERAND_REQUIRED)
791              && ! (top[0].flags & HAVE_VALUE))
792            {
793              cpp_error (pfile, "syntax error - missing left operand");
794              goto syntax_error;
795            }
796          if ((top[1].flags & RIGHT_OPERAND_REQUIRED)
797              && ! (top[1].flags & HAVE_VALUE))
798            {
799              cpp_error (pfile, "syntax error - missing right operand");
800              goto syntax_error;
801            }
802          /* top[0].value = (top[1].op)(v1, v2);*/
803          switch (top[1].op)
804            {
805            case '+':
806              if (!(top->flags & HAVE_VALUE))
807                { /* Unary '+' */
808                  top->value = v2;
809                  top->unsignedp = unsigned2;
810                  top->flags |= HAVE_VALUE;
811                }
812              else
813                {
814                  top->value = v1 + v2;
815                  top->unsignedp = unsigned1 || unsigned2;
816                  if (! top->unsignedp && ! skip_evaluation
817                      && ! possible_sum_sign (v1, v2, top->value))
818                    integer_overflow (pfile);
819                }
820              break;
821            case '-':
822              if (!(top->flags & HAVE_VALUE))
823                { /* Unary '-' */
824                  top->value = - v2;
825                  if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
826                    integer_overflow (pfile);
827                  top->unsignedp = unsigned2;
828                  top->flags |= HAVE_VALUE;
829                }
830              else
831                { /* Binary '-' */
832                  top->value = v1 - v2;
833                  top->unsignedp = unsigned1 || unsigned2;
834                  if (! top->unsignedp && ! skip_evaluation
835                      && ! possible_sum_sign (top->value, v2, v1))
836                    integer_overflow (pfile);
837                }
838              break;
839            case '*':
840              top->unsignedp = unsigned1 || unsigned2;
841              if (top->unsignedp)
842                top->value = (unsigned long) v1 * v2;
843              else if (!skip_evaluation)
844                {
845                  top->value = v1 * v2;
846                  if (v1
847                      && (top->value / v1 != v2
848                          || (top->value & v1 & v2) < 0))
849                    integer_overflow (pfile);
850                }
851              break;
852            case '/':
853              if (skip_evaluation)
854                break;
855              if (v2 == 0)
856                {
857                  cpp_error (pfile, "division by zero in #if");
858                  v2 = 1;
859                }
860              top->unsignedp = unsigned1 || unsigned2;
861              if (top->unsignedp)
862                top->value = (unsigned long) v1 / v2;
863              else
864                {
865                  top->value = v1 / v2;
866                  if ((top->value & v1 & v2) < 0)
867                    integer_overflow (pfile);
868                }
869              break;
870            case '%':
871              if (skip_evaluation)
872                break;
873              if (v2 == 0)
874                {
875                  cpp_error (pfile, "division by zero in #if");
876                  v2 = 1;
877                }
878              top->unsignedp = unsigned1 || unsigned2;
879              if (top->unsignedp)
880                top->value = (unsigned long) v1 % v2;
881              else
882                top->value = v1 % v2;
883              break;
884            case '!':
885              if (top->flags & HAVE_VALUE)
886                {
887                  cpp_error (pfile, "syntax error");
888                  goto syntax_error;
889                }
890              top->value = ! v2;
891              top->unsignedp = 0;
892              top->flags |= HAVE_VALUE;
893              break;
894            case '~':
895              if (top->flags & HAVE_VALUE)
896                {
897                  cpp_error (pfile, "syntax error");
898                  goto syntax_error;
899                }
900              top->value = ~ v2;
901              top->unsignedp = unsigned2;
902              top->flags |= HAVE_VALUE;
903              break;
904            case '<':  COMPARE(<);  break;
905            case '>':  COMPARE(>);  break;
906            case LEQ:  COMPARE(<=); break;
907            case GEQ:  COMPARE(>=); break;
908            case EQUAL:
909              top->value = (v1 == v2);
910              top->unsignedp = 0;
911              break;
912            case NOTEQUAL:
913              top->value = (v1 != v2);
914              top->unsignedp = 0;
915              break;
916            case LSH:
917              if (skip_evaluation)
918                break;
919              top->unsignedp = unsigned1;
920              if (v2 < 0 && ! unsigned2)
921                top->value = right_shift (pfile, v1, unsigned1, -v2);
922              else
923                top->value = left_shift (pfile, v1, unsigned1, v2);
924              break;
925            case RSH:
926              if (skip_evaluation)
927                break;
928              top->unsignedp = unsigned1;
929              if (v2 < 0 && ! unsigned2)
930                top->value = left_shift (pfile, v1, unsigned1, -v2);
931              else
932                top->value = right_shift (pfile, v1, unsigned1, v2);
933              break;
934#define LOGICAL(OP) \
935              top->value = v1 OP v2;\
936              top->unsignedp = unsigned1 || unsigned2;
937            case '&':  LOGICAL(&); break;
938            case '^':  LOGICAL(^);  break;
939            case '|':  LOGICAL(|);  break;
940            case ANDAND:
941              top->value = v1 && v2;  top->unsignedp = 0;
942              if (!v1) skip_evaluation--;
943              break;
944            case OROR:
945              top->value = v1 || v2;  top->unsignedp = 0;
946              if (v1) skip_evaluation--;
947              break;
948            case ',':
949              if (CPP_PEDANTIC (pfile))
950                cpp_pedwarn (pfile, "comma operator in operand of `#if'");
951              top->value = v2;
952              top->unsignedp = unsigned2;
953              break;
954            case '(':  case '?':
955              cpp_error (pfile, "syntax error in #if");
956              goto syntax_error;
957            case ':':
958              if (top[0].op != '?')
959                {
960                  cpp_error (pfile,
961                             "syntax error ':' without preceding '?'");
962                  goto syntax_error;
963                }
964              else if (! (top[1].flags & HAVE_VALUE)
965                       || !(top[-1].flags & HAVE_VALUE)
966                       || !(top[0].flags & HAVE_VALUE))
967                {
968                  cpp_error (pfile, "bad syntax for ?: operator");
969                  goto syntax_error;
970                }
971              else
972                {
973                  top--;
974                  if (top->value) skip_evaluation--;
975                  top->value = top->value ? v1 : v2;
976                  top->unsignedp = unsigned1 || unsigned2;
977                }
978              break;
979            case ')':
980              if ((top[1].flags & HAVE_VALUE)
981                  || ! (top[0].flags & HAVE_VALUE)
982                  || top[0].op != '('
983                  || (top[-1].flags & HAVE_VALUE))
984                {
985                  cpp_error (pfile, "mismatched parentheses in #if");
986                  goto syntax_error;
987                }
988              else
989                {
990                  top--;
991                  top->value = v1;
992                  top->unsignedp = unsigned1;
993                  top->flags |= HAVE_VALUE;
994                }
995              break;
996            default:
997              fprintf (stderr,
998                       top[1].op >= ' ' && top[1].op <= '~'
999                       ? "unimplemented operator '%c'\n"
1000                       : "unimplemented operator '\\%03o'\n",
1001                       top[1].op);
1002            }
1003        }
1004      if (op.op == 0)
1005        {
1006          if (top != stack)
1007            cpp_error (pfile, "internal error in #if expression");
1008          if (stack != init_stack)
1009            free (stack);
1010          return top->value;
1011        }
1012      top++;
1013     
1014      /* Check for and handle stack overflow.  */
1015      if (top == limit)
1016        {
1017          struct operation *new_stack;
1018          int old_size = (char *) limit - (char *) stack;
1019          int new_size = 2 * old_size;
1020          if (stack != init_stack)
1021            new_stack = (struct operation *) xrealloc (stack, new_size);
1022          else
1023            {
1024              new_stack = (struct operation *) xmalloc (new_size);
1025              bcopy ((char *) stack, (char *) new_stack, old_size);
1026            }
1027          stack = new_stack;
1028          top = (struct operation *) ((char *) new_stack + old_size);
1029          limit = (struct operation *) ((char *) new_stack + new_size);
1030        }
1031     
1032      top->flags = flags;
1033      top->rprio = rprio;
1034      top->op = op.op;
1035      if ((op.op == OROR && top[-1].value)
1036          || (op.op == ANDAND && !top[-1].value)
1037          || (op.op == '?' && !top[-1].value))
1038        {
1039          skip_evaluation++;
1040        }
1041      else if (op.op == ':')
1042        {
1043          if (top[-2].value) /* Was condition true? */
1044            skip_evaluation++;
1045          else
1046            skip_evaluation--;
1047        }
1048    }
1049 syntax_error:
1050  if (stack != init_stack)
1051    free (stack);
1052  skip_rest_of_line (pfile);
1053  return 0;
1054}
Note: See TracBrowser for help on using the repository browser.