]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/cppexp.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / cppexp.c
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
deleted file mode 100644 (file)
index 1d4cecc..0000000
+++ /dev/null
@@ -1,889 +0,0 @@
-/* Parse C expressions for cpplib.
-   Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-   2002 Free Software Foundation.
-   Contributed by Per Bothner, 1994.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#include "config.h"
-#include "system.h"
-#include "cpplib.h"
-#include "cpphash.h"
-
-/* Yield nonzero if adding two numbers with A's and B's signs can yield a
-   number with SUM's sign, where A, B, and SUM are all C integers.  */
-#define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
-
-static void integer_overflow PARAMS ((cpp_reader *));
-static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
-                                          unsigned int,
-                                          unsigned HOST_WIDEST_INT));
-static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
-                                           unsigned int,
-                                           unsigned HOST_WIDEST_INT));
-static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
-static struct op parse_defined PARAMS ((cpp_reader *));
-static struct op lex PARAMS ((cpp_reader *, int));
-static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
-
-struct op
-{
-  enum cpp_ttype op;
-  U_CHAR prio;         /* Priority of op.  */
-  U_CHAR flags;
-  U_CHAR unsignedp;    /* True if value should be treated as unsigned.  */
-  HOST_WIDEST_INT value; /* The value logically "right" of op.  */
-};
-
-/* There is no "error" token, but we can't get comments in #if, so we can
-   abuse that token type.  */
-#define CPP_ERROR CPP_COMMENT
-
-/* With -O2, gcc appears to produce nice code, moving the error
-   message load and subsequent jump completely out of the main path.  */
-#define CPP_ICE(msgid) \
-  do { cpp_ice (pfile, msgid); goto syntax_error; } while(0)
-#define SYNTAX_ERROR(msgid) \
-  do { cpp_error (pfile, msgid); goto syntax_error; } while(0)
-#define SYNTAX_ERROR2(msgid, arg) \
-  do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
-
-struct suffix
-{
-  const unsigned char s[4];
-  const unsigned char u;
-  const unsigned char l;
-};
-
-static const struct suffix vsuf_1[] = {
-  { "u", 1, 0 }, { "U", 1, 0 },
-  { "l", 0, 1 }, { "L", 0, 1 }
-};
-
-static const struct suffix vsuf_2[] = {
-  { "ul", 1, 1 }, { "UL", 1, 1 }, { "uL", 1, 1 }, { "Ul", 1, 1 },
-  { "lu", 1, 1 }, { "LU", 1, 1 }, { "Lu", 1, 1 }, { "lU", 1, 1 },
-  { "ll", 0, 2 }, { "LL", 0, 2 }
-};
-
-static const struct suffix vsuf_3[] = {
-  { "ull", 1, 2 }, { "ULL", 1, 2 }, { "uLL", 1, 2 }, { "Ull", 1, 2 },
-  { "llu", 1, 2 }, { "LLU", 1, 2 }, { "LLu", 1, 2 }, { "llU", 1, 2 }
-};
-#define Nsuff(tab) (sizeof tab / sizeof (struct suffix))
-
-/* Parse and convert what is presumably an integer in TOK.  Accepts
-   decimal, hex, or octal with or without size suffixes.  Returned op
-   is CPP_ERROR on error, otherwise it is a CPP_NUMBER.  */
-static struct op
-parse_number (pfile, tok)
-     cpp_reader *pfile;
-     const cpp_token *tok;
-{
-  struct op op;
-  const U_CHAR *start = tok->val.str.text;
-  const U_CHAR *end = start + tok->val.str.len;
-  const U_CHAR *p = start;
-  int c = 0, i, nsuff;
-  unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
-  int base = 10;
-  int overflow = 0;
-  int digit, largest_digit = 0;
-  const struct suffix *sufftab;
-
-  op.unsignedp = 0;
-
-  if (p[0] == '0')
-    {
-      if (end - start >= 3 && (p[1] == 'x' || p[1] == 'X'))
-       {
-         p += 2;
-         base = 16;
-       }
-      else
-       {
-         p += 1;
-         base = 8;
-       }
-    }
-
-  /* Some buggy compilers (e.g. MPW C) seem to need both casts.  */
-  MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
-                  / ((unsigned HOST_WIDEST_INT) base));
-
-  for(; p < end; p++)
-    {
-      c = *p;
-
-      if (ISDIGIT (c)
-         || (base == 16 && ISXDIGIT (c)))
-       digit = hex_value (c);
-      else
-       break;
-
-      if (largest_digit < digit)
-       largest_digit = digit;
-      nd = n * base + digit;
-      overflow |= MAX_over_base < n || nd < n;
-      n = nd;
-    }
-
-  if (p < end)
-    {
-      /* Check for a floating point constant.  Note that float constants
-        with an exponent or suffix but no decimal point are technically
-        invalid (C99 6.4.4.2) but accepted elsewhere.  */
-      if ((c == '.' || c == 'F' || c == 'f')
-         || (base == 10 && (c == 'E' || c == 'e')
-             && p+1 < end && (p[1] == '+' || p[1] == '-'))
-         || (base == 16 && (c == 'P' || c == 'p')
-             && p+1 < end && (p[1] == '+' || p[1] == '-')))
-       SYNTAX_ERROR ("floating point numbers are not valid in #if");
-  
-      /* Determine the suffix. l means long, and u means unsigned.
-        See the suffix tables, above.  */
-      switch (end - p)
-       {
-       case 1: sufftab = vsuf_1; nsuff = Nsuff(vsuf_1); break;
-       case 2: sufftab = vsuf_2; nsuff = Nsuff(vsuf_2); break;
-       case 3: sufftab = vsuf_3; nsuff = Nsuff(vsuf_3); break;
-       default: goto invalid_suffix;
-       }
-
-      for (i = 0; i < nsuff; i++)
-       if (memcmp (p, sufftab[i].s, end - p) == 0)
-         break;
-      if (i == nsuff)
-       goto invalid_suffix;
-      op.unsignedp = sufftab[i].u;
-
-      if (CPP_WTRADITIONAL (pfile)
-         && sufftab[i].u
-         && ! cpp_sys_macro_p (pfile))
-       cpp_warning (pfile, "traditional C rejects the `U' suffix");
-      if (sufftab[i].l == 2 && CPP_OPTION (pfile, pedantic)
-         && ! CPP_OPTION (pfile, c99))
-       cpp_pedwarn (pfile, "too many 'l' suffixes in integer constant");
-    }
-  
-  if (base <= largest_digit)
-    cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
-
-  if (overflow)
-    cpp_pedwarn (pfile, "integer constant out of range");
-
-  /* If too big to be signed, consider it unsigned.  */
-  else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp)
-    {
-      if (base == 10)
-       cpp_warning (pfile, "integer constant is so large that it is unsigned");
-      op.unsignedp = 1;
-    }
-
-  op.value = n;
-  op.op = CPP_NUMBER;
-  return op;
-
- invalid_suffix:
-  cpp_error (pfile, "invalid suffix '%.*s' on integer constant",
-            (int) (end - p), p);
- syntax_error:
-  op.op = CPP_ERROR;
-  return op;
-}
-
-/* Handle meeting "defined" in a preprocessor expression.  */
-static struct op
-parse_defined (pfile)
-     cpp_reader *pfile;
-{
-  int paren = 0;
-  cpp_hashnode *node = 0;
-  const cpp_token *token;
-  struct op op;
-  cpp_context *initial_context = pfile->context;
-
-  /* Don't expand macros.  */
-  pfile->state.prevent_expansion++;
-
-  token = cpp_get_token (pfile);
-  if (token->type == CPP_OPEN_PAREN)
-    {
-      paren = 1;
-      token = cpp_get_token (pfile);
-    }
-
-  if (token->type == CPP_NAME)
-    {
-      node = token->val.node;
-      if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
-       {
-         cpp_error (pfile, "missing ')' after \"defined\"");
-         node = 0;
-       }
-    }
-  else
-    {
-      cpp_error (pfile, "operator \"defined\" requires an identifier");
-      if (token->flags & NAMED_OP)
-       {
-         cpp_token op;
-
-         op.flags = 0;
-         op.type = token->type;
-         cpp_error (pfile,
-                    "(\"%s\" is an alternative token for \"%s\" in C++)",
-                    cpp_token_as_text (pfile, token),
-                    cpp_token_as_text (pfile, &op));
-       }
-    }
-
-  if (!node)
-    op.op = CPP_ERROR;
-  else
-    {
-      if (pfile->context != initial_context)
-       cpp_warning (pfile, "this use of \"defined\" may not be portable");
-
-      op.value = node->type == NT_MACRO;
-      op.unsignedp = 0;
-      op.op = CPP_NUMBER;
-
-      /* A possible controlling macro of the form #if !defined ().
-        _cpp_parse_expr checks there was no other junk on the line.  */
-      pfile->mi_ind_cmacro = node;
-    }
-
-  pfile->state.prevent_expansion--;
-  return op;
-}
-
-/* Read a token.  The returned type is CPP_NUMBER for a valid number
-   (an interpreted preprocessing number or character constant, or the
-   result of the "defined" or "#" operators), CPP_ERROR on error,
-   CPP_EOF, or the type of an operator token.  */
-static struct op
-lex (pfile, skip_evaluation)
-     cpp_reader *pfile;
-     int skip_evaluation;
-{
-  struct op op;
-  const cpp_token *token = cpp_get_token (pfile);
-
-  switch (token->type)
-    {
-    case CPP_NUMBER:
-      return parse_number (pfile, token);
-
-    case CPP_CHAR:
-    case CPP_WCHAR:
-      {
-       unsigned int chars_seen;
-
-       if (token->type == CPP_CHAR)
-         op.unsignedp = 0;
-       else
-         op.unsignedp = WCHAR_UNSIGNED;
-       op.op = CPP_NUMBER;
-       op.value = cpp_interpret_charconst (pfile, token, 1, 0, &chars_seen);
-       return op;
-      }
-
-    case CPP_STRING:
-    case CPP_WSTRING:
-      SYNTAX_ERROR ("string constants are not valid in #if");
-
-    case CPP_OTHER:
-      if (ISGRAPH (token->val.c))
-       SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.c);
-      else
-       SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", token->val.c);
-
-    case CPP_NAME:
-      if (token->val.node == pfile->spec_nodes.n_defined)
-       return parse_defined (pfile);
-      else if (CPP_OPTION (pfile, cplusplus)
-              && (token->val.node == pfile->spec_nodes.n_true
-                  || token->val.node == pfile->spec_nodes.n_false))
-       {
-         op.op = CPP_NUMBER;
-         op.unsignedp = 0;
-         op.value = (token->val.node == pfile->spec_nodes.n_true);
-
-         /* Warn about use of true or false in #if when pedantic
-            and stdbool.h has not been included.  */
-         if (CPP_PEDANTIC (pfile)
-             && ! cpp_defined (pfile, DSC("__bool_true_false_are_defined")))
-           cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if",
-                        NODE_NAME (token->val.node));
-         return op;
-       }
-      else
-       {
-         op.op = CPP_NUMBER;
-         op.unsignedp = 0;
-         op.value = 0;
-
-         if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
-           cpp_warning (pfile, "\"%s\" is not defined",
-                        NODE_NAME (token->val.node));
-         return op;
-       }
-
-    case CPP_HASH:
-      {
-       int temp;
-
-       op.op = CPP_NUMBER;
-       if (_cpp_test_assertion (pfile, &temp))
-         op.op = CPP_ERROR;
-       op.unsignedp = 0;
-       op.value = temp;
-       return op;
-      }
-
-    default:
-      if (((int) token->type > (int) CPP_EQ
-          && (int) token->type < (int) CPP_PLUS_EQ)
-         || token->type == CPP_EOF)
-       {
-         op.op = token->type;
-         return op;
-       }
-
-      SYNTAX_ERROR2 ("\"%s\" is not valid in #if expressions",
-                    cpp_token_as_text (pfile, token));
-    }
-
- syntax_error:
-  op.op = CPP_ERROR;
-  return op;
-}
-
-/* Warn if appropriate on overflow.  */
-static void
-integer_overflow (pfile)
-     cpp_reader *pfile;
-{
-  if (CPP_PEDANTIC (pfile))
-    cpp_pedwarn (pfile, "integer overflow in preprocessor expression");
-}
-
-/* Handle shifting A left by B bits.  UNSIGNEDP is non-zero if A is
-   unsigned.  */
-static HOST_WIDEST_INT
-left_shift (pfile, a, unsignedp, b)
-     cpp_reader *pfile;
-     HOST_WIDEST_INT a;
-     unsigned int unsignedp;
-     unsigned HOST_WIDEST_INT b;
-{
-  if (b >= HOST_BITS_PER_WIDEST_INT)
-    {
-      if (! unsignedp && a != 0)
-       integer_overflow (pfile);
-      return 0;
-    }
-  else if (unsignedp)
-    return (unsigned HOST_WIDEST_INT) a << b;
-  else
-    {
-      HOST_WIDEST_INT l = a << b;
-      if (l >> b != a)
-       integer_overflow (pfile);
-      return l;
-    }
-}
-
-/* Handle shifting A right by B bits.  UNSIGNEDP is non-zero if A is
-   unsigned.  */
-static HOST_WIDEST_INT
-right_shift (pfile, a, unsignedp, b)
-     cpp_reader *pfile ATTRIBUTE_UNUSED;
-     HOST_WIDEST_INT a;
-     unsigned int unsignedp;
-     unsigned HOST_WIDEST_INT b;
-{
-  if (b >= HOST_BITS_PER_WIDEST_INT)
-    return unsignedp ? 0 : a >> (HOST_BITS_PER_WIDEST_INT - 1);
-  else if (unsignedp)
-    return (unsigned HOST_WIDEST_INT) a >> b;
-  else
-    return a >> b;
-}
-\f
-/* Operator precedence and flags table.
-
-After an operator is returned from the lexer, if it has priority less
-than or equal to the operator on the top of the stack, we reduce the
-stack by one operator and repeat the test.  Since equal priorities
-reduce, this is naturally left-associative.
-
-We handle right-associative operators by clearing the lower bit of all
-left-associative operators, and setting it for right-associative ones.
-After the reduction phase of a new operator, just before it is pushed
-onto the stack, its RIGHT_ASSOC bit is cleared.  The effect is that
-during the reduction phase, the current right-associative operator has
-a priority one greater than any other operator of otherwise equal
-precedence that has been pushed on the top of the stack.  This avoids
-a reduction pass, and effectively makes the logic right-associative.
-
-The remaining cases are '(' and ')'.  We handle '(' by skipping the
-reduction phase completely.  ')' is given lower priority than
-everything else, including '(', effectively forcing a reduction of the
-parenthesised expression.  If there is no matching '(', the stack will
-be reduced all the way to the beginning, exiting the parser in the
-same way as the ultra-low priority end-of-expression dummy operator.
-The exit code checks to see if the operator that caused it is ')', and
-if so outputs an appropriate error message.
-
-The parser assumes all shifted operators require a right operand
-unless the flag NO_R_OPERAND is set, and similarly for NO_L_OPERAND.
-These semantics are automatically checked, any extra semantics need to
-be handled with operator-specific code.  */
-
-#define FLAG_BITS  8
-#define FLAG_MASK ((1 << FLAG_BITS) - 1)
-#define PRIO_SHIFT (FLAG_BITS + 1)
-#define EXTRACT_PRIO(CNST) ((CNST) >> FLAG_BITS)
-#define EXTRACT_FLAGS(CNST) ((CNST) & FLAG_MASK)
-
-/* Flags.  */
-#define HAVE_VALUE     (1 << 0)
-#define NO_L_OPERAND   (1 << 1)
-#define NO_R_OPERAND   (1 << 2)
-#define SHORT_CIRCUIT  (1 << 3)
-
-/* Priority and flag combinations.  */
-#define RIGHT_ASSOC         (1 << FLAG_BITS)
-#define FORCE_REDUCE_PRIO   (0 << PRIO_SHIFT)
-#define CLOSE_PAREN_PRIO    (1 << PRIO_SHIFT)
-#define OPEN_PAREN_PRIO    ((2 << PRIO_SHIFT) | NO_L_OPERAND)
-#define COMMA_PRIO          (3 << PRIO_SHIFT)
-#define COND_PRIO          ((4 << PRIO_SHIFT) | RIGHT_ASSOC | SHORT_CIRCUIT)
-#define COLON_PRIO         ((5 << PRIO_SHIFT) | SHORT_CIRCUIT)
-#define OROR_PRIO          ((6 << PRIO_SHIFT) | SHORT_CIRCUIT)
-#define ANDAND_PRIO        ((7 << PRIO_SHIFT) | SHORT_CIRCUIT)
-#define OR_PRIO             (8 << PRIO_SHIFT)
-#define XOR_PRIO            (9 << PRIO_SHIFT)
-#define AND_PRIO           (10 << PRIO_SHIFT)
-#define MINMAX_PRIO       (11 << PRIO_SHIFT)
-#define EQUAL_PRIO         (12 << PRIO_SHIFT)
-#define LESS_PRIO          (13 << PRIO_SHIFT)
-#define SHIFT_PRIO         (14 << PRIO_SHIFT)
-#define PLUS_PRIO          (15 << PRIO_SHIFT)
-#define MUL_PRIO           (16 << PRIO_SHIFT)
-#define UNARY_PRIO        ((17 << PRIO_SHIFT) | RIGHT_ASSOC | NO_L_OPERAND)
-
-/* Operator to priority map.  Must be in the same order as the first
-   N entries of enum cpp_ttype.  */
-static const short
-op_to_prio[] =
-{
-  /* EQ */             0,              /* dummy entry - can't happen */
-  /* NOT */            UNARY_PRIO,
-  /* GREATER */                LESS_PRIO,
-  /* LESS */           LESS_PRIO,
-  /* PLUS */           UNARY_PRIO,     /* note these two can be unary */
-  /* MINUS */          UNARY_PRIO,     /* or binary */
-  /* MULT */           MUL_PRIO,
-  /* DIV */            MUL_PRIO,
-  /* MOD */            MUL_PRIO,
-  /* AND */            AND_PRIO,
-  /* OR */             OR_PRIO,
-  /* XOR */            XOR_PRIO,
-  /* RSHIFT */         SHIFT_PRIO,
-  /* LSHIFT */         SHIFT_PRIO,
-  /* MIN */            MINMAX_PRIO,    /* C++ specific */
-  /* MAX */            MINMAX_PRIO,    /* extensions */
-
-  /* COMPL */          UNARY_PRIO,
-  /* AND_AND */                ANDAND_PRIO,
-  /* OR_OR */          OROR_PRIO,
-  /* QUERY */          COND_PRIO,
-  /* COLON */          COLON_PRIO,
-  /* COMMA */          COMMA_PRIO,
-  /* OPEN_PAREN */     OPEN_PAREN_PRIO,
-  /* CLOSE_PAREN */    CLOSE_PAREN_PRIO,
-  /* EQ_EQ */          EQUAL_PRIO,
-  /* NOT_EQ */         EQUAL_PRIO,
-  /* GREATER_EQ */     LESS_PRIO,
-  /* LESS_EQ */                LESS_PRIO
-};
-
-#define COMPARE(OP) \
-  top->unsignedp = 0; \
-  top->value = (unsigned1 | unsigned2) \
-  ? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 \
-  : (v1 OP v2)
-#define EQUALITY(OP) \
-  top->value = v1 OP v2; \
-  top->unsignedp = 0;
-#define BITWISE(OP) \
-  top->value = v1 OP v2; \
-  top->unsignedp = unsigned1 | unsigned2;
-#define MINMAX(OP) \
-  top->value = (v1 OP v2) ? v1 : v2; \
-  top->unsignedp = unsigned1 | unsigned2;
-#define UNARY(OP) \
-  top->value = OP v2; \
-  top->unsignedp = unsigned2; \
-  top->flags |= HAVE_VALUE;
-#define SHIFT(PSH, MSH) \
-  if (skip_evaluation)  \
-    break;             \
-  top->unsignedp = unsigned1; \
-  if (v2 < 0 && ! unsigned2)  \
-    top->value = MSH (pfile, v1, unsigned1, -v2); \
-  else \
-    top->value = PSH (pfile, v1, unsigned1, v2);
-
-/* Parse and evaluate a C expression, reading from PFILE.
-   Returns the truth value of the expression.  */
-int
-_cpp_parse_expr (pfile)
-     cpp_reader *pfile;
-{
-  /* The implementation is an operator precedence parser, i.e. a
-     bottom-up parser, using a stack for not-yet-reduced tokens.
-
-     The stack base is 'stack', and the current stack pointer is 'top'.
-     There is a stack element for each operator (only),
-     and the most recently pushed operator is 'top->op'.
-     An operand (value) is stored in the 'value' field of the stack
-     element of the operator that precedes it.
-     In that case the 'flags' field has the HAVE_VALUE flag set.  */
-
-#define INIT_STACK_SIZE 20
-  struct op init_stack[INIT_STACK_SIZE];
-  struct op *stack = init_stack;
-  struct op *limit = stack + INIT_STACK_SIZE;
-  struct op *top = stack + 1;
-  int skip_evaluation = 0;
-  int result;
-  unsigned int lex_count, saw_leading_not;
-
-  /* Set up detection of #if ! defined().  */
-  pfile->mi_ind_cmacro = 0;
-  saw_leading_not = 0;
-  lex_count = 0;
-
-  /* We've finished when we try to reduce this.  */
-  top->op = CPP_EOF;
-  /* Nifty way to catch missing '('.  */
-  top->prio = EXTRACT_PRIO(CLOSE_PAREN_PRIO);
-  /* Avoid missing right operand checks.  */
-  top->flags = NO_R_OPERAND;
-
-  for (;;)
-    {
-      unsigned int prio;
-      unsigned int flags;
-      struct op op;
-
-      /* Read a token */
-      op = lex (pfile, skip_evaluation);
-      lex_count++;
-
-      /* If the token is an operand, push its value and get next
-        token.  If it is an operator, get its priority and flags, and
-        try to reduce the expression on the stack.  */
-      switch (op.op)
-       {
-       case CPP_ERROR:
-         goto syntax_error;
-       push_immediate:
-       case CPP_NUMBER:
-         /* Push a value onto the stack.  */
-         if (top->flags & HAVE_VALUE)
-           SYNTAX_ERROR ("missing binary operator");
-         top->value = op.value;
-         top->unsignedp = op.unsignedp;
-         top->flags |= HAVE_VALUE;
-         continue;
-
-       case CPP_EOF:   prio = FORCE_REDUCE_PRIO;       break;
-
-       case CPP_NOT:
-         saw_leading_not = lex_count == 1;
-         prio = op_to_prio[op.op];
-         break;
-       case CPP_PLUS:
-       case CPP_MINUS: prio = PLUS_PRIO;  if (top->flags & HAVE_VALUE) break;
-          /* else unary; fall through */
-       default:        prio = op_to_prio[op.op];       break;
-       }
-
-      /* Separate the operator's code into priority and flags.  */
-      flags = EXTRACT_FLAGS(prio);
-      prio = EXTRACT_PRIO(prio);
-      if (prio == EXTRACT_PRIO(OPEN_PAREN_PRIO))
-       goto skip_reduction;
-
-      /* Check for reductions.  Then push the operator.  */
-      while (prio <= top->prio)
-       {
-         HOST_WIDEST_INT v1, v2;
-         unsigned int unsigned1, unsigned2;
-         
-         /* Most operators that can appear on the stack require a
-            right operand.  Check this before trying to reduce.  */
-         if ((top->flags & (HAVE_VALUE | NO_R_OPERAND)) == 0)
-           {
-             if (top->op == CPP_OPEN_PAREN)
-               SYNTAX_ERROR ("void expression between '(' and ')'");
-             else
-               SYNTAX_ERROR2 ("operator '%s' has no right operand",
-                              op_as_text (pfile, top->op));
-           }
-
-         unsigned2 = top->unsignedp, v2 = top->value;
-         top--;
-         unsigned1 = top->unsignedp, v1 = top->value;
-
-         /* Now set top->value = (top[1].op)(v1, v2); */
-         switch (top[1].op)
-           {
-           default:
-             cpp_ice (pfile, "impossible operator '%s'",
-                              op_as_text (pfile, top[1].op));
-             goto syntax_error;
-
-           case CPP_NOT:        UNARY(!);      break;
-           case CPP_COMPL:      UNARY(~);      break;
-           case CPP_LESS:       COMPARE(<);    break;
-           case CPP_GREATER:    COMPARE(>);    break;
-           case CPP_LESS_EQ:    COMPARE(<=);   break;
-           case CPP_GREATER_EQ: COMPARE(>=);   break;
-           case CPP_EQ_EQ:      EQUALITY(==);  break;
-           case CPP_NOT_EQ:     EQUALITY(!=);  break;
-           case CPP_AND:        BITWISE(&);    break;
-           case CPP_XOR:        BITWISE(^);    break;
-           case CPP_OR:         BITWISE(|);    break;
-           case CPP_LSHIFT:     SHIFT(left_shift, right_shift); break;
-           case CPP_RSHIFT:     SHIFT(right_shift, left_shift); break;
-           case CPP_MIN:        MINMAX(<);     break;
-           case CPP_MAX:        MINMAX(>);     break;
-
-           case CPP_PLUS:
-             if (!(top->flags & HAVE_VALUE))
-               {
-                 /* Can't use UNARY(+) because K+R C did not have unary
-                    plus.  Can't use UNARY() because some compilers object
-                    to the empty argument.  */
-                 top->value = v2;
-                 top->unsignedp = unsigned2;
-                 top->flags |= HAVE_VALUE;
-
-                 if (CPP_WTRADITIONAL (pfile))
-                   cpp_warning (pfile,
-                       "traditional C rejects the unary plus operator");
-               }
-             else
-               {
-                 top->value = v1 + v2;
-                 top->unsignedp = unsigned1 | unsigned2;
-                 if (! top->unsignedp && ! skip_evaluation
-                     && ! possible_sum_sign (v1, v2, top->value))
-                   integer_overflow (pfile);
-               }
-             break;
-           case CPP_MINUS:
-             if (!(top->flags & HAVE_VALUE))
-               {
-                 UNARY(-);
-                 if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
-                   integer_overflow (pfile);
-               }
-             else
-               { /* Binary '-' */
-                 top->value = v1 - v2;
-                 top->unsignedp = unsigned1 | unsigned2;
-                 if (! top->unsignedp && ! skip_evaluation
-                     && ! possible_sum_sign (top->value, v2, v1))
-                   integer_overflow (pfile);
-               }
-             break;
-           case CPP_MULT:
-             top->unsignedp = unsigned1 | unsigned2;
-             if (top->unsignedp)
-               top->value = (unsigned HOST_WIDEST_INT) v1 * v2;
-             else if (!skip_evaluation)
-               {
-                 top->value = v1 * v2;
-                 if (v1 && (top->value / v1 != v2
-                            || (top->value & v1 & v2) < 0))
-                   integer_overflow (pfile);
-               }
-             break;
-           case CPP_DIV:
-           case CPP_MOD:
-             if (skip_evaluation)
-               break;
-             if (v2 == 0)
-               SYNTAX_ERROR ("division by zero in #if");
-             top->unsignedp = unsigned1 | unsigned2;
-             if (top[1].op == CPP_DIV)
-               {
-                 if (top->unsignedp)
-                   top->value = (unsigned HOST_WIDEST_INT) v1 / v2;
-                 else
-                   {
-                     top->value = v1 / v2;
-                     if ((top->value & v1 & v2) < 0)
-                       integer_overflow (pfile);
-                   }
-               }
-             else
-               {
-                 if (top->unsignedp)
-                   top->value = (unsigned HOST_WIDEST_INT) v1 % v2;
-                 else
-                   top->value = v1 % v2;
-               }
-             break;
-
-           case CPP_OR_OR:
-             top->value = v1 || v2;
-             top->unsignedp = 0;
-             if (v1) skip_evaluation--;
-             break;
-           case CPP_AND_AND:
-             top->value = v1 && v2;
-             top->unsignedp = 0;
-             if (!v1) skip_evaluation--;
-             break;
-           case CPP_COMMA:
-             if (CPP_PEDANTIC (pfile))
-               cpp_pedwarn (pfile, "comma operator in operand of #if");
-             top->value = v2;
-             top->unsignedp = unsigned2;
-             break;
-           case CPP_QUERY:
-             SYNTAX_ERROR ("syntax error '?' without following ':'");
-           case CPP_COLON:
-             if (top[0].op != CPP_QUERY)
-               SYNTAX_ERROR ("syntax error ':' without preceding '?'");
-             top--;
-             if (top->value) skip_evaluation--;
-             top->value = top->value ? v1 : v2;
-             top->unsignedp = unsigned1 | unsigned2;
-             break;
-           case CPP_OPEN_PAREN:
-             if (op.op != CPP_CLOSE_PAREN)
-               SYNTAX_ERROR ("missing ')' in expression");
-             op.value = v2;
-             op.unsignedp = unsigned2;
-             goto push_immediate;
-           case CPP_EOF:
-             /* Reducing this dummy operator indicates we've finished.  */
-             if (op.op == CPP_CLOSE_PAREN)
-               SYNTAX_ERROR ("missing '(' in expression");
-             goto done;
-           }
-       }
-
-      /* Handle short-circuit evaluations.  */
-      if (flags & SHORT_CIRCUIT)
-       switch (op.op)
-         {
-         case CPP_OR_OR:    if (top->value) skip_evaluation++; break;
-         case CPP_AND_AND:
-         case CPP_QUERY:    if (!top->value) skip_evaluation++; break;
-         case CPP_COLON:
-           if (top[-1].value) /* Was '?' condition true?  */
-             skip_evaluation++;
-           else
-             skip_evaluation--;
-         default:
-           break;
-         }
-
-    skip_reduction:
-      /* Check we have a left operand iff we need one.  */
-      if (flags & NO_L_OPERAND)
-       {
-         if (top->flags & HAVE_VALUE)
-           SYNTAX_ERROR2 ("missing binary operator before '%s'",
-                          op_as_text (pfile, op.op));
-       }
-      else
-       {
-         if (!(top->flags & HAVE_VALUE))
-           SYNTAX_ERROR2 ("operator '%s' has no left operand",
-                          op_as_text (pfile, op.op));
-       }
-
-      /* Check for and handle stack overflow.  */
-      top++;
-      if (top == limit)
-       {
-         struct op *new_stack;
-         int old_size = (char *) limit - (char *) stack;
-         int new_size = 2 * old_size;
-         if (stack != init_stack)
-           new_stack = (struct op *) xrealloc (stack, new_size);
-         else
-           {
-             new_stack = (struct op *) xmalloc (new_size);
-             memcpy (new_stack, stack, old_size);
-           }
-         stack = new_stack;
-         top = (struct op *) ((char *) new_stack + old_size);
-         limit = (struct op *) ((char *) new_stack + new_size);
-       }
-      
-      top->flags = flags;
-      top->prio = prio & ~EXTRACT_PRIO(RIGHT_ASSOC);
-      top->op = op.op;
-    }
-
- done:
-  /* The controlling macro expression is only valid if we called lex 3
-     times: <!> <defined expression> and <EOF>.  push_conditional ()
-     checks that we are at top-of-file.  */
-  if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
-    pfile->mi_ind_cmacro = 0;
-
-  result = (top[1].value != 0);
-
-  if (top != stack)
-    CPP_ICE ("unbalanced stack in #if");
-  else if (!(top[1].flags & HAVE_VALUE))
-    {
-      SYNTAX_ERROR ("#if with no expression");
-    syntax_error:
-      result = 0;  /* Return 0 on syntax error.  */
-    }
-
-  /* Free dynamic stack if we allocated one.  */
-  if (stack != init_stack)
-    free (stack);
-  return result;
-}
-
-/* Output OP as text for diagnostics.  */
-static const unsigned char *
-op_as_text (pfile, op)
-     cpp_reader *pfile;
-     enum cpp_ttype op;
-{
-  cpp_token token;
-
-  token.type = op;
-  token.flags = 0;
-  return cpp_token_as_text (pfile, &token);
-}