OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tradcpp.c
index ff43902..2c47a69 100644 (file)
@@ -24,6 +24,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "version.h"
 #include "cppdefault.h"
 #include "tradcpp.h"
+#include "mkdeps.h"
 
 typedef unsigned char U_CHAR;
 
@@ -40,12 +41,23 @@ size_t max_include_len;
 
 int put_out_comments = 0;
 
+/* mkdeps.h opaque structure that encapsulates dependency information.  */
+struct deps *deps;
+
 /* Nonzero means print the names of included files rather than
    the preprocessed output.  1 means just the #include "...",
    2 means #include <...> as well.  */
 
 int print_deps = 0;
 
+/* Nonzero means print dummy targets for each header file.  */
+
+int print_deps_phony_targets = 0;
+
+/* If true, fopen (deps_file, "a") else fopen (deps_file, "w").  */
+
+int deps_append = 0;
+
 /* File name which deps are being written to.  This is 0 if deps are
    being written to stdout.  */
 
@@ -54,7 +66,7 @@ const char *deps_file = 0;
 /* Nonzero if missing .h files in -M output are assumed to be
    generated files and not errors.  */
 
-int print_deps_missing_files = 0;
+int deps_missing_files = 0;
        
 /* Nonzero means don't output line number information.  */
 
@@ -70,6 +82,9 @@ int dump_macros;
 
 int inhibit_warnings = 0;
 
+/* Non-0 means don't output the preprocessed program.  */
+int inhibit_output = 0;
+
 /* Nonzero means warn if slash-star appears in a comment.  */
 
 int warn_comments;
@@ -90,6 +105,7 @@ static const char *user_label_prefix;
    It is zero for rescanning results of macro expansion
    and for expanding macro arguments.  */
 #define INPUT_STACK_MAX 200
+struct file_name_list;
 struct file_buf {
   const char *fname;
   int lineno;
@@ -105,6 +121,8 @@ struct file_buf {
   struct if_stack *if_stack;
   /* Object to be freed at end of input at this level.  */
   U_CHAR *free_ptr;
+  /* Position to start scanning for #include_next in this file.  */
+  struct file_name_list *next_header_dir;
 } instack[INPUT_STACK_MAX];
 
 typedef struct file_buf FILE_BUF;
@@ -225,6 +243,7 @@ union hashval {
 enum node_type {
  T_DEFINE = 1, /* `#define' */
  T_INCLUDE,    /* `#include' */
+ T_INCLUDE_NEXT,/* `#include_next' */
  T_IFDEF,      /* `#ifdef' */
  T_IFNDEF,     /* `#ifndef' */
  T_IF,         /* `#if' */
@@ -343,6 +362,7 @@ static void do_error        PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void do_warning PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void do_line    PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void do_include PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
+static void do_include_next    PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void do_undef   PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void do_if      PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void do_ifdef   PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
@@ -390,6 +410,7 @@ static void output_line_command PARAMS ((FILE_BUF *, FILE_BUF *,
 
 static int eval_if_expression  PARAMS ((const U_CHAR *, int));
 
+static void output_deps                PARAMS ((void));
 static void initialize_builtins        PARAMS ((void));
 static void run_directive      PARAMS ((const char *, size_t,
                                         enum node_type));
@@ -399,8 +420,11 @@ static void make_assertion PARAMS ((const char *));
 
 static void grow_outbuf        PARAMS ((FILE_BUF *, int));
 static int handle_directive    PARAMS ((FILE_BUF *, FILE_BUF *));
-static void finclude           PARAMS ((int, const char *, FILE_BUF *));
-static void deps_output                PARAMS ((const char *, int));
+static void process_include    PARAMS ((struct file_name_list *,
+                                        const U_CHAR *, int, int, FILE_BUF *));
+static void finclude           PARAMS ((int, const char *,
+                                        struct file_name_list *, FILE_BUF *));
+static void init_dependency_output PARAMS ((void));
 static void rescan             PARAMS ((FILE_BUF *, int));
 static void newline_fix                PARAMS ((U_CHAR *));
 static void name_newline_fix   PARAMS ((U_CHAR *));
@@ -434,6 +458,7 @@ struct directive directive_table[] = {
   {  4, do_elif,    "elif",    T_ELIF    },
   {  5, do_error,   "error",   T_ERROR   },
   {  7, do_warning, "warning", T_WARNING },
+  { 12, do_include_next, "include_next", T_INCLUDE_NEXT },
   {  6, do_assert,  "assert",  T_ASSERT  },
   {  8, do_unassert,"unassert",T_UNASSERT},
   {  -1, 0, "", T_UNUSED},
@@ -462,19 +487,6 @@ struct if_stack {
 typedef struct if_stack IF_STACK_FRAME;
 IF_STACK_FRAME *if_stack = NULL;
 
-/* Buffer of -M output.  */
-
-char *deps_buffer;
-
-/* Number of bytes allocated in above.  */
-int deps_allocated_size;
-
-/* Number of bytes used.  */
-int deps_size;
-
-/* Number of bytes since the last newline.  */
-int deps_column;
-
 /* Nonzero means -I- has been seen,
    so don't look for #include "foo" the source-file directory.  */
 int ignore_srcdir;
@@ -502,14 +514,6 @@ main (argc, argv)
   pending_dir *pend = (pending_dir *) xcalloc (argc, sizeof (pending_dir));
   int no_standard_includes = 0;
 
-  /* Non-0 means don't output the preprocessed program.  */
-  int inhibit_output = 0;
-
-  /* Stream on which to print the dependency information.  */
-  FILE *deps_stream = 0;
-  /* Target-name to write with the dependency information.  */
-  char *deps_target = 0;
-
 #ifdef RLIMIT_STACK
   /* Get rid of any avoidable limit on stack size.  */
   {
@@ -534,6 +538,10 @@ main (argc, argv)
 
   max_include_len = cpp_GCC_INCLUDE_DIR_len + 7;  /* ??? */
 
+  /* It's simplest to just create this struct whether or not it will
+     be needed.  */
+  deps = deps_init ();
+
   /* Process switches and find input file name.  */
 
   for (i = 1; i < argc; i++) {
@@ -550,7 +558,6 @@ main (argc, argv)
       switch (c) {
       case 'E':
       case '$':
-      case 'g':
        break;  /* Ignore for compatibility with ISO/extended cpp.  */
 
       case 'l':
@@ -621,6 +628,12 @@ main (argc, argv)
        {
          char *p = NULL;
 
+         /* -MD and -MMD for tradcpp are deprecated and undocumented
+            (use -M or -MM with -MF instead), and probably should be
+            removed with the next major GCC version.  For the moment
+            we allow these for the benefit of Automake 1.4, which
+            uses these when dependency tracking is enabled.  Automake
+            1.5 will fix this.  */
          if (!strncmp (argv[i], "-MD", 3)) {
            p = argv[i] + 3;
            print_deps = 2;
@@ -629,12 +642,30 @@ main (argc, argv)
            print_deps = 1;
          } else if (!strcmp (argv[i], "-M")) {
            print_deps = 2;
-           inhibit_output = 1;
          } else if (!strcmp (argv[i], "-MM")) {
            print_deps = 1;
-           inhibit_output = 1;
-         } else if (!strcmp (argv[i], "-MG"))
-           print_deps_missing_files = 1;
+         } else if (!strcmp (argv[i], "-MG")) {
+           deps_missing_files = 1;
+         } else if (!strcmp (argv[i], "-MF")) {
+           p = argv[i] + 3;
+         } else if (!strcmp (argv[i], "-MP")) {
+           print_deps_phony_targets = 1;
+         } else if (!strcmp (argv[i], "-MQ") || !strcmp (argv[i], "-MT")) {
+           /* Add a target.  -MQ quotes for Make.  */
+           const char *tgt = argv[i] + 3;
+           int quoted = argv[i][2] == 'Q';
+
+           if (*tgt == '\0' && i + 1 == argc)
+             fatal ("Target missing after %s option", argv[i]);
+           else
+             {
+               if (*tgt == '\0')
+                 tgt = argv[++i];
+             
+               deps_add_target (deps, tgt, quoted);
+             }
+         }
+
          if (p) {
            if (*p)
              deps_file = p;
@@ -747,12 +778,26 @@ main (argc, argv)
     }
   }
 
-  if (print_deps_missing_files && (!print_deps || !inhibit_output))
-    fatal ("-MG must be specified with one of -M or -MM");
+  init_dependency_output ();
+
+  /* After checking the environment variables, check if -M or -MM has
+     not been specified, but other -M options have.  */
+  if (print_deps == 0
+      && (deps_missing_files || deps_file || print_deps_phony_targets))
+    fatal ("you must additionally specify either -M or -MM");
 
   if (user_label_prefix == 0)
     user_label_prefix = USER_LABEL_PREFIX;
 
+  if (print_deps)
+    {
+      /* Set the default target (if there is none already), and
+        the dependency on the main file.  */
+      deps_add_default_target (deps, in_fname);
+
+      deps_add_dep (deps, in_fname);
+    }
+
   /* Install __LINE__, etc.  Must follow option processing.  */
   initialize_builtins ();
 
@@ -812,7 +857,12 @@ main (argc, argv)
            perror_with_name (pend[i].arg);
            return FATAL_EXIT_CODE;
          }
-       finclude (fd, pend[i].arg, &outbuf);
+
+       /* For -M, add this file to the dependencies.  */
+       if (print_deps)
+         deps_add_dep (deps, pend[i].arg);
+
+       finclude (fd, pend[i].arg, 0, &outbuf);
       }
   indepth--;
   no_output--;
@@ -832,96 +882,6 @@ main (argc, argv)
   } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0)
     goto sys_error;
 
-  /* Either of two environment variables can specify output of deps.
-     Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
-     where OUTPUT_FILE is the file to write deps info to
-     and DEPS_TARGET is the target to mention in the deps.  */
-
-  if (print_deps == 0
-      && (getenv ("SUNPRO_DEPENDENCIES") != 0
-         || getenv ("DEPENDENCIES_OUTPUT") != 0))
-    {
-      char *spec = getenv ("DEPENDENCIES_OUTPUT");
-      char *s;
-
-      if (spec == 0)
-       {
-         spec = getenv ("SUNPRO_DEPENDENCIES");
-         print_deps = 2;
-       }
-      else
-       print_deps = 1;
-
-      /* Find the space before the DEPS_TARGET, if there is one.  */
-      s = strchr (spec, ' ');
-      if (s)
-       {
-         char *out_file;
-
-         deps_target = s + 1;
-         out_file = (char *) xmalloc (s - spec + 1);
-         memcpy (out_file, spec, s - spec);
-         out_file[s - spec] = 0;
-         deps_file = out_file;
-       }
-      else
-       {
-         deps_target = 0;
-         deps_file = spec;
-       }
-    }
-
-  /* For -M, print the expected object file name
-     as the target of this Make-rule.  */
-  if (print_deps) {
-
-    if (deps_file) {
-      deps_stream = fopen (deps_file, "a");
-      if (deps_stream == 0)
-       pfatal_with_name (deps_file);
-    } else
-      /* If the -M option was used, output the deps to standard output.  */
-      deps_stream = stdout;
-
-    deps_allocated_size = 200;
-    deps_buffer = (char *) xmalloc (deps_allocated_size);
-    deps_buffer[0] = 0;
-    deps_size = 0;
-    deps_column = 0;
-
-    if (deps_target) {
-      deps_output (deps_target, 0);
-      deps_output (":", 0);
-    } else if (*in_fname == 0)
-      deps_output ("-: ", 0);
-    else {
-      int len;
-      const char *p = in_fname;
-      const char *p1 = p;
-      /* Discard all directory prefixes from P.  */
-      while (*p1) {
-       if (*p1 == '/')
-         p = p1 + 1;
-       p1++;
-      }
-      /* Output P, but remove known suffixes.  */
-      len = strlen (p);
-      if (p[len - 2] == '.'
-         && (p[len - 1] == 'c' || p[len - 1] == 'C' || p[len - 1] == 'S'))
-       deps_output (p, len - 2);
-      else if (p[len - 3] == '.'
-              && p[len - 2] == 'c'
-              && p[len - 1] == 'c')
-       deps_output (p, len - 3);
-      else
-       deps_output (p, 0);
-      /* Supply our own suffix.  */
-      deps_output (".o : ", 0);
-      deps_output (in_fname, 0);
-      deps_output (" ", 0);
-    }
-  }
-
   if (file_size_and_mode (f, &st_mode, &st_size))
     goto sys_error;
   fp->fname = in_fname;
@@ -998,20 +958,16 @@ main (argc, argv)
 
   if (dump_macros)
     dump_all_macros ();
-  else if (! inhibit_output && deps_stream != stdout) {
+  else if (! inhibit_output)
     if (write (fileno (stdout), outbuf.buf, outbuf.bufp - outbuf.buf) < 0)
       fatal ("I/O error on output");
-  }
 
-  if (print_deps) {
-    fputs (deps_buffer, deps_stream);
-    putc ('\n', deps_stream);
-    if (deps_stream != stdout) {
-      fclose (deps_stream);
-      if (ferror (deps_stream))
-       fatal ("I/O error on output");
-    }
-  }
+  /* Don't write the deps file if preprocessing has failed.  */
+  if (print_deps && errors == 0)
+    output_deps ();
+
+  /* Destruct the deps object.  */
+  deps_free (deps);
 
   if (ferror (stdout))
     fatal ("I/O error on output");
@@ -1024,6 +980,91 @@ main (argc, argv)
   pfatal_with_name (in_fname);
 }
 
+/* Set up dependency-file output.  */
+static void
+init_dependency_output ()
+{
+  char *spec, *s, *output_file;
+
+  /* Either of two environment variables can specify output of deps.
+     Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
+     where OUTPUT_FILE is the file to write deps info to
+     and DEPS_TARGET is the target to mention in the deps.  */
+
+  if (print_deps == 0)
+    {
+      spec = getenv ("DEPENDENCIES_OUTPUT");
+      if (spec)
+       print_deps = 1;
+      else
+       {
+         spec = getenv ("SUNPRO_DEPENDENCIES");
+         if (spec)
+           print_deps = 2;
+         else
+           return;
+       }
+
+      /* Find the space before the DEPS_TARGET, if there is one.  */
+      s = strchr (spec, ' ');
+      if (s)
+       {
+         /* Let the caller perform MAKE quoting.  */
+         deps_add_target (deps, s + 1, 0);
+         output_file = (char *) xmalloc (s - spec + 1);
+         memcpy (output_file, spec, s - spec);
+         output_file[s - spec] = 0;
+       }
+      else
+       output_file = spec;
+
+      /* Command line overrides environment variables.  */
+      if (deps_file == 0)
+       deps_file = output_file;
+      deps_append = 1;
+    }
+
+  /* If dependencies go to standard output, or -MG is used, we should
+     suppress output.  The user may be requesting other stuff to
+     stdout, with -dM, -v etc.  We let them shoot themselves in the
+     foot.  */
+  if (deps_file == 0 || deps_missing_files)
+    inhibit_output = 1;
+}
+
+/* Use mkdeps.c to output dependency information.  */
+static void
+output_deps ()
+{
+  /* Stream on which to print the dependency information.  */
+  FILE *deps_stream = 0;
+  const char *const deps_mode = deps_append ? "a" : "w";
+
+  if (deps_file == 0)
+    deps_stream = stdout;
+  else
+    {
+      deps_stream = fopen (deps_file, deps_mode);
+      if (deps_stream == 0)
+       {
+         error_from_errno (deps_file);
+         return;
+       }
+    }
+
+  deps_write (deps, deps_stream, 72);
+
+  if (print_deps_phony_targets)
+    deps_phony_targets (deps, deps_stream);
+
+  /* Don't close stdout.  */
+  if (deps_file)
+    {
+      if (ferror (deps_stream) || fclose (deps_stream) != 0)
+       fatal ("I/O error on output");
+    }
+}
+
 /* Move all backslash-newline pairs out of embarrassing places.
    Exchange all such pairs following BP
    with any potentially-embarrasing characters that follow them.
@@ -1034,8 +1075,8 @@ static void
 newline_fix (bp)
      U_CHAR *bp;
 {
-  register U_CHAR *p = bp;
-  register int count = 0;
+  U_CHAR *p = bp;
+  int count = 0;
 
   /* First count the backslash-newline pairs here.  */
 
@@ -1069,8 +1110,8 @@ static void
 name_newline_fix (bp)
      U_CHAR *bp;
 {
-  register U_CHAR *p = bp;
-  register int count = 0;
+  U_CHAR *p = bp;
+  int count = 0;
 
   /* First count the backslash-newline pairs here.  */
 
@@ -1140,25 +1181,25 @@ rescan (op, output_marks)
      int output_marks;
 {
   /* Character being scanned in main loop.  */
-  register U_CHAR c;
+  U_CHAR c;
 
   /* Length of pending accumulated identifier.  */
-  register int ident_length = 0;
+  int ident_length = 0;
 
   /* Hash code of pending accumulated identifier.  */
-  register int hash = 0;
+  int hash = 0;
 
   /* Current input level (&instack[indepth]).  */
   FILE_BUF *ip;
 
   /* Pointer for scanning input.  */
-  register U_CHAR *ibp;
+  U_CHAR *ibp;
 
   /* Pointer to end of input.  End of scan is controlled by LIMIT.  */
-  register U_CHAR *limit;
+  U_CHAR *limit;
 
   /* Pointer for storing output.  */
-  register U_CHAR *obp;
+  U_CHAR *obp;
 
   /* REDO_CHAR is nonzero if we are processing an identifier
      after backing up over the terminating character.
@@ -1179,6 +1220,9 @@ rescan (op, output_marks)
   /* Record position of last `real' newline.  */
   U_CHAR *beg_of_line;
 
+  /* This has to be a global bacause of RECACHE.  */
+  U_CHAR *obufp_before_macroname = NULL;
+
 /* Pop the innermost input stack level, assuming it is a macro expansion.  */
 
 #define POPMACRO \
@@ -1196,6 +1240,7 @@ do { ip = &instack[indepth];              \
      op->bufp = obp;                   \
      check_expand (op, limit - ibp);   \
      beg_of_line = 0;                  \
+     obufp_before_macroname += op->bufp - obp;  \
      obp = op->bufp; } while (0)
 
   if (no_output && instack[indepth].fname != 0)
@@ -1584,7 +1629,7 @@ specialchar:
 randomchar:
 
       if (ident_length > 0) {
-       register HASHNODE *hp;
+       HASHNODE *hp;
 
        /* We have just seen an identifier end.  If it's a macro, expand it.
 
@@ -1606,11 +1651,12 @@ randomchar:
             hp = hp->next) {
 
          if (hp->length == ident_length) {
-           U_CHAR *obufp_before_macroname;
+           /* obufp_before_macroname is used only in this block,
+               but it has to be global because of RECACHE.  */
            int op_lineno_before_macroname;
-           register int i = ident_length;
-           register U_CHAR *p = hp->name;
-           register U_CHAR *q = obp - i;
+           int i = ident_length;
+           U_CHAR *p = hp->name;
+           U_CHAR *q = obp - i;
 
            if (! redo_char)
              q--;
@@ -1775,7 +1821,7 @@ expand_to_temp_buffer (buf, limit, output_marks)
      const U_CHAR *buf, *limit;
      int output_marks;
 {
-  register FILE_BUF *ip;
+  FILE_BUF *ip;
   FILE_BUF obuf;
   int length = limit - buf;
   U_CHAR *buf1;
@@ -1788,8 +1834,8 @@ expand_to_temp_buffer (buf, limit, output_marks)
 
   buf1 = (U_CHAR *) alloca (length + 1);
   {
-    register const U_CHAR *p1 = buf;
-    register U_CHAR *p2 = buf1;
+    const U_CHAR *p1 = buf;
+    U_CHAR *p2 = buf1;
 
     while (p1 != limit)
       *p2++ = *p1++;
@@ -1852,9 +1898,9 @@ static int
 handle_directive (ip, op)
      FILE_BUF *ip, *op;
 {
-  register U_CHAR *bp, *cp;
-  register struct directive *kt;
-  register int ident_length;
+  U_CHAR *bp, *cp;
+  struct directive *kt;
+  int ident_length;
   U_CHAR *resume_p;
 
   /* Nonzero means we must copy the entire command
@@ -1911,8 +1957,8 @@ handle_directive (ip, op)
   for (kt = directive_table; kt->length > 0; kt++) {
     if (kt->length == ident_length
        && !strncmp (kt->name, (const char *)ident, ident_length)) {
-      register U_CHAR *buf;
-      register U_CHAR *limit = ip->buf + ip->length;
+      U_CHAR *buf;
+      U_CHAR *limit = ip->buf + ip->length;
       int unterminated = 0;
 
       /* Nonzero means do not delete comments within the directive.
@@ -1926,7 +1972,7 @@ handle_directive (ip, op)
 
       buf = bp = after_ident;
       while (bp < limit) {
-       register U_CHAR c = *bp++;
+       U_CHAR c = *bp++;
        switch (c) {
        case '\\':
          if (bp < limit) {
@@ -1990,7 +2036,7 @@ handle_directive (ip, op)
         A comment may come between.  */
 
       if (copy_command) {
-       register U_CHAR *xp = buf;
+       U_CHAR *xp = buf;
        /* Need to copy entire command into temp buffer before dispatching */
 
        cp = (U_CHAR *) alloca (bp - buf + 5); /* room for cmd plus
@@ -2001,7 +2047,7 @@ handle_directive (ip, op)
           and backslash-newlines (and whitespace surrounding the latter).  */
 
        while (xp < bp) {
-         register U_CHAR c = *xp++;
+         U_CHAR c = *xp++;
          *cp++ = c;
 
          switch (c) {
@@ -2029,7 +2075,7 @@ handle_directive (ip, op)
                while (cp != buf && is_space(cp[-1])) cp--;
                cp++;
                SKIP_WHITE_SPACE (xp);
-             } else if (is_space (*xp)) {
+             } else if (is_nvspace (*xp)) {
                *cp++ = *xp++;
                SKIP_WHITE_SPACE (xp);
              }
@@ -2041,7 +2087,7 @@ handle_directive (ip, op)
          case '\'':
          case '\"':
            {
-             register const U_CHAR *bp1
+             const U_CHAR *bp1
                = skip_quoted_string (xp - 1, limit, ip->lineno, 0, 0, 0);
              while (xp != bp1)
                *cp++ = *xp++;
@@ -2246,22 +2292,17 @@ do_include (buf, limit, op)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
 {
-  char *fname;         /* Dynamically allocated fname buffer */
   U_CHAR *fbeg, *fend;         /* Beginning and end of fname */
 
   struct file_name_list *stackp = include; /* Chain of dirs to search */
   struct file_name_list dsp[1];        /* First in chain, if #include "..." */
   int flen;
 
-  int f;                       /* file number */
-
   int retried = 0;             /* Have already tried macro
                                   expanding the include line*/
   FILE_BUF trybuf;             /* It got expanded into here */
   int system_header_p = 0;     /* 0 for "...", 1 for <...> */
 
-  f= -1;                       /* JF we iz paranoid! */
-
 get_filename:
 
   fbeg = buf;
@@ -2342,12 +2383,96 @@ get_filename:
   }
 
   flen = fend - fbeg;
+  process_include (stackp, fbeg, flen, system_header_p, op);
+}
+
+static void
+do_include_next (buf, limit, op)
+     U_CHAR *buf, *limit;
+     FILE_BUF *op;
+{
+  U_CHAR *fbeg, *fend;         /* Beginning and end of fname */
+
+  struct file_name_list *stackp; /* Chain of dirs to search */
+  int flen;
+
+  int retried = 0;             /* Have already tried macro
+                                  expanding the include line*/
+  FILE_BUF trybuf;             /* It got expanded into here */
+  int system_header_p = 0;     /* 0 for "...", 1 for <...> */
+
+  /* Treat as plain #include if we don't know where to start
+     looking.  */
+  stackp = instack[indepth].next_header_dir;
+  if (stackp == 0)
+    {
+      do_include (buf, limit, op);
+      return;
+    }
+
+get_filename:
+
+  fbeg = buf;
+  SKIP_WHITE_SPACE (fbeg);
+  /* Discard trailing whitespace so we can easily see
+     if we have parsed all the significant chars we were given.  */
+  while (limit != fbeg && is_nvspace (limit[-1])) limit--;
+
+  switch (*fbeg++) {
+  case '\"':
+    fend = fbeg;
+    while (fend != limit && *fend != '\"')
+      fend++;
+    if (*fend == '\"' && fend + 1 == limit)
+      break;
+    goto fail;
+
+  case '<':
+    fend = fbeg;
+    while (fend != limit && *fend != '>') fend++;
+    if (*fend == '>' && fend + 1 == limit) {
+      system_header_p = 1;
+      break;
+    }
+    goto fail;
+
+  default:
+  fail:
+    if (retried) {
+      error ("#include expects \"fname\" or <fname>");
+      return;
+    } else {
+      trybuf = expand_to_temp_buffer (buf, limit, 0);
+      buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
+      memcpy (buf, trybuf.buf, trybuf.bufp - trybuf.buf);
+      limit = buf + (trybuf.bufp - trybuf.buf);
+      free (trybuf.buf);
+      retried++;
+      goto get_filename;
+    }
+  }
+
+  flen = fend - fbeg;
+  process_include (stackp, fbeg, flen, system_header_p, op);
+}
+
+static void
+process_include (stackp, fbeg, flen, system_header_p, op)
+     struct file_name_list *stackp;
+     const U_CHAR *fbeg;
+     int flen;
+     int system_header_p;
+     FILE_BUF *op;
+{
+  char *fname;
+  int f = -1;                  /* file number */
+
   fname = (char *) alloca (max_include_len + flen + 2);
   /* + 2 above for slash and terminating null.  */
 
   /* If specified file name is absolute, just open it.  */
 
-  if (*fbeg == '/') {
+  if (IS_ABSOLUTE_PATHNAME (fbeg)) {
     strncpy (fname, (const char *)fbeg, flen);
     fname[flen] = 0;
     f = open (fname, O_RDONLY, 0666);
@@ -2372,7 +2497,7 @@ get_filename:
   if (f < 0) {
     strncpy (fname, (const char *)fbeg, flen);
     fname[flen] = 0;
-    if (print_deps_missing_files
+    if (deps_missing_files
        && print_deps > (system_header_p || (system_include_depth > 0))) {
 
       /* If requested as a system header, assume it belongs in
@@ -2382,8 +2507,8 @@ get_filename:
       else
        stackp = include;
 
-      if (!system_header_p || *fbeg == '/' || !stackp->fname)
-       deps_output ((const char *)fbeg, flen);
+      if (!system_header_p || IS_ABSOLUTE_PATHNAME (fbeg) || !stackp->fname)
+       deps_add_dep (deps, fname);
       else {
        char *p;
        int len = strlen(stackp->fname);
@@ -2393,10 +2518,9 @@ get_filename:
        p[len++] = '/';
        memcpy (p + len, fbeg, flen);
        len += flen;
-       deps_output (p, len);
+       p[len] = '\0';
+       deps_add_dep (deps, p);
       }
-      deps_output (" ", 0);
-
     } else if (print_deps
               && print_deps <= (system_header_p
                                 || (system_include_depth > 0)))
@@ -2433,17 +2557,15 @@ get_filename:
       ptr->fname = xstrdup (fname);
 
       /* For -M, add this file to the dependencies.  */
-      if (print_deps > (system_header_p || (system_include_depth > 0))) {
-       deps_output (fname, strlen (fname));
-       deps_output (" ", 0);
-      }
+      if (print_deps > (system_header_p || (system_include_depth > 0)))
+       deps_add_dep (deps, fname);
     }   
 
     if (system_header_p)
       system_include_depth++;
 
     /* Actually process the file.  */
-    finclude (f, fname, op);
+    finclude (f, fname, stackp->next, op);
 
     if (system_header_p)
       system_include_depth--;
@@ -2456,9 +2578,10 @@ get_filename:
    with output to OP.  */
 
 static void
-finclude (f, fname, op)
+finclude (f, fname, nhd, op)
      int f;
      const char *fname;
+     struct file_name_list *nhd;
      FILE_BUF *op;
 {
   int st_mode;
@@ -2477,6 +2600,7 @@ finclude (f, fname, op)
   fp->length = 0;
   fp->lineno = 1;
   fp->if_stack = if_stack;
+  fp->next_header_dir = nhd;
 
   if (S_ISREG (st_mode)) {
     fp->buf = (U_CHAR *) xmalloc (st_size + 2);
@@ -2641,8 +2765,8 @@ do_define (buf, limit, op)
       }
     }
 
-    ++bp;                      /* skip paren */
-    while (is_nvspace (*bp))   /* and leading whitespace */
+    ++bp;                                      /* skip paren */
+    while (is_nvspace (*bp) && bp < limit)     /* and leading whitespace */
       ++bp;
     /* now everything from bp before limit is the definition. */
     defn = collect_expansion (bp, limit, argno, arg_ptrs);
@@ -2669,7 +2793,7 @@ do_define (buf, limit, op)
     }
   } else {
     /* simple expansion or empty definition; skip leading whitespace */
-    while (is_nvspace (*bp))
+    while (is_nvspace (*bp) && bp < limit)
       ++bp;
     /* now everything from bp before limit is the definition. */
     defn = collect_expansion (bp, limit, -1, 0);
@@ -2701,9 +2825,9 @@ static int
 compare_defs (d1, d2)
      DEFINITION *d1, *d2;
 {
-  register struct reflist *a1, *a2;
-  register U_CHAR *p1 = d1->expansion;
-  register U_CHAR *p2 = d2->expansion;
+  struct reflist *a1, *a2;
+  U_CHAR *p1 = d1->expansion;
+  U_CHAR *p2 = d2->expansion;
   int first = 1;
 
   if (d1->nargs != d2->nargs)
@@ -2747,8 +2871,8 @@ comp_def_part (first, beg1, len1, beg2, len2, last)
      int len1, len2;
      int last;
 {
-  register const U_CHAR *end1 = beg1 + len1;
-  register const U_CHAR *end2 = beg2 + len2;
+  const U_CHAR *end1 = beg1 + len1;
+  const U_CHAR *end2 = beg2 + len2;
   if (first) {
     while (beg1 != end1 && is_space (*beg1)) beg1++;
     while (beg2 != end2 && is_space (*beg2)) beg2++;
@@ -2796,7 +2920,7 @@ collect_expansion (buf, end, nargs, arglist)
      struct arglist *arglist;
 {
   DEFINITION *defn;
-  register U_CHAR *p, *limit, *lastp, *exp_p;
+  U_CHAR *p, *limit, *lastp, *exp_p;
   struct reflist *endpat = NULL;
   /* Pointer to first nonspace after last ## seen.  */
   U_CHAR *concat = 0;
@@ -2845,7 +2969,7 @@ collect_expansion (buf, end, nargs, arglist)
   /* Process the main body of the definition.  */
   while (p < limit) {
     int skipped_arg = 0;
-    register U_CHAR c = *p++;
+    U_CHAR c = *p++;
 
     *exp_p++ = c;
 
@@ -2896,7 +3020,7 @@ collect_expansion (buf, end, nargs, arglist)
       id_len = p - id_beg;
 
       if (is_idstart (c)) {
-       register struct arglist *arg;
+       struct arglist *arg;
 
        for (arg = arglist; arg != NULL; arg = arg->next) {
          struct reflist *tpat;
@@ -2922,7 +3046,7 @@ collect_expansion (buf, end, nargs, arglist)
            tpat->argno = arg->argno;
            tpat->nchars = exp_p - lastp;
            {
-             register U_CHAR *p1 = p;
+             U_CHAR *p1 = p;
              SKIP_WHITE_SPACE (p1);
              if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
                tpat->raw_after = 1;
@@ -2936,7 +3060,7 @@ collect_expansion (buf, end, nargs, arglist)
 
       /* If this was not a macro arg, copy it into the expansion.  */
       if (! skipped_arg) {
-       register U_CHAR *lim1 = p;
+       U_CHAR *lim1 = p;
        p = id_beg;
        while (p != lim1)
          *exp_p++ = *p++;
@@ -2974,7 +3098,7 @@ do_line (buf, limit, op)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
 {
-  register U_CHAR *bp;
+  U_CHAR *bp;
   FILE_BUF *ip = &instack[indepth];
   FILE_BUF tem;
   int new_lineno;
@@ -3553,8 +3677,8 @@ skip_if_group (ip, any)
      FILE_BUF *ip;
      int any;
 {
-  register U_CHAR *bp = ip->bufp, *cp;
-  register U_CHAR *endb = ip->buf + ip->length;
+  U_CHAR *bp = ip->bufp, *cp;
+  U_CHAR *endb = ip->buf + ip->length;
   struct directive *kt;
   IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */
   U_CHAR *beg_of_line = bp;
@@ -3773,11 +3897,11 @@ do_endif (buf, limit, op)
  */
 static U_CHAR *
 skip_to_end_of_comment (ip, line_counter)
-     register FILE_BUF *ip;
+     FILE_BUF *ip;
      int *line_counter;                /* place to remember newlines, or NULL */
 {
-  register U_CHAR *limit = ip->buf + ip->length;
-  register U_CHAR *bp = ip->bufp;
+  U_CHAR *limit = ip->buf + ip->length;
+  U_CHAR *bp = ip->bufp;
   FILE_BUF *op = &outbuf;      /* JF */
   int output = put_out_comments && !line_counter;
 
@@ -3836,14 +3960,14 @@ skip_to_end_of_comment (ip, line_counter)
  */
 static U_CHAR *
 skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp)
-     register const U_CHAR *bp;
-     register const U_CHAR *limit;
+     const U_CHAR *bp;
+     const U_CHAR *limit;
      int start_line;
      int *count_newlines;
      int *backslash_newlines_p;
      int *eofp;
 {
-  register U_CHAR c, match;
+  U_CHAR c, match;
 
   match = *bp++;
   while (1) {
@@ -3952,7 +4076,7 @@ macroexpand (hp, op)
 {
   int nargs;
   DEFINITION *defn = hp->value.defn;
-  register U_CHAR *xbuf;
+  U_CHAR *xbuf;
   int xbuf_len;
   int start_line = instack[indepth].lineno;
 
@@ -3967,7 +4091,7 @@ macroexpand (hp, op)
   nargs = defn->nargs;
 
   if (nargs >= 0) {
-    register int i;
+    int i;
     struct argdata *args;
     const char *parse_error = 0;
 
@@ -3991,7 +4115,7 @@ macroexpand (hp, op)
        = macarg ((i < nargs || (nargs == 0 && i == 0)) ? &args[i] : 0);
       if (parse_error)
        {
-         error_with_line (line_for_error (start_line), parse_error);
+         error_with_line (line_for_error (start_line), "%s", parse_error);
          break;
        }
       i++;
@@ -3999,8 +4123,8 @@ macroexpand (hp, op)
 
     /* If we got one arg but it was just whitespace, call that 0 args.  */
     if (i == 1) {
-      register const U_CHAR *bp = args[0].raw;
-      register const U_CHAR *lim = bp + args[0].raw_length;
+      const U_CHAR *bp = args[0].raw;
+      const U_CHAR *lim = bp + args[0].raw_length;
       while (bp != lim && is_space (*bp)) bp++;
       if (bp == lim)
        i = 0;
@@ -4030,12 +4154,12 @@ macroexpand (hp, op)
       xbuf = defn->expansion;
       xbuf_len = defn->length;
     } else {
-      register U_CHAR *exp = defn->expansion;
-      register int offset;     /* offset in expansion,
+      U_CHAR *exp = defn->expansion;
+      int offset;      /* offset in expansion,
                                   copied a piece at a time */
-      register int totlen;     /* total amount of exp buffer filled so far */
+      int totlen;      /* total amount of exp buffer filled so far */
 
-      register struct reflist *ap;
+      struct reflist *ap;
 
       /* Macro really takes args.  Compute the expansion of this call.  */
 
@@ -4057,7 +4181,7 @@ macroexpand (hp, op)
         of where we are copying from.  */
       offset = totlen = 0;
       for (ap = defn->pattern; ap != NULL; ap = ap->next) {
-       register struct argdata *arg = &args[ap->argno];
+       struct argdata *arg = &args[ap->argno];
 
        for (i = 0; i < ap->nchars; i++)
          xbuf[totlen++] = exp[offset++];
@@ -4188,7 +4312,7 @@ macroexpand (hp, op)
   /* Now put the expansion on the input stack
      so our caller will commence reading from it.  */
   {
-    register FILE_BUF *ip2;
+    FILE_BUF *ip2;
 
     ip2 = &instack[++indepth];
 
@@ -4210,7 +4334,7 @@ macroexpand (hp, op)
 
 static const char *
 macarg (argptr)
-     register struct argdata *argptr;
+     struct argdata *argptr;
 {
   FILE_BUF *ip = &instack[indepth];
   int paren = 0;
@@ -4296,8 +4420,8 @@ macarg (argptr)
 
   if (argptr != 0) {
     FILE_BUF obuf;
-    register const U_CHAR *buf, *lim;
-    register int totlen;
+    const U_CHAR *buf, *lim;
+    int totlen;
 
     obuf = expand_to_temp_buffer (argptr->raw,
                                  argptr->raw + argptr->raw_length,
@@ -4312,7 +4436,7 @@ macarg (argptr)
 
     totlen = 0;
     while (buf != lim) {
-      register U_CHAR c = *buf++;
+      U_CHAR c = *buf++;
       totlen++;
       /* Internal sequences of whitespace are replaced by one space
         in most cases, but not always.  So count all the whitespace
@@ -4342,10 +4466,10 @@ macarg (argptr)
 static U_CHAR *
 macarg1 (start, limit, depthptr, newlines, comments)
      U_CHAR *start;
-     register const U_CHAR *limit;
+     const U_CHAR *limit;
      int *depthptr, *newlines, *comments;
 {
-  register U_CHAR *bp = start;
+  U_CHAR *bp = start;
 
   while (bp < limit) {
     switch (*bp) {
@@ -4433,10 +4557,10 @@ discard_comments (start, length, newlines)
      int length;
      int newlines;
 {
-  register U_CHAR *ibp;
-  register U_CHAR *obp;
-  register const U_CHAR *limit;
-  register int c;
+  U_CHAR *ibp;
+  U_CHAR *obp;
+  const U_CHAR *limit;
+  int c;
 
   /* If we have newlines to duplicate, copy everything
      that many characters up.  Then, in the second part,
@@ -4562,37 +4686,22 @@ v_message (mtype, line, msgid, ap)
 void
 error VPARAMS ((const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START(ap, msgid);
-  
-#ifndef ANSI_PROTOTYPES
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN(ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   v_message (ERROR, 0, msgid, ap);
+  VA_CLOSE (ap);
 }
 
 void
 error_with_line VPARAMS ((int line, const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  int line;
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START(ap, msgid);
-  
-#ifndef ANSI_PROTOTYPES
-  line = va_arg (ap, int);
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN(ap, msgid);
+  VA_FIXEDARG (ap, int, line);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   v_message (ERROR, line, msgid, ap);
+  VA_CLOSE (ap);
 }
 
 /* Error including a message from `errno'.  */
@@ -4607,35 +4716,21 @@ error_from_errno (name)
 void
 warning VPARAMS ((const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START(ap, msgid);
-  
-#ifndef ANSI_PROTOTYPES
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN(ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   v_message (WARNING, 0, msgid, ap);
+  VA_CLOSE (ap);
 }
 
 void
 fatal VPARAMS ((const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START(ap, msgid);
-  
-#ifndef ANSI_PROTOTYPES
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN(ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   v_message (FATAL, 0, msgid, ap);
+  VA_CLOSE (ap);
   exit (FATAL_EXIT_CODE);
 }
 
@@ -4702,10 +4797,10 @@ line_for_error (line)
 
 static void
 grow_outbuf (obuf, needed)
-     register FILE_BUF *obuf;
-     register int needed;
+     FILE_BUF *obuf;
+     int needed;
 {
-  register U_CHAR *p;
+  U_CHAR *p;
   int minsize;
 
   if (obuf->length - (obuf->bufp - obuf->buf) > needed)
@@ -4749,9 +4844,9 @@ install (name, len, type, hash)
      int hash;
         /* watch out here if sizeof (U_CHAR *) != sizeof (int) */
 {
-  register HASHNODE *hp;
-  register int bucket;
-  register const U_CHAR *p;
+  HASHNODE *hp;
+  int bucket;
+  const U_CHAR *p;
   U_CHAR *q;
 
   if (len < 0) {
@@ -4796,8 +4891,8 @@ lookup (name, len, hash)
      int len;
      int hash;
 {
-  register const U_CHAR *bp;
-  register HASHNODE *bucket;
+  const U_CHAR *bp;
+  HASHNODE *bucket;
 
   if (len < 0) {
     for (bp = name; is_idchar (*bp); bp++) ;
@@ -4854,11 +4949,11 @@ delete_macro (hp)
  */
 static int
 hashf (name, len, hashsize)
-     register const U_CHAR *name;
-     register int len;
+     const U_CHAR *name;
+     int len;
      int hashsize;
 {
-  register int r = 0;
+  int r = 0;
 
   while (len--)
     r = HASHSTEP (r, *name++);
@@ -4874,11 +4969,11 @@ dump_all_macros ()
   int bucket;
 
   for (bucket = 0; bucket < HASHSIZE; bucket++) {
-    register HASHNODE *hp;
+    HASHNODE *hp;
 
     for (hp = hashtab[bucket]; hp; hp= hp->next) {
       if (hp->type == T_MACRO) {
-       register DEFINITION *defn = hp->value.defn;
+       DEFINITION *defn = hp->value.defn;
        struct reflist *ap;
        int offset;
        int concat;
@@ -4960,7 +5055,7 @@ dump_arg_n (defn, argnum)
      DEFINITION *defn;
      int argnum;
 {
-  register const U_CHAR *p = defn->argnames;
+  const U_CHAR *p = defn->argnames;
   while (argnum + 1 < defn->nargs) {
     p = (const U_CHAR *) strchr ((const char *)p, ' ') + 1;
     argnum++;
@@ -5106,38 +5201,6 @@ make_assertion (str)
   run_directive (str, count, type);
 }
 \f
-/* Add output to `deps_buffer' for the -M switch.
-   STRING points to the text to be output.
-   SIZE is the number of bytes, or 0 meaning output until a null.
-   If SIZE is nonzero, we break the line first, if it is long enough.  */
-static void
-deps_output (string, size)
-     const char *string;
-     int size;
-{
-#ifndef MAX_OUTPUT_COLUMNS
-#define MAX_OUTPUT_COLUMNS 75
-#endif
-  if (size != 0 && deps_column != 0
-      && size + deps_column > MAX_OUTPUT_COLUMNS) {
-    deps_output ("\\\n  ", 0);
-    deps_column = 0;
-  }
-
-  if (size == 0)
-    size = strlen (string);
-
-  if (deps_size + size + 1 > deps_allocated_size) {
-    deps_allocated_size = deps_size + size + 50;
-    deps_allocated_size *= 2;
-    deps_buffer = (char *) xrealloc (deps_buffer, deps_allocated_size);
-  }
-  memcpy (&deps_buffer[deps_size], string, size);
-  deps_size += size;
-  deps_column += size;
-  deps_buffer[deps_size] = 0;
-}
-
 /* Get the file-mode and data size of the file open on FD
    and store them in *MODE_POINTER and *SIZE_POINTER.  */