OSDN Git Service

contrib:
[pf3gnuchains/gcc-fork.git] / gcc / tradcpp.c
index 5db2a84..e5e0935 100644 (file)
@@ -1,5 +1,5 @@
 /* C Compatible Compiler Preprocessor (CCCP)
-Copyright (C) 1986, 1987, 1989, 2000 Free Software Foundation, Inc.
+Copyright (C) 1986, 1987, 1989, 2000, 2001 Free Software Foundation, Inc.
                     Written by Paul Rubin, June 1986
                    Adapted to ANSI C, Richard Stallman, Jan 1987
                    Dusted off, polished, and adapted for use as traditional
@@ -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,33 @@ 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.  */
+
+const char *deps_file = 0;
+
+/* Nonzero if missing .h files in -M output are assumed to be
+   generated files and not errors.  */
+
+int deps_missing_files = 0;
+       
 /* Nonzero means don't output line number information.  */
 
 int no_line_commands;
@@ -60,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;
@@ -223,6 +248,8 @@ enum node_type {
  T_UNDEF,      /* `#undef' */
  T_LINE,       /* `#line' */
  T_ENDIF,      /* `#endif' */
+ T_ERROR,      /* `#error' */
+ T_WARNING,    /* `#warning' */
  T_ASSERT,     /* `#assert' */
  T_UNASSERT,   /* `#unassert' */
  T_SPECLINE,   /* special symbol `__LINE__' */
@@ -327,6 +354,8 @@ struct arglist {
 /* Function prototypes.  */
 
 static void do_define  PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
+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_undef   PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
@@ -376,7 +405,7 @@ static void output_line_command PARAMS ((FILE_BUF *, FILE_BUF *,
 
 static int eval_if_expression  PARAMS ((const U_CHAR *, int));
 
-static void initialize_char_syntax     PARAMS ((void));
+static void output_deps                PARAMS ((void));
 static void initialize_builtins        PARAMS ((void));
 static void run_directive      PARAMS ((const char *, size_t,
                                         enum node_type));
@@ -387,7 +416,7 @@ 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 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 *));
@@ -419,22 +448,15 @@ struct directive directive_table[] = {
   {  5, do_undef,   "undef",   T_UNDEF   },
   {  4, do_line,    "line",    T_LINE    },
   {  4, do_elif,    "elif",    T_ELIF    },
+  {  5, do_error,   "error",   T_ERROR   },
+  {  7, do_warning, "warning", T_WARNING },
   {  6, do_assert,  "assert",  T_ASSERT  },
   {  8, do_unassert,"unassert",T_UNASSERT},
   {  -1, 0, "", T_UNUSED},
 };
 
-/* table to tell if char can be part of a C identifier. */
-U_CHAR is_idchar[256];
-/* table to tell if char can be first char of a c identifier. */
-U_CHAR is_idstart[256];
-/* table to tell if c is horizontal space.  */
-U_CHAR is_hor_space[256];
-/* table to tell if c is horizontal or vertical space.  */
-U_CHAR is_space[256];
-
-#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
-#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
+#define SKIP_WHITE_SPACE(p) do { while (is_nvspace(*p)) p++; } while (0)
+#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space(*p)) p++; } while (0)
   
 int errors = 0;                        /* Error counter for exit code */
 
@@ -456,19 +478,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;
@@ -496,14 +505,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.  */
   {
@@ -522,15 +523,16 @@ main (argc, argv)
   in_fname = NULL;
   out_fname = NULL;
 
-  /* Initialize is_idchar to allow $.  */
-  initialize_char_syntax ();
-
   no_line_commands = 0;
   dump_macros = 0;
   no_output = 0;
 
   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++) {
@@ -547,7 +549,6 @@ main (argc, argv)
       switch (c) {
       case 'E':
       case '$':
-      case 'g':
        break;  /* Ignore for compatibility with ISO/extended cpp.  */
 
       case 'l':
@@ -615,11 +616,56 @@ main (argc, argv)
        break;
 
       case 'M':
-       if (!strcmp (argv[i], "-M"))
-         print_deps = 2;
-       else if (!strcmp (argv[i], "-MM"))
-         print_deps = 1;
-       inhibit_output = 1;
+       {
+         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;
+         } else if (!strncmp (argv[i], "-MMD", 4)) {
+           p = argv[i] + 4;
+           print_deps = 1;
+         } else if (!strcmp (argv[i], "-M")) {
+           print_deps = 2;
+         } else if (!strcmp (argv[i], "-MM")) {
+           print_deps = 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;
+           else if (i + 1 == argc)
+             fatal ("Filename missing after %s option", argv[i]);
+           else
+             deps_file = argv[++i];
+         }
+       }
        break;
 
       case 'd':
@@ -723,14 +769,27 @@ main (argc, argv)
     }
   }
 
+  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;
 
-  /* Initialize is_idchar.  */
-  initialize_char_syntax ();
+  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 initialize_char_syntax
-     and option processing.  */
+  /* Install __LINE__, etc.  Must follow option processing.  */
   initialize_builtins ();
 
   /* Do defines specified with -D and undefines specified with -U.  */
@@ -779,6 +838,7 @@ main (argc, argv)
      so that only their macro definitions matter.  */
 
   no_output++;
+  indepth++;
   for (i = 1; i < argc; i++)
     if (pend[i].type == PD_FILE)
       {
@@ -790,6 +850,7 @@ main (argc, argv)
          }
        finclude (fd, pend[i].arg, &outbuf);
       }
+  indepth--;
   no_output--;
 
   /* Pending directives no longer needed.  */
@@ -807,92 +868,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;
-      char *output_file;
-
-      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)
-       {
-         deps_target = s + 1;
-         output_file = (char *) xmalloc (s - spec + 1);
-         memcpy (output_file, spec, s - spec);
-         output_file[s - spec] = 0;
-       }
-      else
-       {
-         deps_target = 0;
-         output_file = spec;
-       }
-      
-      deps_stream = fopen (output_file, "a");
-      if (deps_stream == 0)
-       pfatal_with_name (output_file);
-    }
-  /* If the -M option was used, output the deps to standard output.  */
-  else if (print_deps)
-    deps_stream = stdout;
-
-  /* For -M, print the expected object file name
-     as the target of this Make-rule.  */
-  if (print_deps) {
-    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;
@@ -969,20 +944,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");
@@ -995,6 +966,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 *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.
@@ -1052,14 +1108,14 @@ name_newline_fix (bp)
 
   /* What follows the backslash-newlines is not embarrassing.  */
 
-  if (count == 0 || !is_idchar[*p])
+  if (count == 0 || !is_idchar (*p))
     return;
 
   /* Copy all potentially embarrassing characters
      that follow the backslash-newline pairs
      down to where the pairs originally started.  */
 
-  while (is_idchar[*p])
+  while (is_idchar (*p))
     *bp++ = *p++;
 
   /* Now write the same number of pairs after the embarrassing chars.  */
@@ -1463,7 +1519,7 @@ do { ip = &instack[indepth];              \
            /* If expanding a macro arg, keep the newline -.  */
            *obp++ = '-';
          }
-       } else if (is_space[*ibp]) {
+       } else if (is_space (*ibp)) {
          /* Newline Space does not prevent expansion of preceding token
             so expand the preceding token and then come back.  */
          if (ident_length > 0)
@@ -1514,7 +1570,7 @@ do { ip = &instack[indepth];              \
        ibp--;
        /* If we have an identifier that ends here, process it now, so
           we get the right error for recursion.  */
-       if (ident_length && ! is_idchar[*instack[indepth - 1].bufp]) {
+       if (ident_length && ! is_idchar (*instack[indepth - 1].bufp)) {
          redo_char = 1;
          goto randomchar;
        }
@@ -1642,7 +1698,7 @@ randomchar:
                      *obp++ = '/';
                    }
                  }
-                 else if (is_space[*ibp]) {
+                 else if (is_space (*ibp)) {
                    *obp++ = *ibp++;
                    if (ibp[-1] == '\n') {
                      if (ip->macro == 0) {
@@ -1837,7 +1893,7 @@ handle_directive (ip, op)
   bp = ip->bufp;
   /* Skip whitespace and \-newline.  */
   while (1) {
-    if (is_hor_space[*bp])
+    if (is_nvspace (*bp))
       bp++;
     else if (*bp == '/' && (newline_fix (bp + 1), bp[1]) == '*') {
       ip->bufp = bp;
@@ -1854,12 +1910,12 @@ handle_directive (ip, op)
 
   cp = bp;
   while (1) {
-    if (is_idchar[*cp])
+    if (is_idchar (*cp))
       cp++;
     else {
       if (*cp == '\\' && cp[1] == '\n')
        name_newline_fix (cp);
-      if (is_idchar[*cp])
+      if (is_idchar (*cp))
        cp++;
       else break;
     }
@@ -1996,11 +2052,11 @@ handle_directive (ip, op)
            if (*xp == '\n') {
              xp++;
              cp--;
-             if (cp != buf && is_space[cp[-1]]) {
-               while (cp != buf && is_space[cp[-1]]) cp--;
+             if (cp != buf && is_space (cp[-1])) {
+               while (cp != buf && is_space(cp[-1])) cp--;
                cp++;
                SKIP_WHITE_SPACE (xp);
-             } else if (is_space[*xp]) {
+             } else if (is_space (*xp)) {
                *cp++ = *xp++;
                SKIP_WHITE_SPACE (xp);
              }
@@ -2172,11 +2228,15 @@ special_symbol (hp, op)
       SKIP_WHITE_SPACE (ip->bufp);
     }
 
-    if (!is_idstart[*ip->bufp])
+    if (!is_idstart (*ip->bufp))
       goto oops;
-    if (lookup (ip->bufp, -1, -1))
-      buf = " 1 ";
-    while (is_idchar[*ip->bufp])
+    {
+      HASHNODE *hp = lookup (ip->bufp, -1, -1);
+
+      if (hp && hp->type != T_UNUSED && hp->type != T_SPEC_DEFINED)
+       buf = " 1 ";
+    }
+    while (is_idchar (*ip->bufp))
       ++ip->bufp;
     SKIP_WHITE_SPACE (ip->bufp);
     if (paren) {
@@ -2235,7 +2295,7 @@ get_filename:
   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_hor_space[limit[-1]]) limit--;
+  while (limit != fbeg && is_nvspace (limit[-1])) limit--;
 
   switch (*fbeg++) {
   case '\"':
@@ -2314,7 +2374,7 @@ get_filename:
 
   /* 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);
@@ -2339,19 +2399,37 @@ get_filename:
   if (f < 0) {
     strncpy (fname, (const char *)fbeg, flen);
     fname[flen] = 0;
-    error_from_errno (fname);
+    if (deps_missing_files
+       && print_deps > (system_header_p || (system_include_depth > 0))) {
 
-    /* For -M, add this file to the dependencies.  */
-    if (print_deps > (system_header_p || (system_include_depth > 0))) {
-      if (system_header_p)
-       warning ("nonexistent file <%.*s> omitted from dependency output",
-                fend - fbeg, fbeg);
+      /* If requested as a system header, assume it belongs in
+        the first system header directory. */
+      if (first_bracket_include)
+       stackp = first_bracket_include;
       else
-       {
-         deps_output ((const char *)fbeg, fend - fbeg);
-         deps_output (" ", 0);
-       }
-    }
+       stackp = include;
+
+      if (!system_header_p || IS_ABSOLUTE_PATHNAME (fbeg) || !stackp->fname)
+       deps_add_dep (deps, fname);
+      else {
+       char *p;
+       int len = strlen(stackp->fname);
+
+       p = (char *) alloca (len + flen + 2);
+       memcpy (p, stackp->fname, len);
+       p[len++] = '/';
+       memcpy (p + len, fbeg, flen);
+       len += flen;
+       p[len] = '\0';
+       deps_add_dep (deps, p);
+      }
+    } else if (print_deps
+              && print_deps <= (system_header_p
+                                || (system_include_depth > 0)))
+      warning ("No include path in which to find %.*s", flen, fbeg);
+    else
+      error_from_errno (fname);
+
   } else {
 
     /* Check to see if this include file is a once-only include file.
@@ -2381,10 +2459,8 @@ 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)
@@ -2483,6 +2559,8 @@ finclude (f, fname, op)
   output_line_command (fp, op, 0, enter_file);
   rescan (op, 0);
   indepth--;
+  instack[indepth].lineno++;
+  instack[indepth].bufp++;     /* Skip the new line.  */
   output_line_command (&instack[indepth], op, 0, leave_file);
   free (fp->buf);
   return;
@@ -2514,25 +2592,32 @@ do_define (buf, limit, op)
 
   bp = buf;
 
-  while (is_hor_space[*bp])
+  while (is_nvspace (*bp))
     bp++;
 
   symname = bp;                        /* remember where it starts */
-  while (is_idchar[*bp] && bp < limit) {
+  while (is_idchar (*bp) && bp < limit) {
     bp++;
   }
   sym_length = bp - symname;
   if (sym_length == 0)
-    error ("invalid macro name");
-  else if (!is_idstart[*symname]) {
+    {
+      error ("invalid macro name");
+      return;
+    }
+  else if (!is_idstart (*symname)) {
     U_CHAR *msg;                       /* what pain... */
     msg = (U_CHAR *) alloca (sym_length + 1);
     memcpy (msg, symname, sym_length);
     msg[sym_length] = 0;
     error ("invalid macro name `%s'", msg);
+    return;
   } else {
     if (! strncmp ((const char *)symname, "defined", 7) && sym_length == 7)
-      error ("defining `defined' as a macro");
+      {
+       error ("\"defined\" cannot be used as a macro name");
+       return;
+      }
   }
 
   /* lossage will occur if identifiers or control keywords are broken
@@ -2556,11 +2641,11 @@ do_define (buf, limit, op)
       temp->argno = argno++;
       arg_ptrs = temp;
 
-      if (!is_idstart[*bp])
+      if (!is_idstart (*bp))
        warning ("parameter name starts with a digit in #define");
 
       /* Find the end of the arg name.  */
-      while (is_idchar[*bp]) {
+      while (is_idchar (*bp)) {
        bp++;
       }
       temp->length = bp - temp->name;
@@ -2581,7 +2666,7 @@ do_define (buf, limit, op)
     }
 
     ++bp;                      /* skip paren */
-    while (is_hor_space[*bp])  /* and leading whitespace */
+    while (is_nvspace (*bp))   /* and leading whitespace */
       ++bp;
     /* now everything from bp before limit is the definition. */
     defn = collect_expansion (bp, limit, argno, arg_ptrs);
@@ -2608,7 +2693,7 @@ do_define (buf, limit, op)
     }
   } else {
     /* simple expansion or empty definition; skip leading whitespace */
-    while (is_hor_space[*bp])
+    while (is_nvspace (*bp))
       ++bp;
     /* now everything from bp before limit is the definition. */
     defn = collect_expansion (bp, limit, -1, 0);
@@ -2689,17 +2774,17 @@ comp_def_part (first, beg1, len1, beg2, len2, last)
   register const U_CHAR *end1 = beg1 + len1;
   register const U_CHAR *end2 = beg2 + len2;
   if (first) {
-    while (beg1 != end1 && is_space[*beg1]) beg1++;
-    while (beg2 != end2 && is_space[*beg2]) beg2++;
+    while (beg1 != end1 && is_space (*beg1)) beg1++;
+    while (beg2 != end2 && is_space (*beg2)) beg2++;
   }
   if (last) {
-    while (beg1 != end1 && is_space[end1[-1]]) end1--;
-    while (beg2 != end2 && is_space[end2[-1]]) end2--;
+    while (beg1 != end1 && is_space (end1[-1])) end1--;
+    while (beg2 != end2 && is_space (end2[-1])) end2--;
   }
   while (beg1 != end1 && beg2 != end2) {
-    if (is_space[*beg1] && is_space[*beg2]) {
-      while (beg1 != end1 && is_space[*beg1]) beg1++;
-      while (beg2 != end2 && is_space[*beg2]) beg2++;
+    if (is_space (*beg1) && is_space (*beg2)) {
+      while (beg1 != end1 && is_space (*beg1)) beg1++;
+      while (beg2 != end2 && is_space (*beg2)) beg2++;
     } else if (*beg1 == *beg2) {
       beg1++; beg2++;
     } else break;
@@ -2756,8 +2841,8 @@ collect_expansion (buf, end, nargs, arglist)
   /* Find end of leading whitespace.  */
   limit = end;
   p = buf;
-  while (p < limit && is_space[limit[-1]]) limit--;
-  while (p < limit && is_space[*p]) p++;
+  while (p < limit && is_space (limit[-1])) limit--;
+  while (p < limit && is_space (*p)) p++;
 
   /* Allocate space for the text in the macro definition.
      Leading and trailing whitespace chars need 2 bytes each.
@@ -2776,7 +2861,7 @@ collect_expansion (buf, end, nargs, arglist)
   p = buf;
 
   /* Convert leading whitespace to Newline-markers.  */
-  while (p < limit && is_space[*p]) {
+  while (p < limit && is_space (*p)) {
     *exp_p++ = '\n';
     *exp_p++ = *p++;
   }
@@ -2826,15 +2911,15 @@ collect_expansion (buf, end, nargs, arglist)
       break;
     }
 
-    if (is_idchar[c] && nargs > 0) {
+    if (is_idchar (c) && nargs > 0) {
       U_CHAR *id_beg = p - 1;
       int id_len;
 
       --exp_p;
-      while (p != limit && is_idchar[*p]) p++;
+      while (p != limit && is_idchar (*p)) p++;
       id_len = p - id_beg;
 
-      if (is_idstart[c]) {
+      if (is_idstart (c)) {
        register struct arglist *arg;
 
        for (arg = arglist; arg != NULL; arg = arg->next) {
@@ -2887,7 +2972,7 @@ collect_expansion (buf, end, nargs, arglist)
 
   if (limit < end) {
     /* Convert trailing whitespace to Newline-markers.  */
-    while (limit < end && is_space[*limit]) {
+    while (limit < end && is_space (*limit)) {
       *exp_p++ = '\n';
       *exp_p++ = *limit++;
     }
@@ -2934,19 +3019,12 @@ do_line (buf, limit, op)
   /* The Newline at the end of this line remains to be processed.
      To put the next line at the specified line number,
      we must store a line number now that is one less.  */
-  new_lineno = atoi ((const char *)bp) - 1;
+  new_lineno = atoi ((const char *)bp);
 
   /* skip over the line number.  */
   while (ISDIGIT (*bp))
     bp++;
 
-#if 0 /* #line 10"foo.c" is supposed to be allowed.  */
-  if (*bp && !is_space[*bp]) {
-    error ("invalid format #line command");
-    return;
-  }
-#endif
-
   SKIP_WHITE_SPACE (bp);
 
   if (*bp == '\"') {
@@ -3012,6 +3090,7 @@ do_line (buf, limit, op)
 
   ip->lineno = new_lineno;
   output_line_command (ip, op, 0, file_change);
+  ip->bufp++;                  /* Skip the new line.  */
   check_expand (op, ip->length - (ip->bufp - ip->buf));
 }
 
@@ -3030,7 +3109,7 @@ do_undef (buf, limit, op)
 
   SKIP_WHITE_SPACE (buf);
 
-  if (! strncmp ((const char *)buf, "defined", 7) && ! is_idchar[buf[7]])
+  if (! strncmp ((const char *)buf, "defined", 7) && ! is_idchar (buf[7]))
     warning ("undefining `defined'");
 
   while ((hp = lookup (buf, -1, -1)) != NULL) {
@@ -3121,11 +3200,11 @@ parse_assertion (buf, limit, answerp, type)
   unsigned int len;
 
   bp = symname;
-  if (bp < climit && is_idstart[*bp])
+  if (bp < climit && is_idstart (*bp))
     {
       do
        bp++;
-      while (bp < climit && is_idchar[*bp]);
+      while (bp < climit && is_idchar (*bp));
     }
   len = bp - symname;
 
@@ -3177,9 +3256,9 @@ test_assertion (pbuf)
 
       /* Yuk.  We update pbuf to point after the assertion test.
         First, move past the identifier.  */
-      if (is_space[*buf])
+      if (is_space (*buf))
        buf++;
-      while (is_idchar[*buf])
+      while (is_idchar (*buf))
        buf++;
       /* If we have an answer, we need to move past the parentheses.  */
       if (answer)
@@ -3191,6 +3270,26 @@ test_assertion (pbuf)
   return result;
 }
 
+/* Handle a #error directive.  */
+static void
+do_error (buf, limit, op)
+     U_CHAR *buf;
+     U_CHAR *limit;
+     FILE_BUF *op ATTRIBUTE_UNUSED;
+{
+  error ("#error%.*s", (int) (limit - buf), buf);
+}
+
+/* Handle a #warning directive.  */
+static void
+do_warning (buf, limit, op)
+     U_CHAR *buf;
+     U_CHAR *limit;
+     FILE_BUF *op ATTRIBUTE_UNUSED;
+{
+  warning ("#warning%.*s", (int) (limit - buf), buf);
+}
+
 /* Handle a #assert directive.  */
 static void
 do_assert (buf, limit, op)
@@ -3292,11 +3391,11 @@ canonicalize_text (buf, limit, climit)
 
   for (dest = result; buf < limit;)
     {
-      if (! is_space[*buf])
+      if (! is_space (*buf))
        *dest++ = *buf++;
       else
        {
-         while (++buf < limit && is_space [*buf])
+         while (++buf < limit && is_space (*buf))
            ;
          if (dest != result && buf != limit)
            *dest++ = ' ';
@@ -3411,10 +3510,10 @@ do_xifdef (buf, limit, type)
 
   /* Discard leading and trailing whitespace.  */
   SKIP_WHITE_SPACE (buf);
-  while (limit != buf && is_hor_space[limit[-1]]) limit--;
+  while (limit != buf && is_nvspace (limit[-1])) limit--;
 
   /* Find the end of the identifier at the beginning.  */
-  for (end = buf; is_idchar[*end]; end++);
+  for (end = buf; is_idchar (*end); end++);
 
   if (end == buf)
     skip = (type == T_IFDEF);
@@ -3521,7 +3620,7 @@ skip_if_group (ip, any)
         If not, this # is not special.  */
       bp = beg_of_line;
       while (1) {
-       if (is_hor_space[*bp])
+       if (is_nvspace (*bp))
          bp++;
        else if (*bp == '\\' && bp[1] == '\n')
          bp += 2;
@@ -3545,7 +3644,7 @@ skip_if_group (ip, any)
 
       /* Skip whitespace and \-newline.  */
       while (1) {
-       if (is_hor_space[*bp])
+       if (is_nvspace (*bp))
          bp++;
        else if (*bp == '\\' && bp[1] == '\n')
          bp += 2;
@@ -3565,12 +3664,12 @@ skip_if_group (ip, any)
         symbol-constituents so that we end up with a contiguous name.  */
 
       while (1) {
-       if (is_idchar[*bp])
+       if (is_idchar (*bp))
          bp++;
        else {
          if (*bp == '\\' && bp[1] == '\n')
            name_newline_fix (bp);
-         if (is_idchar[*bp])
+         if (is_idchar (*bp))
            bp++;
          else break;
        }
@@ -3579,7 +3678,7 @@ skip_if_group (ip, any)
       for (kt = directive_table; kt->length >= 0; kt++) {
        IF_STACK_FRAME *temp;
        if (strncmp ((const char *)cp, kt->name, kt->length) == 0
-           && !is_idchar[cp[kt->length]]) {
+           && !is_idchar (cp[kt->length])) {
 
          /* If we are asked to return on next directive,
             do so now.  */
@@ -3926,7 +4025,7 @@ macroexpand (hp, op)
     if (i == 1) {
       register const U_CHAR *bp = args[0].raw;
       register const U_CHAR *lim = bp + args[0].raw_length;
-      while (bp != lim && is_space[*bp]) bp++;
+      while (bp != lim && is_space (*bp)) bp++;
       if (bp == lim)
        i = 0;
     }
@@ -3994,10 +4093,10 @@ macroexpand (hp, op)
          int c;
          i = 0;
          while (i < arglen
-                && (c = arg->raw[i], is_space[c]))
+                && (c = arg->raw[i], is_space (c)))
            i++;
          while (i < arglen
-                && (c = arg->raw[arglen - 1], is_space[c]))
+                && (c = arg->raw[arglen - 1], is_space (c)))
            arglen--;
          for (; i < arglen; i++) {
            c = arg->raw[i];
@@ -4012,13 +4111,13 @@ macroexpand (hp, op)
            /* Internal sequences of whitespace are replaced by one space
               except within an string or char token.  */
            if (! in_string
-               && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) {
+               && (c == '\n' ? arg->raw[i+1] == '\n' : is_space (c))) {
              while (1) {
                /* Note that Newline Space does occur within whitespace
                   sequences; consider it part of the sequence.  */
-               if (c == '\n' && is_space[arg->raw[i+1]])
+               if (c == '\n' && is_space (arg->raw[i+1]))
                  i += 2;
-               else if (c != '\n' && is_space[c])
+               else if (c != '\n' && is_space (c))
                  i++;
                else break;
                c = arg->raw[i];
@@ -4054,8 +4153,8 @@ macroexpand (hp, op)
          const U_CHAR *l1 = p1 + arg->raw_length;
 
          if (ap->raw_before) {
-           while (p1 != l1 && is_space[*p1]) p1++;
-           while (p1 != l1 && is_idchar[*p1])
+           while (p1 != l1 && is_space (*p1)) p1++;
+           while (p1 != l1 && is_idchar (*p1))
              xbuf[totlen++] = *p1++;
            /* Delete any no-reexpansion marker that follows
               an identifier at the beginning of the argument
@@ -4067,7 +4166,7 @@ macroexpand (hp, op)
            /* Arg is concatenated after: delete trailing whitespace,
               whitespace markers, and no-reexpansion markers.  */
            while (p1 != l1) {
-             if (is_space[l1[-1]]) l1--;
+             if (is_space (l1[-1])) l1--;
              else if (l1[-1] == '-') {
                const U_CHAR *p2 = l1 - 1;
                /* If a `-' is preceded by an odd number of newlines then it
@@ -4681,7 +4780,7 @@ install (name, len, type, hash)
 
   if (len < 0) {
     p = name;
-    while (is_idchar[*p])
+    while (is_idchar (*p))
       p++;
     len = p - name;
   }
@@ -4725,7 +4824,7 @@ lookup (name, len, hash)
   register HASHNODE *bucket;
 
   if (len < 0) {
-    for (bp = name; is_idchar[*bp]; bp++) ;
+    for (bp = name; is_idchar (*bp); bp++) ;
     len = bp - name;
   }
 
@@ -4896,44 +4995,6 @@ dump_arg_n (defn, argnum)
     p++;
   }
 }
-\f
-/* Initialize syntactic classifications of characters.  */
-static void
-initialize_char_syntax ()
-{
-  register int i;
-
-  /*
-   * Set up is_idchar and is_idstart tables.  These should be
-   * faster than saying (is_alpha (c) || c == '_'), etc.
-   * Must do set up these things before calling any routines tthat
-   * refer to them.
-   */
-  for (i = 'a'; i <= 'z'; i++) {
-    is_idchar[i - 'a' + 'A'] = 1;
-    is_idchar[i] = 1;
-    is_idstart[i - 'a' + 'A'] = 1;
-    is_idstart[i] = 1;
-  }
-  for (i = '0'; i <= '9'; i++)
-    is_idchar[i] = 1;
-  is_idchar['_'] = 1;
-  is_idstart['_'] = 1;
-
-  /* horizontal space table */
-  is_hor_space[' '] = 1;
-  is_hor_space['\t'] = 1;
-  is_hor_space['\v'] = 1;
-  is_hor_space['\f'] = 1;
-  is_hor_space['\r'] = 1;
-
-  is_space[' '] = 1;
-  is_space['\t'] = 1;
-  is_space['\v'] = 1;
-  is_space['\f'] = 1;
-  is_space['\n'] = 1;
-  is_space['\r'] = 1;
-}
 
 /* Initialize the built-in macros.  */
 #define DSC(x) U x, sizeof x - 1
@@ -5069,38 +5130,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.  */