OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cppexp.c
index 237b8e6..58430c3 100644 (file)
@@ -1,5 +1,6 @@
 /* Parse C expressions for cpplib.
    Copyright (C) 1987, 92, 94, 95, 97, 98, 1999, 2000 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
@@ -14,13 +15,7 @@ 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.
-
- 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.  */
+Boston, MA 02111-1307, USA.  */
 
 /* Parse a C expression from text in a string  */
    
@@ -73,7 +68,7 @@ Written by Per Bothner 1994.  */
    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)
 
-typedef short op_t;
+typedef int op_t;
 
 static void integer_overflow PARAMS ((cpp_reader *));
 static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
@@ -87,6 +82,7 @@ static struct operation parse_number PARAMS ((cpp_reader *, U_CHAR *,
 static struct operation parse_charconst PARAMS ((cpp_reader *, U_CHAR *,
                                                 U_CHAR *));
 static struct operation parse_defined PARAMS ((cpp_reader *));
+static struct operation parse_assertion PARAMS ((cpp_reader *));
 static HOST_WIDEST_INT parse_escape PARAMS ((cpp_reader *, U_CHAR **,
                                             HOST_WIDEST_INT));
 static struct operation lex PARAMS ((cpp_reader *, int));
@@ -115,6 +111,15 @@ struct operation
   HOST_WIDEST_INT value; /* The value logically "right" of op.  */
 };
 
+/* 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)
+
 /* Parse and convert an integer for #if.  Accepts decimal, hex, or octal
    with or without size suffixes.  */
 
@@ -318,7 +323,7 @@ parse_charconst (pfile, start, end)
   /* If char type is signed, sign-extend the constant.  */
   num_bits = num_chars * width;
       
-  if (cpp_defined (pfile, (const U_CHAR *)"__CHAR_UNSIGNED__",
+  if (cpp_defined (pfile, U"__CHAR_UNSIGNED__",
                   sizeof ("__CHAR_UNSIGNED__")-1)
       || ((result >> (num_bits - 1)) & 1) == 0)
     op.value = result & ((unsigned HOST_WIDEST_INT) ~0
@@ -352,7 +357,7 @@ parse_defined (pfile)
 
   pfile->no_macro_expand++;
   token = _cpp_get_directive_token (pfile);
-  if (token == CPP_LPAREN)
+  if (token == CPP_OPEN_PAREN)
     {
       paren++;
       CPP_SET_WRITTEN (pfile, old_written);
@@ -368,7 +373,7 @@ parse_defined (pfile)
 
   if (paren)
     {
-      if (_cpp_get_directive_token (pfile) != CPP_RPAREN)
+      if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
        goto oops;
     }
   CPP_SET_WRITTEN (pfile, old_written);
@@ -384,6 +389,81 @@ parse_defined (pfile)
   return op;
 }
 
+static struct operation
+parse_assertion (pfile)
+     cpp_reader *pfile;
+{
+  struct operation op;
+  cpp_hashnode *hp;
+  struct predicate *pred;
+  cpp_toklist query;
+  enum cpp_ttype type;
+  U_CHAR *tok;
+  size_t len;
+  unsigned int old_written;
+  int specific = 0;
+
+  old_written = CPP_WRITTEN (pfile);
+  CPP_PUTC (pfile, '#');
+  pfile->no_macro_expand++;
+  type = _cpp_get_directive_token (pfile);
+  if (type == CPP_VSPACE)
+    SYNTAX_ERROR ("assertion without predicate");
+  else if (type != CPP_NAME)
+    SYNTAX_ERROR ("assertion predicate is not an identifier");
+
+  tok = pfile->token_buffer + old_written;
+  len = CPP_WRITTEN (pfile) - old_written;
+  hp = cpp_lookup (pfile, tok, len);
+
+  /* Look ahead for an open paren.  */
+  _cpp_skip_hspace (pfile);
+  if (CPP_BUF_PEEK (CPP_BUFFER (pfile)) == '(')
+    {
+      if (_cpp_get_directive_token (pfile) != CPP_OPEN_PAREN)
+       CPP_ICE ("impossible token, expecting ( in parse_assertion");
+
+      _cpp_init_toklist (&query, NO_DUMMY_TOKEN);
+      specific = 1;
+      if (_cpp_scan_until (pfile, &query, CPP_CLOSE_PAREN) != CPP_CLOSE_PAREN)
+       SYNTAX_ERROR ("missing close paren on assertion answer");
+
+      if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
+       CPP_ICE ("impossible token, expecting ) in parse_assertion");
+    }
+
+  /* If we get here, the syntax is valid.  */
+  op.op = INT;
+  op.value = 0;
+  /* Has this predicate been asserted at all?  */
+  if (hp->type == T_ASSERTION)
+    {
+      if (specific)
+       {
+         for (pred = hp->value.pred; pred; pred = pred->next)
+           if (_cpp_equiv_toklists (&query, &pred->answer))
+             {
+               op.value = 1;
+               break;
+             }
+         _cpp_free_toklist (&query);
+       }
+      else
+       op.value = 1;
+    }
+
+ out:
+  pfile->no_macro_expand--;
+  CPP_SET_WRITTEN (pfile, old_written);
+  return op;
+
+ syntax_error:
+  if (specific)
+    _cpp_free_toklist (&query);
+  op.op = ERROR;
+  goto out;
+}
+
 struct token
 {
   const char *operator;
@@ -444,7 +524,7 @@ lex (pfile, skip_evaluation)
       return parse_charconst (pfile, tok_start, tok_end);
 
     case CPP_NAME:
-      if (!strncmp (tok_start, "defined", 7))
+      if (!ustrncmp (tok_start, U"defined", 7))
        return parse_defined (pfile);
 
       op.op = INT;
@@ -456,11 +536,8 @@ lex (pfile, skip_evaluation)
                     (int) (tok_end - tok_start), tok_start);
       return op;
 
-    case CPP_ASSERTION:
-      op.op = INT;
-      op.unsignedp = 0;
-      op.value = cpp_defined (pfile, tok_start, tok_end - tok_start);
-      return op;
+    case CPP_HASH:
+      return parse_assertion (pfile);
 
     case CPP_OTHER:
       /* See if it is a special token of length 2.  */
@@ -471,8 +548,8 @@ lex (pfile, skip_evaluation)
                && tok_start[1] == toktab->operator[1])
                break;
          if (toktab->token == ERROR)
-           cpp_error (pfile, "'%s' not allowed in operand of #if",
-                      tok_start);
+           cpp_error (pfile, "'%.*s' is not allowed in #if expressions",
+                      (int) (tok_end - tok_start), tok_start);
          op.op = toktab->token; 
          return op;
        }
@@ -739,15 +816,6 @@ be handled with operator-specific code.  */
   top->value = v1 OP v2; \
   top->unsignedp = unsigned1 | unsigned2;
 
-/* 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)
-
 /* Parse and evaluate a C expression, reading from PFILE.
    Returns the truth value of the expression.  */
 
@@ -775,7 +843,12 @@ _cpp_parse_expr (pfile)
   int result;
   char buff[5];
 
-  pfile->parsing_if_directive++;
+  /* Save parser state and set it to something sane.  */
+  int save_only_seen_white = pfile->only_seen_white;
+  int save_skipping = pfile->skipping;
+  pfile->only_seen_white = 0;
+  pfile->skipping = 0;
+
   /* We've finished when we try to reduce this.  */
   top->op = FINISHED;
   /* Nifty way to catch missing '('.  */
@@ -801,11 +874,6 @@ _cpp_parse_expr (pfile)
          CPP_ICE ("lex returns a NAME");
        case ERROR:
          goto syntax_error;
-       case '#':
-         /* We get '#' when get_directive_token hits a syntactically
-            invalid assertion predicate.  _cpp_parse_assertion has
-            already issued an error.  */
-         goto syntax_error;
        default:
          SYNTAX_ERROR ("invalid character in #if");
 
@@ -1099,7 +1167,8 @@ _cpp_parse_expr (pfile)
   /* Free dynamic stack if we allocated one.  */
   if (stack != init_stack)
     free (stack);
-  pfile->parsing_if_directive--;
   CPP_SET_WRITTEN (pfile, old_written);
+  pfile->only_seen_white = save_only_seen_white;
+  pfile->skipping = save_skipping;
   return result;
 }