cppexp.c (parse_assertion): New.
authorZack Weinberg <zack@wolery.cumb.org>
Thu, 18 May 2000 15:55:46 +0000 (15:55 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Thu, 18 May 2000 15:55:46 +0000 (15:55 +0000)
* cppexp.c (parse_assertion): New.
(lex): Call it for CPP_HASH.  Remove CPP_ASSERTION case.
(_cpp_parse_expr): Remove case '#'.  Don't set
parsing_if_directive.
* cpphash.c (collect_objlike_expansion,
collect_funlike_expansion, collect_params,
_cpp_create_definition): The list no longer has a trailing
VSPACE token.
* cpphash.h (enum node_type): Add T_ASSERTION.
(struct hashnode): Remove aschain, add pred.
(struct predicate): New.
Update prototypes.

* cpplex.c (expand_token_space): Handle both offset and
nonoffset lists.
(init_token_list, _cpp_free_token_list, _cpp_parse_assertion): Delete.
(_cpp_init_toklist, _cpp_clear_toklist, _cpp_free_toklist,
_cpp_slice_toklist, _cpp_squeeze_toklist, _cpp_equiv_tokens,
_cpp_equiv_toklists): New.
(_cpp_scan_line): Rename to _cpp_scan_until; add ability to
stop at any single-character token, not just newline.
(_cpp_lex_token): Remove special cases for #define and #if.
(cpp_get_token): Expect # as a separate token type.  Remove
DIRECTIVE case.
(_cpp_get_directive_token): Remove DIRECTIVE case.
(_cpp_lex_line, _cpp_lex_file, _cpp_init_input_buffer): Update.

* cpplib.c (_cpp_check_directive): Set dirno and
SYNTAX_INCLUDE bit of flags, not dir_handler and dir_flags.
(_cpp_handle_directive): Run # <number> through the same logic
as normal directives.
(do_define): Don't set parsing_define_directive.  Use
_cpp_scan_until.  The list does not have a VSPACE at the end.
(do_if): Save, clear, and restore only_seen_white around
_cpp_parse_expr.
(skip_if_group): s/CPP_DIRECTIVE/CPP_HASH/
(do_assert, do_unassert): Rewrite.

* cpplib.h (TTYPE_TABLE): Remove CPP_ASSERTION.
(LIST_OFFSET): New flag.
(struct cpp_toklist): Replace dir_handler and dir_flags with
dirno and flags.
(struct cpp_reader): Remove parsing_if_directive and
parsing_define_directive.

From-SVN: r33984

gcc/ChangeLog
gcc/cppexp.c
gcc/cpphash.c
gcc/cpphash.h
gcc/cpplex.c
gcc/cpplib.c
gcc/cpplib.h

index 1637585c78ae3be73a09d3869485a57ea781956c..66fdc617a77b7afd193a0bfa10a4e5d26e61cc0e 100644 (file)
@@ -1,3 +1,50 @@
+2000-05-18  Zack Weinberg  <zack@wolery.cumb.org>
+
+       * cppexp.c (parse_assertion): New.
+       (lex): Call it for CPP_HASH.  Remove CPP_ASSERTION case.
+       (_cpp_parse_expr): Remove case '#'.  Don't set
+       parsing_if_directive.
+       * cpphash.c (collect_objlike_expansion,
+       collect_funlike_expansion, collect_params,
+       _cpp_create_definition): The list no longer has a trailing
+       VSPACE token.
+       * cpphash.h (enum node_type): Add T_ASSERTION.
+       (struct hashnode): Remove aschain, add pred.
+       (struct predicate): New.
+       Update prototypes.
+
+       * cpplex.c (expand_token_space): Handle both offset and
+       nonoffset lists.
+       (init_token_list, _cpp_free_token_list, _cpp_parse_assertion): Delete.
+       (_cpp_init_toklist, _cpp_clear_toklist, _cpp_free_toklist,
+       _cpp_slice_toklist, _cpp_squeeze_toklist, _cpp_equiv_tokens,
+       _cpp_equiv_toklists): New.
+       (_cpp_scan_line): Rename to _cpp_scan_until; add ability to
+       stop at any single-character token, not just newline.
+       (_cpp_lex_token): Remove special cases for #define and #if.
+       (cpp_get_token): Expect # as a separate token type.  Remove
+       DIRECTIVE case.
+       (_cpp_get_directive_token): Remove DIRECTIVE case.
+       (_cpp_lex_line, _cpp_lex_file, _cpp_init_input_buffer): Update.
+
+       * cpplib.c (_cpp_check_directive): Set dirno and
+       SYNTAX_INCLUDE bit of flags, not dir_handler and dir_flags.
+       (_cpp_handle_directive): Run # <number> through the same logic
+       as normal directives.
+       (do_define): Don't set parsing_define_directive.  Use
+       _cpp_scan_until.  The list does not have a VSPACE at the end.
+       (do_if): Save, clear, and restore only_seen_white around 
+       _cpp_parse_expr.
+       (skip_if_group): s/CPP_DIRECTIVE/CPP_HASH/
+       (do_assert, do_unassert): Rewrite.
+
+       * cpplib.h (TTYPE_TABLE): Remove CPP_ASSERTION.
+       (LIST_OFFSET): New flag.
+       (struct cpp_toklist): Replace dir_handler and dir_flags with
+       dirno and flags.
+       (struct cpp_reader): Remove parsing_if_directive and
+       parsing_define_directive.
+
 2000-05-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * fixinc/inclhack.def (broken_cabs): Update fix to handle comments
index 7e99292f9a104534f93ae83d7a40498a410d0fad..4e6191504871265647504b84a135d66fa79cd3f2 100644 (file)
@@ -82,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));
@@ -110,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.  */
 
@@ -379,6 +389,81 @@ parse_defined (pfile)
   return op;
 }
 
+static struct operation
+parse_assertion (pfile)
+     cpp_reader *pfile;
+{
+  struct operation op;
+  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);
+      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;
@@ -451,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.  */
@@ -734,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.  */
 
@@ -770,7 +843,6 @@ _cpp_parse_expr (pfile)
   int result;
   char buff[5];
 
-  pfile->parsing_if_directive++;
   /* We've finished when we try to reduce this.  */
   top->op = FINISHED;
   /* Nifty way to catch missing '('.  */
@@ -796,11 +868,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");
 
@@ -1094,7 +1161,6 @@ _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);
   return result;
 }
index 21efb090ad4648bb7ba9ea413ed2916272ac66c6..3eb7d1a0e7a259e7e0baf42631a95964aa332e7f 100644 (file)
@@ -480,12 +480,6 @@ collect_objlike_expansion (pfile, list)
     {
       switch (TOK_TYPE (list, i))
        {
-       case CPP_EOF:
-         cpp_ice (pfile, "EOF in collect_expansion");
-         /* fall through */
-       case CPP_VSPACE:
-         goto done;
-
        case CPP_PASTE:
          /* ## is not special if it appears right after another ##;
             nor is it special if -traditional.  */
@@ -506,7 +500,6 @@ collect_objlike_expansion (pfile, list)
       CPP_PUTS (pfile, TOK_NAME (list, i), TOK_LEN (list, i));
       last_was_paste = 0;
     }
- done:
 
   if (last_was_paste)
     cpp_error (pfile, "`##' at end of macro definition");
@@ -568,12 +561,6 @@ collect_funlike_expansion (pfile, list, arglist, replacement)
       len = TOK_LEN (list, i);
       switch (token)
        {
-       case CPP_EOF:
-         cpp_ice (pfile, "EOF in collect_expansion");
-         /* fall through */
-       case CPP_VSPACE:
-         goto done;
-
        case CPP_HASH:
          /* # is special in function-like macros with no args.
             (6.10.3.2 para 1.)  However, it is not special after
@@ -677,7 +664,6 @@ collect_funlike_expansion (pfile, list, arglist, replacement)
       }
       last_token = ARG;
     }
- done:
 
   if (last_token == STRIZE)
     cpp_error (pfile, "`#' is not followed by a macro argument name");
@@ -759,8 +745,8 @@ collect_params (pfile, list, arglist)
       case CPP_CLOSE_PAREN:
        goto scanned;
       case CPP_VSPACE:
-       cpp_error_with_line (pfile, list->line, TOK_COL (list, i),
-                            "missing right paren in macro argument list");
+      case CPP_EOF:
+       cpp_ice (pfile, "impossible token in macro argument list");
        return 0;
 
       default:
@@ -783,9 +769,8 @@ collect_params (pfile, list, arglist)
          }
        goto scanned;
       }
-
-  cpp_ice (pfile, "collect_params: unreachable - i=%d, ntokens=%d, type=%d",
-          i, list->tokens_used, TOK_TYPE (list, i-1));
+  cpp_error_with_line (pfile, list->line, TOK_COL (list, i-1),
+                      "missing right paren in macro argument list");
   return 0;
 
  scanned:
@@ -892,9 +877,9 @@ _cpp_create_definition (pfile, list, hp)
      #define FUNC(a, b, ...) // nothing
      #define FUNC(a, b, c) FUNC(a, b, c)  */
 
-  if (list->tokens_used == 2)
+  if (list->tokens_used == 1)
     ntype = T_EMPTY;    /* Empty definition of object-like macro.  */
-  else if (list->tokens_used == 3 && TOK_TYPE (list, 1) == CPP_NAME
+  else if (list->tokens_used == 2 && TOK_TYPE (list, 1) == CPP_NAME
           && TOK_LEN (list, 0) == TOK_LEN (list, 1)
           && !ustrncmp (TOK_NAME (list, 0), TOK_NAME (list, 1),
                         TOK_LEN (list, 0)))
index 4b8c50ec7c04ef0fa9448d27c56f376bb9f614c3..927927c03d3657128eea16dcf850a0f5851ac5b1 100644 (file)
@@ -49,7 +49,8 @@ enum node_type
   T_MACRO,        /* object-like macro */
   T_FMACRO,       /* function-like macro */
   T_IDENTITY,     /* macro defined to itself */
-  T_EMPTY         /* macro defined to nothing */
+  T_EMPTY,        /* macro defined to nothing */
+  T_ASSERTION     /* predicate for #assert */
 };
 
 typedef struct hashnode HASHNODE;
@@ -64,12 +65,19 @@ struct hashnode
     const U_CHAR *cpval;               /* some predefined macros */
     const struct object_defn *odefn;   /* #define foo bar */
     const struct funct_defn *fdefn;    /* #define foo(x) bar(x) */
-    struct hashnode *aschain;          /* #assert */
+    struct predicate *pred;            /* #assert */
   } value;
 
   const U_CHAR name[1];                        /* name[length] */
 };
 
+/* Structure used for assertion predicates.  */
+struct predicate
+{
+  struct predicate *next;
+  struct cpp_toklist answer;
+};
+
 /* List of directories to look for include files in. */
 struct file_name_list
 {
@@ -250,7 +258,20 @@ extern enum cpp_ttype _cpp_get_directive_token
                                        PARAMS ((cpp_reader *));
 extern enum cpp_ttype _cpp_get_define_token
                                        PARAMS ((cpp_reader *));
-extern void _cpp_scan_line             PARAMS ((cpp_reader *, cpp_toklist *));
+extern enum cpp_ttype _cpp_scan_until  PARAMS ((cpp_reader *, cpp_toklist *,
+                                                enum cpp_ttype));
+extern void _cpp_init_toklist          PARAMS ((cpp_toklist *));
+extern void _cpp_clear_toklist         PARAMS ((cpp_toklist *));
+extern void _cpp_free_toklist          PARAMS ((cpp_toklist *));
+extern void _cpp_slice_toklist         PARAMS ((cpp_toklist *,
+                                                const cpp_token *,
+                                                const cpp_token *));
+extern void _cpp_squeeze_toklist       PARAMS ((cpp_toklist *));
+extern int _cpp_equiv_tokens           PARAMS ((const cpp_token *,
+                                                const cpp_token *));
+extern int _cpp_equiv_toklists         PARAMS ((const cpp_toklist *,
+                                                const cpp_toklist *));
+
 
 /* In cpplib.c */
 extern int _cpp_handle_directive       PARAMS ((cpp_reader *));
index f0414a0fdca0864c023bade6e1150130600b2843..117f61039f341dec0780d73eb15cd60479549443 100644 (file)
@@ -55,7 +55,6 @@ static void bump_column               PARAMS ((cpp_printer *, unsigned int,
                                         unsigned int));
 static void expand_name_space   PARAMS ((cpp_toklist *, unsigned int));
 static void expand_token_space PARAMS ((cpp_toklist *));
-static void init_token_list    PARAMS ((cpp_reader *, cpp_toklist *, int));
 static void pedantic_whitespace        PARAMS ((cpp_reader *, U_CHAR *,
                                         unsigned int));
 
@@ -491,7 +490,7 @@ cpp_scan_buffer (pfile, print)
   for (;;)
     {
       token = cpp_get_token (pfile);
-      if (token == CPP_EOF || token == CPP_VSPACE
+      if (token == CPP_VSPACE || token == CPP_EOF
          /* XXX Temporary kluge - force flush after #include only */
          || (token == CPP_DIRECTIVE
              && CPP_BUFFER (pfile)->nominal_fname != print->last_fname))
@@ -548,63 +547,212 @@ expand_token_space (list)
      cpp_toklist *list;
 {
   list->tokens_cap *= 2;
+  if (list->flags & LIST_OFFSET)
+    list->tokens--;
   list->tokens = (cpp_token *)
-    xrealloc (list->tokens - 1, (list->tokens_cap + 1) * sizeof (cpp_token));
-  list->tokens++;              /* Skip the dummy.  */
+    xrealloc (list->tokens, (list->tokens_cap + 1) * sizeof (cpp_token));
+  if (list->flags & LIST_OFFSET)
+    list->tokens++;            /* Skip the dummy.  */
 }
 
 /* Initialize a token list.  We allocate an extra token in front of
    the token list, as this allows us to always peek at the previous
    token without worrying about underflowing the list.  */
-static void
-init_token_list (pfile, list, recycle)
-     cpp_reader *pfile;
+void
+_cpp_init_toklist (list)
      cpp_toklist *list;
-     int recycle;
 {
-  /* Recycling a used list saves 3 free-malloc pairs.  */
-  if (!recycle)
-    {
-      /* Initialize token space.  Put a dummy token before the start
-         that will fail matches.  */
-      list->tokens_cap = 256;  /* 4K's worth.  */
-      list->tokens = (cpp_token *)
-       xmalloc ((list->tokens_cap + 1) * sizeof (cpp_token));
-      list->tokens[0].type = CPP_EOF;
-      list->tokens++;
-
-      /* Initialize name space.  */
-      list->name_cap = 1024;
-      list->namebuf = (unsigned char *) xmalloc (list->name_cap);
-
-      /* Only create a comment space on demand.  */
-      list->comments_cap = 0;
-      list->comments = 0;
-    }
+  /* Initialize token space.  Put a dummy token before the start
+     that will fail matches.  */
+  list->tokens_cap = 256;      /* 4K's worth.  */
+  list->tokens = (cpp_token *)
+    xmalloc ((list->tokens_cap + 1) * sizeof (cpp_token));
+  list->tokens[0].type = CPP_EOF;
+  list->tokens++;
+
+  /* Initialize name space.  */
+  list->name_cap = 1024;
+  list->namebuf = (unsigned char *) xmalloc (list->name_cap);
+
+  /* Only create a comment space on demand.  */
+  list->comments_cap = 0;
+  list->comments = 0;
+
+  list->flags = LIST_OFFSET;
+  _cpp_clear_toklist (list);
+}
 
+/* Clear a token list.  */
+void
+_cpp_clear_toklist (list)
+     cpp_toklist *list;
+{
   list->tokens_used = 0;
   list->name_used = 0;
   list->comments_used = 0;
-  if (pfile->buffer)
-    list->line = pfile->buffer->lineno;
-  list->dir_handler = 0;
-  list->dir_flags = 0;
+  list->dirno = -1;
+  list->flags &= LIST_OFFSET;  /* clear all but that one */
+}
+
+/* Free a token list.  Does not free the list itself, which may be
+   embedded in a larger structure.  */
+void
+_cpp_free_toklist (list)
+     cpp_toklist *list;
+{
+  if (list->comments)
+    free (list->comments);
+  if (list->flags & LIST_OFFSET)
+    free (list->tokens - 1);   /* Backup over dummy token.  */
+  else
+    free (list->tokens);
+  free (list->namebuf);
 }
 
-/* Scan an entire line and create a token list for it.  Does not
-   macro-expand or execute directives.  */
+/* Slice a token list: copy the sublist [START, FINISH) into COPY.
+   COPY is assumed not to be initialized.  The comment space is not
+   copied.  */
+void
+_cpp_slice_toklist (copy, start, finish)
+     cpp_toklist *copy;
+     const cpp_token *start, *finish;
+{
+  unsigned int i, n;
+  size_t bytes;
+
+  n = finish - start;
+  copy->tokens_cap = n;
+  copy->tokens = (cpp_token *) xmalloc (n * sizeof (cpp_token));
+  memcpy (copy->tokens, start, n * sizeof (cpp_token));
+
+  bytes = 0;
+  for (i = 0; i < n; i++)
+    if (token_spellings[start[i].type].type > SPELL_NONE)
+      bytes += start[i].val.name.len;
+
+  copy->namebuf = xmalloc (bytes);
+  bytes = 0;
+  for (i = 0; i < n; i++)
+    if (token_spellings[start[i].type].type > SPELL_NONE)
+      {
+       memcpy (copy->namebuf + bytes,
+               start[i].val.name.text, start[i].val.name.len);
+       copy->tokens[i].val.name.text = copy->namebuf + bytes;
+       bytes += start[i].val.name.len;
+      }
+
+  copy->tokens_cap = n;
+  copy->tokens_used = n;
+  copy->name_used = bytes;
+  copy->name_cap = bytes;
+  copy->comments = 0;
+  copy->comments_cap = 0;
+  copy->comments_used = 0;
+  
+  copy->flags = 0;
+  copy->dirno = -1;
+}
 
+/* Shrink a token list down to the minimum size.  */
 void
-_cpp_scan_line (pfile, list)
+_cpp_squeeze_toklist (list)
+     cpp_toklist *list;
+{
+  long delta;
+  const U_CHAR *old_namebuf;
+
+  if (list->flags & LIST_OFFSET)
+    {
+      list->tokens--;
+      memmove (list->tokens, list->tokens + 1,
+              list->tokens_used * sizeof (cpp_token));
+      list->tokens = xrealloc (list->tokens,
+                              list->tokens_used * sizeof (cpp_token));
+      list->flags &= ~LIST_OFFSET;
+    }
+  else
+    list->tokens = xrealloc (list->tokens,
+                            list->tokens_used * sizeof (cpp_token));
+  list->tokens_cap = list->tokens_used;
+
+  old_namebuf = list->namebuf;
+  list->namebuf = xrealloc (list->namebuf, list->name_used);
+  list->name_cap = list->name_used;
+
+  /* Fix up token text pointers.  */
+  delta = list->namebuf - old_namebuf;
+  if (delta)
+    {
+      unsigned int i;
+
+      for (i = 0; i < list->tokens_used; i++)
+       if (token_spellings[list->tokens[i].type].type > SPELL_NONE)
+         list->tokens[i].val.name.text += delta;
+    }
+  
+  if (list->comments_cap)
+    {
+      list->comments = xrealloc (list->comments,
+                                list->comments_used * sizeof (cpp_token));
+      list->comments_cap = list->comments_used;
+    }
+}
+
+/* Compare two tokens.  */
+int
+_cpp_equiv_tokens (a, b)
+     const cpp_token *a, *b;
+{
+  if (a->type != b->type
+      || a->flags != b->flags
+      || a->aux != b->aux)
+    return 0;
+
+  if (token_spellings[a->type].type > SPELL_NONE)
+    {
+      if (a->val.name.len != b->val.name.len
+         || ustrncmp(a->val.name.text,
+                     b->val.name.text,
+                     a->val.name.len))
+       return 0;
+    }
+  return 1;
+}
+
+/* Compare two token lists.  */
+int
+_cpp_equiv_toklists (a, b)
+     const cpp_toklist *a, *b;
+{
+  unsigned int i;
+
+  if (a->tokens_used != b->tokens_used)
+    return 0;
+
+  for (i = 0; i < a->tokens_used; i++)
+    if (! _cpp_equiv_tokens (&a->tokens[i], &b->tokens[i]))
+      return 0;
+  return 1;
+}
+
+/* Scan until we encounter a token of type STOP or a newline, and
+   create a token list for it.  Does not macro-expand or execute
+   directives.  The final token is not included in the list or
+   consumed from the input.  Returns the type of the token stopped at. */
+
+enum cpp_ttype
+_cpp_scan_until (pfile, list, stop)
      cpp_reader *pfile;
      cpp_toklist *list;
+     enum cpp_ttype stop;
 {
   int i, col;
   long written, len;
   enum cpp_ttype type;
   int space_before;
 
-  init_token_list (pfile, list, 1);
+  _cpp_clear_toklist (list);
+  list->line = CPP_BUF_LINE (CPP_BUFFER (pfile));
 
   written = CPP_WRITTEN (pfile);
   i = 0;
@@ -636,14 +784,14 @@ _cpp_scan_line (pfile, list)
       if (type == CPP_MACRO)
        type = CPP_NAME;
 
+      if (type == CPP_VSPACE || type == stop)
+       break;
+
       list->tokens_used++;
       TOK_TYPE  (list, i) = type;
       TOK_COL   (list, i) = col;
       TOK_FLAGS (list, i) = space_before ? PREV_WHITESPACE : 0;
       
-      if (type == CPP_VSPACE)
-       break;
-
       TOK_LEN (list, i) = len;
       if (token_spellings[type].type > SPELL_NONE)
        {
@@ -656,12 +804,14 @@ _cpp_scan_line (pfile, list)
       i++;
       space_before = 0;
     }
-  TOK_AUX (list, i) = CPP_BUFFER (pfile)->lineno + 1;
 
-  /* XXX Temporary kluge: put back the newline.  */
+  /* XXX Temporary kluge: put back the newline (or whatever).  */
   FORWARD(-1);
-}
 
+  /* Don't consider the first token to have white before.  */
+  TOK_FLAGS (list, 0) &= ~PREV_WHITESPACE;
+  return type;
+}
 
 /* Skip a C-style block comment.  We know it's a comment, and point is
    at the second character of the starter.  */
@@ -1060,85 +1210,6 @@ parse_string (pfile, c)
       CPP_PUTC_Q (pfile, *start);
 }
 
-/* Read an assertion into the token buffer, converting to
-   canonical form: `#predicate(a n swe r)'  The next non-whitespace
-   character to read should be the first letter of the predicate.
-   Returns 0 for syntax error, 1 for bare predicate, 2 for predicate
-   with answer (see callers for why). In case of 0, an error has been
-   printed. */
-int
-_cpp_parse_assertion (pfile)
-     cpp_reader *pfile;
-{
-  int c, dropwhite;
-  _cpp_skip_hspace (pfile);
-  c = PEEKC();
-  if (c == '\n')
-    {
-      cpp_error (pfile, "assertion without predicate");
-      return 0;
-    }
-  else if (! is_idstart(c))
-    {
-      cpp_error (pfile, "assertion predicate is not an identifier");
-      return 0;
-    }
-  CPP_PUTC(pfile, '#');
-  FORWARD(1);
-  _cpp_parse_name (pfile, c);
-
-  c = PEEKC();
-  if (c != '(')
-    {
-      if (is_hspace(c) || c == '\r')
-       _cpp_skip_hspace (pfile);
-      c = PEEKC();
-    }
-  if (c != '(')
-    return 1;
-
-  CPP_PUTC(pfile, '(');
-  FORWARD(1);
-  dropwhite = 1;
-  while ((c = GETC()) != ')')
-    {
-      if (is_space(c))
-       {
-         if (! dropwhite)
-           {
-             CPP_PUTC(pfile, ' ');
-             dropwhite = 1;
-           }
-       }
-      else if (c == '\n' || c == EOF)
-       {
-         if (c == '\n') FORWARD(-1);
-         cpp_error (pfile, "un-terminated assertion answer");
-         return 0;
-       }
-      else if (c == '\r')
-       /* \r cannot be a macro escape here. */
-       CPP_BUMP_LINE (pfile);
-      else
-       {
-         CPP_PUTC (pfile, c);
-         dropwhite = 0;
-       }
-    }
-
-  if (pfile->limit[-1] == ' ')
-    pfile->limit[-1] = ')';
-  else if (pfile->limit[-1] == '(')
-    {
-      cpp_error (pfile, "empty token sequence in assertion");
-      return 0;
-    }
-  else
-    CPP_PUTC (pfile, ')');
-
-  return 2;
-}
-
 /* Get the next token, and add it to the text in pfile->token_buffer.
    Return the kind of token we got.  */
 
@@ -1176,11 +1247,7 @@ _cpp_lex_token (pfile)
       if (!CPP_OPTION (pfile, discard_comments))
        return CPP_COMMENT;
       else if (CPP_TRADITIONAL (pfile))
-       {
-         if (pfile->parsing_define_directive)
-           return CPP_COMMENT;
-         goto get_next;
-       }
+       goto get_next;
       else
        {
          CPP_PUTC (pfile, c);
@@ -1191,42 +1258,24 @@ _cpp_lex_token (pfile)
       CPP_PUTC (pfile, c);
 
     hash:
-      if (pfile->parsing_if_directive)
+      c2 = PEEKC ();
+      if (c2 == '#')
        {
-         CPP_ADJUST_WRITTEN (pfile, -1);
-         if (_cpp_parse_assertion (pfile))
-           return CPP_ASSERTION;
-         return CPP_OTHER;
+         FORWARD (1);
+         CPP_PUTC (pfile, c2);
+         return CPP_PASTE;
        }
-
-      if (pfile->parsing_define_directive)
+      else if (c2 == '%' && PEEKN (1) == ':')
        {
-         c2 = PEEKC ();
-         if (c2 == '#')
-           {
-             FORWARD (1);
-             CPP_PUTC (pfile, c2);
-           }
-         else if (c2 == '%' && PEEKN (1) == ':')
-           {
-             /* Digraph: "%:" == "#".  */
-             FORWARD (1);
-             CPP_RESERVE (pfile, 2);
-             CPP_PUTC_Q (pfile, c2);
-             CPP_PUTC_Q (pfile, GETC ());
-           }
-         else
-           return CPP_HASH;
-
+         /* Digraph: "%:" == "#".  */
+         FORWARD (1);
+         CPP_RESERVE (pfile, 2);
+         CPP_PUTC_Q (pfile, c2);
+         CPP_PUTC_Q (pfile, GETC ());
          return CPP_PASTE;
        }
-
-      if (!pfile->only_seen_white)
-       return CPP_OTHER;
-
-      /* Remove the "#" or "%:" from the token buffer.  */
-      CPP_ADJUST_WRITTEN (pfile, (c == '#' ? -1 : -2));
-      return CPP_DIRECTIVE;
+      else
+       return CPP_HASH;
 
     case '\"':
     case '\'':
@@ -1697,13 +1746,22 @@ cpp_get_token (pfile)
     case CPP_COMMENT:
       return token;
 
-    case CPP_DIRECTIVE:
+    case CPP_HASH:
       pfile->potential_control_macro = 0;
+      if (!pfile->only_seen_white)
+       return CPP_HASH;
+      /* XXX shouldn't have to do this - remove the hash or %: from
+        the token buffer.  */
+      if (CPP_PWRITTEN (pfile)[-1] == '#')
+       CPP_ADJUST_WRITTEN (pfile, -1);
+      else
+       CPP_ADJUST_WRITTEN (pfile, -2);
+
       if (_cpp_handle_directive (pfile))
-       return CPP_DIRECTIVE;
+       return CPP_DIRECTIVE; 
       pfile->only_seen_white = 0;
       CPP_PUTC (pfile, '#');
-      return CPP_OTHER;
+      return CPP_HASH;
 
     case CPP_MACRO:
       pfile->potential_control_macro = 0;
@@ -1777,11 +1835,6 @@ _cpp_get_directive_token (pfile)
       goto get_next;
       return CPP_HSPACE;
 
-    case CPP_DIRECTIVE:
-      /* Don't execute the directive, but don't smash it to OTHER either.  */
-      CPP_PUTC (pfile, '#');
-      return CPP_DIRECTIVE;
-
     case CPP_MACRO:
       if (! pfile->no_macro_expand
          && maybe_macroexpand (pfile, old_written))
@@ -2134,7 +2187,7 @@ _cpp_init_input_buffer (pfile)
   U_CHAR *tmp;
 
   init_chartab ();
-  init_token_list (pfile, &pfile->directbuf, 0);
+  _cpp_init_toklist (&pfile->directbuf);
 
   /* Determine the appropriate size for the input buffer.  Normal C
      source files are smaller than eight K.  */
@@ -2294,17 +2347,6 @@ expand_comment_space (list)
     }
 }
 
-void
-cpp_free_token_list (list)
-     cpp_toklist *list;
-{
-  if (list->comments)
-    free (list->comments);
-  free (list->tokens - 1);     /* Backup over dummy token.  */
-  free (list->namebuf);
-  free (list);
-}
-
 void
 init_trigraph_map ()
 {
@@ -3175,7 +3217,7 @@ _cpp_lex_line (pfile, list)
              break;
            }
          /* Is this the beginning of a header name?  */
-         if (list->dir_flags & SYNTAX_INCLUDE)
+         if (list->flags & SYNTAX_INCLUDE)
            {
              c = '>';  /* Terminator.  */
              cur_token->type = CPP_HEADER_NAME;
@@ -3304,7 +3346,7 @@ _cpp_lex_line (pfile, list)
      invalid directives in assembly source, we don't know where the
      comments are, and # may introduce assembler pseudo-ops.  */
 
-  if (IS_DIRECTIVE (list) && list->dir_handler == 0
+  if (IS_DIRECTIVE (list) && list->dirno == -1
       && list->tokens[1].type != CPP_VSPACE
       && !CPP_OPTION (pfile, lang_asm))
     cpp_error_with_line (pfile, list->line, list->tokens[1].col,
@@ -3385,31 +3427,25 @@ void
 _cpp_lex_file (pfile)
      cpp_reader* pfile;
 {
-  int recycle;
   cpp_toklist* list;
 
   init_trigraph_map ();
   list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist));
+  _cpp_init_toklist (list);
 
-  for (recycle = 0; ;)
+  for (;;)
     {
-      init_token_list (pfile, list, recycle);
-      recycle = 1;
-
       _cpp_lex_line (pfile, list);
       if (list->tokens[0].type == CPP_EOF)
        break;
 
-      if (list->dir_handler)
-       {
-         if (list->dir_handler (pfile))
-           {
-             list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist));
-             recycle = 0;
-           }
-       }
+#if 0
+      if (list->dirno)
+       _cpp_handle_directive (pfile, list);
       else
+#endif
        _cpp_output_list (pfile, list);
+      _cpp_clear_toklist (list);
     }
 }
 
index e249555057a2534f1d7532377a1db9ecfb7ed6db..23b522c2b957e475ce32f26745d490da8ff725d1 100644 (file)
@@ -160,14 +160,15 @@ _cpp_check_directive (list, token)
   size_t len = token->val.name.len;
   unsigned int i;
 
-  list->dir_handler = 0;
-  list->dir_flags = 0;
+  list->dirno = -1;
+  list->flags &= ~SYNTAX_INCLUDE;
 
   for (i = 0; i < N_DIRECTIVES; i++)
     if (dtable[i].length == len && !ustrncmp (dtable[i].name, name, len)) 
       {
-       list->dir_handler = dtable[i].func;
-       list->dir_flags = dtable[i].flags;
+       list->dirno = i;
+       if (dtable[i].flags & SYNTAX_INCLUDE)
+         list->flags |= SYNTAX_INCLUDE;
        break;
       }
 }
@@ -219,8 +220,8 @@ _cpp_handle_directive (pfile)
          && CPP_BUFFER (pfile)->ihash
          && ! CPP_OPTION (pfile, preprocessed))
        cpp_pedwarn (pfile, "# followed by integer");
-      do_line (pfile);
-      return 1;
+      i = T_LINE;
+      goto process_directive;
     }
 
   /* If we are rescanning preprocessed input, don't obey any directives
@@ -300,6 +301,7 @@ _cpp_handle_directive (pfile)
   pfile->no_macro_expand--;
   CPP_SET_WRITTEN (pfile, old_written);
 
+ process_directive:
   /* Some directives (e.g. #if) may return a request to execute
      another directive handler immediately.  No directive ever
      requests that #define be executed immediately, so it is safe for
@@ -343,14 +345,14 @@ do_define (pfile)
   cpp_toklist *list = &pfile->directbuf;
 
   pfile->no_macro_expand++;
-  pfile->parsing_define_directive++;
   CPP_OPTION (pfile, discard_comments)++;
 
-  _cpp_scan_line (pfile, list);
+  _cpp_scan_until (pfile, list, CPP_VSPACE);
 
-  /* First token on the line must be a NAME.  There must be at least
-     one token (the VSPACE at the end).  */
-  if (TOK_TYPE (list, 0) != CPP_NAME)
+  /* First token on the line must be a NAME.  There may not be any
+     tokens in the list (if we had #define all by itself on a line).  */
+  if (list->tokens_used == 0
+      || TOK_TYPE (list, 0) != CPP_NAME)
     {
       cpp_error_with_line (pfile, list->line, TOK_COL (list, 0),
                           "#define must be followed by an identifier");
@@ -389,7 +391,6 @@ do_define (pfile)
 
  out:
   pfile->no_macro_expand--;
-  pfile->parsing_define_directive--;
   CPP_OPTION (pfile, discard_comments)--;
   return 0;
 }
@@ -1097,8 +1098,16 @@ static int
 do_if (pfile)
      cpp_reader *pfile;
 {
-  U_CHAR *control_macro = detect_if_not_defined (pfile);
-  int value = _cpp_parse_expr (pfile);
+  U_CHAR *control_macro;
+  int value;
+  int save_only_seen_white = pfile->only_seen_white;
+
+  control_macro = detect_if_not_defined (pfile);  
+
+  pfile->only_seen_white = 0;
+  value = _cpp_parse_expr (pfile);
+  pfile->only_seen_white = save_only_seen_white;
+
   return conditional_skip (pfile, value == 0, T_IF, control_macro);
 }
 
@@ -1383,7 +1392,7 @@ skip_if_group (pfile)
 
       token = _cpp_get_directive_token (pfile);
 
-      if (token == CPP_DIRECTIVE)
+      if (token == CPP_HASH)
        {
          ret = consider_directive_while_skipping (pfile, save_if_stack);
          if (ret)
@@ -1509,56 +1518,84 @@ _cpp_unwind_if_stack (pfile, pbuf)
   pfile->if_stack = ifs;
 }
 
+#define WARNING(msgid) do { cpp_warning(pfile, msgid); goto error; } while (0)
+#define ERROR(msgid) do { cpp_error(pfile, msgid); goto error; } while (0)
+#define ICE(msgid) do { cpp_ice(pfile, msgid); goto error; } while (0)
 static int
 do_assert (pfile)
      cpp_reader *pfile;
 {
   long old_written;
   U_CHAR *sym;
-  int ret;
-  HASHNODE *base, *this;
-  size_t blen, tlen;
+  size_t len;
+  HASHNODE *hp;
+  struct predicate *pred = 0;
+  enum cpp_ttype type;
 
-  old_written = CPP_WRITTEN (pfile);   /* remember where it starts */
-  ret = _cpp_parse_assertion (pfile);
-  if (ret == 0)
-    goto error;
-  else if (ret == 1)
-    {
-      cpp_error (pfile, "missing token-sequence in #assert");
-      goto error;
-    }
-  tlen = CPP_WRITTEN (pfile) - old_written;
+  old_written = CPP_WRITTEN (pfile);
+  pfile->no_macro_expand++;
+
+  CPP_PUTC (pfile, '#');       /* force token out of macro namespace */
+  type = _cpp_get_directive_token (pfile);
+  if (type == CPP_VSPACE)
+    ERROR ("#assert without predicate");
+  else if (type != CPP_NAME)
+    ERROR ("assertion predicate is not an identifier");
 
-  if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
-    {
-      cpp_error (pfile, "junk at end of #assert");
-      goto error;
-    }
   sym = pfile->token_buffer + old_written;
+  len = CPP_WRITTEN (pfile) - old_written;
+  hp = _cpp_lookup (pfile, sym, len);
+
+  if (_cpp_get_directive_token (pfile) != CPP_OPEN_PAREN)
+    ERROR ("missing token-sequence in #assert");
+
+  pred = (struct predicate *) xmalloc (sizeof (struct predicate));
+  _cpp_init_toklist (&pred->answer);
+
+  if (_cpp_scan_until (pfile, &pred->answer, CPP_CLOSE_PAREN)
+      != CPP_CLOSE_PAREN)
+    ERROR ("missing close paren in #assert");
 
-  this = _cpp_lookup (pfile, sym, tlen);
-  if (this->type == T_ASSERT)
+  if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
+    ICE ("impossible token, expecting ) in do_assert");
+
+  if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
+    ERROR ("junk at end of #assert");
+
+  if (hp->type == T_ASSERTION)
     {
-      cpp_warning (pfile, "%s re-asserted", sym);
-      goto error;
+      /* Check for reassertion.  */
+      const struct predicate *old;
+
+      for (old = hp->value.pred; old; old = old->next)
+       if (_cpp_equiv_toklists (&pred->answer, &old->answer))
+         /* We used to warn about this, but SVR4 cc doesn't, so let's
+            match that (also consistent with #define).  goto error will
+            clean up.  */
+         goto error;
+      pred->next = hp->value.pred;
     }
-      
-  blen = ustrchr (sym, '(') - sym;
-  base = _cpp_lookup (pfile, sym, blen);
-  if (base->type == T_VOID)
+  else
     {
-      base->type = T_ASSERT;
-      base->value.aschain = 0;
+      hp->type = T_ASSERTION;
+      pred->next = 0;
     }
-
-  this->type = T_ASSERT;
-  this->value.aschain = base->value.aschain;
-  base->value.aschain = this;
+  
+  _cpp_squeeze_toklist (&pred->answer);
+  hp->value.pred = pred;
+  pfile->no_macro_expand--;
+  CPP_SET_WRITTEN (pfile, old_written);
+  return 0;
 
  error:
   _cpp_skip_rest_of_line (pfile);
+  pfile->no_macro_expand--;
   CPP_SET_WRITTEN (pfile, old_written);
+  if (pred)
+    {
+      _cpp_free_toklist (&pred->answer);
+      free (pred);
+    }
   return 0;
 }
 
@@ -1566,68 +1603,90 @@ static int
 do_unassert (pfile)
      cpp_reader *pfile;
 {
-  int ret;
   long old_written;
   U_CHAR *sym;
-  long baselen, thislen;
-  HASHNODE *base, *this, *next;
+  size_t len;
+  HASHNODE *hp;
+  struct predicate *pred = 0;
+  enum cpp_ttype type;
 
   old_written = CPP_WRITTEN (pfile);
-  ret = _cpp_parse_assertion (pfile);
-  if (ret == 0)
-    goto out;
-  thislen = CPP_WRITTEN (pfile) - old_written;
+  pfile->no_macro_expand++;
 
-  if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
+  CPP_PUTC (pfile, '#');       /* force token out of macro namespace */
+  if (_cpp_get_directive_token (pfile) != CPP_NAME)
+    ERROR ("#unassert must be followed by an identifier");
+
+  sym = pfile->token_buffer + old_written;
+  len = CPP_WRITTEN (pfile) - old_written;
+  hp = _cpp_lookup (pfile, sym, len);
+
+  type = _cpp_get_directive_token (pfile);
+  if (type == CPP_OPEN_PAREN)
     {
-      cpp_error (pfile, "junk at end of #unassert");
-      goto out;
+      pred = (struct predicate *) xmalloc (sizeof (struct predicate));
+      _cpp_init_toklist (&pred->answer);
+
+      if (_cpp_scan_until (pfile, &pred->answer, CPP_CLOSE_PAREN)
+         != CPP_CLOSE_PAREN)
+       ERROR ("missing close paren in #unassert");
+
+      if (_cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN)
+       ICE ("impossible token, expecting ) in do_unassert");
+
+      type = _cpp_get_directive_token (pfile);
     }
-  sym = pfile->token_buffer + old_written;
-  CPP_SET_WRITTEN (pfile, old_written);
 
-  if (ret == 1)
+  if (type != CPP_VSPACE)
+    ERROR ("junk at end of #unassert");
+
+  if (hp->type != T_ASSERTION)
+    /* Not an error to #unassert something that isn't asserted.
+       goto error to clean up.  */
+    goto error;
+
+  if (pred)
     {
-      base = _cpp_lookup (pfile, sym, thislen);
-      if (base->type == T_VOID)
-       goto out;  /* It isn't an error to #undef what isn't #defined,
-                     so it isn't an error to #unassert what isn't
-                     #asserted either. */
-
-      for (this = base->value.aschain; this; this = next)
-        {
-         next = this->value.aschain;
-         this->value.aschain = NULL;
-         this->type = T_VOID;
-       }
-      base->value.aschain = NULL;
-      base->type = T_VOID;
+      /* Find this specific answer and remove it.  */
+      struct predicate *o, *p;
+
+      for (p = NULL, o = hp->value.pred; o; p = o, o = o->next)
+       if (_cpp_equiv_toklists (&pred->answer, &o->answer))
+         {
+           if (p)
+             p->next = o->next;
+           else
+             hp->value.pred = o->next;
+
+           _cpp_free_toklist (&o->answer);
+           free (o);
+           break;
+         }
     }
   else
     {
-      baselen = ustrchr (sym, '(') - sym;
-      base = _cpp_lookup (pfile, sym, baselen);
-      if (base->type == T_VOID) goto out;
-      this = _cpp_lookup (pfile, sym, thislen);
-      if (this->type == T_VOID) goto out;
-
-      next = base;
-      while (next->value.aschain != this)
-       next = next->value.aschain;
-
-      next->value.aschain = this->value.aschain;
-      this->value.aschain = NULL;
-      this->type = T_VOID;
-
-      if (base->value.aschain == NULL)
-       /* Last answer for this predicate deleted. */
-       base->type = T_VOID;
+      struct predicate *o, *p;
+      for (o = hp->value.pred; o; o = p)
+       {
+         p = o->next;
+         _cpp_free_toklist ((cpp_toklist *) &o->answer);
+         free (o);
+       }
+      hp->value.pred = NULL;
     }
-  return 0;
 
- out:
+  if (hp->value.pred == NULL)
+    hp->type = T_VOID;  /* Last answer for this predicate deleted.  */
+
+ error:
   _cpp_skip_rest_of_line (pfile);
+  pfile->no_macro_expand--;
   CPP_SET_WRITTEN (pfile, old_written);
+  if (pred)
+    {
+      _cpp_free_toklist (&pred->answer);
+      free (pred);
+    }
   return 0;
 }
 
index a46ada3eacc10d28716e3ae9193b51f85b03c805..6ecab526c48e2178c713c2dba887809549e6cbc5 100644 (file)
@@ -124,7 +124,6 @@ typedef struct cpp_name cpp_name;
   T(CPP_VSPACE,                "\n")   /* End of line.  */             \
   N(CPP_EOF,           0)      /* End of file.  */             \
   N(CPP_HEADER_NAME,   0)      /* <stdio.h> in #include */     \
-  N(CPP_ASSERTION,     0)      /* (...) in #assert */          \
 \
   /* Obsolete - will be removed when no code uses them still.  */      \
   N(CPP_HSPACE,                0)      /* Horizontal white space.  */  \
@@ -189,6 +188,9 @@ struct cpp_token
   } val;
 };
 
+/* General flags.  */
+#define LIST_OFFSET    (1 << 0)
+
 /* Directive flags.  */
 #define SYNTAX_INCLUDE (1 << 8)
 
@@ -211,12 +213,12 @@ struct cpp_toklist
   unsigned int comments_used;  /* comment tokens used.  */
   unsigned int comments_cap;   /* comment token capacity.  */
 
-  /* Only used if tokens[0].type == CPP_DIRECTIVE.  This is the
-     handler to call after lexing the rest of this line.  The flags
-     indicate whether the rest of the line gets special treatment
-     during lexing (#include, #if, #assert, #unassert).  */
-  directive_handler dir_handler;
-  unsigned short dir_flags;
+  /* The handler to call after lexing the rest of this line.
+     -1 for none */
+  short dirno;
+
+  /* Per-list flags, see above */
+  unsigned short flags;
 };
 
 struct cpp_buffer
@@ -544,12 +546,6 @@ struct cpp_reader
   /* If true, characters between '<' and '>' are a single (string) token.  */
   unsigned char parsing_include_directive;
 
-  /* If true, # introduces an assertion (see do_assert) */
-  unsigned char parsing_if_directive;
-
-  /* If true, # and ## are the STRINGIZE and TOKPASTE operators */
-  unsigned char parsing_define_directive;
-
   /* True if escape sequences (as described for has_escapes in
      parse_buffer) should be emitted.  */
   unsigned char output_escapes;