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