This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Cleaning up #if


The #if expression parser was still coded to the old internal
interface (using a couple of shims).  This patch updates it to the new
way of things.  We get some nice simplifications out of it, too -
e.g. note the replacement of an entire switch block with a single
table lookup.

Some of the number- and constant-parsing code is more general than
this needs; that's because it will eventually be used by more than
just #if.

Bootstrapped i386-linux; committed.

zw

	* cppexp.c: Update all code for new lexer interface.
	(op_t, operator codes, struct token, tokentab2, op_to_str): Remove.
	(struct suffix, vsuf_1, vsuf_2, vsuf_3, op_to_prio): New.
	* cpplex.c (token_names): Trim leading CPP_ from names; make
	the strings unsigned.
	(_cpp_spell_operator): New.
	(is_macro_disabled): Disable all macros if rescanning
	preprocessed text.
	(_cpp_get_directive_token): Remove.

	* cppinit.c: Don't set no_macro_expand.
	* cpplib.c (read_line_number, do_line): Check only for EOF,
	not VSPACE.
	* cpphash.h: Update prototypes.
	* cpplib.h (CPP_VSPACE): Remove.
	(struct cpp_reader): Remove no_macro_expand.

testsuite:
	* gcc.dg/cpp/19951227-1.c, gcc.dg/cpp/assert2.c,
	gcc.dg/cpp/if-1.c, gcc.dg/cpp/if-4.c: Tweak error regexps.

===================================================================
Index: cppexp.c
--- cppexp.c	2000/07/05 05:33:55	1.62
+++ cppexp.c	2000/07/08 02:19:27
@@ -68,8 +68,6 @@ Boston, MA 02111-1307, USA.  */
    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 int op_t;
-
 static void integer_overflow PARAMS ((cpp_reader *));
 static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
 					   unsigned int,
@@ -77,40 +75,27 @@ static HOST_WIDEST_INT left_shift PARAMS
 static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
 					    unsigned int,
 					    unsigned HOST_WIDEST_INT));
-static struct operation parse_number PARAMS ((cpp_reader *, U_CHAR *,
-					      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));
-static const char * op_to_str PARAMS ((op_t, char *));
-
-#define ERROR 299
-#define OROR 300
-#define ANDAND 301
-#define EQUAL 302
-#define NOTEQUAL 303
-#define LEQ 304
-#define GEQ 305
-#define LSH 306
-#define RSH 307
-#define NAME 308
-#define INT 309
-#define CHAR 310
-#define FINISHED 311
+static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
+static struct op parse_charconst PARAMS ((cpp_reader *, const cpp_token *));
+static struct op parse_defined PARAMS ((cpp_reader *));
+static struct op parse_assertion PARAMS ((cpp_reader *));
+static HOST_WIDEST_INT parse_escape PARAMS ((cpp_reader *, const U_CHAR **,
+					     const U_CHAR *, HOST_WIDEST_INT));
+static struct op lex PARAMS ((cpp_reader *, int));
 
-struct operation
+struct op
 {
-  op_t 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) \
@@ -122,21 +107,45 @@ struct operation
 
 /* Parse and convert an integer for #if.  Accepts decimal, hex, or octal
    with or without size suffixes.  */
+struct suffix
+{
+  unsigned char s[4];
+  unsigned char u;
+  unsigned char l;
+};
+
+const struct suffix vsuf_1[] = {
+  { "u", 1, 0 }, { "U", 1, 0 },
+  { "l", 0, 1 }, { "L", 0, 1 }
+};
+
+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 struct operation
-parse_number (pfile, start, end)
+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))
+
+static struct op
+parse_number (pfile, tok)
      cpp_reader *pfile;
-     U_CHAR *start;
-     U_CHAR *end;
+     const cpp_token *tok;
 {
-  struct operation op;
-  U_CHAR *p = start;
-  int c;
+  struct op op;
+  const U_CHAR *start = tok->val.name.text;
+  const U_CHAR *end = start + tok->val.name.len;
+  const U_CHAR *p = start;
+  int c, i, nsuff;
   unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
   int base = 10;
   int overflow = 0;
   int digit, largest_digit = 0;
-  int spec_long = 0;
+  const struct suffix *sufftab;
 
   op.unsignedp = 0;
 
@@ -158,49 +167,21 @@ parse_number (pfile, start, end)
   MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
 		   / ((unsigned HOST_WIDEST_INT) base));
 
-  while (p < end)
+  for(; p < end; p++)
     {
-      c = *p++;
+      c = *p;
 
       if (c >= '0' && c <= '9')
 	digit = c - '0';
-      /* FIXME: assumes ASCII */
+      /* We believe that in all live character sets, a-f are
+	 consecutive, and so are A-F.  */
       else if (base == 16 && c >= 'a' && c <= 'f')
 	digit = c - 'a' + 10;
       else if (base == 16 && c >= 'A' && c <= 'F')
 	digit = c - 'A' + 10;
-      else if (c == '.')
-	{
-	  /* It's a float since it contains a point.  */
-	  cpp_error (pfile,
-	     "floating point numbers are not allowed in #if expressions");
-	  goto error;
-	}
       else
-	{
-	  /* `l' means long, and `u' means unsigned.  */
-	  for (;;)
-	    {
-	      if (c == 'l' || c == 'L')
-		  spec_long++;
-	      else if (c == 'u' || c == 'U')
-		  op.unsignedp++;
-	      else
-		{
-		  /* Decrement p here so that the error for an invalid
-		     number will be generated below in the case where
-		     this is the last character in the buffer.  */
-		  p--;
-		  break;
-		}
-	      if (p == end)
-		break;
-	      c = *p++;
-	    }
-	  /* Don't look for any more digits after the suffixes.  */
-	  break;
-	}
-      
+	break;
+
       if (largest_digit < digit)
 	largest_digit = digit;
       nd = n * base + digit;
@@ -208,25 +189,41 @@ parse_number (pfile, start, end)
       n = nd;
     }
 
-  if (p != end)
-    {
-      cpp_error (pfile, "invalid number in #if expression");
-      goto error;
-    }
-  else if (spec_long > (CPP_OPTION (pfile, c89) ? 1 : 2))
+  if (p < end)
     {
-      cpp_error (pfile, "too many 'l' suffixes in integer constant");
-      goto error;
-    }
-  else if (op.unsignedp > 1)
-    {
-      cpp_error (pfile, "too many 'u' suffixes in integer constant");
-      goto error;
+      /* Check for a floating point constant.  Note that float constants
+	 with an exponent or suffix but no decimal point are technically
+	 illegal (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_OPTION (pfile, c89) && sufftab[i].l == 2)
+	SYNTAX_ERROR ("too many 'l' suffixes in integer constant");
     }
   
   if (base <= largest_digit)
-    cpp_pedwarn (pfile,
-		 "integer constant contains digits beyond the radix");
+    cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
 
   if (overflow)
     cpp_pedwarn (pfile, "integer constant out of range");
@@ -235,55 +232,52 @@ parse_number (pfile, start, end)
   else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp)
     {
       if (base == 10)
-	cpp_warning (pfile,
-		     "integer constant is so large that it is unsigned");
+	cpp_warning (pfile, "integer constant is so large that it is unsigned");
       op.unsignedp = 1;
     }
 
   op.value = n;
-  op.op = INT;
+  op.op = CPP_INT;
   return op;
 
- error:
-  op.op = ERROR;
+ invalid_suffix:
+  cpp_error (pfile, "invalid suffix '%.*s' on integer constant",
+	     (int) (end - p), p);
+ syntax_error:
+  op.op = CPP_ERROR;
   return op;
 }
 
 /* Parse and convert a character constant for #if.  Understands backslash
    escapes (\n, \031) and multibyte characters (if so configured).  */
-static struct operation
-parse_charconst (pfile, start, end)
+static struct op
+parse_charconst (pfile, tok)
      cpp_reader *pfile;
-     U_CHAR *start;
-     U_CHAR *end;
+     const cpp_token *tok;
 {
-  struct operation op;
+  struct op op;
   HOST_WIDEST_INT result = 0;
   int num_chars = 0;
   int num_bits;
   unsigned int width = MAX_CHAR_TYPE_SIZE, mask = MAX_CHAR_TYPE_MASK;
   int max_chars;
-  U_CHAR *ptr = start;
+  const U_CHAR *ptr = tok->val.name.text;
+  const U_CHAR *end = ptr + tok->val.name.len;
 
   int c = -1;
 
-  if (*ptr == 'L')
-    {
-      ++ptr;
-      width = MAX_WCHAR_TYPE_SIZE, mask = MAX_WCHAR_TYPE_MASK;
-    }
+  if (tok->type == CPP_WCHAR)
+    width = MAX_WCHAR_TYPE_SIZE, mask = MAX_WCHAR_TYPE_MASK;
   max_chars = MAX_LONG_TYPE_SIZE / width;
 
-  ++ptr;  /* skip initial quote */
-
   while (ptr < end)
     {
       c = *ptr++;
       if (c == '\'')
-	break;
+	CPP_ICE ("unescaped ' in character constant");
       else if (c == '\\')
 	{
-	  c = parse_escape (pfile, &ptr, mask);
+	  c = parse_escape (pfile, &ptr, end, mask);
 	  if (width < HOST_BITS_PER_INT
 	      && (unsigned int) c >= (unsigned int)(1 << width))
 	    cpp_pedwarn (pfile,
@@ -301,22 +295,9 @@ parse_charconst (pfile, start, end)
     }
 
   if (num_chars == 0)
-    {
-      cpp_error (pfile, "empty character constant");
-      goto error;
-    }
-  else if (c != '\'')
-    {
-      /* cpp_get_token has already emitted an error if !traditional. */
-      if (! CPP_TRADITIONAL (pfile))
-	cpp_error (pfile, "malformatted character constant");
-      goto error;
-    }
+    SYNTAX_ERROR ("empty character constant");
   else if (num_chars > max_chars)
-    {
-      cpp_error (pfile, "character constant too long");
-      goto error;
-    }
+    SYNTAX_ERROR ("character constant too long");
   else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
     cpp_warning (pfile, "multi-character character constant");
 
@@ -334,75 +315,61 @@ parse_charconst (pfile, start, end)
 
   /* This is always a signed type.  */
   op.unsignedp = 0;
-  op.op = CHAR;
+  op.op = CPP_INT;
   return op;
 
- error:
-  op.op = ERROR;
+ syntax_error:
+  op.op = CPP_ERROR;
   return op;
 }
 
-static struct operation
+static struct op
 parse_defined (pfile)
      cpp_reader *pfile;
 {
-  int paren = 0, len;
-  U_CHAR *tok;
-  enum cpp_ttype token;
-  struct operation op;
-  long old_written = CPP_WRITTEN (pfile);
+  int paren;
+  const cpp_token *tok;
+  struct op op;
 
-  op.unsignedp = 0;
-  op.op = INT;
-
-  pfile->no_macro_expand++;
-  token = _cpp_get_directive_token (pfile);
-  if (token == CPP_OPEN_PAREN)
+  paren = 0;
+  tok = _cpp_get_raw_token (pfile);
+  if (tok->type == CPP_OPEN_PAREN)
     {
-      paren++;
-      CPP_SET_WRITTEN (pfile, old_written);
-      token = _cpp_get_directive_token (pfile);
+      paren = 1;
+      tok = _cpp_get_raw_token (pfile);
     }
 
-  if (token != CPP_NAME)
-    goto oops;
+  if (tok->type != CPP_NAME)
+    SYNTAX_ERROR ("\"defined\" without an identifier");
 
-  tok = pfile->token_buffer + old_written;
-  len = CPP_PWRITTEN (pfile) - tok;
-  op.value = cpp_defined (pfile, tok, len);
+  if (paren && _cpp_get_raw_token (pfile)->type != CPP_CLOSE_PAREN)
+    SYNTAX_ERROR ("missing close paren after \"defined\"");
 
-  if (paren)
-    {
-      if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
-	goto oops;
-    }
-  CPP_SET_WRITTEN (pfile, old_written);
-  pfile->no_macro_expand--;
+  op.unsignedp = 0;
+  op.op = CPP_INT;
+  op.value = cpp_defined (pfile, tok->val.name.text, tok->val.name.len);
   return op;
 
- oops:
-  CPP_SET_WRITTEN (pfile, old_written);
-  pfile->no_macro_expand--;
-  cpp_error (pfile, "'defined' without an identifier");
-
-  op.op = ERROR;
+ syntax_error:
+  op.op = CPP_ERROR;
   return op;
 }
 
-static struct operation
+static struct op
 parse_assertion (pfile)
      cpp_reader *pfile;
 {
-  struct operation op;
+  struct op op;
   struct answer *answer;
   cpp_hashnode *hp;
 
-  op.op = ERROR;
+  op.op = CPP_ERROR;
   hp = _cpp_parse_assertion (pfile, &answer);
   if (hp)
     {
       /* If we get here, the syntax is valid.  */
-      op.op = INT;
+      op.op = CPP_INT;
+      op.unsignedp = 0;
       op.value = (hp->type == T_ASSERTION &&
 		  (answer == 0 || *_cpp_find_answer (hp, &answer->list) != 0));
 
@@ -412,132 +379,76 @@ parse_assertion (pfile)
   return op;
 }
 
-struct token
-{
-  const char *operator;
-  op_t token;
-};
-
-static const struct token tokentab2[] =
-{
-  {"&&", ANDAND},
-  {"||", OROR},
-  {"<<", LSH},
-  {">>", RSH},
-  {"==", EQUAL},
-  {"!=", NOTEQUAL},
-  {"<=", LEQ},
-  {">=", GEQ},
-  {NULL, ERROR}
-};
-
 /* Read one token.  */
 
-static struct operation
+static struct op
 lex (pfile, skip_evaluation)
      cpp_reader *pfile;
      int skip_evaluation;
 {
-  const struct token *toktab;
-  enum cpp_ttype token;
-  struct operation op;
-  U_CHAR *tok_start, *tok_end;
-  long old_written = CPP_WRITTEN (pfile);
+  struct op op;
+  const cpp_token *tok;
 
  retry:
-  token = _cpp_get_directive_token (pfile);
-  tok_start = pfile->token_buffer + old_written;
-  tok_end = CPP_PWRITTEN (pfile);
-  CPP_SET_WRITTEN (pfile, old_written);
+  tok = cpp_get_token (pfile);
 
-  switch (token)
+  switch (tok->type)
     {
     case CPP_PLACEMARKER:
-      CPP_SET_WRITTEN (pfile, old_written);
+      /* XXX These shouldn't be visible outside cpplex.c.  */
       goto retry;
 
-    case CPP_EOF: /* Should not happen ...  */
-    case CPP_VSPACE:
-      op.op = 0;
-      return op;
+    case CPP_INT:
     case CPP_NUMBER:
-      return parse_number (pfile, tok_start, tok_end);
+      return parse_number (pfile, tok);
+    case CPP_CHAR:
+    case CPP_WCHAR:
+      return parse_charconst (pfile, tok);
+
     case CPP_STRING:
     case CPP_WSTRING:
-      cpp_error (pfile,
-		 "string constants are not allowed in #if expressions");
-      op.op = ERROR;
-      return op;
+      SYNTAX_ERROR ("string constants are not valid in #if");
 
-    case CPP_CHAR:
-    case CPP_WCHAR:
-      return parse_charconst (pfile, tok_start, tok_end);
+    case CPP_FLOAT:
+      SYNTAX_ERROR ("floating point numbers are not valid in #if");
+
+    case CPP_OTHER:
+      if (ISGRAPH (tok->val.aux))
+	SYNTAX_ERROR2 ("invalid character '%c' in #if", tok->val.aux);
+      else
+	SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", tok->val.aux);
 
     case CPP_NAME:
-      /* FIXME:  could this not overflow the tok_start buffer? */
-      if (!ustrncmp (tok_start, U"defined", 7))
+      if (!cpp_idcmp (tok->val.name.text, tok->val.name.len, "defined"))
 	return parse_defined (pfile);
 
-      op.op = INT;
+      op.op = CPP_INT;
       op.unsignedp = 0;
       op.value = 0;
 
       if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
-	cpp_warning (pfile, "'%.*s' is not defined",
-		     (int) (tok_end - tok_start), tok_start);
+	cpp_warning (pfile, "\"%.*s\" is not defined",
+		     (int) tok->val.name.len, tok->val.name.text);
       return op;
 
     case CPP_HASH:
       return parse_assertion (pfile);
 
-    case CPP_AND_AND:	op.op = ANDAND; return op;
-    case CPP_OR_OR:	op.op = OROR;	return op;
-    case CPP_LSHIFT:	op.op = LSH;	return op;
-    case CPP_RSHIFT:	op.op = RSH;	return op;
-    case CPP_EQ_EQ:	op.op = EQUAL;	return op;
-    case CPP_NOT_EQ:	op.op = NOTEQUAL; return op;
-    case CPP_LESS_EQ:	op.op = LEQ;	return op;
-    case CPP_GREATER_EQ:op.op = GEQ;	return op;
-
     default:
-      /* See if it is a special token of length 2.  */
-      if (tok_start + 2 == tok_end)
-        {
-	  for (toktab = tokentab2; toktab->operator != NULL; toktab++)
-	    if (tok_start[0] == toktab->operator[0]
-		&& tok_start[1] == toktab->operator[1])
-		break;
-	  if (toktab->token == ERROR)
-	    cpp_error (pfile, "'%.*s' is not allowed in #if expressions",
-		       (int) (tok_end - tok_start), tok_start);
-	  op.op = toktab->token; 
+      if ((tok->type > CPP_EQ && tok->type < CPP_PLUS_EQ)
+	  || tok->type == CPP_EOF)
+	{
+	  op.op = tok->type;
 	  return op;
 	}
-      op.op = *tok_start;
-      return op;
-  }
-}
-
-/* Convert an operator ID to a string.  BUFF is a buffer at least 5
-   characters long which might be used to store the string.  */
-/* XXX FIXME: Remove BUFF when new lexer is implemented.  */
-static const char *
-op_to_str (op, buff)
-     op_t op;
-     char *buff;
-{
-  const struct token *toktab;
 
-  /* See if it is a special token of length 2.  */
-  for (toktab = tokentab2; toktab->operator != NULL; toktab++)
-    if (op == toktab->token)
-      return toktab->operator;
+      SYNTAX_ERROR2("'%s' is not valid in #if expressions",
+		    _cpp_spell_operator (tok->type));
+  }
 
-  if (ISGRAPH (op))
-    sprintf (buff, "%c", (int) op);
-  else
-    sprintf (buff, "\\%03o", (int) op);
-  return buff;
+ syntax_error:
+  op.op = CPP_ERROR;
+  return op;
 }
 
 /* Parse a C escape sequence.  STRING_PTR points to a variable
@@ -545,85 +456,69 @@ op_to_str (op, buff)
    is updated past the characters we use.  The value of the
    escape sequence is returned.
 
-   A negative value means the sequence \ newline was seen,
-   which is supposed to be equivalent to nothing at all.
-
-   If \ is followed by a null character, we return a negative
-   value and leave the string pointer pointing at the null character.
-
    If \ is followed by 000, we return 0 and leave the string pointer
    after the zeros.  A value of 0 does not mean end of string.  */
 
 static HOST_WIDEST_INT
-parse_escape (pfile, string_ptr, result_mask)
+parse_escape (pfile, string_ptr, limit, result_mask)
      cpp_reader *pfile;
-     U_CHAR **string_ptr;
+     const U_CHAR **string_ptr;
+     const U_CHAR *limit;
      HOST_WIDEST_INT result_mask;
 {
-  register int c = *(*string_ptr)++;
+  const U_CHAR *ptr = *string_ptr;
+  /* We know we have at least one following character.  */
+  int c = *ptr++;
   switch (c)
     {
-    case 'a':
-      return TARGET_BELL;
-    case 'b':
-      return TARGET_BS;
-    case 'e':
-    case 'E':
+    case 'a': c = TARGET_BELL;	  break;
+    case 'b': c = TARGET_BS;	  break;
+    case 'f': c = TARGET_FF;	  break;
+    case 'n': c = TARGET_NEWLINE; break;
+    case 'r': c = TARGET_CR;	  break;
+    case 't': c = TARGET_TAB;	  break;
+    case 'v': c = TARGET_VT;	  break;
+
+    case 'e': case 'E':
       if (CPP_PEDANTIC (pfile))
 	cpp_pedwarn (pfile, "non-ISO-standard escape sequence, '\\%c'", c);
-      return TARGET_ESC;
-    case 'f':
-      return TARGET_FF;
-    case 'n':
-      return TARGET_NEWLINE;
-    case 'r':
-      return TARGET_CR;
-    case 't':
-      return TARGET_TAB;
-    case 'v':
-      return TARGET_VT;
-    case '\n':
-      return -2;
-    case 0:
-      (*string_ptr)--;
-      return 0;
+      c = TARGET_ESC;
+      break;
       
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
+    case '0': case '1': case '2': case '3':
+    case '4': case '5': case '6': case '7':
       {
-	register HOST_WIDEST_INT i = c - '0';
-	register int count = 0;
+	unsigned int i = c - '0';
+	int count = 0;
 	while (++count < 3)
 	  {
-	    c = *(*string_ptr)++;
-	    if (c >= '0' && c <= '7')
-	      i = (i << 3) + c - '0';
-	    else
-	      {
-		(*string_ptr)--;
-		break;
-	      }
+	    if (ptr >= limit)
+	      break;
+	    
+	    c = *ptr;
+	    if (c < '0' || c > '7')
+	      break;
+	    ptr++;
+	    i = (i << 3) + c - '0';
 	  }
 	if (i != (i & result_mask))
 	  {
 	    i &= result_mask;
 	    cpp_pedwarn (pfile, "octal escape sequence out of range");
 	  }
-	return i;
+	c = i;
+	break;
       }
+
     case 'x':
       {
-	register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
-	register int digits_found = 0, digit;
+	unsigned int i = 0, overflow = 0;
+	int digits_found = 0, digit;
 	for (;;)
 	  {
-	    c = *(*string_ptr)++;
+	    if (ptr >= limit)
+	      break;
+	    c = *ptr;
 	    if (c >= '0' && c <= '9')
 	      digit = c - '0';
 	    else if (c >= 'a' && c <= 'f')
@@ -631,10 +526,8 @@ parse_escape (pfile, string_ptr, result_
 	    else if (c >= 'A' && c <= 'F')
 	      digit = c - 'A' + 10;
 	    else
-	      {
-		(*string_ptr)--;
-		break;
-	      }
+	      break;
+	    ptr++;
 	    overflow |= i ^ (i << 4 >> 4);
 	    i = (i << 4) + digit;
 	    digits_found = 1;
@@ -646,11 +539,12 @@ parse_escape (pfile, string_ptr, result_
 	    i &= result_mask;
 	    cpp_pedwarn (pfile, "hex escape sequence out of range");
 	  }
-	return i;
+	c = i;
+	break;
       }
-    default:
-      return c;
     }
+  *string_ptr = ptr;
+  return c;
 }
 
 static void
@@ -762,6 +656,40 @@ be handled with operator-specific code. 
 #define MUL_PRIO           (15 << PRIO_SHIFT)
 #define UNARY_PRIO        ((16 << 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,
+
+  /* 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) \
@@ -770,9 +698,25 @@ be handled with operator-specific code. 
 #define EQUALITY(OP) \
   top->value = v1 OP v2; \
   top->unsignedp = 0;
-#define LOGICAL(OP) \
+#define BITWISE(OP) \
   top->value = v1 OP v2; \
   top->unsignedp = unsigned1 | unsigned2;
+#define UNARY(OP) \
+  top->value = OP v2; \
+  top->unsignedp = unsigned2; \
+  top->flags |= HAVE_VALUE;
+#define LOGICAL(OP, NEG) \
+  top->value = v1 OP v2; \
+  top->unsignedp = 0; \
+  if (NEG v1) skip_evaluation--;
+#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.  */
@@ -792,21 +736,19 @@ _cpp_parse_expr (pfile)
      In that case the 'flags' field has the HAVE_VALUE flag set.  */
 
 #define INIT_STACK_SIZE 20
-  struct operation init_stack[INIT_STACK_SIZE];
-  struct operation *stack = init_stack;
-  struct operation *limit = stack + INIT_STACK_SIZE;
-  register struct operation *top = stack + 1;
-  long old_written = CPP_WRITTEN (pfile);
+  struct op init_stack[INIT_STACK_SIZE];
+  struct op *stack = init_stack;
+  struct op *limit = stack + INIT_STACK_SIZE;
+  register struct op *top = stack + 1;
   int skip_evaluation = 0;
   int result;
-  char buff[5];
 
   /* Save parser state and set it to something sane.  */
   int save_skipping = pfile->skipping;
   pfile->skipping = 0;
 
   /* We've finished when we try to reduce this.  */
-  top->op = FINISHED;
+  top->op = CPP_EOF;
   /* Nifty way to catch missing '('.  */
   top->prio = EXTRACT_PRIO(CLOSE_PAREN_PRIO);
   /* Avoid missing right operand checks.  */
@@ -816,7 +758,7 @@ _cpp_parse_expr (pfile)
     {
       unsigned int prio;
       unsigned int flags;
-      struct operation op;
+      struct op op;
 
       /* Read a token */
       op = lex (pfile, skip_evaluation);
@@ -826,17 +768,10 @@ _cpp_parse_expr (pfile)
 	 try to reduce the expression on the stack.  */
       switch (op.op)
 	{
-	case NAME:
-	  CPP_ICE ("lex returns a NAME");
-	case ERROR:
+	case CPP_ERROR:
 	  goto syntax_error;
-	default:
-	  SYNTAX_ERROR2 ("invalid character '%s' in #if",
-			 op_to_str (op.op, buff));
-
 	push_immediate:
-	case INT:
-	case CHAR:
+	case CPP_INT:
 	  /* Push a value onto the stack.  */
 	  if (top->flags & HAVE_VALUE)
 	    SYNTAX_ERROR ("missing binary operator");
@@ -845,40 +780,17 @@ _cpp_parse_expr (pfile)
 	  top->flags |= HAVE_VALUE;
 	  continue;
 
-	case '+':
-	case '-':    prio = PLUS_PRIO;  if (top->flags & HAVE_VALUE) break;
+	case CPP_EOF:	prio = FORCE_REDUCE_PRIO;	break;
+	case CPP_PLUS:
+	case CPP_MINUS: prio = PLUS_PRIO;  if (top->flags & HAVE_VALUE) break;
           /* else unary; fall through */
-	case '!':
-	case '~':    prio = UNARY_PRIO;  break;
-
-	case '*':
-	case '/':
-	case '%':    prio = MUL_PRIO;  break;
-	case '<':
-	case '>':
-	case LEQ:
-	case GEQ:    prio = LESS_PRIO;  break;
-	case NOTEQUAL:
-	case EQUAL:  prio = EQUAL_PRIO;  break;
-	case LSH:
-	case RSH:    prio = SHIFT_PRIO;  break;
-	case '&':    prio = AND_PRIO;  break;
-	case '^':    prio = XOR_PRIO;  break;
-	case '|':    prio = OR_PRIO;  break;
-	case ANDAND: prio = ANDAND_PRIO;  break;
-	case OROR:   prio = OROR_PRIO;  break;
-	case ',':    prio = COMMA_PRIO;  break;
-	case '(':    prio = OPEN_PAREN_PRIO; break;
-	case ')':    prio = CLOSE_PAREN_PRIO;  break;
-        case ':':    prio = COLON_PRIO;  break;
-        case '?':    prio = COND_PRIO;  break;
-	case 0:      prio = FORCE_REDUCE_PRIO;  break;
+	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 (op.op == '(')
+      if (prio == EXTRACT_PRIO(OPEN_PAREN_PRIO))
 	goto skip_reduction;
 
       /* Check for reductions.  Then push the operator.  */
@@ -891,11 +803,11 @@ _cpp_parse_expr (pfile)
 	     right operand.  Check this before trying to reduce.  */
 	  if ((top->flags & (HAVE_VALUE | NO_R_OPERAND)) == 0)
 	    {
-	      if (top->op == '(')
+	      if (top->op == CPP_OPEN_PAREN)
 		SYNTAX_ERROR ("void expression between '(' and ')'");
 	      else
 		SYNTAX_ERROR2 ("operator '%s' has no right operand",
-			       op_to_str (top->op, buff));
+			       _cpp_spell_operator (top->op));
 	    }
 
 	  unsigned2 = top->unsignedp, v2 = top->value;
@@ -905,12 +817,31 @@ _cpp_parse_expr (pfile)
 	  /* Now set top->value = (top[1].op)(v1, v2); */
 	  switch (top[1].op)
 	    {
-	    case '+':
+	    default:
+	      cpp_ice (pfile, "impossible operator type %s",
+		       _cpp_spell_operator (op.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_AND_AND:	 LOGICAL(&&,!); break;
+	    case CPP_OR_OR:	 LOGICAL(||,);	break;
+	    case CPP_LSHIFT:	 SHIFT(left_shift, right_shift); break;
+	    case CPP_RSHIFT:	 SHIFT(right_shift, left_shift); break;
+
+	    case CPP_PLUS:
 	      if (!(top->flags & HAVE_VALUE))
-		{ /* Unary '+' */
-		  top->value = v2;
-		  top->unsignedp = unsigned2;
-		  top->flags |= HAVE_VALUE;
+		{
+		  UNARY(+);
 		}
 	      else
 		{
@@ -921,15 +852,12 @@ _cpp_parse_expr (pfile)
 		    integer_overflow (pfile);
 		}
 	      break;
-	    case '-':
+	    case CPP_MINUS:
 	      if (!(top->flags & HAVE_VALUE))
-		{ /* Unary '-' */
-		  top->value = - v2;
-		  if (!skip_evaluation && (top->value & v2) < 0
-		      && !unsigned2)
+		{
+		  UNARY(-);
+		  if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
 		    integer_overflow (pfile);
-		  top->unsignedp = unsigned2;
-		  top->flags |= HAVE_VALUE;
 		}
 	      else
 		{ /* Binary '-' */
@@ -940,7 +868,7 @@ _cpp_parse_expr (pfile)
 		    integer_overflow (pfile);
 		}
 	      break;
-	    case '*':
+	    case CPP_MULT:
 	      top->unsignedp = unsigned1 | unsigned2;
 	      if (top->unsignedp)
 		top->value = (unsigned HOST_WIDEST_INT) v1 * v2;
@@ -952,14 +880,14 @@ _cpp_parse_expr (pfile)
 		    integer_overflow (pfile);
 		}
 	      break;
-	    case '/':
-	    case '%':
+	    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 == '/')
+	      if (top[1].op == CPP_DIV)
 		{
 		  if (top->unsignedp)
 		    top->value = (unsigned HOST_WIDEST_INT) v1 / v2;
@@ -977,80 +905,33 @@ _cpp_parse_expr (pfile)
 		  else
 		    top->value = v1 % v2;
 		}
-	      break;
-	    case '!':
-	      top->value = ! v2;
-	      top->unsignedp = 0;
-	      top->flags |= HAVE_VALUE;
 	      break;
-	    case '~':
-	      top->value = ~ v2;
-	      top->unsignedp = unsigned2;
-	      top->flags |= HAVE_VALUE;
-	      break;
-	    case '<':  COMPARE(<);  break;
-	    case '>':  COMPARE(>);  break;
-	    case LEQ:  COMPARE(<=);  break;
-	    case GEQ:  COMPARE(>=);  break;
-	    case EQUAL:    EQUALITY(==);  break;
-	    case NOTEQUAL: EQUALITY(!=);  break;
-	    case LSH:
-	      if (skip_evaluation)
-		break;
-	      top->unsignedp = unsigned1;
-	      if (v2 < 0 && ! unsigned2)
-		top->value = right_shift (pfile, v1, unsigned1, -v2);
-	      else
-		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);
-	      else
-		top->value = right_shift (pfile, v1, unsigned1, v2);
-	      break;
-	    case '&':  LOGICAL(&); break;
-	    case '^':  LOGICAL(^);  break;
-	    case '|':  LOGICAL(|);  break;
-	    case ANDAND:
-	      top->value = v1 && v2;  top->unsignedp = 0;
-	      if (!v1) skip_evaluation--;
-	      break;
-	    case OROR:
-	      top->value = v1 || v2;  top->unsignedp = 0;
-	      if (v1) skip_evaluation--;
-	      break;
-	    case ',':
+
+	    case CPP_COMMA:
 	      if (CPP_PEDANTIC (pfile))
 		cpp_pedwarn (pfile, "comma operator in operand of #if");
 	      top->value = v2;
 	      top->unsignedp = unsigned2;
 	      break;
-	    case '?':
+	    case CPP_QUERY:
 	      SYNTAX_ERROR ("syntax error '?' without following ':'");
-	    case ':':
-	      if (top[0].op != '?')
+	    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 '(':
-	      if (op.op != ')')
+	    case CPP_OPEN_PAREN:
+	      if (op.op != CPP_CLOSE_PAREN)
 		SYNTAX_ERROR ("missing ')' in expression");
 	      op.value = v2;
 	      op.unsignedp = unsigned2;
 	      goto push_immediate;
-	    default:
-	      SYNTAX_ERROR2 ("unimplemented operator '%s'",
-			     op_to_str (top[1].op, buff));
-	    case FINISHED:
+	    case CPP_EOF:
 	      /* Reducing this dummy operator indicates we've finished.  */
-	      if (op.op == ')')
+	      if (op.op == CPP_CLOSE_PAREN)
 		SYNTAX_ERROR ("missing '(' in expression");
 	      goto done;
 	    }
@@ -1060,14 +941,16 @@ _cpp_parse_expr (pfile)
       if (flags & SHORT_CIRCUIT)
 	switch (op.op)
 	  {
-	  case OROR:    if (top->value) skip_evaluation++; break;
-	  case ANDAND:
-	  case '?':     if (!top->value) skip_evaluation++; break;
-	  case ':':
+	  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:
@@ -1076,32 +959,32 @@ _cpp_parse_expr (pfile)
 	{
 	  if (top->flags & HAVE_VALUE)
 	    SYNTAX_ERROR2 ("missing binary operator before '%s'",
-			   op_to_str (op.op, buff));
+			   _cpp_spell_operator (op.op));
 	}
       else
 	{
 	  if (!(top->flags & HAVE_VALUE))
 	    SYNTAX_ERROR2 ("operator '%s' has no left operand",
-			   op_to_str (op.op, buff));
+			   _cpp_spell_operator (op.op));
 	}
 
       /* Check for and handle stack overflow.  */
       top++;
       if (top == limit)
 	{
-	  struct operation *new_stack;
+	  struct op *new_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 op *) xrealloc (stack, new_size);
 	  else
 	    {
-	      new_stack = (struct operation *) xmalloc (new_size);
+	      new_stack = (struct op *) xmalloc (new_size);
 	      memcpy (new_stack, stack, old_size);
 	    }
 	  stack = new_stack;
-	  top = (struct operation *) ((char *) new_stack + old_size);
-	  limit = (struct operation *) ((char *) new_stack + new_size);
+	  top = (struct op *) ((char *) new_stack + old_size);
+	  limit = (struct op *) ((char *) new_stack + new_size);
 	}
       
       top->flags = flags;
@@ -1112,19 +995,17 @@ _cpp_parse_expr (pfile)
  done:
   result = (top[1].value != 0);
   if (top != stack)
-    CPP_ICE ("unbalanced stack in #if expression");
+    CPP_ICE ("unbalanced stack in #if");
   else if (!(top[1].flags & HAVE_VALUE))
     {
       SYNTAX_ERROR ("#if with no expression");
     syntax_error:
-      _cpp_skip_rest_of_line (pfile);
       result = 0;  /* Return 0 on syntax error.  */
     }
 
   /* Free dynamic stack if we allocated one.  */
   if (stack != init_stack)
     free (stack);
-  CPP_SET_WRITTEN (pfile, old_written);
   pfile->skipping = save_skipping;
   return result;
 }
===================================================================
Index: cpphash.h
--- cpphash.h	2000/07/05 05:33:56	1.58
+++ cpphash.h	2000/07/08 02:19:27
@@ -213,8 +213,6 @@ extern void _cpp_skip_rest_of_line	PARAM
 extern void _cpp_free_temp_tokens	PARAMS ((cpp_reader *));
 extern void _cpp_init_input_buffer	PARAMS ((cpp_reader *));
 extern void _cpp_grow_token_buffer	PARAMS ((cpp_reader *, long));
-extern enum cpp_ttype _cpp_get_directive_token
-					PARAMS ((cpp_reader *));
 extern void _cpp_init_toklist		PARAMS ((cpp_toklist *, int));
 extern void _cpp_clear_toklist		PARAMS ((cpp_toklist *));
 extern void _cpp_free_toklist		PARAMS ((const cpp_toklist *));
@@ -238,6 +236,7 @@ extern unsigned int _cpp_get_line	PARAMS
 extern const cpp_token *_cpp_get_raw_token PARAMS ((cpp_reader *));
 extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token*));
 extern const cpp_token *_cpp_glue_header_name PARAMS ((cpp_reader *));
+extern const U_CHAR *_cpp_spell_operator PARAMS ((enum cpp_ttype));
 
 /* In cpplib.c */
 extern const struct directive *_cpp_check_directive
===================================================================
Index: cppinit.c
--- cppinit.c	2000/07/06 22:52:03	1.88
+++ cppinit.c	2000/07/08 02:19:28
@@ -776,11 +776,6 @@ cpp_start_read (pfile, print, fname)
   if (user_label_prefix == NULL)
     user_label_prefix = USER_LABEL_PREFIX;
 
-  /* Don't bother trying to do macro expansion if we've already done
-     preprocessing.  */
-  if (CPP_OPTION (pfile, preprocessed))
-    pfile->no_macro_expand++;
-
   /* Figure out if we need to save function macro parameter spellings.
      We don't use CPP_PEDANTIC() here because that depends on whether
      or not the current file is a system header, and there is no
===================================================================
Index: cpplex.c
--- cpplex.c	2000/07/08 02:18:21	1.63
+++ cpplex.c	2000/07/08 02:19:29
@@ -167,13 +167,13 @@ token_spellings [N_TTYPES + 1] = {TTYPE_
 #undef N
 
 /* For debugging: the internal names of the tokens.  */
-#define T(e, s) STRINGX(e),
-#define I(e, s) STRINGX(e),
-#define S(e, s) STRINGX(e),
-#define C(e, s) STRINGX(e),
-#define N(e, s) STRINGX(e),
+#define T(e, s) U STRINGX(e) + 4,
+#define I(e, s) U STRINGX(e) + 4,
+#define S(e, s) U STRINGX(e) + 4,
+#define C(e, s) U STRINGX(e) + 4,
+#define N(e, s) U STRINGX(e) + 4,
 
-const char * const token_names[N_TTYPES] = { TTYPE_TABLE };
+const U_CHAR *const token_names[N_TTYPES] = { TTYPE_TABLE };
 
 #undef T
 #undef I
@@ -1872,10 +1872,9 @@ output_token (pfile, token, prev)
 }
 
 /* Write the spelling of a token TOKEN to BUFFER.  The buffer must
-   already contain the enough space to hold the token's spelling.  If
-   WHITESPACE is true, and the token was preceded by whitespace,
-   output a single space before the token proper.  Returns a pointer
-   to the character after the last character written.  */
+   already contain the enough space to hold the token's spelling.
+   Returns a pointer to the character after the last character
+   written.  */
 
 static unsigned char *
 spell_token (pfile, token, buffer)
@@ -1933,6 +1932,19 @@ spell_token (pfile, token, buffer)
   return buffer;
 }
 
+/* Return the spelling of a token known to be an operator.
+   Does not distinguish digraphs from their counterparts.  */
+const unsigned char *
+_cpp_spell_operator (type)
+     enum cpp_ttype type;
+{
+  if (token_spellings[type].type == SPELL_OPERATOR)
+    return token_spellings[type].spelling;
+  else
+    return token_names[type];
+}
+
+
 /* Macro expansion algorithm.  TODO.  */
 
 static const cpp_token placemarker_token = {0, 0, CPP_PLACEMARKER, 0 UNION_INIT_ZERO};
@@ -2022,6 +2034,10 @@ is_macro_disabled (pfile, expansion, tok
 {
   cpp_context *context = CURRENT_CONTEXT (pfile);
 
+  /* Don't expand anything if this file has already been preprocessed.  */
+  if (CPP_OPTION (pfile, preprocessed))
+    return 1;
+
   /* Arguments on either side of ## are inserted in place without
      macro expansion (6.10.3.3.2).  Conceptually, any macro expansion
      occurs during a later rescan pass.  The effect is that we expand
@@ -3273,26 +3289,6 @@ _cpp_dump_list (pfile, list, token, flus
 
   if (flush && pfile->printer)
     cpp_output_tokens (pfile, pfile->printer, pfile->token_list.line);
-}
-
-/* Stub function during conversion, mainly for cppexp.c's benefit.  */
-enum cpp_ttype
-_cpp_get_directive_token (pfile)
-     cpp_reader *pfile;
-{
-  const cpp_token *tok;
-
-  if (pfile->no_macro_expand)
-    tok = _cpp_get_raw_token (pfile);
-  else
-    tok = cpp_get_token (pfile);
-
-  if (tok->type == CPP_EOF)
-    return CPP_VSPACE;  /* backward compat; and don't try to spell EOF */
-
-  CPP_RESERVE (pfile, TOKEN_LEN (tok));
-  pfile->limit = spell_token (pfile, tok, pfile->limit);
-  return tok->type;
 }
 
 /* Allocate pfile->input_buffer, and initialize trigraph_map[]
===================================================================
Index: cpplib.c
--- cpplib.c	2000/07/06 09:51:57	1.183
+++ cpplib.c	2000/07/08 02:19:29
@@ -476,7 +476,7 @@ read_line_number (pfile, num)
     }
   else
     {
-      if (type != CPP_VSPACE && type != CPP_EOF)
+      if (type != CPP_EOF)
 	cpp_error (pfile, "invalid format #line");
       return 0;
     }
@@ -545,7 +545,7 @@ do_line (pfile)
   str = tok->val.name.text;
   len = tok->val.name.len;
 
-  if (type == CPP_VSPACE || type == CPP_EOF)
+  if (type == CPP_EOF)
     goto done;
   else if (type != CPP_STRING)
     {
===================================================================
Index: cpplib.h
--- cpplib.h	2000/07/08 02:18:21	1.105
+++ cpplib.h	2000/07/08 02:19:30
@@ -123,10 +123,7 @@ typedef struct cpp_hashnode cpp_hashnode
   I(CPP_COMMENT,	0)	/* Only if output comments.  */ \
   N(CPP_MACRO_ARG,      0)	/* Macro argument.  */          \
   N(CPP_EOF,		0)	/* End of file.  */		\
-  I(CPP_HEADER_NAME,	0)	/* <stdio.h> in #include */	\
-\
-  /* Obsolete - will be removed when no code uses them still.  */	\
-  T(CPP_VSPACE,		"\n")	/* End of line.  */
+  I(CPP_HEADER_NAME,	0)	/* <stdio.h> in #include */
 
 #define T(e, s) e,
 #define I(e, s) e,
@@ -542,9 +539,6 @@ struct cpp_reader
      containing files that matches the current status.  */
   unsigned char input_stack_listing_current;
 
-  /* If non-zero, macros are not expanded.  */
-  unsigned char no_macro_expand;
-
   /* We're printed a warning recommending against using #import.  */
   unsigned char import_warning;
 
@@ -555,7 +549,8 @@ struct cpp_reader
   /* True if we are skipping a failed conditional group.  */
   unsigned char skipping;
 
-  /* Do we need to save paramter spellings.  */
+  /* True if we need to save parameter spellings - only if -pedantic,
+     or we might need to write out definitions.  */
   unsigned char save_parameter_spellings;
 
   /* If we're in lex_line.  */
===================================================================
Index: testsuite/gcc.dg/cpp/19951227-1.c
--- testsuite/gcc.dg/cpp/19951227-1.c	2000/06/29 19:55:26	1.1
+++ testsuite/gcc.dg/cpp/19951227-1.c	2000/07/08 02:19:30
@@ -1,3 +1,3 @@
 /* { dg-do preprocess } */
-#if 0xe-1	/* { dg-error "invalid number" } */
+#if 0xe-1	/* { dg-error "invalid suffix" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/assert2.c
--- testsuite/gcc.dg/cpp/assert2.c	2000/06/27 22:26:11	1.1
+++ testsuite/gcc.dg/cpp/assert2.c	2000/07/08 02:19:30
@@ -20,5 +20,5 @@
 #error		/* { dg-bogus "error" "test w/o answer" } */
 #endif
 
-#if #abc[def]	/* { dg-error "invalid char" "test with malformed answer" } */
+#if #abc[def]	/* { dg-error "is not valid" "test with malformed answer" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/if-1.c
--- testsuite/gcc.dg/cpp/if-1.c	2000/06/27 22:26:11	1.1
+++ testsuite/gcc.dg/cpp/if-1.c	2000/07/08 02:19:30
@@ -9,22 +9,29 @@
 #error 077 != 63 /* { dg-bogus "#error" "normal conversion" } */
 #endif
 
-#if 12wrt /* { dg-error "nvalid number|missing white" "invalid number" } */
+#if 12wrt /* { dg-error "invalid suffix" "invalid number" } */
 #endif
 
-#if 0abc /* { dg-error "nvalid number|missing white" "invalid number" } */
+#if 0abc /* { dg-error "invalid suffix" "invalid number" } */
 #endif
 
-#if 42abc /* { dg-error "nvalid number|missing white" "invalid number" } */
+#if 42abc /* { dg-error "invalid suffix" "invalid number" } */
 #endif
 
+#if 0xabc != 2748
+#error 0xabc	/* { dg-bogus "#error" "normal conversion" } */
+#endif
+
 #if 1.2 /* { dg-error "loating point numbers" "floating point in #if" } */
 #endif
+
+#if 4uu /* { dg-error "invalid suffix" "too many suffixes" } */
+#endif
 
-#if 4uu /* { dg-error "too many 'u'" "too many suffixes" } */
+#if 124123231lll /* { dg-error "invalid suffix" "too many suffixes" } */
 #endif
 
-#if 124123231lll /* { dg-error "too many 'l'" "too many suffixes" } */
+#if 1234lul	/* { dg-error "invalid suffix" "u between ls" } */
 #endif
 
 #if 099 /* { dg-error "digits beyond the radix" "decimal in octal constant" } */
===================================================================
Index: testsuite/gcc.dg/cpp/if-4.c
--- testsuite/gcc.dg/cpp/if-4.c	2000/06/27 22:26:11	1.1
+++ testsuite/gcc.dg/cpp/if-4.c	2000/07/08 02:19:30
@@ -2,7 +2,7 @@
    NUL terminated, so we would print garbage after it.  */
 /* { dg-do compile } */
 
-#if 1 += 2   /* { dg-error "'\\+=' is not allowed" "+= in if" } */
+#if 1 += 2   /* { dg-error "'\\+=' is not valid" "+= in if" } */
 syntax_error
 #endif
 int foo;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]