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