OSDN Git Service

* cppfiles.c: Include mkdeps.h.
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Mar 2000 06:34:11 +0000 (06:34 +0000)
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Mar 2000 06:34:11 +0000 (06:34 +0000)
(find_include_file, read_include_file): Remove _cpp_ prefix
from name, make static.
(_cpp_execute_include): New function, broken out of
do_include.

* cpplib.c: Don't include mkdeps.h.
(struct directive): Remove type field. Reorder entries.  The
function takes only one argument.
(struct if_stack): Make type field an int.
(directive_table): Rename to dtable.  Generate it, the
prototypes of the directive handlers, and the enum for the
directive numbers, from a template macro.
(do_ifndef, do_include_next, do_import): New functions.
(do_define, do_include, do_endif, do_ifdef, do_if, do_else,
do_undef, do_line, do_elif, do_error, do_pragma, do_warning,
do_ident, do_assert, do_unassert, do_sccs): Take only one
argument.
(do_sccs): Define always, but alter behavior based on
SCCS_DIRECTIVE.
(_cpp_handle_directive, consider_directive_while_skipping):
Restructure for new directive table layout.

(pass_thru_directive): Take a directive number, not a pointer
to a struct directive.
(parse_include): New function, broken out of do_include.
(do_include, do_import, do_include_next): Use parse_include
and _cpp_execute_include.
(do_elif, do_else): Test for T_ELSE specifically when checking
for #elif/#else after #else.
(parse_ifdef): New function, broken out of do_ifdef.
(validate_else): Expect a name arg without a leading #.
(if_directive_name): Delete.
(cpp_define, cpp_assert, cpp_undef, cpp_unassert): Call
directive handlers with only one argument.

* cpphash.h: Update prototypes.
(enum node_type): Remove entries for directives.
* Makefile.in: Update dependencies.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32519 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/cppfiles.c
gcc/cpphash.h
gcc/cpplib.c

index c12bf95..2559e36 100644 (file)
@@ -1,5 +1,45 @@
 2000-03-13  Zack Weinberg  <zack@wolery.cumb.org>
 
+       * cppfiles.c: Include mkdeps.h.
+       (find_include_file, read_include_file): Remove _cpp_ prefix
+       from name, make static.
+       (_cpp_execute_include): New function, broken out of
+       do_include.
+
+       * cpplib.c: Don't include mkdeps.h.
+       (struct directive): Remove type field. Reorder entries.  The
+       function takes only one argument.
+       (struct if_stack): Make type field an int.
+       (directive_table): Rename to dtable.  Generate it, the
+       prototypes of the directive handlers, and the enum for the
+       directive numbers, from a template macro.
+       (do_ifndef, do_include_next, do_import): New functions.
+       (do_define, do_include, do_endif, do_ifdef, do_if, do_else,
+       do_undef, do_line, do_elif, do_error, do_pragma, do_warning,
+       do_ident, do_assert, do_unassert, do_sccs): Take only one
+       argument.
+       (do_sccs): Define always, but alter behavior based on
+       SCCS_DIRECTIVE.
+       (_cpp_handle_directive, consider_directive_while_skipping):
+       Restructure for new directive table layout.
+
+       (pass_thru_directive): Take a directive number, not a pointer
+       to a struct directive.
+       (parse_include): New function, broken out of do_include.
+       (do_include, do_import, do_include_next): Use parse_include
+       and _cpp_execute_include.
+       (do_elif, do_else): Test for T_ELSE specifically when checking
+       for #elif/#else after #else.
+       (parse_ifdef): New function, broken out of do_ifdef.
+       (validate_else): Expect a name arg without a leading #.
+       (if_directive_name): Delete.
+       (cpp_define, cpp_assert, cpp_undef, cpp_unassert): Call
+       directive handlers with only one argument.
+
+       * cpphash.h: Update prototypes.
+       (enum node_type): Remove entries for directives.
+       * Makefile.in: Update dependencies.
+
        * cpphash.c (dump_hash_helper): Only dump nodes of type
        T_MACRO.  Emit a newline after each definition.
 
index cd4a22d..59b792a 100644 (file)
@@ -2050,9 +2050,9 @@ cppulp.o:   cppulp.c   $(CONFIG_H) system.h output.h
 cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
 cppexp.o:   cppexp.c   $(CONFIG_H) $(LIBCPP_DEPS)
 cpplex.o:   cpplex.c   $(CONFIG_H) $(LIBCPP_DEPS)
-cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H)
+cpplib.o:   cpplib.c   $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H)
 cpphash.o:  cpphash.c  $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H)
-cpplib.o:   cpplib.c   $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h
+cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h
 
 cppinit.o:  cppinit.c  $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h \
                prefix.h output.h Makefile version.h
index ec7529f..cff8cd2 100644 (file)
@@ -30,6 +30,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include "cpphash.h"
 #include "hashtab.h"
 #include "intl.h"
+#include "mkdeps.h"
 
 static IHASH *redundant_include_p PARAMS ((cpp_reader *, IHASH *,
                                           struct file_name_list *));
@@ -40,11 +41,14 @@ static char *remap_filename         PARAMS ((cpp_reader *, char *,
                                         struct file_name_list *));
 static struct file_name_list *actual_directory
                                PARAMS ((cpp_reader *, const char *));
-
 static unsigned int hash_IHASH PARAMS ((const void *));
 static int eq_IHASH            PARAMS ((const void *, const void *));
-
 static int file_cleanup                PARAMS ((cpp_buffer *, cpp_reader *));
+static int find_include_file   PARAMS ((cpp_reader *, const char *,
+                                       struct file_name_list *,
+                                       IHASH **, int *));
+static int read_include_file   PARAMS ((cpp_reader *, int, IHASH *));
+
 
 #if 0
 static void hack_vms_include_specification PARAMS ((char *));
@@ -58,7 +62,7 @@ static void hack_vms_include_specification PARAMS ((char *));
 #endif
 
 /* Open files in nonblocking mode, so we don't get stuck if someone
-   clever has asked cpp to process /dev/rmt0.  _cpp_read_include_file
+   clever has asked cpp to process /dev/rmt0.  read_include_file
    will check that we have a real file to work with.  Also take care
    not to acquire a controlling terminal by mistake (this can't happen
    on sane systems, but paranoia is a virtue).  */
@@ -185,8 +189,8 @@ file_cleanup (pbuf, pfile)
    *IHASH is set to point to the include hash entry for this file, and
    *BEFORE is set to 1 if the file was included before (but needs to be read
    again). */
-int
-_cpp_find_include_file (pfile, fname, search_start, ihash, before)
+static int
+find_include_file (pfile, fname, search_start, ihash, before)
      cpp_reader *pfile;
      const char *fname;
      struct file_name_list *search_start;
@@ -465,6 +469,120 @@ remap_filename (pfile, name, loc)
   return name;
 }
 
+
+void
+_cpp_execute_include (pfile, fname, len, no_reinclude, search_start)
+     cpp_reader *pfile;
+     char *fname;
+     unsigned int len;
+     int no_reinclude;
+     struct file_name_list *search_start;
+{
+  IHASH *ihash;
+  int fd;
+  int angle_brackets = fname[0] == '<';
+  int before;
+
+  if (!search_start)
+    {
+      if (angle_brackets)
+       search_start = CPP_OPTIONS (pfile)->bracket_include;
+      else if (CPP_OPTIONS (pfile)->ignore_srcdir)
+       search_start = CPP_OPTIONS (pfile)->quote_include;
+      else
+       search_start = CPP_BUFFER (pfile)->actual_dir;
+    }
+
+  if (!search_start)
+    {
+      cpp_error (pfile, "No include path in which to find %s", fname);
+      return;
+    }
+
+  /* Remove quote marks.  */
+  fname++;
+  len -= 2;
+  fname[len] = '\0';
+
+  fd = find_include_file (pfile, fname, search_start, &ihash, &before);
+
+  if (fd == -2)
+    return;
+  
+  if (fd == -1)
+    {
+      if (CPP_OPTIONS (pfile)->print_deps_missing_files
+         && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
+                                      (pfile->system_include_depth > 0)))
+        {
+         if (!angle_brackets)
+           deps_add_dep (pfile->deps, fname);
+         else
+           {
+             char *p;
+             struct file_name_list *ptr;
+             /* If requested as a system header, assume it belongs in
+                the first system header directory. */
+             if (CPP_OPTIONS (pfile)->bracket_include)
+               ptr = CPP_OPTIONS (pfile)->bracket_include;
+             else
+               ptr = CPP_OPTIONS (pfile)->quote_include;
+
+             p = (char *) alloca (strlen (ptr->name)
+                                  + strlen (fname) + 2);
+             if (*ptr->name != '\0')
+               {
+                 strcpy (p, ptr->name);
+                 strcat (p, "/");
+               }
+             strcat (p, fname);
+             deps_add_dep (pfile->deps, p);
+           }
+       }
+      /* If -M was specified, and this header file won't be added to
+        the dependency list, then don't count this as an error,
+        because we can still produce correct output.  Otherwise, we
+        can't produce correct output, because there may be
+        dependencies we need inside the missing file, and we don't
+        know what directory this missing file exists in. */
+      else if (CPP_PRINT_DEPS (pfile)
+              && (CPP_PRINT_DEPS (pfile)
+                  <= (angle_brackets || (pfile->system_include_depth > 0))))
+       cpp_warning (pfile, "No include path in which to find %s", fname);
+      else
+       cpp_error_from_errno (pfile, fname);
+
+      return;
+    }
+
+  /* For -M, add the file to the dependencies on its first inclusion. */
+  if (!before && (CPP_PRINT_DEPS (pfile)
+                 > (angle_brackets || (pfile->system_include_depth > 0))))
+    deps_add_dep (pfile->deps, ihash->name);
+
+  /* Handle -H option.  */
+  if (CPP_OPTIONS(pfile)->print_include_names)
+    {
+      cpp_buffer *fp = CPP_BUFFER (pfile);
+      while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
+       putc ('.', stderr);
+      fprintf (stderr, " %s\n", ihash->name);
+    }
+
+  /* Actually process the file */
+
+  if (no_reinclude)
+    ihash->control_macro = (const U_CHAR *) "";
+  
+  if (read_include_file (pfile, fd, ihash))
+    {
+      _cpp_output_line_command (pfile, enter_file);
+      if (angle_brackets)
+       pfile->system_include_depth++;   /* Decremented in file_cleanup. */
+    }
+}
+
+
 /* Push an input buffer and load it up with the contents of FNAME.
    If FNAME is "" or NULL, read standard input.  */
 int
@@ -506,7 +624,7 @@ cpp_read_file (pfile, fname)
   else
     f = open (fname, OMODES);
 
-  return _cpp_read_include_file (pfile, f, ih);
+  return read_include_file (pfile, f, ih);
 }
 
 /* Read the contents of FD into the buffer on the top of PFILE's stack.
@@ -515,8 +633,8 @@ cpp_read_file (pfile, fname)
 
    The caller is responsible for the cpp_push_buffer.  */
 
-int
-_cpp_read_include_file (pfile, fd, ihash)
+static int
+read_include_file (pfile, fd, ihash)
      cpp_reader *pfile;
      int fd;
      IHASH *ihash;
index 4468d42..704cab4 100644 (file)
@@ -83,28 +83,9 @@ struct definition
    It does not contain control words like "#define", which are recognized
    by a separate piece of code. */
 
-/* different flavors of hash nodes --- also used in keyword table */
+/* different flavors of hash nodes */
 enum node_type
 {
-  T_DEFINE = 1,           /* `#define' */
-  T_INCLUDE,      /* `#include' */
-  T_INCLUDE_NEXT,  /* `#include_next' */
-  T_IMPORT,        /* `#import' */
-  T_IFDEF,        /* `#ifdef' */
-  T_IFNDEF,       /* `#ifndef' */
-  T_IF,                   /* `#if' */
-  T_ELSE,         /* `#else' */
-  T_PRAGMA,       /* `#pragma' */
-  T_ELIF,         /* `#elif' */
-  T_UNDEF,        /* `#undef' */
-  T_LINE,         /* `#line' */
-  T_ERROR,        /* `#error' */
-  T_WARNING,      /* `#warning' */
-  T_ENDIF,        /* `#endif' */
-  T_SCCS,         /* `#sccs' */
-  T_IDENT,        /* `#ident' */
-  T_ASSERT,       /* `#assert' */
-  T_UNASSERT,     /* `#unassert', */
   T_SPECLINE,     /* `__LINE__' */
   T_DATE,         /* `__DATE__' */
   T_FILE,         /* `__FILE__' */
@@ -292,10 +273,9 @@ extern void _cpp_dump_macro_hash   PARAMS ((cpp_reader *));
 
 /* In cppfiles.c */
 extern void _cpp_simplify_pathname     PARAMS ((char *));
-extern int _cpp_find_include_file      PARAMS ((cpp_reader *, const char *,
-                                               struct file_name_list *,
-                                               IHASH **, int *));
-extern int _cpp_read_include_file      PARAMS ((cpp_reader *, int, IHASH *));
+extern void _cpp_execute_include       PARAMS ((cpp_reader *, char *,
+                                                unsigned int, int,
+                                                struct file_name_list *));
 extern void _cpp_init_include_hash     PARAMS ((cpp_reader *));
 
 /* In cppexp.c */
index 1de14d3..dac186d 100644 (file)
@@ -26,7 +26,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "cpphash.h"
 #include "hashtab.h"
 #include "intl.h"
-#include "mkdeps.h"
 
 #define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) \
                  ? CPP_BUFFER (pfile)->cur[N] : EOF)
@@ -38,11 +37,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 struct directive
 {
-  int length;                  /* Length of name */
-  int (*func)                  /* Function to handle directive */
-    PARAMS ((cpp_reader *, const struct directive *));
+  unsigned int length;         /* Length of name */
   const char *name;            /* Name of directive */
-  enum node_type type;         /* Code which describes which directive.  */
+  int (*func)                  /* Function to handle directive */
+    PARAMS ((cpp_reader *));
 };
 
 /* Stack of conditionals currently in progress
@@ -54,84 +52,83 @@ struct if_stack
   int lineno;                  /* line number where condition started */
   int if_succeeded;            /* truth of last condition in this group */
   const U_CHAR *control_macro; /* macro name for #ifndef around entire file */
-  enum node_type type;         /* type of last directive seen in this group */
+  int type;                    /* type of last directive seen in this group */
 };
 typedef struct if_stack IF_STACK;
 
-
-/* These functions are declared to return int instead of void since they
-   are going to be placed in a table and some old compilers have trouble with
-   pointers to functions returning void.  */
-
-static int do_define PARAMS ((cpp_reader *, const struct directive *));
-static int do_line PARAMS ((cpp_reader *, const struct directive *));
-static int do_include PARAMS ((cpp_reader *, const struct directive *));
-static int do_undef PARAMS ((cpp_reader *, const struct directive *));
-static int do_error PARAMS ((cpp_reader *, const struct directive *));
-static int do_pragma PARAMS ((cpp_reader *, const struct directive *));
-static int do_ident PARAMS ((cpp_reader *, const struct directive *));
-static int do_if PARAMS ((cpp_reader *, const struct directive *));
-static int do_ifdef PARAMS ((cpp_reader *, const struct directive *));
-static int do_else PARAMS ((cpp_reader *, const struct directive *));
-static int do_elif PARAMS ((cpp_reader *, const struct directive *));
-static int do_endif PARAMS ((cpp_reader *, const struct directive *));
-#ifdef SCCS_DIRECTIVE
-static int do_sccs PARAMS ((cpp_reader *, const struct directive *));
-#endif
-static int do_assert PARAMS ((cpp_reader *, const struct directive *));
-static int do_unassert PARAMS ((cpp_reader *, const struct directive *));
-static int do_warning PARAMS ((cpp_reader *, const struct directive *));
-
 /* Forward declarations.  */
 
 static void validate_else              PARAMS ((cpp_reader *, const char *));
-static void conditional_skip           PARAMS ((cpp_reader *, int,
-                                               enum node_type, U_CHAR *));
+static int parse_ifdef                 PARAMS ((cpp_reader *, const char *));
+static unsigned int parse_include      PARAMS ((cpp_reader *, const char *));
+static void conditional_skip           PARAMS ((cpp_reader *, int, int,
+                                                U_CHAR *));
 static void skip_if_group              PARAMS ((cpp_reader *));
 static void pass_thru_directive                PARAMS ((const U_CHAR *, size_t,
-                                                cpp_reader *,
-                                                const struct directive *));
+                                                cpp_reader *, int));
 static int read_line_number            PARAMS ((cpp_reader *, int *));
 static U_CHAR *detect_if_not_defined   PARAMS ((cpp_reader *));
 static int consider_directive_while_skipping
                                        PARAMS ((cpp_reader *, IF_STACK *));
 static int get_macro_name              PARAMS ((cpp_reader *));
-static const char *if_directive_name   PARAMS ((cpp_reader *,
-                                                struct if_stack *));
-
-/* Here is the actual list of #-directives.
-   This table is ordered by frequency of occurrence; the numbers
-   at the end are directive counts from all the source code I have
-   lying around (egcs and libc CVS as of 1999-05-18, plus grub-0.5.91,
-   linux-2.2.9, and pcmcia-cs-3.0.9).  */
-
-static const struct directive directive_table[] = {
-  /* In C89 */
-  {  6, do_define,   "define",       T_DEFINE },       /* 270554 */
-  {  7, do_include,  "include",      T_INCLUDE },      /*  52262 */
-  {  5, do_endif,    "endif",        T_ENDIF },                /*  45855 */
-  {  5, do_ifdef,   "ifdef",        T_IFDEF },         /*  22000 */
-  {  2, do_if,       "if",           T_IF },           /*  18162 */
-  {  4, do_else,     "else",         T_ELSE },         /*   9863 */
-  {  6, do_ifdef,   "ifndef",       T_IFNDEF },        /*   9675 */
-  {  5, do_undef,    "undef",        T_UNDEF },                /*   4837 */
-  {  4, do_line,     "line",         T_LINE },         /*   2465 */
-  {  4, do_elif,     "elif",         T_ELIF },         /*    610 */
-  {  5, do_error,    "error",        T_ERROR },                /*    475 */
-  {  6, do_pragma,   "pragma",       T_PRAGMA },       /*    195 */
-
-  /* Extensions.  All deprecated except #warning and #include_next.  */
-  {  7, do_warning,  "warning",      T_WARNING },      /*     22 - GNU   */
-  { 12, do_include,  "include_next", T_INCLUDE_NEXT }, /*     19 - GNU   */
-  {  5, do_ident,    "ident",        T_IDENT },                /*     11 - SVR4  */
-  {  6, do_include,  "import",       T_IMPORT },       /*      0 - ObjC  */
-  {  6, do_assert,   "assert",       T_ASSERT },       /*      0 - SVR4  */
-  {  8, do_unassert, "unassert",     T_UNASSERT },     /*      0 - SVR4  */
-#ifdef SCCS_DIRECTIVE
-  {  4, do_sccs,     "sccs",         T_SCCS },         /*      0 - SVR2? */
-#endif
-  {  -1, 0, "", T_UNUSED }
+
+/* This is the table of directive handlers.  It is ordered by
+   frequency of occurrence; the numbers at the end are directive
+   counts from all the source code I have lying around (egcs and libc
+   CVS as of 1999-05-18, plus grub-0.5.91, linux-2.2.9, and
+   pcmcia-cs-3.0.9).
+
+   The entries with a dash and a name after the count are extensions,
+   of which all but #warning and #include_next are deprecated.  The name
+   is where the extension appears to have come from.  */
+
+#define DIRECTIVE_TABLE                                                        \
+D("define",      do_define,       T_DEFINE)            /* 270554 */    \
+D("include",     do_include,      T_INCLUDE)           /*  52262 */    \
+D("endif",       do_endif,        T_ENDIF)             /*  45855 */    \
+D("ifdef",       do_ifdef,        T_IFDEF)             /*  22000 */    \
+D("if",                  do_if,           T_IF)                /*  18162 */    \
+D("else",        do_else,         T_ELSE)              /*   9863 */    \
+D("ifndef",      do_ifndef,       T_IFNDEF)            /*   9675 */    \
+D("undef",       do_undef,        T_UNDEF)             /*   4837 */    \
+D("line",        do_line,         T_LINE)              /*   2465 */    \
+D("elif",        do_elif,         T_ELIF)              /*    610 */    \
+D("error",       do_error,        T_ERROR)             /*    475 */    \
+D("pragma",      do_pragma,       T_PRAGMA)            /*    195 */    \
+D("warning",     do_warning,      T_WARNING)           /*     22 - GNU   */ \
+D("include_next", do_include_next, T_INCLUDE_NEXT)     /*     19 - GNU   */ \
+D("ident",       do_ident,        T_IDENT)             /*     11 - SVR4  */ \
+D("import",      do_import,       T_IMPORT)            /*      0 - ObjC  */ \
+D("assert",      do_assert,       T_ASSERT)            /*      0 - SVR4  */ \
+D("unassert",    do_unassert,     T_UNASSERT)          /*      0 - SVR4  */ \
+D("sccs",        do_sccs,         T_SCCS)              /*      0 - SVR2? */
+
+/* Use the table to generate a series of prototypes, an enum for the
+   directive names, and an array of directive handlers.  */
+
+/* The directive-processing functions are declared to return int
+   instead of void, because some old compilers have trouble with
+   pointers to functions returning void.  */
+
+#define D(name, fun, tag) static int fun PARAMS ((cpp_reader *));
+DIRECTIVE_TABLE
+#undef D
+
+#define D(name, fun, tag) tag,
+enum
+{
+  DIRECTIVE_TABLE
+  N_DIRECTIVES
 };
+#undef D
+
+#define D(name, fun, tag) { sizeof name - 1, name, fun },
+static const struct directive dtable[] =
+{
+DIRECTIVE_TABLE
+};
+#undef D
+#undef DIRECTIVE_TABLE
 
 /* Handle a possible # directive.
    '#' has already been read.  */
@@ -140,9 +137,8 @@ int
 _cpp_handle_directive (pfile)
      cpp_reader *pfile;
 {
-  int c;
-  register const struct directive *kt;
-  int ident_length;
+  int c, i;
+  unsigned int len;
   U_CHAR *ident;
   long old_written = CPP_WRITTEN (pfile);
 
@@ -168,7 +164,7 @@ _cpp_handle_directive (pfile)
          && ! CPP_OPTIONS (pfile)->preprocessed
          && ! CPP_BUFFER (pfile)->manual_pop)
        cpp_pedwarn (pfile, "`#' followed by integer");
-      do_line (pfile, NULL);
+      do_line (pfile);
       return 1;
     }
 
@@ -181,8 +177,8 @@ _cpp_handle_directive (pfile)
   CPP_PUTC (pfile, '#');
   _cpp_parse_name (pfile, GETC());
   ident = pfile->token_buffer + old_written + 1;
-  ident_length = CPP_PWRITTEN (pfile) - ident;
-  if (ident_length == 0)
+  len = CPP_PWRITTEN (pfile) - ident;
+  if (len == 0)
     {
       /* A line of just `#' becomes blank.  A line with something
         other than an identifier after the # is reparsed as a non-
@@ -192,27 +188,27 @@ _cpp_handle_directive (pfile)
     }
 
   /* Decode the keyword and call the appropriate expansion routine.  */
-  for (kt = directive_table; ; kt++)
+  for (i = 0; i < N_DIRECTIVES; i++)
     {
-      if (kt->length <= 0)
-       /* # identifier, but not a legit directive.  Pass onward as a
-          CPP_DIRECTIVE token anyway - let the consumer worry about it.  */
-       return 1;
-      if (kt->length == ident_length
-         && !strncmp (kt->name, ident, ident_length)) 
+      if (dtable[i].length == len
+         && !strncmp (dtable[i].name, ident, len)) 
        break;
     }
+  if (i == N_DIRECTIVES)
+    /* # identifier, but not a legit directive.  Pass onward as a
+       CPP_DIRECTIVE token anyway - let the consumer worry about it.  */
+    return 1;
 
   CPP_SET_WRITTEN (pfile, old_written);
 
   if (pfile->no_directives)
     {
       cpp_error (pfile, "`#%s' may not be used inside a macro argument",
-                kt->name);
+                dtable[i].name);
       _cpp_skip_rest_of_line (pfile);
     }
   else
-    (*kt->func) (pfile, kt);
+    (*dtable[i].func) (pfile);
 
   return 1;
 }
@@ -227,13 +223,14 @@ pass_thru_directive (buf, len, pfile, keyword)
      const U_CHAR *buf;
      size_t len;
      cpp_reader *pfile;
-     const struct directive *keyword;
+     int keyword;
 {
-  register unsigned keyword_length = keyword->length;
+  const struct directive *kt = &dtable[keyword];
+  register unsigned klen = kt->length;
 
-  CPP_RESERVE (pfile, 1 + keyword_length + len);
+  CPP_RESERVE (pfile, 1 + klen + len);
   CPP_PUTC_Q (pfile, '#');
-  CPP_PUTS_Q (pfile, keyword->name, keyword_length);
+  CPP_PUTS_Q (pfile, kt->name, klen);
   if (len != 0 && buf[0] != ' ')
     CPP_PUTC_Q (pfile, ' ');
   CPP_PUTS_Q (pfile, buf, len);
@@ -272,14 +269,11 @@ get_macro_name (pfile)
   return 0;
 }
 
-/* Process a #define command.
-   KEYWORD is the keyword-table entry for #define,
-   or NULL for a "predefined" macro.  */
+/* Process a #define command.  */
 
 static int
-do_define (pfile, keyword)
+do_define (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   HASHNODE **slot;
   DEFINITION *def;
@@ -364,7 +358,7 @@ do_define (pfile, keyword)
       || CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
     _cpp_dump_definition (pfile, sym, len, def);
   else if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
-    pass_thru_directive (sym, len, pfile, keyword);
+    pass_thru_directive (sym, len, pfile, T_DEFINE);
 
   return 0;
 }
@@ -446,227 +440,145 @@ _cpp_output_line_command (pfile, file_change)
 
 /* Handle #include and #import.  */
 
-static int
-do_include (pfile, keyword)
+static unsigned int
+parse_include (pfile, name)
      cpp_reader *pfile;
-     const struct directive *keyword;
+     const char *name;
 {
-  int importing = (keyword->type == T_IMPORT);
-  int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
-  int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
-  int before;  /* included before? */
-  long flen;
-  unsigned char *ftok;
-  cpp_buffer *fp;
-
-  enum cpp_token token;
-
-  /* Chain of dirs to search */
-  IHASH *ihash;
-  struct file_name_list *search_start;
-  
   long old_written = CPP_WRITTEN (pfile);
-
-  int fd;
-
-  if (CPP_PEDANTIC (pfile))
-    {
-      if (importing)
-       cpp_pedwarn (pfile, "ANSI C does not allow `#import'");
-      if (skip_dirs)
-       cpp_pedwarn (pfile, "ANSI C does not allow `#include_next'");
-    }
-
-  if (importing && CPP_OPTIONS (pfile)->warn_import
-      && !CPP_OPTIONS (pfile)->inhibit_warnings
-      && !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
-    {
-      pfile->import_warning = 1;
-      cpp_warning (pfile,
-          "#import is obsolete, use an #ifndef wrapper in the header file");
-    }
+  enum cpp_token token;
+  int len;
 
   pfile->parsing_include_directive++;
   token = _cpp_get_directive_token (pfile);
   pfile->parsing_include_directive--;
 
+  len = CPP_WRITTEN (pfile) - old_written;
+
   if (token == CPP_STRING)
-    {
-      if (pfile->token_buffer[old_written] == '<')
-       angle_brackets = 1;
-    }
+    ; /* No special treatment required.  */
 #ifdef VMS
   else if (token == CPP_NAME)
     {
       /* Support '#include xyz' like VAX-C.  It is taken as
          '#include <xyz.h>' and generates a warning.  */
-      cpp_warning (pfile,
-              "`#include filename' is obsolete, use `#include <filename.h>'");
-      angle_brackets = 1;
-
-      /* Append the missing `.h' to the name. */
-      CPP_PUTS (pfile, ".h", 2);
+      cpp_warning (pfile, "#%s filename is obsolete, use #%s <filename.h>",
+                  name, name);
+
+      /* Rewrite the token to <xyz.h>.  */
+      CPP_RESERVE (pfile, 4);
+      len += 4;
+      memmove (pfile->token_buffer + old_written + 1,
+              pfile->token_buffer + old_written,
+              CPP_WRITTEN (pfile) - old_written);
+      pfile->token_buffer[old_written] = '<';
+      CPP_PUTS_Q (pfile, ".h>", 2);
     }
 #endif
   else
     {
-      cpp_error (pfile,
-                "`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
+      cpp_error (pfile, "`#%s' expects \"FILENAME\" or <FILENAME>", name);
       CPP_SET_WRITTEN (pfile, old_written);
       _cpp_skip_rest_of_line (pfile);
       return 0;
     }
 
-  flen = CPP_WRITTEN (pfile) - old_written;
-  ftok = (unsigned char *) alloca (flen + 1);
-  memcpy (ftok, pfile->token_buffer + old_written, flen);
-  ftok[flen] = '\0';
+  CPP_NUL_TERMINATE (pfile);
+  CPP_ADJUST_WRITTEN (pfile, 1);
 
   if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
     {
-      cpp_error (pfile, "junk at end of `#include'");
+      cpp_error (pfile, "junk at end of `#%s'", name);
       _cpp_skip_rest_of_line (pfile);
     }
 
   CPP_SET_WRITTEN (pfile, old_written);
 
-  if (flen == 0)
-    {
-      cpp_error (pfile, "empty file name in `#%s'", keyword->name);
-      return 0;
-    }
+  if (len == 0)
+    cpp_error (pfile, "empty file name in `#%s'", name);
 
-  if (CPP_OPTIONS (pfile)->dump_includes)
-    pass_thru_directive (ftok,
-                        flen
-#ifdef VMS
-         - ((token == CPP_NAME) ? 2 : 0)
-#endif
-                        , pfile, keyword);
+  return len;
+}
 
-#ifdef VMS
-  if (token == CPP_STRING)
-#endif
-    {
-      ftok++;
-      flen -= 2;
-      ftok[flen] = '\0';
-    }
+static int
+do_include (pfile)
+     cpp_reader *pfile;
+{
+  unsigned int len;
+  char *token;
 
-  search_start = 0;
+  len = parse_include (pfile, dtable[T_INCLUDE].name);
+  token = alloca (len + 1);
+  strcpy (token, CPP_PWRITTEN (pfile));
+  
+  if (CPP_OPTIONS (pfile)->dump_includes)
+    pass_thru_directive (token, len, pfile, T_INCLUDE);
 
-  fp = cpp_file_buffer (pfile);
+  _cpp_execute_include (pfile, token, len, 0, 0);
+  return 0;
+}
 
-  /* For #include_next, skip in the search path past the dir in which the
-     containing file was found.  Treat files specified using an absolute path
-     as if there are no more directories to search.  Treat the primary source
-     file like any other included source, but generate a warning.  */
-  if (skip_dirs && CPP_PREV_BUFFER (fp))
-    {
-      if (fp->ihash->foundhere != ABSOLUTE_PATH)
-       search_start = fp->ihash->foundhere->next;
-    }
-  else
-    {
-      if (skip_dirs)
-       cpp_warning (pfile, "#include_next in primary source file");
-      
-      if (angle_brackets)
-       search_start = CPP_OPTIONS (pfile)->bracket_include;
-      else
-        {
-         if (!CPP_OPTIONS (pfile)->ignore_srcdir)
-           {
-             if (fp)
-               search_start = fp->actual_dir;
-           }
-         else
-           search_start = CPP_OPTIONS (pfile)->quote_include;
-       }
-    }
+static int
+do_import (pfile)
+     cpp_reader *pfile;
+{
+  unsigned int len;
+  char *token;
+
+  if (CPP_PEDANTIC (pfile))
+    cpp_pedwarn (pfile, "ANSI C does not allow `#import'");
 
-  if (!search_start)
+  if (CPP_OPTIONS (pfile)->warn_import
+      && !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
     {
-      cpp_error (pfile, "No include path in which to find %s", ftok);
-      return 0;
+      pfile->import_warning = 1;
+      cpp_warning (pfile,
+          "#import is obsolete, use an #ifndef wrapper in the header file");
     }
 
-  fd = _cpp_find_include_file (pfile, ftok, search_start, &ihash, &before);
-
-  if (fd == -2)
-    return 0;
+  len = parse_include (pfile, dtable[T_IMPORT].name);
+  token = alloca (len + 1);
+  strcpy (token, CPP_PWRITTEN (pfile));
   
-  if (fd == -1)
-    {
-      if (CPP_OPTIONS (pfile)->print_deps_missing_files
-         && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
-                                      (pfile->system_include_depth > 0)))
-        {
-         if (!angle_brackets)
-           deps_add_dep (pfile->deps, ftok);
-         else
-           {
-             char *p;
-             struct file_name_list *ptr;
-             /* If requested as a system header, assume it belongs in
-                the first system header directory. */
-             if (CPP_OPTIONS (pfile)->bracket_include)
-               ptr = CPP_OPTIONS (pfile)->bracket_include;
-             else
-               ptr = CPP_OPTIONS (pfile)->quote_include;
-
-             p = (char *) alloca (strlen (ptr->name)
-                                  + strlen (ftok) + 2);
-             if (*ptr->name != '\0')
-               {
-                 strcpy (p, ptr->name);
-                 strcat (p, "/");
-               }
-             strcat (p, ftok);
-             deps_add_dep (pfile->deps, p);
-           }
-       }
-      /* If -M was specified, and this header file won't be added to
-        the dependency list, then don't count this as an error,
-        because we can still produce correct output.  Otherwise, we
-        can't produce correct output, because there may be
-        dependencies we need inside the missing file, and we don't
-        know what directory this missing file exists in. */
-      else if (CPP_PRINT_DEPS (pfile)
-              && (CPP_PRINT_DEPS (pfile)
-                  <= (angle_brackets || (pfile->system_include_depth > 0))))
-       cpp_warning (pfile, "No include path in which to find %s", ftok);
-      else
-       cpp_error_from_errno (pfile, ftok);
-
-      return 0;
-    }
+  if (CPP_OPTIONS (pfile)->dump_includes)
+    pass_thru_directive (token, len, pfile, T_IMPORT);
 
-  /* For -M, add the file to the dependencies on its first inclusion. */
-  if (!before && (CPP_PRINT_DEPS (pfile)
-                 > (angle_brackets || (pfile->system_include_depth > 0))))
-    deps_add_dep (pfile->deps, ihash->name);
+  _cpp_execute_include (pfile, token, len, 1, 0);
+  return 0;
+}
 
-  /* Handle -H option.  */
-  if (CPP_OPTIONS(pfile)->print_include_names)
-    {
-      fp = CPP_BUFFER (pfile);
-      while ((fp = CPP_PREV_BUFFER (fp)) != NULL)
-       putc ('.', stderr);
-      fprintf (stderr, " %s\n", ihash->name);
-    }
+static int
+do_include_next (pfile)
+     cpp_reader *pfile;
+{
+  unsigned int len;
+  char *token;
+  struct file_name_list *search_start = 0;
 
-  /* Actually process the file */
+  if (CPP_PEDANTIC (pfile))
+    cpp_pedwarn (pfile, "ANSI C does not allow `#include_next'");
+  
+  len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name);
 
-  if (importing)
-    ihash->control_macro = (const U_CHAR *) "";
+  token = alloca (len + 1);
+  strcpy (token, CPP_PWRITTEN (pfile));
   
-  if (_cpp_read_include_file (pfile, fd, ihash))
+  if (CPP_OPTIONS (pfile)->dump_includes)
+    pass_thru_directive (token, len, pfile, T_INCLUDE_NEXT);
+
+  /* For #include_next, skip in the search path past the dir in which the
+     containing file was found.  Treat files specified using an absolute path
+     as if there are no more directories to search.  Treat the primary source
+     file like any other included source, but generate a warning.  */
+  if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)))
     {
-      _cpp_output_line_command (pfile, enter_file);
-      if (angle_brackets)
-       pfile->system_include_depth++;   /* Decremented in file_cleanup. */
+      if (CPP_BUFFER (pfile)->ihash->foundhere != ABSOLUTE_PATH)
+       search_start = CPP_BUFFER (pfile)->ihash->foundhere->next;
     }
+  else
+    cpp_warning (pfile, "#include_next in primary source file");
+
+  _cpp_execute_include (pfile, token, len, 0, search_start);
   return 0;
 }
 
@@ -704,9 +616,8 @@ read_line_number (pfile, num)
    include filename.  That means no escape handling.  */
 
 static int
-do_line (pfile, keyword)
+do_line (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   cpp_buffer *ip = CPP_BUFFER (pfile);
   int new_lineno;
@@ -823,9 +734,8 @@ do_line (pfile, keyword)
    According to the C standard, it is not an error to undef
    something that has no definitions. */
 static int
-do_undef (pfile, keyword)
+do_undef (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword;
 {
   int len;
   HASHNODE **slot;
@@ -867,8 +777,8 @@ do_undef (pfile, keyword)
       HASHNODE *hp = *slot;
       /* If we are generating additional info for debugging (with -g) we
         need to pass through all effective #undef commands.  */
-      if (CPP_OPTIONS (pfile)->debug_output && keyword)
-       pass_thru_directive (name, len, pfile, keyword);
+      if (CPP_OPTIONS (pfile)->debug_output)
+       pass_thru_directive (name, len, pfile, T_UNDEF);
       if (hp->type == T_POISON)
        cpp_error (pfile, "cannot undefine poisoned `%s'", hp->name);
       else 
@@ -890,9 +800,8 @@ do_undef (pfile, keyword)
  */
 
 static int
-do_error (pfile, keyword)
+do_error (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   const U_CHAR *text, *limit;
 
@@ -911,9 +820,8 @@ do_error (pfile, keyword)
  */
 
 static int
-do_warning (pfile, keyword)
+do_warning (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   const U_CHAR *text, *limit;
 
@@ -932,9 +840,8 @@ do_warning (pfile, keyword)
 /* Report program identification.  */
 
 static int
-do_ident (pfile, keyword)
+do_ident (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   long old_written = CPP_WRITTEN (pfile);
 
@@ -977,9 +884,8 @@ static int do_pragma_poison         PARAMS ((cpp_reader *));
 static int do_pragma_default           PARAMS ((cpp_reader *));
 
 static int
-do_pragma (pfile, keyword)
+do_pragma (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   long here, key;
   U_CHAR *buf;
@@ -1154,20 +1060,21 @@ do_pragma_poison (pfile)
   return !writeit;
 }
  
-#ifdef SCCS_DIRECTIVE
 /* Just ignore #sccs, on systems where we define it at all.  */
-
 static int
-do_sccs (pfile, keyword)
+do_sccs (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
+#ifdef SCCS_DIRECTIVE
   if (CPP_PEDANTIC (pfile))
     cpp_pedwarn (pfile, "ANSI C does not allow `#sccs'");
+#else
+  cpp_error (pfile, "undefined or invalid # directive `sccs'");
+#endif
   _cpp_skip_rest_of_line (pfile);
   return 0;
 }
-#endif
+
 
 /* We've found an `#if' directive.  If the only thing before it in
    this file is white space, and if it is of the form
@@ -1249,9 +1156,8 @@ detect_if_not_defined (pfile)
  */
 
 static int
-do_if (pfile, keyword)
+do_if (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   U_CHAR *control_macro = detect_if_not_defined (pfile);
   int value = _cpp_parse_expr (pfile);
@@ -1265,9 +1171,8 @@ do_if (pfile, keyword)
  */
 
 static int
-do_elif (pfile, keyword)
+do_elif (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
     {
@@ -1276,7 +1181,7 @@ do_elif (pfile, keyword)
     }
   else
     {
-      if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
+      if (pfile->if_stack->type == T_ELSE)
        {
          cpp_error (pfile, "`#elif' after `#else'");
          cpp_error_with_line (pfile, pfile->if_stack->lineno, -1,
@@ -1300,72 +1205,90 @@ do_elif (pfile, keyword)
   return 0;
 }
 
-/*
- * routine to handle ifdef/ifndef.  Try to look up the symbol,
- * then do or don't skip to the #endif/#else/#elif depending
- * on what directive is actually being processed.
- */
+/* Parse an #ifdef or #ifndef directive.  Returns 1 for defined, 0 for
+   not defined; the macro tested is left in the token buffer (but
+   popped).  */
 
 static int
-do_ifdef (pfile, keyword)
+parse_ifdef (pfile, name)
      cpp_reader *pfile;
-     const struct directive *keyword;
+     const char *name;
 {
-  int skip;
   U_CHAR *ident;
-  int ident_length;
+  unsigned int len;
   enum cpp_token token;
-  int start_of_file = 0;
-  U_CHAR *control_macro = 0;
-  int old_written = CPP_WRITTEN (pfile);
-
-  /* Detect a #ifndef at start of file (not counting comments).  */
-  if (keyword->type == T_IFNDEF)
-    start_of_file = pfile->only_seen_white == 2;
+  long old_written = CPP_WRITTEN (pfile);
+  int defined;
 
   pfile->no_macro_expand++;
   token = _cpp_get_directive_token (pfile);
   pfile->no_macro_expand--;
 
   ident = pfile->token_buffer + old_written;
-  ident_length = CPP_WRITTEN (pfile) - old_written;
-  CPP_SET_WRITTEN (pfile, old_written); /* Pop */
+  len = CPP_WRITTEN (pfile) - old_written;
 
-  if (token == CPP_VSPACE || token == CPP_POP || token == CPP_EOF)
+  if (token == CPP_VSPACE)
     {
-      skip = (keyword->type == T_IFDEF);
       if (! CPP_TRADITIONAL (pfile))
-       cpp_pedwarn (pfile, "`#%s' with no argument", keyword->name);
+       cpp_pedwarn (pfile, "`#%s' with no argument", name);
+      defined = 0;
+      goto done;
     }
   else if (token == CPP_NAME)
     {
-      skip = cpp_defined (pfile, ident, ident_length);
-      if (keyword->type == T_IFDEF)
-       skip = !skip;
-
-      if (start_of_file && !skip)
-       {
-         control_macro = (U_CHAR *) xmalloc (ident_length + 1);
-         memcpy (control_macro, ident, ident_length + 1);
-       }
+      defined = cpp_defined (pfile, ident, len);
+      CPP_NUL_TERMINATE (pfile);
+      CPP_ADJUST_WRITTEN (pfile, 1);
     }
   else
     {
-      skip = (keyword->type == T_IFDEF);
+      defined = 0;
       if (! CPP_TRADITIONAL (pfile))
-       cpp_error (pfile, "`#%s' with invalid argument", keyword->name);
+       cpp_error (pfile, "`#%s' with invalid argument", name);
     }
 
   if (!CPP_TRADITIONAL (pfile))
-    { int c;
-      _cpp_skip_hspace (pfile);
-      c = PEEKC ();
-      if (c != EOF && c != '\n')
-       cpp_pedwarn (pfile, "garbage at end of `#%s' argument", keyword->name);
+    {
+      if (_cpp_get_directive_token (pfile) == CPP_VSPACE)
+       goto done;
+      
+      cpp_pedwarn (pfile, "garbage at end of `#%s' argument", name);
     }
   _cpp_skip_rest_of_line (pfile);
+  
+ done:
+  CPP_SET_WRITTEN (pfile, old_written); /* Pop */
+  return defined;
+}
 
-  conditional_skip (pfile, skip, T_IF, control_macro);
+/* #ifdef is dead simple.  */
+
+static int
+do_ifdef (pfile)
+     cpp_reader *pfile;
+{
+  int skip = ! parse_ifdef (pfile, dtable[T_IFDEF].name);
+  conditional_skip (pfile, skip, T_IFDEF, 0);
+  return 0;
+}
+
+/* #ifndef is a tad more complex, because we need to check for a
+   no-reinclusion wrapper.  */
+
+static int
+do_ifndef (pfile)
+     cpp_reader *pfile;
+{
+  int start_of_file, skip;
+  U_CHAR *control_macro = 0;
+
+  start_of_file = pfile->only_seen_white == 2;
+  skip = parse_ifdef (pfile, dtable[T_IFNDEF].name);
+
+  if (start_of_file && !skip)
+    control_macro = xstrdup (CPP_PWRITTEN (pfile));
+
+  conditional_skip (pfile, skip, T_IFNDEF, control_macro);
   return 0;
 }
 
@@ -1378,7 +1301,7 @@ static void
 conditional_skip (pfile, skip, type, control_macro)
      cpp_reader *pfile;
      int skip;
-     enum node_type type;
+     int type;
      U_CHAR *control_macro;
 {
   IF_STACK *temp;
@@ -1410,60 +1333,65 @@ consider_directive_while_skipping (pfile, stack)
     cpp_reader *pfile;
     IF_STACK *stack; 
 {
-  long ident_len, ident;
+  long ident;
   const struct directive *kt;
+  int i;
+  unsigned int len;
   IF_STACK *temp;
     
   _cpp_skip_hspace (pfile);
 
   ident = CPP_WRITTEN (pfile);
   _cpp_parse_name (pfile, GETC());
-  ident_len = CPP_WRITTEN (pfile) - ident;
+  len = CPP_WRITTEN (pfile) - ident;
 
   CPP_SET_WRITTEN (pfile, ident);
 
-  for (kt = directive_table; kt->length >= 0; kt++)
-    if (kt->length == ident_len
-       && strncmp (pfile->token_buffer + ident, kt->name, kt->length) == 0)
-      switch (kt->type)
-       {
-       case T_IF:
-       case T_IFDEF:
-       case T_IFNDEF:
+  for (i = 0; i < N_DIRECTIVES; i++)
+    {
+      kt = &dtable[i];
+      if (kt->length == len
+         && strncmp (pfile->token_buffer + ident, kt->name, kt->length) == 0)
+       switch (i)
+         {
+         case T_IF:
+         case T_IFDEF:
+         case T_IFNDEF:
            temp = (IF_STACK *) xmalloc (sizeof (IF_STACK));
            temp->next = pfile->if_stack;
            pfile->if_stack = temp;
-           temp->type = kt->type;
+           temp->type = i;
            return 0;
 
-       case T_ELSE:
+         case T_ELSE:
            if (pfile->if_stack != stack)
-             validate_else (pfile, "#else");
+             validate_else (pfile, dtable[i].name);
            /* fall through */
-       case T_ELIF:
+         case T_ELIF:
            if (pfile->if_stack == stack)
              return 1;
            else
              {
-               pfile->if_stack->type = kt->type;
+               pfile->if_stack->type = i;
                return 0;
              }
 
-           case T_ENDIF:
-               if (pfile->if_stack != stack)
-                 validate_else (pfile, "#endif");
+         case T_ENDIF:
+           if (pfile->if_stack != stack)
+             validate_else (pfile, dtable[i].name);
 
-               if (pfile->if_stack == stack)
-                 return 1;
+           if (pfile->if_stack == stack)
+             return 1;
                    
-               temp = pfile->if_stack;
-               pfile->if_stack = temp->next;
-               free (temp);
-               return 0;
+           temp = pfile->if_stack;
+           pfile->if_stack = temp->next;
+           free (temp);
+           return 0;
 
-           default:
-               return 0;
-           }
+         default:
+           return 0;
+         }
+    }
 
     /* Don't let erroneous code go by. */
     if (!CPP_OPTIONS (pfile)->lang_asm && CPP_PEDANTIC (pfile))
@@ -1529,11 +1457,10 @@ skip_if_group (pfile)
  */
 
 static int
-do_else (pfile, keyword)
+do_else (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  validate_else (pfile, "#else");
+  validate_else (pfile, dtable[T_ELSE].name);
   _cpp_skip_rest_of_line (pfile);
 
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
@@ -1547,7 +1474,7 @@ do_else (pfile, keyword)
         if it has a #else clause.  */
       pfile->if_stack->control_macro = 0;
 
-      if (pfile->if_stack->type != T_IF && pfile->if_stack->type != T_ELIF)
+      if (pfile->if_stack->type == T_ELSE)
        {
          cpp_error (pfile, "`#else' after `#else'");
          cpp_error_with_line (pfile, pfile->if_stack->lineno, -1,
@@ -1571,11 +1498,10 @@ do_else (pfile, keyword)
  */
 
 static int
-do_endif (pfile, keyword)
+do_endif (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  validate_else (pfile, "#endif");
+  validate_else (pfile, dtable[T_ENDIF].name);
   _cpp_skip_rest_of_line (pfile);
 
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
@@ -1631,26 +1557,7 @@ validate_else (pfile, directive)
   _cpp_skip_hspace (pfile);
   if (PEEKC () != '\n')
     cpp_pedwarn (pfile,
-                "text following `%s' violates ANSI standard", directive);
-}
-
-/* Convert T_IF, etc. to a string.   Used in error messages.  */
-static const char *
-if_directive_name (pfile, ifs)
-     cpp_reader *pfile;
-     struct if_stack *ifs;
-{
-  switch (ifs->type)
-    {
-    case T_IF:     return "#if";
-    case T_IFDEF:   return "#ifdef";
-    case T_IFNDEF:  return "#ifndef";
-    case T_ELIF:    return "#elif";
-    case T_ELSE:    return "#else";
-    default:
-      cpp_ice (pfile, "impossible if_stack->type value %d", ifs->type);
-      return "unknown";
-    }
+                "text following `#%s' violates ANSI standard", directive);
 }
 
 void
@@ -1666,8 +1573,8 @@ _cpp_handle_eof (pfile)
        ifs = nifs)
     {
       cpp_error_with_line (pfile, ifs->lineno, -1,
-                          "unterminated `%s' conditional",
-                          if_directive_name (pfile, ifs));
+                          "unterminated `#%s' conditional",
+                          dtable[ifs->type].name);
 
       nifs = ifs->next;
       free (ifs);
@@ -1690,9 +1597,8 @@ _cpp_handle_eof (pfile)
 }
 
 static int
-do_assert (pfile, keyword)
+do_assert (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   U_CHAR *sym;
   int ret, c;
@@ -1759,9 +1665,8 @@ do_assert (pfile, keyword)
 }
 
 static int
-do_unassert (pfile, keyword)
+do_unassert (pfile)
      cpp_reader *pfile;
-     const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   int c, ret;
   U_CHAR *sym;
@@ -1866,7 +1771,7 @@ cpp_define (pfile, str)
 
   if (cpp_push_buffer (pfile, buf, count - 1) != NULL)
     {
-      do_define (pfile, NULL);
+      do_define (pfile);
       cpp_pop_buffer (pfile);
     }
 }
@@ -1885,7 +1790,7 @@ cpp_undef (pfile, macro)
   buf[len + 1] = '\0';
   if (cpp_push_buffer (pfile, buf, len + 1))
     {
-      do_undef (pfile, NULL);
+      do_undef (pfile);
       cpp_pop_buffer (pfile);
     }
 }
@@ -1898,7 +1803,7 @@ cpp_assert (pfile, str)
 {
   if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
     {
-      do_assert (pfile, NULL);
+      do_assert (pfile);
       cpp_pop_buffer (pfile);
     }
 }
@@ -1911,7 +1816,7 @@ cpp_unassert (pfile, str)
 {
   if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
     {
-      do_unassert (pfile, NULL);
+      do_unassert (pfile);
       cpp_pop_buffer (pfile);
     }
 }