OSDN Git Service

* flags.h: New flag (optimize_size).
[pf3gnuchains/gcc-fork.git] / gcc / cpplib.c
index 78ac535..9cfd3ac 100644 (file)
@@ -1,7 +1,7 @@
 /* CPP Library.
-   Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
-   Written by Per Bothner, 1994-95.
-   Based on CCCP program by by Paul Rubin, June 1986
+   Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.
+   Contributed by Per Bothner, 1994-95.
+   Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
 
 This program is free software; you can redistribute it and/or modify it
@@ -16,88 +16,81 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them.   Help stamp out software-hoarding!  */
-
-#ifdef EMACS
-#define NO_SHORTNAMES
-#include "../src/config.h"
-#ifdef open
-#undef open
-#undef read
-#undef write
-#endif /* open */
-#endif /* EMACS */
-
-/* The macro EMACS is defined when cpp is distributed as part of Emacs,
-   for the sake of machines with limited C compilers.  */
-#ifndef EMACS
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
 #include "config.h"
-#endif /* not EMACS */
 
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
+#ifndef STDC_VALUE
+#define STDC_VALUE 1
 #endif
 
-#ifndef LOCAL_INCLUDE_DIR
-#define LOCAL_INCLUDE_DIR "/usr/local/include"
+#include <ctype.h>
+#include <stdio.h>
+#include <signal.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
 #endif
 
-#if 0 /* We can't get ptrdiff_t, so I arranged not to need PTR_INT_TYPE.  */
-#ifdef __STDC__
-#define PTR_INT_TYPE ptrdiff_t
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
 #else
-#define PTR_INT_TYPE long
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+#  include <time.h>
+#endif
 #endif
-#endif /* 0 */
 
-#include "cpplib.h"
-#include "cpphash.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
 
-#ifndef STDC_VALUE
-#define STDC_VALUE 1
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
 #endif
 
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
 #endif
 
-/* In case config.h defines these.  */
-#undef bcopy
-#undef bzero
-#undef bcmp
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <signal.h>
-#ifdef __STDC__
-#include <string.h>
-#include <stdlib.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
 #endif
 
-#ifndef VMS
-#ifndef USG
-#include <sys/time.h>          /* for __DATE__ and __TIME__ */
-#include <sys/resource.h>
-#else
-#include <sys/param.h>                 /* CYGNUS LOCAL: shebs -noquiet */
-#include <sys/times.h>
-#include <time.h>
-#include <fcntl.h>
-#endif /* USG */
-#endif /* not VMS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+#endif
+#endif
 
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+/* This defines "errno" properly for VMS, and gives us EACCES.  */
 #include <errno.h>
 
+#include "cpplib.h"
+#include "cpphash.h"
+#include "gansidecl.h"
+
+#ifdef NEED_DECLARATION_INDEX
 extern char *index ();
+#endif
+
+#ifdef NEED_DECLARATION_RINDEX
 extern char *rindex ();
+#endif
+
+#ifdef NEED_DECLARATION_GETENV
+extern char *getenv ();
+#endif
+
+extern char *update_path ();
 
 #ifndef O_RDONLY
 #define O_RDONLY 0
@@ -108,18 +101,26 @@ extern char *rindex ();
 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
 
-/* Find the largest host integer type and set its size and type.  */
-
-#ifndef HOST_BITS_PER_WIDE_INT
-
-#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
-#define HOST_WIDE_INT long
-#else
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
-#define HOST_WIDE_INT int
-#endif
-
+/* Find the largest host integer type and set its size and type.
+   Watch out: on some crazy hosts `long' is shorter than `int'.  */
+
+#ifndef HOST_WIDE_INT
+# if HAVE_INTTYPES_H
+#  include <inttypes.h>
+#  define HOST_WIDE_INT intmax_t
+# else
+#  if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
+       && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
+#   define HOST_WIDE_INT int
+#  else
+#  if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
+       || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
+#   define HOST_WIDE_INT long
+#  else
+#   define HOST_WIDE_INT long long
+#  endif
+#  endif
+# endif
 #endif
 
 #ifndef S_ISREG
@@ -130,24 +131,14 @@ extern char *rindex ();
 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
 #endif
 
-/* Define a generic NULL if one hasn't already been defined.  */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef GENERIC_PTR
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define GENERIC_PTR void *
-#else
-#define GENERIC_PTR char *
-#endif
+/* By default, colon separates directories in a path.  */
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
 #endif
 
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
+#ifndef STANDARD_INCLUDE_DIR
+#define STANDARD_INCLUDE_DIR "/usr/include"
 #endif
-
 #ifndef INCLUDE_LEN_FUDGE
 #define INCLUDE_LEN_FUDGE 0
 #endif
@@ -213,7 +204,7 @@ struct assertion_hashnode {
   struct assertion_hashnode *prev;
   /* also, a back pointer to this node's hash
      chain is kept, in case the node is the head
-     of the chain and gets deleted. */
+     of the chain and gets deleted.  */
   struct assertion_hashnode **bucket_hdr;
   int length;                  /* length of token, for quick comparison */
   U_CHAR *name;                        /* the actual name */
@@ -242,15 +233,11 @@ struct assertion_hashnode {
 #define NEWLINE_FIX \
   do {while (PEEKC() == '\\' && PEEKN(1) == '\n') FORWARD(2); } while(0)
 
-/* Same, but assume we've already read the potential '\\' into C. */
+/* Same, but assume we've already read the potential '\\' into C.  */
 #define NEWLINE_FIX1(C) do { \
     while ((C) == '\\' && PEEKC() == '\n') { FORWARD(1); (C) = GETC(); }\
   } while(0)
 
-/* Name under which this program was invoked.  */
-
-char *progname;
-
 struct cpp_pending {
   struct cpp_pending *next;
   char *cmd;
@@ -259,50 +246,49 @@ struct cpp_pending {
 
 /* Forward declarations.  */
 
-extern char *xmalloc ();
+char *xmalloc ();
+void cpp_fatal ();
+void cpp_file_line_for_message PARAMS ((cpp_reader *, char *, int, int));
+void cpp_hash_cleanup PARAMS ((cpp_reader *));
+void cpp_message ();
+void cpp_print_containing_files PARAMS ((cpp_reader *));
 
 static void add_import ();
 static void append_include_chain ();
-static void make_undef ();
-static void make_definition ();
 static void make_assertion ();
 static void path_include ();
 static void initialize_builtins ();
 static void initialize_char_syntax ();
-static void dump_arg_n ();
-static void dump_defn_1 ();
 extern void delete_macro ();
+#if 0
 static void trigraph_pcp ();
+#endif
 static int finclude ();
 static void validate_else ();
 static int comp_def_part ();
+#ifdef abort
 extern void fancy_abort ();
-static void pipe_closed ();
-static void print_containing_files ();
+#endif
 static int lookup_import ();
 static int redundant_include_p ();
 static is_system_include ();
 static struct file_name_map *read_name_map ();
 static char *read_filename_string ();
 static int open_include_file ();
-static int check_preconditions ();
-static void pcfinclude ();
-static void pcstring_used ();
 static int check_macro_name ();
 static int compare_defs ();
 static int compare_token_lists ();
 static HOST_WIDE_INT eval_if_expression ();
 static int change_newlines ();
-static int line_for_error ();
 extern int hashf ();
-static int file_size_and_mode ();
 static struct arglist *read_token_list ();
 static void free_token_list ();
 static int safe_read ();
 static void push_macro_expansion PARAMS ((cpp_reader *,
-                                         U_CHAR*, int, HASHNODE*));
+                                         U_CHAR *, int, HASHNODE *));
+static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
 extern char *xrealloc ();
-extern char *xcalloc ();
+static char *xcalloc ();
 static char *savestring ();
 
 static void conditional_skip ();
@@ -313,9 +299,8 @@ enum file_change_code {same_file, enter_file, leave_file};
 
 /* External declarations.  */
 
-extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader*));
+extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader *));
 
-extern char *getenv ();
 extern FILE *fdopen ();
 extern char *version_string;
 extern struct tm *localtime ();
@@ -358,12 +343,17 @@ struct file_name_list
     int got_name_map;
   };
 
-/* #include "file" looks in source file dir, then stack. */
-/* #include <file> just looks in the stack. */
-/* -I directories are added to the end, then the defaults are added. */
+/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
+   via the same directory as the file that #included it.  */
+#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
+
+/* #include "file" looks in source file dir, then stack.  */
+/* #include <file> just looks in the stack.  */
+/* -I directories are added to the end, then the defaults are added.  */
 /* The */
 static struct default_include {
   char *fname;                 /* The name of the directory.  */
+  char *component;             /* The component containing the directory */
   int cplusplus;               /* Only look here if we're compiling C++.  */
   int cxx_aware;               /* Includes in this directory don't need to
                                   be wrapped in extern "C" when compiling
@@ -374,33 +364,43 @@ static struct default_include {
 #else
   = {
     /* Pick up GNU C++ specific include files.  */
-    { GPLUSPLUS_INCLUDE_DIR, 1, 1 },
+    { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
+    { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 },
 #ifdef CROSS_COMPILE
     /* This is the dir for fixincludes.  Put it just before
        the files that we fix.  */
-    { GCC_INCLUDE_DIR, 0, 0 },
+    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
     /* For cross-compilation, this dir name is generated
        automatically in Makefile.in.  */
-    { CROSS_INCLUDE_DIR, 0, 0 },
+    { CROSS_INCLUDE_DIR, "GCC",0, 0 },
+#ifdef TOOL_INCLUDE_DIR
     /* This is another place that the target system's headers might be.  */
-    { TOOL_INCLUDE_DIR, 0, 1 },
+    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
 #else /* not CROSS_COMPILE */
+#ifdef LOCAL_INCLUDE_DIR
     /* This should be /usr/local/include and should come before
        the fixincludes-fixed header files.  */
-    { LOCAL_INCLUDE_DIR, 0, 1 },
+    { LOCAL_INCLUDE_DIR, 0, 0, 1 },
+#endif
+#ifdef TOOL_INCLUDE_DIR
     /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
        Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h.  */
-    { TOOL_INCLUDE_DIR, 0, 1 },
+    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
     /* This is the dir for fixincludes.  Put it just before
        the files that we fix.  */
-    { GCC_INCLUDE_DIR, 0, 0 },
+    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
     /* Some systems have an extra dir of include files.  */
 #ifdef SYSTEM_INCLUDE_DIR
-    { SYSTEM_INCLUDE_DIR, 0, 0 },
+    { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
 #endif
-    { STANDARD_INCLUDE_DIR, 0, 0 },
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
+#endif
+    { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
 #endif /* not CROSS_COMPILE */
-    { 0, 0, 0 }
+    { 0, 0, 0, 0 }
     };
 #endif /* no INCLUDE_DEFAULTS */
 
@@ -410,17 +410,17 @@ struct directive {
   int length;                  /* Length of name */
   int (*func)();               /* Function to handle directive */
   char *name;                  /* Name of directive */
-  enum node_type type;         /* Code which describes which directive. */
-  char command_reads_line;      /* One if rest of line is read by func. */
-  char traditional_comments;   /* Nonzero: keep comments if -traditional.  */
-  char pass_thru;              /* Copy preprocessed directive to output file.*/
+  enum node_type type;         /* Code which describes which directive.  */
+  char command_reads_line;      /* One if rest of line is read by func.  */
 };
 
+#define IS_INCLUDE_DIRECTIVE_TYPE(t) (T_INCLUDE <= (t) && (t) <= T_IMPORT)
+
 /* Here is the actual list of #-directives, most-often-used first.
    The initialize_builtins function assumes #define is the very first.  */
 
 static struct directive directive_table[] = {
-  {  6, do_define, "define", T_DEFINE, 0, 1},
+  {  6, do_define, "define", T_DEFINE},
   {  5, do_xifdef, "ifdef", T_IFDEF, 1},
   {  6, do_xifdef, "ifndef", T_IFNDEF, 1},
   {  7, do_include, "include", T_INCLUDE, 1},
@@ -433,9 +433,9 @@ static struct directive directive_table[] = {
   {  5, do_undef, "undef", T_UNDEF},
   {  5, do_error, "error", T_ERROR},
   {  7, do_warning, "warning", T_WARNING},
-  {  6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1},
+  {  6, do_pragma, "pragma", T_PRAGMA},
   {  4, do_line, "line", T_LINE, 1},
-  {  5, do_ident, "ident", T_IDENT, 1, 0, 1},
+  {  5, do_ident, "ident", T_IDENT, 1},
 #ifdef SCCS_DIRECTIVE
   {  4, do_sccs, "sccs", T_SCCS},
 #endif
@@ -444,9 +444,9 @@ static struct directive directive_table[] = {
   {  -1, 0, "", T_UNUSED},
 };
 \f
-/* table to tell if char can be part of a C identifier. */
+/* 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. */
+/* 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];
@@ -495,69 +495,10 @@ initialize_char_syntax (opts)
   is_space['\r'] = 1;
 }
 
-/*
- * Skip over a quoted string.  BP points to the opening quote.
- * Returns a pointer after the closing quote.  Don't go past LIMIT.
- * START_LINE is the line number of the starting point (but it need
- * not be valid if the starting point is inside a macro expansion).
- *
- * The input stack state is not changed.
- */
-static U_CHAR *
-skip_quoted_string (pfile, first, start_line)
-     cpp_reader *pfile;
-     int first;
-     int start_line;
-{
-  int c;
-
-  while (1)
-    {
-      c = GETC ();
-      if (c == EOF)
-       {
-         cpp_error_with_line (pfile, line_for_error (start_line),
-                              "unterminated string or character constant");
-#if 0
-         cpp_error_with_line (pfile, multiline_string_line,
-                              "possible real start of unterminated constant");
-         multiline_string_line = 0;
-#endif
-         break;
-       }
-      if (c == '\\')
-       {
-         c = GETC ();
-         NEWLINE_FIX1(c);
-       }
-      else if (c == '\n')
-       {
-         if (CPP_TRADITIONAL (pfile))
-           {
-             /* Unterminated strings and character constants are 'legal'.  */
-             FORWARD(-1);      /* Don't consume the newline. */
-             break;
-           }
-         if (CPP_PEDANTIC (pfile) || first == '\'')
-           {
-             cpp_error_with_line (pfile, line_for_error (start_line),
-                                  "unterminated string or character constant");
-             FORWARD(-1);
-             break;
-           }
-         /* If not traditional, then allow newlines inside strings.  */
-#if 0
-         if (multiline_string_line == 0)
-           multiline_string_line = start_line;
-#endif
-      }
-      else if (c == first)
-       break;
-    }
-}
 
 /* Place into PFILE a quoted string representing the string SRC.
-   Caller must reserve enough space in pfile->token_buffer. */
+   Caller must reserve enough space in pfile->token_buffer.  */
+
 static void
 quote_string (pfile, src)
      cpp_reader *pfile;
@@ -574,7 +515,7 @@ quote_string (pfile, src)
          CPP_PUTC_Q (pfile, c);
        else
          {
-           sprintf (CPP_PWRITTEN (pfile), "\\%03o", c);
+           sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
            CPP_ADJUST_WRITTEN (pfile, 4);
          }
        break;
@@ -592,7 +533,7 @@ quote_string (pfile, src)
       }
 }
 
-/* Make sure PFILE->token_buffer will hold at least N more chars. */
+/* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */
 
 void
 cpp_grow_buffer (pfile, n)
@@ -601,7 +542,7 @@ cpp_grow_buffer (pfile, n)
 {
   long old_written = CPP_WRITTEN (pfile);
   pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
-  pfile->token_buffer = (char*)
+  pfile->token_buffer = (U_CHAR *)
     xrealloc(pfile->token_buffer, pfile->token_buffer_size);
   CPP_SET_WRITTEN (pfile, old_written);
 }
@@ -614,8 +555,8 @@ cpp_grow_buffer (pfile, n)
  * be identifier=definition.
  */
 
-static void
-make_definition (pfile, str)
+void
+cpp_define (pfile, str)
      cpp_reader *pfile;
      U_CHAR *str;
 {
@@ -674,7 +615,6 @@ make_assertion (pfile, option, str)
      char *option;
      U_CHAR *str;
 {
-  cpp_buffer *ip;
   struct directive *kt;
   U_CHAR *buf, *p, *q;
 
@@ -706,9 +646,11 @@ make_assertion (pfile, option, str)
     return;
   }
   
-  ip = cpp_push_buffer (pfile, buf, strlen (buf));
-  do_assert (pfile, NULL, NULL, NULL);
-  cpp_pop_buffer (pfile);
+  if (cpp_push_buffer (pfile, buf, strlen (buf)) != NULL)
+    {
+      do_assert (pfile, NULL, NULL, NULL);
+      cpp_pop_buffer (pfile);
+    }
 }
 \f
 /* Append a chain of `struct file_name_list's
@@ -840,17 +782,16 @@ path_include (pfile, path)
 }
 \f
 void
-init_parse_options (opts)
-     struct cpp_options *opts;
+cpp_options_init (opts)
+     cpp_options *opts;
 {
-  bzero (opts, sizeof *opts);
+  bzero ((char *) opts, sizeof *opts);
   opts->in_fname = NULL;
   opts->out_fname = NULL;
 
   /* Initialize is_idchar to allow $.  */
   opts->dollars_in_ident = 1;
   initialize_char_syntax (opts);
-  opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0;
 
   opts->no_line_commands = 0;
   opts->no_trigraphs = 1;
@@ -858,6 +799,7 @@ init_parse_options (opts)
   opts->print_include_names = 0;
   opts->dump_macros = dump_none;
   opts->no_output = 0;
+  opts->remap = 0;
   opts->cplusplus = 0;
   opts->cplusplus_comments = 0;
 
@@ -893,7 +835,7 @@ macro_cleanup (pbuf, pfile)
      cpp_buffer *pbuf;
      cpp_reader *pfile;
 {
-  HASHNODE *macro = (HASHNODE*)pbuf->data;
+  HASHNODE *macro = (HASHNODE *) pbuf->data;
   if (macro->type == T_DISABLED)
     macro->type = T_MACRO;
   if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
@@ -906,55 +848,26 @@ file_cleanup (pbuf, pfile)
      cpp_buffer *pbuf;
      cpp_reader *pfile;
 {
+  if (pbuf->buf)
+    {
+      free (pbuf->buf);
+      pbuf->buf = 0;
+    }
   return 0;
 }
 
-static void
-newline_fix (pfile)
-     cpp_reader *pfile;
-{
-#if 1
-  NEWLINE_FIX;
-#else
-  register U_CHAR *p = bp;
-
-  /* First count the backslash-newline pairs here.  */
-
-  while (p[0] == '\\' && p[1] == '\n')
-    p += 2;
-
-  /* What follows the backslash-newlines is not embarrassing.  */
-
-  if (*p != '/' && *p != '*')
-    return;
-
-  /* Copy all potentially embarrassing characters
-     that follow the backslash-newline pairs
-     down to where the pairs originally started.  */
-
-  while (*p == '*' || *p == '/')
-    *bp++ = *p++;
-
-  /* Now write the same number of pairs after the embarrassing chars.  */
-  while (bp < p) {
-    *bp++ = '\\';
-    *bp++ = '\n';
-  }
-#endif
-}
-
 /* Assuming we have read '/'.
    If this is the start of a comment (followed by '*' or '/'),
    skip to the end of the comment, and return ' '.
    Return EOF if we reached the end of file before the end of the comment.
-   If not the start of a comment, return '/'. */
+   If not the start of a comment, return '/'.  */
 
 static int
 skip_comment (pfile, linep)
      cpp_reader *pfile;
      long *linep;
 {
-  int c;
+  int c = 0;
   while (PEEKC() == '\\' && PEEKN(1) == '\n')
     {
       if (linep)
@@ -989,7 +902,7 @@ skip_comment (pfile, linep)
        {
          c = GETC ();
          if (c == EOF)
-           return ' '; /* Allow // to be terminated by EOF. */
+           return ' '; /* Allow // to be terminated by EOF.  */
          while (c == '\\' && PEEKC() == '\n')
            {
              FORWARD(1);
@@ -999,7 +912,7 @@ skip_comment (pfile, linep)
            }
          if (c == '\n')
            {
-             /* Don't consider final '\n' to be part of comment. */
+             /* Don't consider final '\n' to be part of comment.  */
              FORWARD(-1);
              return ' ';
            }
@@ -1010,6 +923,7 @@ skip_comment (pfile, linep)
 }     
 
 /* Skip whitespace \-newline and comments.  Does not macro-expand.  */
+
 void
 cpp_skip_hspace (pfile)
      cpp_reader *pfile;
@@ -1038,14 +952,17 @@ cpp_skip_hspace (pfile)
       else if (c == '\\' && PEEKN(1) == '\n') {
        FORWARD(2);
       }
+      else if (c == '@' && CPP_BUFFER (pfile)->has_escapes
+              && is_hor_space[PEEKN(1)])
+       FORWARD(2);
       else return;
     }
 }
 
 /* Read the rest of the current line.
-   The line is appended to PFILE's output buffer. */
+   The line is appended to PFILE's output buffer.  */
 
-void
+static void
 copy_rest_of_line (pfile)
      cpp_reader *pfile;
 {
@@ -1070,7 +987,7 @@ copy_rest_of_line (pfile)
          break;
        case '/':
          nextc = PEEKC();
-         if (nextc == '*' || (opts->cplusplus_comments && nextc == '*'))
+         if (nextc == '*' || (opts->cplusplus_comments && nextc == '/'))
            goto scan_directive_token;
          break;
        case '\f':
@@ -1128,7 +1045,7 @@ handle_directive (pfile)
       goto done_a_directive;
     }
 
-  /* Now find the directive name. */
+  /* Now find the directive name.  */
   CPP_PUTC (pfile, '#');
   parse_name (pfile, GETC());
   ident = pfile->token_buffer + old_written + 1;
@@ -1174,11 +1091,13 @@ handle_directive (pfile)
       break;
   }
 
-  if (! kt->command_reads_line)
+  if (kt->command_reads_line)
+    after_ident = 0;
+  else
     {
       /* Nonzero means do not delete comments within the directive.
          #define needs this when -traditional.  */
-       int comments = CPP_TRADITIONAL (pfile) && kt->traditional_comments; 
+       int comments = CPP_TRADITIONAL (pfile) && kt->type == T_DEFINE;
        int save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
        CPP_OPTIONS (pfile)->put_out_comments = comments;
        after_ident = CPP_WRITTEN (pfile);
@@ -1186,37 +1105,39 @@ handle_directive (pfile)
        CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
     }
 
-  /* For #pragma and #define, we may want to pass through the directive.
+  /* We may want to pass through #define, #pragma, and #include.
      Other directives may create output, but we don't want the directive
-     itself out, so we pop it now.  For example #include may write a #line
-     command (see comment in do_include), and conditionals may emit
+     itself out, so we pop it now.  For example conditionals may emit
      #failed ... #endfailed stuff.  But note that popping the buffer
      means the parameters to kt->func may point after pfile->limit
      so these parameters are invalid as soon as something gets appended
      to the token_buffer.  */
 
   line_end = CPP_PWRITTEN (pfile);
-  if (!kt->pass_thru && kt->type != T_DEFINE)
+  if (! (kt->type == T_DEFINE
+        || kt->type == T_PRAGMA
+        || (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)
+            && CPP_OPTIONS (pfile)->dump_includes)))
     CPP_SET_WRITTEN (pfile, old_written);
 
   (*kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
-  if (kt->pass_thru
-      || (kt->type == T_DEFINE
-         && CPP_OPTIONS (pfile)->dump_macros == dump_definitions))
-    {
-      /* Just leave the entire #define in the output stack. */
-    }
-  else if (kt->type == T_DEFINE
-          && CPP_OPTIONS (pfile)->dump_macros == dump_names)
+
+  if (kt->type == T_DEFINE)
     {
-      U_CHAR *p = pfile->token_buffer + old_written + 7;  /* Skip "#define". */
-      SKIP_WHITE_SPACE (p);
-      while (is_idchar[*p]) p++;
-      pfile->limit = p;
-      CPP_PUTC (pfile, '\n');
+      if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
+       {
+         /* Skip "#define". */
+         U_CHAR *p = pfile->token_buffer + old_written + 7;
+
+         SKIP_WHITE_SPACE (p);
+         while (is_idchar[*p]) p++;
+         pfile->limit = p;
+         CPP_PUTC (pfile, '\n');
+       }
+      else if (CPP_OPTIONS (pfile)->dump_macros != dump_definitions)
+       CPP_SET_WRITTEN (pfile, old_written);
     }
-  else if (kt->type == T_DEFINE)
-    CPP_SET_WRITTEN (pfile, old_written);
+
  done_a_directive:
   return 1;
 
@@ -1260,7 +1181,7 @@ pass_thru_directive (buf, limit, pfile, keyword)
    appeared.  So the arglist is just convenience data passed
    between these two routines.  It is not kept around after
    the current #define has been processed and entered into the
-   hash table. */
+   hash table.  */
 
 struct arglist {
   struct arglist *next;
@@ -1279,18 +1200,18 @@ struct arglist {
    MACRONAME is the macro name itself (so we can avoid recursive expansion)
    and NAMELEN is its length in characters.
    
-Note that comments and backslash-newlines have already been deleted
-from the argument.  */
+   Note that comments, backslash-newlines, and leading white space
+   have already been deleted from the argument.  */
 
 static DEFINITION *
-collect_expansion (pfile, buf, end, nargs, arglist)
+collect_expansion (pfile, buf, limit, nargs, arglist)
      cpp_reader *pfile;
-     U_CHAR *buf, *end;
+     U_CHAR *buf, *limit;
      int nargs;
      struct arglist *arglist;
 {
   DEFINITION *defn;
-  register U_CHAR *p, *limit, *lastp, *exp_p;
+  register U_CHAR *p, *lastp, *exp_p;
   struct reflist *endpat = NULL;
   /* Pointer to first nonspace after last ## seen.  */
   U_CHAR *concat = 0;
@@ -1302,26 +1223,26 @@ collect_expansion (pfile, buf, end, nargs, arglist)
   /* Scan thru the replacement list, ignoring comments and quoted
      strings, picking up on the macro calls.  It does a linear search
      thru the arg list on every potential symbol.  Profiling might say
-     that something smarter should happen. */
+     that something smarter should happen.  */
 
-  if (end < buf)
+  if (limit < buf)
     abort ();
 
   /* Find the beginning of the trailing whitespace.  */
-  /* Find end of leading whitespace.  */
-  limit = end;
   p = buf;
   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.
      Each other input char may or may not need 1 byte,
-     so this is an upper bound.
-     The extra 2 are for invented trailing newline-marker and final null.  */
+     so this is an upper bound.  The extra 5 are for invented
+     leading and trailing newline-marker and final null.  */
   maxsize = (sizeof (DEFINITION)
-            + 2 * (end - limit) + 2 * (p - buf)
-            + (limit - p) + 3);
+            + (limit - p) + 5);
+  /* Occurrences of '@' get doubled, so allocate extra space for them.  */
+  while (p < limit)
+    if (*p++ == '@')
+      maxsize++;
   defn = (DEFINITION *) xcalloc (1, maxsize);
 
   defn->nargs = nargs;
@@ -1330,7 +1251,9 @@ collect_expansion (pfile, buf, end, nargs, arglist)
 
   p = buf;
 
-  /* Add one initial space (often removed by macroexpand). */
+  /* Add one initial space escape-marker to prevent accidental
+     token-pasting (often removed by macroexpand).  */
+  *exp_p++ = '@';
   *exp_p++ = ' ';
 
   if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
@@ -1356,16 +1279,8 @@ collect_expansion (pfile, buf, end, nargs, arglist)
           expected_delimiter = c;
        break;
 
-       /* Special hack: if a \# is written in the #define
-          include a # in the definition.  This is useless for C code
-          but useful for preprocessing other things.  */
-
       case '\\':
-       /* \# quotes a # even outside of strings.  */
-       if (p < limit && *p == '#' && !expected_delimiter) {
-         exp_p--;
-         *exp_p++ = *p++;
-       } else if (p < limit && expected_delimiter) {
+       if (p < limit && expected_delimiter) {
          /* In a string, backslash goes through
             and makes next char ordinary.  */
          *exp_p++ = *p++;
@@ -1373,7 +1288,10 @@ collect_expansion (pfile, buf, end, nargs, arglist)
        break;
 
       case '@':
-       *exp_p++ = c;
+       /* An '@' in a string or character constant stands for itself,
+          and does not need to be escaped.  */
+       if (!expected_delimiter)
+         *exp_p++ = c;
        break;
 
       case '#':
@@ -1398,7 +1316,8 @@ collect_expansion (pfile, buf, end, nargs, arglist)
             Don't leave the # in the expansion.  */
          exp_p--;
          SKIP_WHITE_SPACE (p);
-         if (p == limit || ! is_idstart[*p])
+         if (p == limit || ! is_idstart[*p]
+             || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
            cpp_error (pfile,
                     "`#' operator is not followed by a macro argument name");
          else
@@ -1459,7 +1378,8 @@ collect_expansion (pfile, buf, end, nargs, arglist)
       while (p != limit && is_idchar[*p]) p++;
       id_len = p - id_beg;
 
-      if (is_idstart[c]) {
+      if (is_idstart[c]
+         && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
        register struct arglist *arg;
 
        for (arg = arglist; arg != NULL; arg = arg->next) {
@@ -1526,16 +1446,14 @@ collect_expansion (pfile, buf, end, nargs, arglist)
     }
   }
 
-  if (limit < end) {
-    while (limit < end && is_space[*limit]) {
-      *exp_p++ = *limit++;
+  if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
+    {
+      /* If ANSI, put in a "@ " marker to prevent token pasting.
+         But not if "inside a string" (which in ANSI mode
+         happens only for -D option).  */
+      *exp_p++ = '@';
+      *exp_p++ = ' ';
     }
-  } else if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0) {
-    /* There is no trailing whitespace, so invent some in ANSI mode.
-       But not if "inside a string" (which in ANSI mode
-       happens only for -D option).  */
-    *exp_p++ = ' ';
-  }
 
   *exp_p = '\0';
 
@@ -1570,7 +1488,8 @@ static char rest_extension[] = "...";
 #define REST_EXTENSION_LENGTH  (sizeof (rest_extension) - 1)
 
 /* Create a DEFINITION node from a #define directive.  Arguments are 
-   as for do_define. */
+   as for do_define.  */
+
 static MACRODEF
 create_definition (buf, limit, pfile, predefinition)
      U_CHAR *buf, *limit;
@@ -1601,7 +1520,7 @@ create_definition (buf, limit, pfile, predefinition)
 
   /* Lossage will occur if identifiers or control keywords are broken
      across lines using backslash.  This is not the right place to take
-     care of that. */
+     care of that.  */
 
   if (*bp == '(') {
     struct arglist *arg_ptrs = NULL;
@@ -1631,8 +1550,8 @@ create_definition (buf, limit, pfile, predefinition)
       while (is_idchar[*bp]) {
        bp++;
        /* do we have a "special" rest-args extension here? */
-       if (limit - bp > REST_EXTENSION_LENGTH &&
-           strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
+       if (limit - bp > REST_EXTENSION_LENGTH
+           && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
          rest_args = 1;
          temp->rest_args = 1;
          break;
@@ -1659,8 +1578,8 @@ create_definition (buf, limit, pfile, predefinition)
        struct arglist *otemp;
 
        for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
-         if (temp->length == otemp->length &&
-           strncmp (temp->name, otemp->name, temp->length) == 0) {
+         if (temp->length == otemp->length
+             && strncmp (temp->name, otemp->name, temp->length) == 0) {
              U_CHAR *name;
 
              name = (U_CHAR *) alloca (temp->length + 1);
@@ -1674,9 +1593,8 @@ create_definition (buf, limit, pfile, predefinition)
     }
 
     ++bp;                      /* skip paren */
-    /* Skip exactly one space or tab if any.  */
-    if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp;
-    /* now everything from bp before limit is the definition. */
+    SKIP_WHITE_SPACE (bp);
+    /* now everything from bp before limit is the definition.  */
     defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
     defn->rest_args = rest_args;
 
@@ -1723,7 +1641,7 @@ create_definition (buf, limit, pfile, predefinition)
          }
        }
       }
-    /* now everything from bp before limit is the definition. */
+    /* now everything from bp before limit is the definition.  */
     defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
     defn->args.argnames = (U_CHAR *) "";
   }
@@ -1759,10 +1677,11 @@ check_macro_name (pfile, symname, usage)
   for (p = symname; is_idchar[*p]; p++)
     ;
   sym_length = p - symname;
-  if (sym_length == 0)
+  if (sym_length == 0
+      || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
     cpp_error (pfile, "invalid %s name", usage);
   else if (!is_idstart[*symname]) {
-    U_CHAR *msg;                       /* what pain... */
+    U_CHAR *msg;                       /* what pain...  */
     msg = (U_CHAR *) alloca (sym_length + 1);
     bcopy (symname, msg, sym_length);
     msg[sym_length] = 0;
@@ -1774,11 +1693,11 @@ check_macro_name (pfile, symname, usage)
   return sym_length;
 }
 
-/*
- * return zero if two DEFINITIONs are isomorphic
- */
+/* Return zero if two DEFINITIONs are isomorphic.  */
+
 static int
-compare_defs (d1, d2)
+compare_defs (pfile, d1, d2)
+     cpp_reader *pfile;
      DEFINITION *d1, *d2;
 {
   register struct reflist *a1, *a2;
@@ -1788,7 +1707,8 @@ compare_defs (d1, d2)
 
   if (d1->nargs != d2->nargs)
     return 1;
-  if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
+  if (CPP_PEDANTIC (pfile)
+      && strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
     return 1;
   for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
        a1 = a1->next, a2 = a2->next) {
@@ -1884,14 +1804,14 @@ do_define (pfile, keyword, buf, limit)
        ok = 1;
       /* Redefining a macro is ok if the definitions are the same.  */
       else if (hp->type == T_MACRO)
-       ok = ! compare_defs (mdef.defn, hp->value.defn);
+       ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
       /* Redefining a constant is ok with -D.  */
       else if (hp->type == T_CONST)
         ok = ! CPP_OPTIONS (pfile)->done_initializing;
       /* Print the warning if it's not ok.  */
       if (!ok)
        {
-         U_CHAR *msg;          /* what pain... */
+         U_CHAR *msg;          /* what pain...  */
 
          /* If we are passing through #define and #undef directives, do
             that for this re-definition now.  */
@@ -1936,7 +1856,7 @@ nope:
    if stringified.
    `use_count' is the number of times this macro arg is substituted
    into the macro.  If the actual use count exceeds 10, 
-   the value stored is 10. */
+   the value stored is 10.  */
 
 /* raw and expanded are relative to ARG_BASE */
 #define ARG_BASE ((pfile)->token_buffer)
@@ -1947,30 +1867,30 @@ struct argdata {
   int raw_length, expand_length;
   int stringified_length;
   char newlines;
-  char comments;
   char use_count;
 };
 
+/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
+   If BUFFER != NULL, then use the LENGTH characters in BUFFER
+   as the new input buffer.
+   Return the new buffer, or NULL on failure.  */
 
-cpp_buffer*
+cpp_buffer *
 cpp_push_buffer (pfile, buffer, length)
      cpp_reader *pfile;
      U_CHAR *buffer;
      long length;
 {
-#ifdef STATIC_BUFFERS
-  register cpp_buffer *buf;
+  register cpp_buffer *buf = CPP_BUFFER (pfile);
   if (buf == pfile->buffer_stack)
-    fatal ("macro or `#include' recursion too deep");
-  buf = CPP_BUFFER (pfile) - 1;
-  bzero ((char *) buf, sizeof (cpp_buffer));
-  CPP_BUFFER (pfile) = buf;
-#else
-  register cpp_buffer *buf = (cpp_buffer*) xmalloc (sizeof(cpp_buffer));
+    {
+      cpp_fatal (pfile, "%s: macro or `#include' recursion too deep",
+                buf->fname);
+      return NULL;
+    }
+  buf--;
   bzero ((char *) buf, sizeof (cpp_buffer));
-  CPP_PREV_BUFFER (buf) = CPP_BUFFER (pfile);
   CPP_BUFFER (pfile) = buf;
-#endif
   buf->if_stack = pfile->if_stack;
   buf->cleanup = null_cleanup;
   buf->underflow = null_underflow;
@@ -1980,25 +1900,17 @@ cpp_push_buffer (pfile, buffer, length)
   return buf;
 }
 
-cpp_buffer*
+cpp_buffer *
 cpp_pop_buffer (pfile)
      cpp_reader *pfile;
 {
   cpp_buffer *buf = CPP_BUFFER (pfile);
-#ifdef STATIC_BUFFERS
   (*buf->cleanup) (buf, pfile);
   return ++CPP_BUFFER (pfile);
-#else
-  cpp_buffer *next_buf = CPP_PREV_BUFFER (buf);
-  (*buf->cleanup) (buf, pfile);
-  CPP_BUFFER (pfile) = next_buf;
-  free (buf);
-  return next_buf;
-#endif
 }
 
 /* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.
-   Pop the buffer when done. */
+   Pop the buffer when done.  */
 
 void
 cpp_scan_buffer (pfile)
@@ -2008,7 +1920,7 @@ cpp_scan_buffer (pfile)
   for (;;)
     {
       enum cpp_token token = cpp_get_token (pfile);
-      if (token == CPP_EOF) /* Should not happen ... */
+      if (token == CPP_EOF) /* Should not happen ...  */
        break;
       if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
        {
@@ -2019,20 +1931,15 @@ cpp_scan_buffer (pfile)
 }
 
 /*
- * Rescan a string into pfile's buffer.
+ * Rescan a string (which may have escape marks) into pfile's buffer.
  * Place the result in pfile->token_buffer.
  *
  * The input is copied before it is scanned, so it is safe to pass
  * it something from the token_buffer that will get overwritten
  * (because it follows CPP_WRITTEN).  This is used by do_include.
- *
- * OUTPUT_MARKS nonzero means keep Newline markers found in the input
- * and insert such markers when appropriate.  See `rescan' for details.
- * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately
- * before substitution; it is 0 for other uses.
  */
 
-void
+static void
 cpp_expand_to_buffer (pfile, buf, length)
      cpp_reader *pfile;
      U_CHAR *buf;
@@ -2062,6 +1969,9 @@ cpp_expand_to_buffer (pfile, buf, length)
   buf1[length] = 0;
 
   ip = cpp_push_buffer (pfile, buf1, length);
+  if (ip == NULL)
+    return;
+  ip->has_escapes = 1;
 #if 0
   ip->lineno = obuf.lineno = 1;
 #endif
@@ -2095,7 +2005,7 @@ adjust_position (buf, limit, linep, colp)
     }
 }
 
-/* Move line_base forward, updating lineno and colno. */
+/* Move line_base forward, updating lineno and colno.  */
 
 static void
 update_position (pbuf)
@@ -2134,15 +2044,15 @@ cpp_buf_line_and_col (pbuf, linep, colp)
     }
 }
 
-/* Return the cpp_buffer that corresponds to a file (not a macro). */
+/* Return the cpp_buffer that corresponds to a file (not a macro).  */
 
-cpp_buffer*
+cpp_buffer *
 cpp_file_buffer (pfile)
      cpp_reader *pfile;
 {
-  cpp_buffer *ip;
+  cpp_buffer *ip = CPP_BUFFER (pfile);
 
-  for (ip = CPP_BUFFER (pfile); ip != NULL; ip = CPP_PREV_BUFFER (ip))
+  for ( ; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
     if (ip->fname != NULL)
       return ip;
   return NULL;
@@ -2182,16 +2092,22 @@ output_line_command (pfile, conditional, file_change)
   long line, col;
   cpp_buffer *ip = CPP_BUFFER (pfile);
 
-  if (CPP_OPTIONS (pfile)->no_line_commands
-      || ip->fname == NULL || CPP_OPTIONS (pfile)->no_output) {
+  if (ip->fname == NULL)
     return;
-  }
 
   update_position (ip);
+
+  if (CPP_OPTIONS (pfile)->no_line_commands
+      || CPP_OPTIONS (pfile)->no_output)
+    return;
+
   line = CPP_BUFFER (pfile)->lineno;
   col = CPP_BUFFER (pfile)->colno;
   adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
 
+  if (CPP_OPTIONS (pfile)->no_line_commands)
+    return;
+
   if (conditional) {
     if (line == pfile->lineno)
       return;
@@ -2227,7 +2143,7 @@ output_line_command (pfile, conditional, file_change)
     CPP_PUTS_Q (pfile, sharp_line, sizeof(sharp_line)-1);
   }
 
-  sprintf (CPP_PWRITTEN (pfile), "%d ", line);
+  sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
   CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
 
   quote_string (pfile, ip->nominal_fname); 
@@ -2252,7 +2168,7 @@ output_line_command (pfile, conditional, file_change)
 }
 \f
 /*
- * Parse a macro argument and store the info on it into *ARGPTR.
+ * Parse a macro argument and append the info on PFILE's token_buffer.
  * REST_ARGS means to absorb the rest of the args.
  * Return nonzero to indicate a syntax error.
  */
@@ -2299,7 +2215,7 @@ macarg (pfile, rest_args)
            goto found;
          break;
        found:
-         /* Remove ',' or ')' from argument buffer. */
+         /* Remove ',' or ')' from argument buffer.  */
          CPP_ADJUST_WRITTEN (pfile, -1);
          goto done;
       default: ;
@@ -2361,7 +2277,7 @@ timestamp (pfile)
      cpp_reader *pfile;
 {
   if (!pfile->timebuf) {
-    time_t t = time ((time_t *)0);
+    time_t t = time ((time_t *) 0);
     pfile->timebuf = localtime (&t);
   }
   return pfile->timebuf;
@@ -2399,7 +2315,7 @@ special_symbol (hp, pfile)
     
   for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
     {
-      if (ip == NULL)
+      if (ip == CPP_NULL_BUFFER (pfile))
        {
          cpp_error (pfile, "cccp error: not in any file?!");
          return;                       /* the show must go on */
@@ -2416,7 +2332,7 @@ special_symbol (hp, pfile)
        char *string;
        if (hp->type == T_BASE_FILE)
          {
-           while (CPP_PREV_BUFFER (ip))
+           while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
              ip = CPP_PREV_BUFFER (ip);
          }
        string = ip->nominal_fname;
@@ -2430,7 +2346,8 @@ special_symbol (hp, pfile)
 
     case T_INCLUDE_LEVEL:
       true_indepth = 0;
-      for (ip = CPP_BUFFER (pfile);  ip != NULL; ip = CPP_PREV_BUFFER (ip))
+      ip = CPP_BUFFER (pfile);
+      for (;  ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
        if (ip->fname != NULL)
          true_indepth++;
 
@@ -2470,6 +2387,12 @@ special_symbol (hp, pfile)
   case T_CONST:
       buf = (char *) alloca (4 * sizeof (int));
       sprintf (buf, "%d", hp->value.ival);
+#ifdef STDC_0_IN_SYSTEM_HEADERS
+      if (ip->system_header_p
+         && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
+         && ! cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", -1, -1))
+       strcpy (buf, "0");
+#endif
 #if 0
       if (pcp_inside_if && pcp_outfile)
        /* Output a precondition for this macro use */
@@ -2479,13 +2402,12 @@ special_symbol (hp, pfile)
 
     case T_SPECLINE:
       {
-       long line = CPP_BUFFER (pfile)->lineno;
-       long col = CPP_BUFFER (pfile)->colno;
-       cpp_buffer *ip = CPP_BUFFER (pfile);
+       long line = ip->lineno;
+       long col = ip->colno;
        adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
 
        buf = (char *) alloca (10);
-       sprintf (buf, "%d", line);
+       sprintf (buf, "%ld", line);
       }
       break;
 
@@ -2514,13 +2436,15 @@ special_symbol (hp, pfile)
 
       if (!is_idstart[*ip->cur])
        goto oops;
+      if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
+       goto oops;
       if (hp = cpp_lookup (pfile, ip->cur, -1, -1))
        {
 #if 0
          if (pcp_outfile && pcp_inside_if
              && (hp->type == T_CONST
                  || (hp->type == T_MACRO && hp->value.defn->predefined)))
-           /* Output a precondition for this macro use. */
+           /* Output a precondition for this macro use.  */
            fprintf (pcp_outfile, "#define %s\n", hp->name);
 #endif
          buf = " 1 ";
@@ -2565,100 +2489,77 @@ special_symbol (hp, pfile)
   return;
 }
 
+/* Write out a #define command for the special named MACRO_NAME
+   to PFILE's token_buffer.  */
+
+static void
+dump_special_to_buffer (pfile, macro_name)
+     cpp_reader *pfile;
+     char *macro_name;
+{
+  static char define_directive[] = "#define ";
+  int macro_name_length = strlen (macro_name);
+  output_line_command (pfile, 0, same_file);
+  CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
+  CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
+  CPP_PUTS_Q (pfile, macro_name, macro_name_length);
+  CPP_PUTC_Q (pfile, ' ');
+  cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
+  CPP_PUTC (pfile, '\n');
+}
+
 /* Initialize the built-in macros.  */
 
 static void
 initialize_builtins (pfile)
      cpp_reader *pfile;
 {
-  install ("__LINE__", -1, T_SPECLINE, 0, 0, -1);
-  install ("__DATE__", -1, T_DATE, 0, 0, -1);
-  install ("__FILE__", -1, T_FILE, 0, 0, -1);
-  install ("__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
-  install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
-  install ("__VERSION__", -1, T_VERSION, 0, 0, -1);
+  install ((U_CHAR *)"__LINE__", -1, T_SPECLINE, 0, 0, -1);
+  install ((U_CHAR *)"__DATE__", -1, T_DATE, 0, 0, -1);
+  install ((U_CHAR *)"__FILE__", -1, T_FILE, 0, 0, -1);
+  install ((U_CHAR *)"__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
+  install ((U_CHAR *)"__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
+  install ((U_CHAR *)"__VERSION__", -1, T_VERSION, 0, 0, -1);
 #ifndef NO_BUILTIN_SIZE_TYPE
-  install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
+  install ((U_CHAR *)"__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
 #endif
 #ifndef NO_BUILTIN_PTRDIFF_TYPE
-  install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
+  install ((U_CHAR *)"__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
 #endif
-  install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
-  install ("__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
-  install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
-  install ("__TIME__", -1, T_TIME, 0, 0, -1);
+  install ((U_CHAR *)"__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
+  install ((U_CHAR *)"__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
+  install ((U_CHAR *)"__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
+  install ((U_CHAR *)"__TIME__", -1, T_TIME, 0, 0, -1);
   if (!CPP_TRADITIONAL (pfile))
-    install ("__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
+    install ((U_CHAR *)"__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
   if (CPP_OPTIONS (pfile)->objc)
-    install ("__OBJC__", -1, T_CONST, 1, 0, -1);
+    install ((U_CHAR *)"__OBJC__", -1, T_CONST, 1, 0, -1);
 /*  This is supplied using a -D by the compiler driver
     so that it is present only when truly compiling with GNU C.  */
 /*  install ("__GNUC__", -1, T_CONST, 2, 0, -1);  */
 
   if (CPP_OPTIONS (pfile)->debug_output)
     {
-      char directive[2048];
-      register struct directive *dp = &directive_table[0];
-      struct tm *timebuf = timestamp ();
-      cpp_buffer *pbuffer = CPP_BUFFER (pfile);
-
-      while (CPP_PREV_BUFFER (pbuffer))
-       pbuffer = CPP_PREV_BUFFER (pbuffer);
-      sprintf (directive, " __BASE_FILE__ \"%s\"\n",
-              pbuffer->nominal_fname);
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
-      sprintf (directive, " __VERSION__ \"%s\"\n", version_string);
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
+      dump_special_to_buffer (pfile, "__BASE_FILE__");
+      dump_special_to_buffer (pfile, "__VERSION__");
 #ifndef NO_BUILTIN_SIZE_TYPE
-      sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE);
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
+      dump_special_to_buffer (pfile, "__SIZE_TYPE__");
 #endif
-
 #ifndef NO_BUILTIN_PTRDIFF_TYPE
-      sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE);
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
+      dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
 #endif
-
-      sprintf (directive, " __WCHAR_TYPE__ %s\n", CPP_WCHAR_TYPE (pfile));
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
-      sprintf (directive, " __DATE__ \"%s %2d %4d\"\n",
-              monthnames[timebuf->tm_mon],
-              timebuf->tm_mday, timebuf->tm_year + 1900);
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
-      sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n",
-              timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
-      output_line_command (pfile, 0, same_file);
-      pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
+      dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
+      dump_special_to_buffer (pfile, "__DATE__");
+      dump_special_to_buffer (pfile, "__TIME__");
       if (!CPP_TRADITIONAL (pfile))
-       {
-          sprintf (directive, " __STDC__ 1");
-          output_line_command (pfile, 0, same_file);
-          pass_thru_directive (directive, &directive[strlen (directive)],
-                              pfile, dp);
-       }
+       dump_special_to_buffer (pfile, "__STDC__");
       if (CPP_OPTIONS (pfile)->objc)
-       {
-          sprintf (directive, " __OBJC__ 1");
-          output_line_command (pfile, 0, same_file);
-          pass_thru_directive (directive, &directive[strlen (directive)],
-                              pfile, dp);
-       }
+       dump_special_to_buffer (pfile, "__OBJC__");
     }
 }
 \f
 /* Return 1 iff a token ending in C1 followed directly by a token C2
-   could cause mis-tokenization. */
+   could cause mis-tokenization.  */
 
 static int
 unsafe_chars (c1, c2)
@@ -2673,27 +2574,27 @@ unsafe_chars (c1, c2)
     case '.':
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
-    case 'e': case 'E':
+    case 'e': case 'E': case 'p': case 'P':
       if (c2 == '-' || c2 == '+')
        return 1; /* could extend a pre-processing number */
       goto letter;
     case 'L':
       if (c2 == '\'' || c2 == '\"')
-       return 1;   /* Could turn into L"xxx" or L'xxx'. */
+       return 1;   /* Could turn into L"xxx" or L'xxx'.  */
       goto letter;
     letter:
     case '_':
     case 'a': case 'b': case 'c': case 'd':           case 'f':
     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
-    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 'm': case 'n': case 'o':           case 'q': case 'r':
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
     case 'y': case 'z':
     case 'A': case 'B': case 'C': case 'D':           case 'F':
     case 'G': case 'H': case 'I': case 'J': case 'K':
-    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'M': case 'N': case 'O':           case 'Q': case 'R':
     case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
     case 'Y': case 'Z':
-      /* We're in the middle of either a name or a pre-processing number. */
+      /* We're in the middle of either a name or a pre-processing number.  */
       return (is_idchar[c2] || c2 == '.');
     case '<': case '>': case '!': case '%': case '#': case ':':
     case '^': case '&': case '|': case '*': case '/': case '=':
@@ -2718,6 +2619,7 @@ macroexpand (pfile, hp)
   int nargs;
   DEFINITION *defn = hp->value.defn;
   register U_CHAR *xbuf;
+  long start_line, start_column;
   int xbuf_len;
   struct argdata *args;
   long old_written = CPP_WRITTEN (pfile);
@@ -2738,11 +2640,13 @@ macroexpand (pfile, hp)
     dump_single_macro (hp, pcp_outfile);
 #endif
 
+  pfile->output_escapes++;
+  cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
+
   nargs = defn->nargs;
 
   if (nargs >= 0)
     {
-      char *parse_error = 0;
       enum cpp_token token;
 
       args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
@@ -2758,7 +2662,7 @@ macroexpand (pfile, hp)
       /* Parse all the macro args that are supplied.  I counts them.
         The first NARGS args are stored in ARGS.
         The rest are discarded.  If rest_args is set then we assume
-        macarg absorbed the rest of the args. */
+        macarg absorbed the rest of the args.  */
       i = 0;
       rest_args = 0;
       rest_args = 0;
@@ -2781,13 +2685,9 @@ macroexpand (pfile, hp)
            token = macarg (pfile, 0);
          if (token == CPP_EOF || token == CPP_POP)
            {
-             parse_error = "unterminated macro call";
-#if 1
-             cpp_error_with_line (pfile, line_for_error (0), parse_error);
-#else
-             cpp_error_with_line (pfile, line_for_error (start_line), parse_error);
-#endif
-             break;
+             cpp_error_with_line (pfile, start_line, start_column,
+                                  "unterminated macro call");
+             return;
            }
          i++;
        } while (token == CPP_COMMA);
@@ -2810,8 +2710,7 @@ macroexpand (pfile, hp)
       rest_zero = 0;
       if (nargs == 0 && i > 0)
        {
-         if (! parse_error)
-           cpp_error (pfile, "arguments given to macro `%s'", hp->name);
+         cpp_error (pfile, "arguments given to macro `%s'", hp->name);
        }
       else if (i < nargs)
        {
@@ -2821,8 +2720,6 @@ macroexpand (pfile, hp)
          /* the rest args token is allowed to absorb 0 tokens */
          else if (i == nargs - 1 && defn->rest_args)
            rest_zero = 1;
-         else if (parse_error)
-           ;
          else if (i == 0)
            cpp_error (pfile, "macro `%s' used without args", hp->name);
          else if (i == 1)
@@ -2833,9 +2730,8 @@ macroexpand (pfile, hp)
       }
       else if (i > nargs)
        {
-         if (! parse_error)
-           cpp_error (pfile,
-                      "macro `%s' used with too many (%d) args", hp->name, i);
+         cpp_error (pfile,
+                    "macro `%s' used with too many (%d) args", hp->name, i);
        }
     }
 
@@ -2874,7 +2770,7 @@ macroexpand (pfile, hp)
                  int c;
                  /* Initially need_space is -1.  Otherwise, 1 means the
                     previous character was a space, but we suppressed it;
-                    0 means the previous character was a non-space. */
+                    0 means the previous character was a non-space.  */
                  int need_space = -1;
                  i = 0;
                  arg->stringified = CPP_WRITTEN (pfile);
@@ -2890,6 +2786,13 @@ macroexpand (pfile, hp)
                             one space except within an string or char token.*/
                          if (is_space[c])
                            {
+                             if (CPP_WRITTEN (pfile) > arg->stringified
+                                 && (CPP_PWRITTEN (pfile))[-1] == '@')
+                               {
+                                 /* "@ " escape markers are removed */
+                                 CPP_ADJUST_WRITTEN (pfile, -1);
+                                 continue;
+                               }
                              if (need_space == 0)
                                need_space = 1;
                              continue;
@@ -2922,7 +2825,7 @@ macroexpand (pfile, hp)
                      else
                        {
                          CPP_RESERVE (pfile, 4);
-                         sprintf (CPP_PWRITTEN (pfile), "\\%03o",
+                         sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o",
                                   (unsigned int) c);
                          CPP_ADJUST_WRITTEN (pfile, 4);
                        }
@@ -2945,12 +2848,10 @@ macroexpand (pfile, hp)
              if (args[ap->argno].expand_length < 0)
                {
                  args[ap->argno].expanded = CPP_WRITTEN (pfile);
-                 pfile->output_escapes++;
                  cpp_expand_to_buffer (pfile,
                                        ARG_BASE + args[ap->argno].raw,
                                        args[ap->argno].raw_length);
 
-                 pfile->output_escapes--;
                  args[ap->argno].expand_length
                    = CPP_WRITTEN (pfile) - args[ap->argno].expanded;
                }
@@ -3012,6 +2913,11 @@ macroexpand (pfile, hp)
                  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
+                    if the argument is concatenated with what precedes it.  */
+                 if (p1[0] == '@' && p1[1] == '-')
+                   p1 += 2;
                }
              if (ap->raw_after)
                {
@@ -3044,7 +2950,10 @@ macroexpand (pfile, hp)
              if (!ap->raw_before && totlen > 0 && arg->expand_length
                  && !CPP_TRADITIONAL(pfile)
                  && unsafe_chars (xbuf[totlen-1], expanded[0]))
-               xbuf[totlen++] = ' ';
+               {
+                 xbuf[totlen++] = '@';
+                 xbuf[totlen++] = ' ';
+               }
 
              bcopy (expanded, xbuf + totlen, arg->expand_length);
              totlen += arg->expand_length;
@@ -3052,7 +2961,10 @@ macroexpand (pfile, hp)
              if (!ap->raw_after && totlen > 0 && offset < defn->length
                  && !CPP_TRADITIONAL(pfile)
                  && unsafe_chars (xbuf[totlen-1], exp[offset]))
-               xbuf[totlen++] = ' ';
+               {
+                 xbuf[totlen++] = '@';
+                 xbuf[totlen++] = ' ';
+               }
 
              /* If a macro argument with newlines is used multiple times,
                 then only expand the newlines once.  This avoids creating
@@ -3073,7 +2985,7 @@ macroexpand (pfile, hp)
       }
 
       /* if there is anything left of the definition
-        after handling the arg list, copy that in too. */
+        after handling the arg list, copy that in too.  */
 
       for (i = offset; i < defn->length; i++)
        {
@@ -3090,12 +3002,14 @@ macroexpand (pfile, hp)
 
     }
 
+  pfile->output_escapes--;
+
   /* Now put the expansion on the input stack
      so our caller will commence reading from it.  */
   push_macro_expansion (pfile, xbuf, xbuf_len, hp);
   CPP_BUFFER (pfile)->has_escapes = 1;
 
-  /* Pop the space we've used in the token_buffer for argument expansion. */
+  /* Pop the space we've used in the token_buffer for argument expansion.  */
   CPP_SET_WRITTEN (pfile, old_written);
     
   /* Recursive macro use sometimes works traditionally.
@@ -3114,10 +3028,12 @@ push_macro_expansion (pfile, xbuf, xbuf_len, hp)
      HASHNODE *hp;
 {
   register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
+  if (mbuf == NULL)
+    return;
   mbuf->cleanup = macro_cleanup;
   mbuf->data = hp;
 
-  /* The first char of the expansion should be a ' ' added by
+  /* The first chars of the expansion should be a "@ " added by
      collect_expansion.  This is to prevent accidental token-pasting
      between the text preceding the macro invocation, and the macro
      expansion text.
@@ -3135,10 +3051,10 @@ push_macro_expansion (pfile, xbuf, xbuf_len, hp)
      Also, we don't need the extra space if the first char is '(',
      or some other (less common) characters.  */
 
-  if (xbuf[0] == ' '
-      && (is_idchar[xbuf[1]] || xbuf[1] == '(' || xbuf[1] == '\''
-         || xbuf[1] == '\"'))
-    mbuf->cur++;
+  if (xbuf[0] == '@' && xbuf[1] == ' '
+      && (is_idchar[xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
+         || xbuf[2] == '\"'))
+    mbuf->cur += 2;
 }
 \f
 /* Like cpp_get_token, except that it does not read past end-of-line.
@@ -3161,7 +3077,7 @@ get_directive_token (pfile)
       case CPP_POP:
          if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
              return token;
-         /* ... else fall though ... */
+         /* ... else fall though ...  */
       case CPP_HSPACE:  case CPP_COMMENT:
          CPP_SET_WRITTEN (pfile, old_written);
          break;
@@ -3175,9 +3091,9 @@ get_directive_token (pfile)
    This function expects to see "fname" or <fname> on the input.
 
    The input is normally in part of the output_buffer following
-   CPP_WRITTEN, and will get overwriiten by output_line_command.
+   CPP_WRITTEN, and will get overwritten by output_line_command.
    I.e. in input file specification has been popped by handle_directive.
-   This is safe. */
+   This is safe.  */
 
 static int
 do_include (pfile, keyword, unused1, unused2)
@@ -3204,7 +3120,7 @@ do_include (pfile, keyword, unused1, unused2)
   int f;                       /* file number */
 
   int retried = 0;             /* Have already tried macro
-                                  expanding the include line*/
+                                  expanding the include line */
   int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
   int pcf = -1;
   char *pcfbuf;
@@ -3212,6 +3128,14 @@ do_include (pfile, keyword, unused1, unused2)
   int pcfnum;
   f= -1;                       /* JF we iz paranoid! */
 
+  if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
+    {
+      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)
@@ -3246,14 +3170,14 @@ do_include (pfile, keyword, unused1, unused2)
          if (CPP_OPTIONS (pfile)->first_bracket_include)
            search_start = CPP_OPTIONS (pfile)->first_bracket_include;
        }
-      /* If -I- was specified, don't search current dir, only spec'd ones. */
+      /* If -I- was specified, don't search current dir, only spec'd ones.  */
       else if (! CPP_OPTIONS (pfile)->ignore_srcdir)
        {
-         cpp_buffer *fp;
+         cpp_buffer *fp = CPP_BUFFER (pfile);
          /* We have "filename".  Figure out directory this source
-            file is coming from and put it on the front of the list. */
+            file is coming from and put it on the front of the list.  */
 
-         for (fp = CPP_BUFFER (pfile); fp != NULL; fp = CPP_PREV_BUFFER (fp))
+         for ( ; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
            {
              int n;
              char *ep,*nam;
@@ -3332,13 +3256,15 @@ do_include (pfile, keyword, unused1, unused2)
      past the dir in which the containing file was found.  */
   if (skip_dirs)
     {
-      cpp_buffer *fp;
-      for (fp = CPP_BUFFER (pfile); fp != NULL; fp = CPP_PREV_BUFFER (fp))
+      cpp_buffer *fp = CPP_BUFFER (pfile);
+      for (; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
        if (fp->fname != NULL)
          {
            /* fp->dir is null if the containing file was specified with
               an absolute file name.  In that case, don't skip anything.  */
-           if (fp->dir)
+           if (fp->dir == SELF_DIR_DUMMY)
+             search_start = CPP_OPTIONS (pfile)->include;
+           else if (fp->dir)
              search_start = fp->dir->next;
            break;
          }
@@ -3370,7 +3296,7 @@ do_include (pfile, keyword, unused1, unused2)
     if (importing)
       f = lookup_import (pfile, fname, NULL_PTR);
     else
-      f = open_include_file (fname, NULL_PTR);
+      f = open_include_file (pfile, fname, NULL_PTR);
     if (f == -2)
       return 0;                /* Already included this file */
   } else {
@@ -3415,7 +3341,7 @@ do_include (pfile, keyword, unused1, unused2)
       if (importing)
        f = lookup_import (pfile, fname, searchptr);
       else
-       f = open_include_file (fname, searchptr);
+       f = open_include_file (pfile, fname, searchptr);
       if (f == -2)
        return 0;                       /* Already included this file */
 #ifdef EACCES
@@ -3455,8 +3381,8 @@ do_include (pfile, keyword, unused1, unused2)
 
                      if (searchptr->fname[0] == 0)
                        continue;
-                     p = xmalloc (strlen (searchptr->fname)
-                                  + strlen (fname) + 2);
+                     p = (char *) alloca (strlen (searchptr->fname)
+                                          + strlen (fname) + 2);
                      strcpy (p, searchptr->fname);
                      strcat (p, "/");
                      strcat (p, fname);
@@ -3490,18 +3416,18 @@ do_include (pfile, keyword, unused1, unused2)
     /* Check to see if this include file is a once-only include file.
        If so, give up.  */
 
-    struct file_name_listptr;
+    struct file_name_list *ptr;
 
     for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) {
       if (!strcmp (ptr->fname, fname)) {
        close (f);
-        return 0;                              /* This file was once'd. */
+        return 0;                              /* This file was once'd.  */
       }
     }
 
     for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
       if (!strcmp (ptr->fname, fname))
-        break;                         /* This file was included before. */
+        break;                         /* This file was included before.  */
     }
 
     if (ptr == 0) {
@@ -3526,7 +3452,7 @@ do_include (pfile, keyword, unused1, unused2)
     if (CPP_OPTIONS(pfile)->print_include_names)
       {
        cpp_buffer *buf = CPP_BUFFER (pfile);
-       while ((buf = CPP_PREV_BUFFER (buf)) != NULL)
+       while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
          putc ('.', stderr);
        fprintf (stderr, "%s\n", fname);
       }
@@ -3536,7 +3462,7 @@ do_include (pfile, keyword, unused1, unused2)
 
     /* Actually process the file.  */
 
-    /* Record file on "seen" list for #import. */
+    /* Record file on "seen" list for #import.  */
     add_import (pfile, f, fname);
 
     pcftry = (char *) alloca (strlen (fname) + 30);
@@ -3579,8 +3505,10 @@ do_include (pfile, keyword, unused1, unused2)
 #endif
     
     /* Actually process the file */
+    if (cpp_push_buffer (pfile, NULL, 0) == NULL)
+      return 0;
     if (finclude (pfile, f, fname, is_system_include (pfile, fname),
-                 searchptr))
+                 searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
       {
        output_line_command (pfile, 0, enter_file);
        pfile->only_seen_white = 2;
@@ -3655,6 +3583,7 @@ is_system_include (pfile, filename)
  * If HASH is >= 0, it is the precomputed hash code.
  * Otherwise, compute the hash code.
  */
+
 static ASSERTION_HASHNODE *
 assertion_install (pfile, name, len, hash)
      cpp_reader *pfile;
@@ -3718,14 +3647,22 @@ static void
 delete_assertion (hp)
      ASSERTION_HASHNODE *hp;
 {
-
+  struct tokenlist_list *tail;
   if (hp->prev != NULL)
     hp->prev->next = hp->next;
   if (hp->next != NULL)
     hp->next->prev = hp->prev;
 
-  /* make sure that the bucket chain header that
-     the deleted guy was on points to the right thing afterwards. */
+  for (tail = hp->value; tail; )
+    {
+      struct tokenlist_list *next = tail->next;
+      free_token_list (tail->tokens);
+      free (tail);
+      tail = next;
+    }
+
+  /* Make sure that the bucket chain header that
+     the deleted guy was on points to the right thing afterwards.  */
   if (hp == *hp->bucket_hdr)
     *hp->bucket_hdr = hp->next;
 
@@ -3738,7 +3675,7 @@ delete_assertion (hp)
    The value returned in the end of the string written to RESULT,
    or NULL on error.  */
 
-static U_CHAR*
+static U_CHAR *
 convert_string (pfile, result, in, limit, handle_escapes)
      cpp_reader *pfile;
      register U_CHAR *result, *in, *limit;
@@ -3807,7 +3744,7 @@ do_line (pfile, keyword)
   /* 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 (pfile->token_buffer + old_written) - 1;
+  new_lineno = atoi ((char *)(pfile->token_buffer + old_written)) - 1;
   CPP_SET_WRITTEN (pfile, old_written);
 
   /* NEW_LINENO is one less than the actual line number here.  */
@@ -3877,11 +3814,10 @@ do_line (pfile, keyword)
       }
     }
 
-    hash_bucket =
-      &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
+    hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
     for (hp = *hash_bucket; hp != NULL; hp = hp->next)
-      if (hp->length == fname_length &&
-         strncmp (hp->value.cpval, fname, fname_length) == 0) {
+      if (hp->length == fname_length
+         && strncmp (hp->value.cpval, fname, fname_length) == 0) {
        ip->nominal_fname = hp->value.cpval;
        break;
       }
@@ -3967,7 +3903,7 @@ do_error (pfile, keyword, buf, limit)
      U_CHAR *buf, *limit;
 {
   int length = limit - buf;
-  U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+  U_CHAR *copy = (U_CHAR *) alloca (length + 1);
   bcopy (buf, copy, length);
   copy[length] = 0;
   SKIP_WHITE_SPACE (copy);
@@ -3988,11 +3924,13 @@ do_warning (pfile, keyword, buf, limit)
      U_CHAR *buf, *limit;
 {
   int length = limit - buf;
-  U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+  U_CHAR *copy = (U_CHAR *) alloca (length + 1);
   bcopy (buf, copy, length);
   copy[length] = 0;
   SKIP_WHITE_SPACE (copy);
-  cpp_warning (pfile, "#warning %s", copy);
+  /* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
+     if -pedantic-errors is given, #warning should cause an error.  */
+  cpp_pedwarn (pfile, "#warning %s", copy);
   return 0;
 }
 
@@ -4008,7 +3946,7 @@ do_once (pfile)
 
   for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
     {
-      if (ip == NULL)
+      if (ip == CPP_NULL_BUFFER (pfile))
        return 0;
       if (ip->fname != NULL)
        break;
@@ -4026,7 +3964,7 @@ do_once (pfile)
   return 0;
 }
 
-/* #ident has already been copied to the output file, so just ignore it.  */
+/* Report program identification.  */
 
 static int
 do_ident (pfile, keyword, buf, limit)
@@ -4041,7 +3979,7 @@ do_ident (pfile, keyword, buf, limit)
   if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
     cpp_pedwarn (pfile, "ANSI C does not allow `#ident'");
 
-  /* Leave rest of line to be read by later calls to cpp_get_token. */
+  /* Leave rest of line to be read by later calls to cpp_get_token.  */
 
   return 0;
 }
@@ -4203,6 +4141,7 @@ do_elif (pfile, keyword, buf, limit)
  * evaluate a #if expression in BUF, of length LENGTH,
  * then parse the result as a C expression and return the value as an int.
  */
+
 static HOST_WIDE_INT
 eval_if_expression (pfile, buf, length)
      cpp_reader *pfile;
@@ -4213,7 +4152,7 @@ eval_if_expression (pfile, buf, length)
   HOST_WIDE_INT value;
   long old_written = CPP_WRITTEN (pfile);
 
-  save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);
+  save_defined = install ((U_CHAR *)"defined", -1, T_SPEC_DEFINED, 0, 0, -1);
   pfile->pcp_inside_if = 1;
 
   value = cpp_parse_expr (pfile);
@@ -4239,7 +4178,7 @@ do_xifdef (pfile, keyword, unused1, unused2)
 {
   int skip;
   cpp_buffer *ip = CPP_BUFFER (pfile);
-  U_CHARident;
+  U_CHAR *ident;
   int ident_length;
   enum cpp_token token;
   int start_of_file = 0;
@@ -4347,6 +4286,7 @@ conditional_skip (pfile, skip, type, control_macro)
  * leaves input ptr at the sharp sign found.
  * If ANY is nonzero, return at next directive of any sort.
  */
+
 static void
 skip_if_group (pfile, any)
      cpp_reader *pfile;
@@ -4464,10 +4404,11 @@ skip_if_group (pfile, any)
        }
       c = GETC ();
     }
-  /* We're in the middle of a line.  Skip the rest of it. */
+  /* We're in the middle of a line.  Skip the rest of it.  */
   for (;;) {
     switch (c)
       {
+       long old;
       case EOF:
        goto done;
       case '/':                        /* possible comment */
@@ -4477,7 +4418,10 @@ skip_if_group (pfile, any)
        break;
       case '\"':
       case '\'':
-       skip_quoted_string (pfile, c, 0 /* FIXME */);
+       FORWARD(-1);
+       old = CPP_WRITTEN (pfile);
+       cpp_get_token (pfile);
+       CPP_SET_WRITTEN (pfile, old);
        break;
       case '\\':
        /* Char after backslash loses its special meaning.  */
@@ -4638,16 +4582,16 @@ validate_else (pfile, directive)
                 "text following `%s' violates ANSI standard", directive);
 }
 
-/* Get the next token, and add it to the tex in pfile->token_buffer.
-   Return the kind of token we got. */
+/* Get the next token, and add it to the text in pfile->token_buffer.
+   Return the kind of token we got.  */
   
-
 enum cpp_token
 cpp_get_token (pfile)
      cpp_reader *pfile;
 {
   register int c, c2, c3;
   long old_written;
+  long start_line, start_column;
   enum cpp_token token;
   struct cpp_options *opts = CPP_OPTIONS (pfile);
   CPP_BUFFER (pfile)->prev = CPP_BUFFER (pfile)->cur;
@@ -4668,11 +4612,12 @@ cpp_get_token (pfile)
          cpp_buffer *next_buf
            = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
          CPP_BUFFER (pfile)->seen_eof = 1;
-         if (CPP_BUFFER (pfile)->nominal_fname && next_buf != 0)
+         if (CPP_BUFFER (pfile)->nominal_fname
+             && next_buf != CPP_NULL_BUFFER (pfile))
            {
              /* We're about to return from an #include file.
-                Emit #line information now (as part of the CPP_POP) restult.
-                But the #line refers to the file we will pop to. */
+                Emit #line information now (as part of the CPP_POP) result.
+                But the #line refers to the file we will pop to.  */
              cpp_buffer *cur_buffer = CPP_BUFFER (pfile);
              CPP_BUFFER (pfile) = next_buf;
              pfile->input_stack_listing_current = 0;
@@ -4694,6 +4639,8 @@ cpp_get_token (pfile)
          if (opts->put_out_comments)
            parse_set_mark (&start_mark, pfile);
          newlines = 0;
+         cpp_buf_line_and_col (cpp_file_buffer (pfile),
+                               &start_line, &start_column);
          c = skip_comment (pfile, &newlines);
          if (opts->put_out_comments && (c == '/' || c == EOF))
            parse_clear_mark (&start_mark);
@@ -4701,11 +4648,11 @@ cpp_get_token (pfile)
            goto randomchar;
          if (c == EOF)
            {
-             cpp_error_with_line (pfile, line_for_error (pfile->start_line),
+             cpp_error_with_line (pfile, start_line, start_column,
                                   "unterminated comment");
              goto handle_eof;
            }
-         c = '/';  /* Initial letter of comment. */
+         c = '/';  /* Initial letter of comment.  */
        return_comment:
          /* Comments are equivalent to spaces.
             For -traditional, a comment is equivalent to nothing.  */
@@ -4723,12 +4670,14 @@ cpp_get_token (pfile)
              return CPP_COMMENT;
            }
          else if (CPP_TRADITIONAL (pfile))
-           goto get_next;
+           {
+             return CPP_COMMENT;
+           }
          else
            {
 #if 0
              /* This may not work if cpp_get_token is called recursively,
-                since many places look for horizontal space. */
+                since many places look for horizontal space.  */
              if (newlines)
                {
                  /* Copy the newlines into the output buffer, in order to
@@ -4747,8 +4696,8 @@ cpp_get_token (pfile)
              CPP_PUTC_Q (pfile, ' ');
              return CPP_HSPACE;
            }
-         if (opts->for_lint) {
 #if 0
+         if (opts->for_lint) {
            U_CHAR *argbp;
            int cmdlen, arglen;
            char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
@@ -4768,14 +4717,14 @@ cpp_get_token (pfile)
              }
 
              /* OK, now bring us back to the state we were in before we entered
-                this branch.  We need #line b/c the newline for the pragma
-                could fuck things up. */
+                this branch.  We need #line because the newline for the pragma
+                could mess things up.  */
              output_line_command (pfile, 0, same_file);
              *(obp++) = ' ';   /* just in case, if comments are copied thru */
              *(obp++) = '/';
            }
-#endif
          }
+#endif
 
        case '#':
 #if 0
@@ -4803,9 +4752,8 @@ cpp_get_token (pfile)
        case '\'':
          /* A single quoted string is treated like a double -- some
             programs (e.g., troff) are perverse this way */
-#if 0
-         start_line = pfile->lineno;
-#endif
+         cpp_buf_line_and_col (cpp_file_buffer (pfile),
+                               &start_line, &start_column);
          old_written = CPP_WRITTEN (pfile);
        string:
          CPP_PUTC (pfile, c);
@@ -4827,16 +4775,17 @@ cpp_get_token (pfile)
                        CPP_BUFFER (pfile) = next_buf;
                        continue;
                    }
-#if 0
                  if (!CPP_TRADITIONAL (pfile))
                    {
-                     cpp_error_with_line (pfile, line_for_error (start_line),
+                     cpp_error_with_line (pfile, start_line, start_column,
                              "unterminated string or character constant");
-                     cpp_error_with_line (pfile, multiline_string_line,
-                                "possible real start of unterminated constant");
-                     multiline_string_line = 0;
+                     if (pfile->multiline_string_line != start_line
+                         && pfile->multiline_string_line != 0)
+                       cpp_error_with_line (pfile,
+                                            pfile->multiline_string_line, -1,
+                              "possible real start of unterminated constant");
+                     pfile->multiline_string_line = 0;
                    }
-#endif
                  break;
                }
              CPP_PUTC (pfile, cc);
@@ -4847,29 +4796,27 @@ cpp_get_token (pfile)
                 no error.  So exit the loop and record the new line.  */
                  if (CPP_TRADITIONAL (pfile))
                    goto while2end;
-#if 0
                  if (c == '\'')
                    {
-                     cpp_error_with_line (pfile, line_for_error (start_line),
-                                    "unterminated character constant");
+                     cpp_error_with_line (pfile, start_line, start_column,
+                                          "unterminated character constant");
                      goto while2end;
                    }
-                 if (CPP_PEDANTIC (pfile) && multiline_string_line == 0)
+                 if (CPP_PEDANTIC (pfile)
+                     && pfile->multiline_string_line == 0)
                    {
-                     cpp_pedwarn_with_line (pfile,
-                                            line_for_error (start_line),
+                     cpp_pedwarn_with_line (pfile, start_line, start_column,
                               "string constant runs past end of line");
                    }
-                 if (multiline_string_line == 0)
-                   multiline_string_line = ip->lineno - 1;
-#endif
+                 if (pfile->multiline_string_line == 0)
+                   pfile->multiline_string_line = start_line;
                  break;
                
                case '\\':
                  cc = GETC();
                  if (cc == '\n')
                    {
-                     /* Backslash newline is replaced by nothing at all. */
+                     /* Backslash newline is replaced by nothing at all.  */
                      CPP_ADJUST_WRITTEN (pfile, -1);
                      pfile->lineno++;
                    }
@@ -4933,7 +4880,7 @@ cpp_get_token (pfile)
              /* Chill style comment */
              if (opts->put_out_comments)
                parse_set_mark (&start_mark, pfile);
-             FORWARD(1);  /* Skip second '-'. */
+             FORWARD(1);  /* Skip second '-'.  */
              for (;;)
                {
                  c = GETC ();
@@ -4941,7 +4888,7 @@ cpp_get_token (pfile)
                    break;
                  if (c == '\n')
                    {
-                     /* Don't consider final '\n' to be part of comment. */
+                     /* Don't consider final '\n' to be part of comment.  */
                      FORWARD(-1);
                      break;
                    }
@@ -5003,6 +4950,14 @@ cpp_get_token (pfile)
                  parse_name (pfile, GETC ());
                  return CPP_NAME;
                }
+             else if (is_space [c])
+               {
+                 CPP_RESERVE (pfile, 2);
+                 if (pfile->output_escapes)
+                   CPP_PUTC_Q (pfile, '@');
+                 CPP_PUTC_Q (pfile, c);
+                 return CPP_HSPACE;
+               }
            }
          if (pfile->output_escapes)
            {
@@ -5069,7 +5024,9 @@ cpp_get_token (pfile)
              if (c == EOF)
                break;
              if (!is_idchar[c] && c != '.'
-                 && ((c2 != 'e' && c2 != 'E') || (c != '+' && c != '-')))
+                 && ((c2 != 'e' && c2 != 'E'
+                      && ((c2 != 'p' && c2 != 'P') || CPP_C89 (pfile)))
+                     || (c != '+' && c != '-')))
                break;
              FORWARD(1);
              c2= c;
@@ -5146,7 +5103,7 @@ cpp_get_token (pfile)
            if (hp->type == T_DISABLED)
              {
                if (pfile->output_escapes)
-                 { /* Return "@-IDENT", followed by '\0'. */
+                 { /* Return "@-IDENT", followed by '\0'.  */
                    int i;
                    CPP_RESERVE (pfile, 3);
                    ident = pfile->token_buffer + before_name_written;
@@ -5192,7 +5149,7 @@ cpp_get_token (pfile)
              if (!is_macro_call)
                return CPP_NAME;
            }
-           /* This is now known to be a macro call. */
+           /* This is now known to be a macro call.  */
 
            /* it might not actually be a macro.  */
            if (hp->type != T_MACRO) {
@@ -5213,22 +5170,21 @@ cpp_get_token (pfile)
                CPP_SET_WRITTEN (pfile, before_name_written);
              }
 
-           /* An extra space is added to the end of a macro expansion
+           /* An extra "@ " is added to the end of a macro expansion
               to prevent accidental token pasting.  We prefer to avoid
               unneeded extra spaces (for the sake of cpp-using tools like
-              imake).  Here we remove the space if it is safe to do so. */
-           if (pfile->buffer->rlimit - pfile->buffer->cur >= 2
-               && pfile->buffer->cur[-1] == ' ')
+              imake).  Here we remove the space if it is safe to do so.  */
+           if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
+               && pfile->buffer->rlimit[-2] == '@'
+               && pfile->buffer->rlimit[-1] == ' ')
              {
-               int c1 = pfile->buffer->rlimit[-2];
+               int c1 = pfile->buffer->rlimit[-3];
                int c2 = CPP_BUF_PEEK (CPP_PREV_BUFFER (CPP_BUFFER (pfile)));
                if (c2 == EOF || ! unsafe_chars (c1, c2))
-                 pfile->buffer->rlimit--;
+                 pfile->buffer->rlimit -= 2;
              }
-
-           goto get_next;
          }
-         return CPP_NAME;
+         goto get_next;
 
        case ' ':  case '\t':  case '\v':  case '\r':
          for (;;)
@@ -5274,7 +5230,8 @@ cpp_get_token (pfile)
     }
 }
 
-/* Like cpp_get_token, but skip spaces and comments. */
+/* Like cpp_get_token, but skip spaces and comments.  */
+
 enum cpp_token
 cpp_get_non_space_token (pfile)
      cpp_reader *pfile;
@@ -5290,7 +5247,7 @@ cpp_get_non_space_token (pfile)
     }
 }
 
-/* Parse an identifier starting with C. */
+/* Parse an identifier starting with C.  */
 
 int
 parse_name (pfile, c)
@@ -5309,7 +5266,10 @@ parse_name (pfile, c)
          break;
       }
 
-      CPP_RESERVE(pfile, 2); /* One more for final NUL. */
+      if (c == '$' && CPP_PEDANTIC (pfile))
+       cpp_pedwarn ("`$' in identifier");
+
+      CPP_RESERVE(pfile, 2); /* One more for final NUL.  */
       CPP_PUTC_Q (pfile, c);
       c = GETC();
       if (c == EOF)
@@ -5341,7 +5301,7 @@ import_hash (f)
 
 static int
 lookup_import (pfile, filename, searchptr)
-cpp_reader *pfile;
+     cpp_reader *pfile;
      char *filename;
      struct file_name_list *searchptr;
 {
@@ -5362,7 +5322,7 @@ cpp_reader *pfile;
     i = i->next;
   }
   /* Open it and try a match on inode/dev */
-  fd = open_include_file (filename, searchptr);
+  fd = open_include_file (pfile, filename, searchptr);
   if (fd < 0)
     return fd;
   fstat (fd, &sb);
@@ -5371,7 +5331,7 @@ cpp_reader *pfile;
     while (i) {
       /* Compare the inode and the device.
         Supposedly on some systems the inode is not a scalar.  */
-      if (!bcmp (&i->inode, &sb.st_ino, sizeof (sb.st_ino))
+      if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
          && i->dev == sb.st_dev) {
         close (fd);
         return -2;             /* return found */
@@ -5399,7 +5359,7 @@ add_import (pfile, fd, fname)
   i = (struct import_file *)xmalloc (sizeof (struct import_file));
   i->name = (char *)xmalloc (strlen (fname)+1);
   strcpy (i->name, fname);
-  bcopy (&sb.st_ino, &i->inode, sizeof (sb.st_ino));
+  bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
   i->dev = sb.st_dev;
   i->next = pfile->import_hash_table[hashval];
   pfile->import_hash_table[hashval] = i;
@@ -5454,26 +5414,27 @@ read_filename_string (ch, f)
   return alloc;
 }
 
-/* Read the file name map file for DIRNAME.  */
+/* This structure holds a linked list of file name maps, one per directory.  */
 
-static struct file_name_map *
-read_name_map (dirname)
+struct file_name_map_list
+{
+  struct file_name_map_list *map_list_next;
+  char *map_list_name;
+  struct file_name_map *map_list_map;
+};
+
+/* Read the file name map file for DIRNAME.  */
+
+static struct file_name_map *
+read_name_map (pfile, dirname)
+     cpp_reader *pfile;
      char *dirname;
 {
-  /* This structure holds a linked list of file name maps, one per
-     directory.  */
-  struct file_name_map_list
-    {
-      struct file_name_map_list *map_list_next;
-      char *map_list_name;
-      struct file_name_map *map_list_map;
-    };
-  static struct file_name_map_list *map_list;
   register struct file_name_map_list *map_list_ptr;
   char *name;
   FILE *f;
 
-  for (map_list_ptr = map_list; map_list_ptr;
+  for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
        map_list_ptr = map_list_ptr->map_list_next)
     if (! strcmp (map_list_ptr->map_list_name, dirname))
       return map_list_ptr->map_list_map;
@@ -5534,8 +5495,8 @@ read_name_map (dirname)
       fclose (f);
     }
   
-  map_list_ptr->map_list_next = map_list;
-  map_list = map_list_ptr;
+  map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
+  CPP_OPTIONS (pfile)->map_list = map_list_ptr;
 
   return map_list_ptr->map_list_map;
 }  
@@ -5546,68 +5507,73 @@ read_name_map (dirname)
    read_name_map.  */
 
 static int
-open_include_file (filename, searchptr)
+open_include_file (pfile, filename, searchptr)
+     cpp_reader *pfile;
      char *filename;
      struct file_name_list *searchptr;
 {
-  register struct file_name_map *map;
-  register char *from;
-  char *p, *dir;
-
-  if (searchptr && ! searchptr->got_name_map)
+  if (CPP_OPTIONS (pfile)->remap)
     {
-      searchptr->name_map = read_name_map (searchptr->fname
-                                          ? searchptr->fname : ".");
-      searchptr->got_name_map = 1;
-    }
+      register struct file_name_map *map;
+      register char *from;
+      char *p, *dir;
 
-  /* First check the mapping for the directory we are using.  */
-  if (searchptr && searchptr->name_map)
-    {
-      from = filename;
-      if (searchptr->fname)
-       from += strlen (searchptr->fname) + 1;
-      for (map = searchptr->name_map; map; map = map->map_next)
+      if (searchptr && ! searchptr->got_name_map)
        {
-         if (! strcmp (map->map_from, from))
+         searchptr->name_map = read_name_map (pfile,
+                                              searchptr->fname
+                                              ? searchptr->fname : ".");
+         searchptr->got_name_map = 1;
+       }
+
+      /* First check the mapping for the directory we are using.  */
+      if (searchptr && searchptr->name_map)
+       {
+         from = filename;
+         if (searchptr->fname)
+           from += strlen (searchptr->fname) + 1;
+         for (map = searchptr->name_map; map; map = map->map_next)
            {
-             /* Found a match.  */
-             return open (map->map_to, O_RDONLY, 0666);
+             if (! strcmp (map->map_from, from))
+               {
+                 /* Found a match.  */
+                 return open (map->map_to, O_RDONLY, 0666);
+               }
            }
        }
-    }
 
-  /* Try to find a mapping file for the particular directory we are
-     looking in.  Thus #include <sys/types.h> will look up sys/types.h
-     in /usr/include/header.gcc and look up types.h in
-     /usr/include/sys/header.gcc.  */
-  p = rindex (filename, '/');
-  if (! p)
-    p = filename;
-  if (searchptr
-      && searchptr->fname
-      && strlen (searchptr->fname) == p - filename
-      && ! strncmp (searchptr->fname, filename, p - filename))
-    {
-      /* FILENAME is in SEARCHPTR, which we've already checked.  */
-      return open (filename, O_RDONLY, 0666);
-    }
+      /* Try to find a mapping file for the particular directory we are
+        looking in.  Thus #include <sys/types.h> will look up sys/types.h
+        in /usr/include/header.gcc and look up types.h in
+        /usr/include/sys/header.gcc.  */
+      p = rindex (filename, '/');
+      if (! p)
+       p = filename;
+      if (searchptr
+         && searchptr->fname
+         && strlen (searchptr->fname) == p - filename
+         && ! strncmp (searchptr->fname, filename, p - filename))
+       {
+         /* FILENAME is in SEARCHPTR, which we've already checked.  */
+         return open (filename, O_RDONLY, 0666);
+       }
 
-  if (p == filename)
-    {
-      dir = ".";
-      from = filename;
-    }
-  else
-    {
-      dir = (char *) alloca (p - filename + 1);
-      bcopy (filename, dir, p - filename);
-      dir[p - filename] = '\0';
-      from = p + 1;
+      if (p == filename)
+       {
+         dir = ".";
+         from = filename;
+       }
+      else
+       {
+         dir = (char *) alloca (p - filename + 1);
+         bcopy (filename, dir, p - filename);
+         dir[p - filename] = '\0';
+         from = p + 1;
+       }
+      for (map = read_name_map (pfile, dir); map; map = map->map_next)
+       if (! strcmp (map->map_from, from))
+         return open (map->map_to, O_RDONLY, 0666);
     }
-  for (map = read_name_map (dir); map; map = map->map_next)
-    if (! strcmp (map->map_from, from))
-      return open (map->map_to, O_RDONLY, 0666);
 
   return open (filename, O_RDONLY, 0666);
 }
@@ -5618,8 +5584,10 @@ open_include_file (filename, searchptr)
    "system" include directories (as decided by the `is_system_include'
    function above).
    DIRPTR is the link in the dir path through which this file was found,
-   or 0 if the file name was absolute.
-   Return 1 on success, 0 on failure. */
+   or 0 if the file name was absolute or via the current directory.
+   Return 1 on success, 0 on failure.
+
+   The caller is responsible for the cpp_push_buffer.  */
 
 static int
 finclude (pfile, f, fname, system_header_p, dirptr)
@@ -5629,25 +5597,22 @@ finclude (pfile, f, fname, system_header_p, dirptr)
      int system_header_p;
      struct file_name_list *dirptr;
 {
-  int st_mode;
-  long st_size;
+  struct stat st;
+  size_t st_size;
   long i;
   int length;
   cpp_buffer *fp;                      /* For input stack frame */
   int missing_newline = 0;
 
-#if 0
-  CHECK_DEPTH (return 0;);
-#endif
-
-  if (file_size_and_mode (f, &st_mode, &st_size) < 0)
+  if (fstat (f, &st) < 0)
     {
       cpp_perror_with_name (pfile, fname);
       close (f);
+      cpp_pop_buffer (pfile);
       return 0;
     }
 
-  fp = cpp_push_buffer (pfile, NULL, 0);
+  fp = CPP_BUFFER (pfile);
   fp->nominal_fname = fp->fname = fname;
 #if 0
   fp->length = 0;
@@ -5658,7 +5623,13 @@ finclude (pfile, f, fname, system_header_p, dirptr)
   fp->colno = 1;
   fp->cleanup = file_cleanup;
 
-  if (S_ISREG (st_mode)) {
+  if (S_ISREG (st.st_mode)) {
+    st_size = (size_t) st.st_size;
+    if (st_size != st.st_size || st_size + 2 < st_size) {
+      cpp_error (pfile, "file `%s' too large", fname);
+      close (f);
+      return 0;
+    }
     fp->buf = (U_CHAR *) xmalloc (st_size + 2);
     fp->alimit = fp->buf + st_size + 2;
     fp->cur = fp->buf;
@@ -5669,14 +5640,14 @@ finclude (pfile, f, fname, system_header_p, dirptr)
     fp->rlimit = fp->buf + length;
     if (length < 0) goto nope;
   }
-  else if (S_ISDIR (st_mode)) {
+  else if (S_ISDIR (st.st_mode)) {
     cpp_error (pfile, "directory `%s' specified in #include", fname);
     close (f);
     return 0;
   } else {
     /* Cannot count its file size before reading.
        First read the entire file into heap and
-       copy them into buffer on stack. */
+       copy them into buffer on stack.  */
 
     int bsize = 2000;
 
@@ -5693,6 +5664,7 @@ finclude (pfile, f, fname, system_header_p, dirptr)
       bsize *= 2;
       fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
     }
+    fp->cur = fp->buf;
     length = st_size;
   }
 
@@ -5743,8 +5715,14 @@ finclude (pfile, f, fname, system_header_p, dirptr)
   return 1;
 }
 
+/* This is called after options have been processed.
+ * Check options for consistency, and setup for processing input
+ * from the file named FNAME.  (Use standard input if FNAME==NULL.)
+ * Return 1 on success, 0 on failure.
+ */
+
 int
-push_parse_file (pfile, fname)
+cpp_start_read (pfile, fname)
      cpp_reader *pfile;
      char *fname;
 {
@@ -5752,6 +5730,7 @@ push_parse_file (pfile, fname)
   struct cpp_pending *pend;
   char *p;
   int f;
+  cpp_buffer *fp;
 
   /* The code looks at the defaults through this pointer, rather than through
      the constant structure above.  This pointer gets changed if an environment
@@ -5771,16 +5750,15 @@ push_parse_file (pfile, fname)
   /* Now that dollars_in_ident is known, initialize is_idchar.  */
   initialize_char_syntax (opts);
 
-#if 0
   /* Do partial setup of input buffer for the sake of generating
      early #line directives (when -g is in effect).  */
-
-  fp = &instack[++indepth];
-  if (in_fname == NULL)
-    in_fname = "";
-  fp->nominal_fname = fp->fname = in_fname;
+  fp = cpp_push_buffer (pfile, NULL, 0);
+  if (!fp)
+    return 0;
+  if (opts->in_fname == NULL)
+    opts->in_fname = "";
+  fp->nominal_fname = fp->fname = opts->in_fname;
   fp->lineno = 0;
-#endif
 
   /* Install __LINE__, etc.  Must follow initialize_char_syntax
      and option processing.  */
@@ -5805,7 +5783,7 @@ push_parse_file (pfile, fname)
          *p++= 0;
        if (opts->debug_output)
          output_line_command (pfile, 0, same_file);
-       make_definition (pfile, q);
+       cpp_define (pfile, q);
        while (*p == ' ' || *p == '\t')
          p++;
       } else if (p[0] == '-' && p[1] == 'A') {
@@ -5861,46 +5839,36 @@ push_parse_file (pfile, fname)
   /* Now handle the command line options.  */
 
   /* Do -U's, -D's and -A's in the order they were seen.  */
-  /* First reverse the list. */
-  {
-    struct cpp_pending *prev = 0, *next;
-    for (pend = opts->pending;  pend;  pend = next)
-      {
-       next = pend->next;
-       pend->next = prev;
-       prev = pend;
-      }
-    opts->pending = prev;
+  /* First reverse the list.  */
+  opts->pending = nreverse_pending (opts->pending);
 
-    for (pend = opts->pending;  pend;  pend = pend->next)
-      {
-       if (pend->cmd != NULL && pend->cmd[0] == '-')
-         {
-           switch (pend->cmd[1])
-             {
-             case 'U':
-               if (opts->debug_output)
-                 output_line_command (pfile, 0, same_file);
-               do_undef (pfile, NULL, pend->arg, pend->arg + strlen (pend->arg));
-               break;
-             case 'D':
-               if (opts->debug_output)
-                 output_line_command (pfile, 0, same_file);
-               make_definition (pfile, pend->arg);
-               break;
-             case 'A':
-               make_assertion (pfile, "-A", pend->arg);
-               break;
-             }
-         }
-      }
-    opts->pending = NULL;
-  }
+  for (pend = opts->pending;  pend;  pend = pend->next)
+    {
+      if (pend->cmd != NULL && pend->cmd[0] == '-')
+       {
+         switch (pend->cmd[1])
+           {
+           case 'U':
+             if (opts->debug_output)
+               output_line_command (pfile, 0, same_file);
+             do_undef (pfile, NULL, pend->arg, pend->arg + strlen (pend->arg));
+             break;
+           case 'D':
+             if (opts->debug_output)
+               output_line_command (pfile, 0, same_file);
+             cpp_define (pfile, pend->arg);
+             break;
+           case 'A':
+             make_assertion (pfile, "-A", pend->arg);
+             break;
+           }
+       }
+    }
 
   opts->done_initializing = 1;
 
-  { /* read the appropriate environment variable and if it exists
-       replace include_defaults with the listed path. */
+  { /* Read the appropriate environment variable and if it exists
+       replace include_defaults with the listed path.  */
     char *epath = 0;
     switch ((opts->objc << 1) + opts->cplusplus)
       {
@@ -5944,6 +5912,7 @@ push_parse_file (pfile, fname)
            nstore[endp-startp] = '\0';
 
          include_defaults[num_dirs].fname = savestring (nstore);
+         include_defaults[num_dirs].component = 0;
          include_defaults[num_dirs].cplusplus = opts->cplusplus;
          include_defaults[num_dirs].cxx_aware = 1;
          num_dirs++;
@@ -5954,7 +5923,8 @@ push_parse_file (pfile, fname)
          endp++;
       }
       /* Put the usual defaults back in at the end.  */
-      bcopy (include_defaults_array, &include_defaults[num_dirs],
+      bcopy ((char *) include_defaults_array,
+            (char *) &include_defaults[num_dirs],
             sizeof (include_defaults_array));
     }
   }
@@ -6009,7 +5979,7 @@ push_parse_file (pfile, fname)
          = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
        new->control_macro = 0;
        new->c_system_include_path = !p->cxx_aware;
-       new->fname = p->fname;
+       new->fname = update_path (p->fname, p->component);
        new->got_name_map = 0;
        append_include_chain (pfile, new, new);
        if (opts->first_system_include == 0)
@@ -6048,8 +6018,10 @@ push_parse_file (pfile, fname)
          if (fd < 0)
            {
              cpp_perror_with_name (pfile, pend->arg);
-             return FAILURE_EXIT_CODE;
+             return 0;
            }
+         if (!cpp_push_buffer (pfile, NULL, 0))
+             return 0;
          finclude (pfile, fd, pend->arg, 0, NULL_PTR);
          cpp_scan_buffer (pfile);
        }
@@ -6069,7 +6041,10 @@ push_parse_file (pfile, fname)
      inhibit compilation.  */
   if (opts->print_deps_missing_files
       && (opts->print_deps == 0 || !opts->no_output))
-    fatal (pfile, "-MG must be specified with one of -M or -MM");
+    {
+      cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
+      return 0;
+    }
 
   /* Either of two environment variables can specify output of deps.
      Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
@@ -6128,8 +6103,12 @@ push_parse_file (pfile, fname)
        deps_output (pfile, "-", ':');
       else
        {
-         char *p, *q;
-         int len;
+         char *p, *q, *r;
+         int len, x;
+         static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
+                                    ".cc", ".cxx", ".cpp", ".cp",
+                                    ".c++", 0
+                                  };
 
          /* Discard all directory prefixes from filename.  */
          if ((q = rindex (opts->in_fname, '/')) != NULL
@@ -6148,27 +6127,21 @@ push_parse_file (pfile, fname)
          /* Output P, but remove known suffixes.  */
          len = strlen (p);
          q = p + len;
-         if (len >= 2
-             && p[len - 2] == '.'
-             && index("cCsSm", p[len - 1]))
-           q = p + (len - 2);
-         else if (len >= 3
-                  && p[len - 3] == '.'
-                  && p[len - 2] == 'c'
-                  && p[len - 1] == 'c')
-           q = p + (len - 3);
-         else if (len >= 4
-                  && p[len - 4] == '.'
-                  && p[len - 3] == 'c'
-                  && p[len - 2] == 'x'
-                  && p[len - 1] == 'x')
-           q = p + (len - 4);
-         else if (len >= 4
-                  && p[len - 4] == '.'
-                  && p[len - 3] == 'c'
-                  && p[len - 2] == 'p'
-                  && p[len - 1] == 'p')
-           q = p + (len - 4);
+         /* Point to the filename suffix.  */
+         r = rindex (p, '.');
+         /* Compare against the known suffixes.  */
+         x = 0;
+         while (known_suffixes[x] != 0)
+           {
+             if (strncmp (known_suffixes[x], r, q - r) == 0)
+               {
+                 /* Make q point to the bit we're going to overwrite
+                    with an object suffix.  */
+                 q = r;
+                 break;
+               }
+             x++;
+           }
 
          /* Supply our own suffix.  */
 #ifndef VMS
@@ -6199,9 +6172,11 @@ push_parse_file (pfile, fname)
     trigraph_pcp (fp);
 #endif
 
-  /* Scan the -include files before the main input.  */
+  /* Scan the -include files before the main input.
+   We push these in reverse order, so that the first one is handled first.  */
 
   pfile->no_record_file++;
+  opts->pending = nreverse_pending (opts->pending);
   for (pend = opts->pending;  pend;  pend = pend->next)
     {
       if (pend->cmd != NULL && strcmp (pend->cmd, "-include") == 0)
@@ -6210,15 +6185,16 @@ push_parse_file (pfile, fname)
          if (fd < 0)
            {
              cpp_perror_with_name (pfile, pend->arg);
-             return FAILURE_EXIT_CODE;
+             return 0;
            }
+         if (!cpp_push_buffer (pfile, NULL, 0))
+           return 0;
          finclude (pfile, fd, pend->arg, 0, NULL_PTR);
-         cpp_scan_buffer (pfile);
        }
     }
   pfile->no_record_file--;
 
-  /* Free the pending list. */
+  /* Free the pending list.  */
   for (pend = opts->pending;  pend; )
     {
       struct cpp_pending *next = pend->next;
@@ -6239,20 +6215,20 @@ push_parse_file (pfile, fname)
     pedwarn ("file does not end in newline");
 
 #endif
-  if (finclude (pfile, f, fname, 0, 0))
+  if (finclude (pfile, f, fname, 0, NULL_PTR))
     output_line_command (pfile, 0, same_file);
-  return SUCCESS_EXIT_CODE;
+  return 1;
 }
 
 void
-init_parse_file (pfile)
+cpp_reader_init (pfile)
      cpp_reader *pfile;
 {
-  bzero (pfile, sizeof (cpp_reader));
+  bzero ((char *) pfile, sizeof (cpp_reader));
   pfile->get_token = cpp_get_token;
 
   pfile->token_buffer_size = 200;
-  pfile->token_buffer = (char*)xmalloc (pfile->token_buffer_size);
+  pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
   CPP_SET_WRITTEN (pfile, 0);
 
   pfile->system_include_depth = 0;
@@ -6264,6 +6240,21 @@ init_parse_file (pfile)
   pfile->buffer = CPP_NULL_BUFFER(pfile);
 }
 
+static struct cpp_pending *
+nreverse_pending (list)
+     struct cpp_pending *list;
+     
+{
+  register struct cpp_pending *prev = 0, *next, *pend;
+  for (pend = list;  pend;  pend = next)
+    {
+      next = pend->next;
+      pend->next = prev;
+      prev = pend;
+    }
+  return prev;
+}
+
 static void
 push_pending (pfile, cmd, arg)
      cpp_reader *pfile;
@@ -6271,7 +6262,7 @@ push_pending (pfile, cmd, arg)
      char *arg;
 {
   struct cpp_pending *pend
-    = (struct cpp_pending*)xmalloc (sizeof (struct cpp_pending));
+    = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
   pend->cmd = cmd;
   pend->arg = arg;
   pend->next = CPP_OPTIONS (pfile)->pending;
@@ -6294,7 +6285,10 @@ cpp_handle_options (pfile, argc, argv)
   for (i = 0; i < argc; i++) {
     if (argv[i][0] != '-') {
       if (opts->out_fname != NULL)
-       fatal ("Usage: %s [switches] input output", argv[0]);
+       {
+         cpp_fatal (pfile, "Usage: %s [switches] input output", argv[0]);
+         return argc;
+       }
       else if (opts->in_fname != NULL)
        opts->out_fname = argv[i];
       else
@@ -6302,17 +6296,24 @@ cpp_handle_options (pfile, argc, argv)
     } else {
       switch (argv[i][1]) {
 
+      missing_filename:
+       cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
+       return argc;
+      missing_dirname:
+       cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
+       return argc;
+
       case 'i':
        if (!strcmp (argv[i], "-include")
            || !strcmp (argv[i], "-imacros")) {
          if (i + 1 == argc)
-           fatal ("Filename missing after `%s' option", argv[i]);
+           goto missing_filename;
          else
            push_pending (pfile, argv[i], argv[i+1]), i++;
        }
        if (!strcmp (argv[i], "-iprefix")) {
          if (i + 1 == argc)
-           fatal ("Filename missing after `-iprefix' option");
+           goto missing_filename;
          else
            opts->include_prefix = argv[++i];
        }
@@ -6323,7 +6324,7 @@ cpp_handle_options (pfile, argc, argv)
          struct file_name_list *dirtmp;
 
          if (i + 1 == argc)
-           fatal ("Filename missing after `-isystem' option");
+           goto missing_filename;
 
          dirtmp = (struct file_name_list *)
            xmalloc (sizeof (struct file_name_list));
@@ -6361,7 +6362,7 @@ cpp_handle_options (pfile, argc, argv)
          dirtmp->control_macro = 0;
          dirtmp->c_system_include_path = 0;
          if (i + 1 == argc)
-           fatal ("Directory name missing after `-iwithprefix' option");
+           goto missing_dirname;
 
          dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
                                            + strlen (prefix) + 1);
@@ -6396,7 +6397,7 @@ cpp_handle_options (pfile, argc, argv)
          dirtmp->control_macro = 0;
          dirtmp->c_system_include_path = 0;
          if (i + 1 == argc)
-           fatal ("Directory name missing after `-iwithprefixbefore' option");
+           goto missing_dirname;
 
          dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
                                            + strlen (prefix) + 1);
@@ -6416,7 +6417,7 @@ cpp_handle_options (pfile, argc, argv)
          dirtmp->control_macro = 0;
          dirtmp->c_system_include_path = 0;
          if (i + 1 == argc)
-           fatal ("Directory name missing after `-idirafter' option");
+           goto missing_dirname;
          else
            dirtmp->fname = argv[++i];
          dirtmp->got_name_map = 0;
@@ -6431,9 +6432,12 @@ cpp_handle_options (pfile, argc, argv)
 
       case 'o':
        if (opts->out_fname != NULL)
-         fatal ("Output filename specified twice");
+         {
+           cpp_fatal (pfile, "Output filename specified twice");
+           return argc;
+         }
        if (i + 1 == argc)
-         fatal ("Filename missing after -o option");
+         goto missing_filename;
        opts->out_fname = argv[++i];
        if (!strcmp (opts->out_fname, "-"))
          opts->out_fname = "";
@@ -6449,10 +6453,9 @@ cpp_handle_options (pfile, argc, argv)
 #if 0
        else if (!strcmp (argv[i], "-pcp")) {
          char *pcp_fname = argv[++i];
-         pcp_outfile = 
-           ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
-            ? fopen (pcp_fname, "w")
-            : fdopen (dup (fileno (stdout)), "w"));
+         pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
+                        ? fopen (pcp_fname, "w")
+                        : fdopen (dup (fileno (stdout)), "w"));
          if (pcp_outfile == 0)
            cpp_pfatal_with_name (pfile, pcp_fname);
          no_precomp = 1;
@@ -6463,8 +6466,6 @@ cpp_handle_options (pfile, argc, argv)
       case 't':
        if (!strcmp (argv[i], "-traditional")) {
          opts->traditional = 1;
-         if (opts->dollars_in_ident > 0)
-           opts->dollars_in_ident = 1;
        } else if (!strcmp (argv[i], "-trigraphs")) {
          if (!opts->chill)
            opts->no_trigraphs = 0;
@@ -6473,15 +6474,20 @@ cpp_handle_options (pfile, argc, argv)
 
       case 'l':
        if (! strcmp (argv[i], "-lang-c"))
-         opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->objc = 0;
+         opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->objc = 0;
+       if (! strcmp (argv[i], "-lang-c89"))
+         opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
+         opts->objc = 0;
        if (! strcmp (argv[i], "-lang-c++"))
-         opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->objc = 0;
-       if (! strcmp (argv[i], "-lang-c-c++-comments"))
-         opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->objc = 0;
+         opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->objc = 0;
        if (! strcmp (argv[i], "-lang-objc"))
-         opts->objc = 1, opts->cplusplus = 0, opts->cplusplus_comments = 1;
+         opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->objc = 1;
        if (! strcmp (argv[i], "-lang-objc++"))
-         opts->objc = 1, opts->cplusplus = 1, opts->cplusplus_comments = 1;
+         opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+         opts->objc = 1;
        if (! strcmp (argv[i], "-lang-asm"))
          opts->lang_asm = 1;
        if (! strcmp (argv[i], "-lint"))
@@ -6516,6 +6522,10 @@ cpp_handle_options (pfile, argc, argv)
          opts->warn_stringify = 1;
        else if (!strcmp (argv[i], "-Wno-traditional"))
          opts->warn_stringify = 0;
+       else if (!strcmp (argv[i], "-Wundef"))
+         opts->warn_undef = 1;
+       else if (!strcmp (argv[i], "-Wno-undef"))
+         opts->warn_undef = 0;
        else if (!strcmp (argv[i], "-Wimport"))
          opts->warn_import = 1;
        else if (!strcmp (argv[i], "-Wno-import"))
@@ -6561,7 +6571,7 @@ cpp_handle_options (pfile, argc, argv)
        if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
          {
            if (i+1 == argc)
-             fatal ("Filename missing after %s option", argv[i]);
+             goto missing_filename;
            opts->deps_file = argv[++i];
          }
        else
@@ -6589,6 +6599,9 @@ cpp_handle_options (pfile, argc, argv)
            case 'D':
              opts->dump_macros = dump_definitions;
              break;
+           case 'I':
+             opts->dump_includes = 1;
+             break;
            }
          }
        }
@@ -6616,7 +6629,10 @@ cpp_handle_options (pfile, argc, argv)
        if (argv[i][2] != 0)
          push_pending (pfile, "-D", argv[i] + 2);
        else if (i + 1 == argc)
-         fatal ("Macro name missing after -D option");
+         {
+           cpp_fatal (pfile, "Macro name missing after -D option");
+           return argc;
+         }
        else
          i++, push_pending (pfile, "-D", argv[i]);
        break;
@@ -6628,7 +6644,10 @@ cpp_handle_options (pfile, argc, argv)
          if (argv[i][2] != 0)
            p = argv[i] + 2;
          else if (i + 1 == argc)
-           fatal ("Assertion missing after -A option");
+           {
+             cpp_fatal (pfile, "Assertion missing after -A option");
+             return argc;
+           }
          else
            p = argv[++i];
 
@@ -6662,7 +6681,10 @@ cpp_handle_options (pfile, argc, argv)
        if (argv[i][2] != 0)
          push_pending (pfile, "-U", argv[i] + 2);
        else if (i + 1 == argc)
-         fatal ("Macro name missing after -U option");
+         {
+           cpp_fatal (pfile, "Macro name missing after -U option", NULL);
+           return argc;
+         }
        else
          push_pending (pfile, "-U", argv[i+1]), i++;
        break;
@@ -6701,7 +6723,7 @@ cpp_handle_options (pfile, argc, argv)
            if (argv[i][2] != 0)
              dirtmp->fname = argv[i] + 2;
            else if (i + 1 == argc)
-             fatal ("Directory name missing after -I option");
+             goto missing_dirname;
            else
              dirtmp->fname = argv[++i];
            dirtmp->got_name_map = 0;
@@ -6724,6 +6746,11 @@ cpp_handle_options (pfile, argc, argv)
 #endif
        break;
 
+      case 'r':
+       if (!strcmp (argv[i], "-remap"))
+         opts->remap = 1;
+       break;
+
       case 'u':
        /* Sun compiler passes undocumented switch "-undef".
           Let's assume it means to inhibit the predefined symbols.  */
@@ -6771,11 +6798,80 @@ cpp_finish (pfile)
          if (opts->deps_file)
            {
              if (ferror (deps_stream) || fclose (deps_stream) != 0)
-               fatal ("I/O error on output");
+               cpp_fatal (pfile, "I/O error on output");
            }
        }
     }
 }
+
+/* Free resources used by PFILE.
+   This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology).  */
+
+void
+cpp_cleanup (pfile)
+     cpp_reader *pfile;
+{
+  int i;
+  while ( CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
+    cpp_pop_buffer (pfile);
+
+  if (pfile->token_buffer)
+    {
+      free (pfile->token_buffer);
+      pfile->token_buffer = NULL;
+    }
+
+  if (pfile->deps_buffer)
+    {
+      free (pfile->deps_buffer);
+      pfile->deps_buffer = NULL;
+      pfile->deps_allocated_size = 0;
+    }
+
+  while (pfile->if_stack)
+    {
+      IF_STACK_FRAME *temp = pfile->if_stack;
+      pfile->if_stack = temp->next;
+      free (temp);
+    }
+
+  while (pfile->dont_repeat_files)
+    {
+      struct file_name_list *temp = pfile->dont_repeat_files;
+      pfile->dont_repeat_files = temp->next;
+      free (temp->fname);
+      free (temp);
+    }
+
+  while (pfile->all_include_files)
+    {
+      struct file_name_list *temp = pfile->all_include_files;
+      pfile->all_include_files = temp->next;
+      free (temp->fname);
+      free (temp);
+    }
+
+  for (i = IMPORT_HASH_SIZE; --i >= 0; )
+    {
+      register struct import_file *imp = pfile->import_hash_table[i];
+      while (imp)
+       {
+         struct import_file *next = imp->next;
+         free (imp->name);
+         free (imp);
+         imp = next;
+       }
+      pfile->import_hash_table[i] = 0;
+    }
+
+  for (i = ASSERTION_HASHSIZE; --i >= 0; )
+    {
+      while (pfile->assertion_hashtab[i])
+       delete_assertion (pfile->assertion_hashtab[i]);
+    }
+
+  cpp_hash_cleanup (pfile);
+}
 \f
 static int
 do_assert (pfile, keyword, buf, limit)
@@ -6907,15 +7003,9 @@ do_unassert (pfile, keyword, buf, limit)
 
     /* If no token list was specified, then eliminate this assertion
        entirely.  */
-    if (! tokens_specified) {
-      struct tokenlist_list *next;
-      for (tail = hp->value; tail; tail = next) {
-       next = tail->next;
-       free_token_list (tail->tokens);
-       free (tail);
-      }
+    if (! tokens_specified)
       delete_assertion (hp);
-    else {
+    else {
       /* If a list of tokens was given, then delete any matching list.  */
 
       tail = hp->value;
@@ -7121,25 +7211,9 @@ free_token_list (tokens)
   }
 }
 \f
-/* Get the file-mode and data size of the file open on FD
-   and store them in *MODE_POINTER and *SIZE_POINTER.  */
-
-static int
-file_size_and_mode (fd, mode_pointer, size_pointer)
-     int fd;
-     int *mode_pointer;
-     long int *size_pointer;
-{
-  struct stat sbuf;
-
-  if (fstat (fd, &sbuf) < 0) return (-1);
-  if (mode_pointer) *mode_pointer = sbuf.st_mode;
-  if (size_pointer) *size_pointer = sbuf.st_size;
-  return 0;
-}
-
 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
-   retrying if necessary.  Return a negative value if an error occurs,
+   retrying if necessary.  If MAX_READ_LEN is defined, read at most
+   that bytes at a time.  Return a negative value if an error occurs,
    otherwise return the actual number of bytes read,
    which must be LEN unless end-of-file was reached.  */
 
@@ -7149,9 +7223,16 @@ safe_read (desc, ptr, len)
      char *ptr;
      int len;
 {
-  int left = len;
+  int left, rcount, nchars;
+
+  left = len;
   while (left > 0) {
-    int nchars = read (desc, ptr, left);
+    rcount = left;
+#ifdef MAX_READ_LEN
+    if (rcount > MAX_READ_LEN)
+      rcount = MAX_READ_LEN;
+#endif
+    nchars = read (desc, ptr, rcount);
     if (nchars < 0)
       {
 #ifdef EINTR
@@ -7169,6 +7250,16 @@ safe_read (desc, ptr, len)
 }
 
 static char *
+xcalloc (number, size)
+     unsigned number, size;
+{
+  register unsigned total = number * size;
+  register char *ptr = (char *) xmalloc (total);
+  bzero (ptr, total);
+  return ptr;
+}
+
+static char *
 savestring (input)
      char *input;
 {
@@ -7178,37 +7269,8 @@ savestring (input)
   return output;
 }
 \f
-/* Return the line at which an error occurred.
-   The error is not necessarily associated with the current spot
-   in the input stack, so LINE says where.  LINE will have been
-   copied from ip->lineno for the current input level.
-   If the current level is for a file, we return LINE.
-   But if the current level is not for a file, LINE is meaningless.
-   In that case, we return the lineno of the innermost file.  */
+/* Initialize PMARK to remember the current position of PFILE.  */
 
-static int
-line_for_error (line)
-     int line;
-{
-#if 0
-  int i;
-  int line1 = line;
-
-  for (i = indepth; i >= 0; ) {
-    if (instack[i].fname != 0)
-      return line1;
-    i--;
-    if (i < 0)
-      return 0;
-    line1 = instack[i].lineno;
-  }
-  abort ();
-  /*NOTREACHED*/
-#endif
-  return 0;
-}
-\f
-/* Initialize PMARK to remember the current position of PFILE. */
 void
 parse_set_mark (pmark, pfile)
      struct parse_marker *pmark;
@@ -7221,20 +7283,21 @@ parse_set_mark (pmark, pfile)
   pmark->position = pbuf->cur - pbuf->buf;
 }
 
-/* Cleanup PMARK - we no longer need it. */
+/* Cleanup PMARK - we no longer need it.  */
+
 void
 parse_clear_mark (pmark)
      struct parse_marker *pmark;
 {
   struct parse_marker **pp = &pmark->buf->marks;
   for (; ; pp = &(*pp)->next) {
-    if (*pp == NULL) fatal ("internal error", "in parse_set_mark");
+    if (*pp == NULL) abort ();
     if (*pp == pmark) break;
   }
   *pp = pmark->next;
 }
 
-/* Backup the current position of PFILE to that saved in PMARK. */
+/* Backup the current position of PFILE to that saved in PMARK.  */
 
 void
 parse_goto_mark (pmark, pfile)
@@ -7243,12 +7306,12 @@ parse_goto_mark (pmark, pfile)
 {
   cpp_buffer *pbuf = CPP_BUFFER (pfile);
   if (pbuf != pmark->buf)
-    fatal ("internal error %s", "parse_goto_mark");
+    cpp_fatal (pfile, "internal error %s", "parse_goto_mark");
   pbuf->cur = pbuf->buf + pmark->position;
 }
 
 /* Reset PMARK to point to the current position of PFILE.  (Same
-   as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
+   as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster.  */
 
 void
 parse_move_mark (pmark, pfile)
@@ -7257,7 +7320,7 @@ parse_move_mark (pmark, pfile)
 {
   cpp_buffer *pbuf = CPP_BUFFER (pfile);
   if (pbuf != pmark->buf)
-    fatal ("internal error %s", "parse_move_mark");
+    cpp_fatal (pfile, "internal error %s", "parse_move_mark");
   pmark->position = pbuf->cur - pbuf->buf;
 }
 
@@ -7289,14 +7352,223 @@ cpp_read_check_assertion (pfile)
   CPP_ADJUST_WRITTEN (pfile, - name_length);  /* pop */
   return result;
 }
+\f
+void
+cpp_print_file_and_line (pfile)
+     cpp_reader *pfile;
+{
+  cpp_buffer *ip = cpp_file_buffer (pfile);
+
+  if (ip != NULL)
+    {
+      long line, col;
+      cpp_buf_line_and_col (ip, &line, &col);
+      cpp_file_line_for_message (pfile, ip->nominal_fname,
+                                line, pfile->show_column ? col : -1);
+    }
+}
+
+void
+cpp_error (pfile, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  cpp_print_containing_files (pfile);
+  cpp_print_file_and_line (pfile);
+  cpp_message (pfile, 1, msg, arg1, arg2, arg3);
+}
+
+/* Print error message but don't count it.  */
+
+void
+cpp_warning (pfile, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  if (CPP_OPTIONS (pfile)->inhibit_warnings)
+    return;
+
+  if (CPP_OPTIONS (pfile)->warnings_are_errors)
+    pfile->errors++;
+
+  cpp_print_containing_files (pfile);
+  cpp_print_file_and_line (pfile);
+  cpp_message (pfile, 0, msg, arg1, arg2, arg3);
+}
+
+/* Print an error message and maybe count it.  */
+
+void
+cpp_pedwarn (pfile, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  if (CPP_OPTIONS (pfile)->pedantic_errors)
+    cpp_error (pfile, msg, arg1, arg2, arg3);
+  else
+    cpp_warning (pfile, msg, arg1, arg2, arg3);
+}
+
+void
+cpp_error_with_line (pfile, line, column, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     int line, column;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  int i;
+  cpp_buffer *ip = cpp_file_buffer (pfile);
+
+  cpp_print_containing_files (pfile);
+
+  if (ip != NULL)
+    cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
+
+  cpp_message (pfile, 1, msg, arg1, arg2, arg3);
+}
+
+static void
+cpp_warning_with_line (pfile, line, column, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     int line, column;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  int i;
+  cpp_buffer *ip;
+
+  if (CPP_OPTIONS (pfile)->inhibit_warnings)
+    return;
+
+  if (CPP_OPTIONS (pfile)->warnings_are_errors)
+    pfile->errors++;
+
+  cpp_print_containing_files (pfile);
+
+  ip = cpp_file_buffer (pfile);
+
+  if (ip != NULL)
+    cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
+
+  cpp_message (pfile, 0, msg, arg1, arg2, arg3);
+}
+
+void
+cpp_pedwarn_with_line (pfile, line, column, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     int line;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  if (CPP_OPTIONS (pfile)->pedantic_errors)
+    cpp_error_with_line (pfile, column, line, msg, arg1, arg2, arg3);
+  else
+    cpp_warning_with_line (pfile, line, column, msg, arg1, arg2, arg3);
+}
+
+/* Report a warning (or an error if pedantic_errors)
+   giving specified file name and line number, not current.  */
+
+void
+cpp_pedwarn_with_file_and_line (pfile, file, line, msg, arg1, arg2, arg3)
+     cpp_reader *pfile;
+     char *file;
+     int line;
+     char *msg;
+     char *arg1, *arg2, *arg3;
+{
+  if (!CPP_OPTIONS (pfile)->pedantic_errors
+      && CPP_OPTIONS (pfile)->inhibit_warnings)
+    return;
+  if (file != NULL)
+    cpp_file_line_for_message (pfile, file, line, -1);
+  cpp_message (pfile, CPP_OPTIONS (pfile)->pedantic_errors,
+              msg, arg1, arg2, arg3);
+}
+
+/* This defines "errno" properly for VMS, and gives us EACCES.  */
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifndef VMS
+#ifndef HAVE_STRERROR
+extern int sys_nerr;
+extern char *sys_errlist[];
+#else  /* HAVE_STRERROR */
+char *strerror ();
+#endif
+#else  /* VMS */
+char *strerror (int,...);
+#endif
+
+/* my_strerror - return the descriptive text associated with an
+   `errno' code.  */
+
+char *
+my_strerror (errnum)
+     int errnum;
+{
+  char *result;
+
+#ifndef VMS
+#ifndef HAVE_STRERROR
+  result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0);
+#else
+  result = strerror (errnum);
+#endif
+#else  /* VMS */
+  /* VAXCRTL's strerror() takes an optional second argument, which only
+     matters when the first argument is EVMSERR.  However, it's simplest
+     just to pass it unconditionally.  `vaxc$errno' is declared in
+     <errno.h>, and maintained by the library in parallel with `errno'.
+     We assume that caller's `errnum' either matches the last setting of
+     `errno' by the library or else does not have the value `EVMSERR'.  */
+
+  result = strerror (errnum, vaxc$errno);
+#endif
+
+  if (!result)
+    result = "undocumented I/O error";
+
+  return result;
+}
+
+/* Error including a message from `errno'.  */
+
+void
+cpp_error_from_errno (pfile, name)
+     cpp_reader *pfile;
+     char *name;
+{
+  int i;
+  cpp_buffer *ip = cpp_file_buffer (pfile);
+
+  cpp_print_containing_files (pfile);
+
+  if (ip != NULL)
+    cpp_file_line_for_message (pfile, ip->nominal_fname, ip->lineno, -1);
+
+  cpp_message (pfile, 1, "%s: %s", name, my_strerror (errno));
+}
+
+void
+cpp_perror_with_name (pfile, name)
+     cpp_reader *pfile;
+     char *name;
+{
+  cpp_message (pfile, 1, "%s: %s: %s", progname, name, my_strerror (errno));
+}
 
 /* TODO:
  * No pre-compiled header file support.
  *
  * Possibly different enum token codes for each C/C++ token.
  *
- * Better error messages for non-terminated strings and comments.
- *
  * Should clean up remaining directives to that do_XXX functions
  *   only take two arguments and all have command_reads_line.
  *
@@ -7306,7 +7578,5 @@ cpp_read_check_assertion (pfile)
  *
  * Support -dM flag (dump_all_macros).
  *
- * -include should be made to returns results incrementally.
- *    (current implementation only works when cpp is used as main program)
- *
+ * Support for_lint flag.
  */