OSDN Git Service

* jump.c (jump_optimize, follow_jumps, mark_jump_label): Disable some
[pf3gnuchains/gcc-fork.git] / gcc / cppexp.c
index 11fdfdd..471818a 100644 (file)
@@ -1,5 +1,5 @@
 /* Parse C expressions for CCCP.
-   Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation.
+   Copyright (C) 1987, 1992, 1994, 1995, 1997 Free Software Foundation.
 
 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
@@ -13,19 +13,23 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
 
  In other words, you are welcome to use, share and improve this program.
  You are forbidden to forbid anyone else to use, share and improve
  what you give them.   Help stamp out software-hoarding!
 
-Written by Per Bothner 1994. */
+Written by Per Bothner 1994.  */
 
 /* Parse a C expression from text in a string  */
    
 #include "config.h"
 #include "cpplib.h"
 
+extern char *xmalloc PARAMS ((unsigned));
+extern char *xrealloc PARAMS ((char *, unsigned));
+
 #ifdef MULTIBYTE_CHARS
 #include <stdlib.h>
 #include <locale.h>
@@ -56,7 +60,7 @@ struct arglist {
 #endif
 
 #ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
+#define NULL_PTR ((GENERIC_PTR) 0)
 #endif
 
 extern char *xmalloc ();
@@ -117,14 +121,29 @@ static long right_shift ();
 #define LEFT_OPERAND_REQUIRED 1
 #define RIGHT_OPERAND_REQUIRED 2
 #define HAVE_VALUE 4
-/*#define UNSIGNEDP 8*/
+/* SKIP_OPERAND is set for '&&' '||' '?' and ':' when the
+   following operand should be short-circuited instead of evaluated.  */
+#define SKIP_OPERAND 8
+/*#define UNSIGNEDP 16*/
+
+#ifndef HOST_BITS_PER_WIDE_INT
+
+#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
+#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
+#define HOST_WIDE_INT long
+#else
+#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
+#define HOST_WIDE_INT int
+#endif
+
+#endif
 
 struct operation {
     short op;
-    char rprio; /* Priority of op (relative to it right operand). */
+    char rprio; /* Priority of op (relative to it right operand).  */
     char flags;
     char unsignedp;    /* true if value should be treated as unsigned */
-    long value;        /* The value logically "right" of op. */
+    HOST_WIDE_INT value;        /* The value logically "right" of op.  */
 };
 \f
 /* Take care of parsing a number (anything that starts with a digit).
@@ -167,13 +186,8 @@ parse_number (pfile, start, olen)
   else if (*p == '0')
     base = 8;
 
-  ULONG_MAX_over_base = (unsigned long) -1 / base;
-/* start-sanitize-mpw */
-  /* Work around yet another MPW C bug. */
-#ifdef MPW_C
+  /* Some buggy compilers (e.g. MPW C) seem to need both casts.  */
   ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
-#endif /* MPW_C */
-/* end-sanitize-mpw */
 
   for (; len > 0; len--) {
     c = *p++;
@@ -224,10 +238,10 @@ parse_number (pfile, start, olen)
     }
 
   if (base <= largest_digit)
-    cpp_warning (pfile, "integer constant contains digits beyond the radix");
+    cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
 
   if (overflow)
-    cpp_warning (pfile, "integer constant out of range");
+    cpp_pedwarn (pfile, "integer constant out of range");
 
   /* If too big to be signed, consider it unsigned.  */
   if ((long) n < 0 && ! op.unsignedp)
@@ -261,11 +275,11 @@ static struct token tokentab2[] = {
   {NULL, ERROR}
 };
 
-/* Read one token. */
+/* Read one token.  */
 
 struct operation
 cpp_lex (pfile)
-cpp_reader *pfile;
+     cpp_reader *pfile;
 {
   register int c;
   register int namelen;
@@ -277,13 +291,13 @@ cpp_reader *pfile;
 
  retry:
 
+  old_written = CPP_WRITTEN (pfile);
+  cpp_skip_hspace (pfile);
   c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
   if (c == '#')
     return parse_number (pfile,
                         cpp_read_check_assertion (pfile) ? "1" : "0", 1);
 
-  old_written = CPP_WRITTEN (pfile);
-  cpp_skip_hspace (pfile);
   if (c == '\n')
     {
       op.op = 0;
@@ -296,16 +310,17 @@ cpp_reader *pfile;
   pfile->limit = tok_start;
   switch (token)
   {
-    case CPP_EOF: /* Should not happen ... */
+    case CPP_EOF: /* Should not happen ...  */
+    case CPP_VSPACE:
       op.op = 0;
       return op;
-    case CPP_VSPACE:
     case CPP_POP:
       if (CPP_BUFFER (pfile)->fname != NULL)
        {
          op.op = 0;
          return op;
        }
+      cpp_pop_buffer (pfile);
       goto retry;
     case CPP_HSPACE:   case CPP_COMMENT: 
       goto retry;
@@ -346,11 +361,9 @@ cpp_reader *pfile;
        else
            max_chars = MAX_LONG_TYPE_SIZE / width;
 
-       while (1)
+       ++ptr;
+       while (ptr < tok_end && ((c = *ptr++) != '\''))
          {
-           if (ptr >= CPP_PWRITTEN (pfile) || (c = *ptr++) == '\'')
-             break;
-
            if (c == '\\')
              {
                c = cpp_parse_escape (pfile, &ptr);
@@ -416,7 +429,7 @@ cpp_reader *pfile;
                  if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
                    result = wc;
                  else
-                   cpp_warning (pfile,"Ignoring invalid multibyte character");
+                   cpp_pedwarn (pfile,"Ignoring invalid multibyte character");
                }
 #endif
              op.value = result;
@@ -529,7 +542,7 @@ cpp_parse_escape (pfile, string_ptr)
        if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
          {
            i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
-           cpp_warning (pfile,
+           cpp_pedwarn (pfile,
                          "octal character constant does not fit in a byte");
          }
        return i;
@@ -560,7 +573,7 @@ cpp_parse_escape (pfile, string_ptr)
        if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
          {
            i &= (1 << BITS_PER_UNIT) - 1;
-           cpp_warning (pfile,
+           cpp_pedwarn (pfile,
                         "hex character constant does not fit in a byte");
          }
        return i;
@@ -617,7 +630,7 @@ right_shift (pfile, a, unsignedp, b)
     return a >> b;
 }
 \f
-/* These priorities are all even, so we can handle associatively. */
+/* These priorities are all even, so we can handle associatively.  */
 #define PAREN_INNER_PRIO 0
 #define COMMA_PRIO 4
 #define COND_PRIO (COMMA_PRIO+2)
@@ -641,7 +654,7 @@ right_shift (pfile, a, unsignedp, b)
 /* Parse and evaluate a C expression, reading from PFILE.
    Returns the value of the expression.  */
 
-long
+HOST_WIDE_INT
 cpp_parse_expr (pfile)
      cpp_reader *pfile;
 {
@@ -661,6 +674,7 @@ cpp_parse_expr (pfile)
   struct operation *limit = stack + INIT_STACK_SIZE;
   register struct operation *top = stack;
   int lprio, rprio;
+  int skip_evaluation = 0;
 
   top->rprio = 0;
   top->flags = 0;
@@ -674,7 +688,7 @@ cpp_parse_expr (pfile)
 
       /* See if the token is an operand, in which case go to set_value.
         If the token is an operator, figure out its left and right
-        priorities, and then goto maybe_reduce. */
+        priorities, and then goto maybe_reduce.  */
 
       switch (op.op)
        {
@@ -731,7 +745,7 @@ cpp_parse_expr (pfile)
        }
 
     set_value:
-      /* Push a value onto the stack. */
+      /* Push a value onto the stack.  */
       if (top->flags & HAVE_VALUE)
        {
          cpp_error (pfile, "syntax error in #if");
@@ -741,7 +755,7 @@ cpp_parse_expr (pfile)
       continue;
 
     maybe_reduce:
-      /* Push an operator, and check if we can reduce now. */
+      /* Push an operator, and check if we can reduce now.  */
       while (top->rprio > lprio)
        {
          long v1 = top[-1].value, v2 = top[0].value;
@@ -773,7 +787,7 @@ cpp_parse_expr (pfile)
                {
                  top->value = v1 + v2;
                  top->unsignedp = unsigned1 || unsigned2;
-                 if (! top->unsignedp
+                 if (! top->unsignedp && ! skip_evaluation
                      && ! possible_sum_sign (v1, v2, top->value))
                    integer_overflow (pfile);
                }
@@ -782,7 +796,7 @@ cpp_parse_expr (pfile)
              if (!(top->flags & HAVE_VALUE))
                { /* Unary '-' */
                  top->value = - v2;
-                 if ((top->value & v2) < 0 && ! unsigned2)
+                 if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
                    integer_overflow (pfile);
                  top->unsignedp = unsigned2;
                  top->flags |= HAVE_VALUE;
@@ -791,7 +805,7 @@ cpp_parse_expr (pfile)
                { /* Binary '-' */
                  top->value = v1 - v2;
                  top->unsignedp = unsigned1 || unsigned2;
-                 if (! top->unsignedp
+                 if (! top->unsignedp && ! skip_evaluation
                      && ! possible_sum_sign (top->value, v2, v1))
                    integer_overflow (pfile);
                }
@@ -800,7 +814,7 @@ cpp_parse_expr (pfile)
              top->unsignedp = unsigned1 || unsigned2;
              if (top->unsignedp)
                top->value = (unsigned long) v1 * v2;
-             else
+             else if (!skip_evaluation)
                {
                  top->value = v1 * v2;
                  if (v1
@@ -810,6 +824,8 @@ cpp_parse_expr (pfile)
                }
              break;
            case '/':
+             if (skip_evaluation)
+               break;
              if (v2 == 0)
                {
                  cpp_error (pfile, "division by zero in #if");
@@ -826,6 +842,8 @@ cpp_parse_expr (pfile)
                }
              break;
            case '%':
+             if (skip_evaluation)
+               break;
              if (v2 == 0)
                {
                  cpp_error (pfile, "division by zero in #if");
@@ -870,6 +888,8 @@ cpp_parse_expr (pfile)
              top->unsignedp = 0;
              break;
            case LSH:
+             if (skip_evaluation)
+               break;
              top->unsignedp = unsigned1;
              if (v2 < 0 && ! unsigned2)
                top->value = right_shift (pfile, v1, unsigned1, -v2);
@@ -877,6 +897,8 @@ cpp_parse_expr (pfile)
                top->value = left_shift (pfile, v1, unsigned1, v2);
              break;
            case RSH:
+             if (skip_evaluation)
+               break;
              top->unsignedp = unsigned1;
              if (v2 < 0 && ! unsigned2)
                top->value = left_shift (pfile, v1, unsigned1, -v2);
@@ -890,9 +912,13 @@ cpp_parse_expr (pfile)
            case '^':  LOGICAL(^);  break;
            case '|':  LOGICAL(|);  break;
            case ANDAND:
-             top->value = v1 && v2;  top->unsignedp = 0;  break;
+             top->value = v1 && v2;  top->unsignedp = 0;
+             if (!v1) skip_evaluation--;
+             break;
            case OROR:
-             top->value = v1 || v2;  top->unsignedp = 0;  break;
+             top->value = v1 || v2;  top->unsignedp = 0;
+             if (v1) skip_evaluation--;
+             break;
            case ',':
              if (CPP_PEDANTIC (pfile))
                cpp_pedwarn (pfile, "comma operator in operand of `#if'");
@@ -919,6 +945,7 @@ cpp_parse_expr (pfile)
              else
                {
                  top--;
+                 if (top->value) skip_evaluation--;
                  top->value = top->value ? v1 : v2;
                  top->unsignedp = unsigned1 || unsigned2;
                }
@@ -958,27 +985,40 @@ cpp_parse_expr (pfile)
        }
       top++;
       
-      /* Check for and handle stack overflow. */
+      /* Check for and handle stack overflow.  */
       if (top == limit)
        {
          struct operation *new_stack;
-         int old_size = (char*)limit - (char*)stack;
+         int old_size = (char *) limit - (char *) stack;
          int new_size = 2 * old_size;
          if (stack != init_stack)
-           new_stack = (struct operation*) xrealloc (stack, new_size);
+           new_stack = (struct operation *) xrealloc (stack, new_size);
          else
            {
-             new_stack = (struct operation*) xmalloc (new_size);
-             bcopy (stack, new_stack, old_size);
+             new_stack = (struct operation *) xmalloc (new_size);
+             bcopy ((char *) stack, (char *) new_stack, old_size);
            }
          stack = new_stack;
-         top = (struct operation*)((char*) new_stack + old_size);
-         limit = (struct operation*)((char*) new_stack + new_size);
+         top = (struct operation *) ((char *) new_stack + old_size);
+         limit = (struct operation *) ((char *) new_stack + new_size);
        }
       
       top->flags = flags;
       top->rprio = rprio;
       top->op = op.op;
+      if ((op.op == OROR && top[-1].value)
+         || (op.op == ANDAND && !top[-1].value)
+         || (op.op == '?' && !top[-1].value))
+       {
+         skip_evaluation++;
+       }
+      else if (op.op == ':')
+       {
+         if (top[-2].value) /* Was condition true? */
+           skip_evaluation++;
+         else
+           skip_evaluation--;
+       }
     }
  syntax_error:
   if (stack != init_stack)