OSDN Git Service

* flags.h: New flag (optimize_size).
[pf3gnuchains/gcc-fork.git] / gcc / cpplib.c
index 3f3e212..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,80 +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
 
-#include <ctype.h>
-#include <stdio.h>
-#include <signal.h>
-#ifdef __STDC__
-#include <stdlib.h>
+#if HAVE_LIMITS_H
+# include <limits.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_STDLIB_H
+# include <stdlib.h>
+#endif
 
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+#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.  */
 #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
@@ -100,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
@@ -122,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
@@ -205,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 */
@@ -234,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;
@@ -251,49 +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_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 ();
 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*));
-static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending*));
+                                         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 ();
@@ -304,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 ();
@@ -350,15 +344,16 @@ struct file_name_list
   };
 
 /* 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))
+   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. */
+/* #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
@@ -369,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
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
 #endif
-    { STANDARD_INCLUDE_DIR, 0, 0 },
+    { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
 #endif /* not CROSS_COMPILE */
-    { 0, 0, 0 }
+    { 0, 0, 0, 0 }
     };
 #endif /* no INCLUDE_DEFAULTS */
 
@@ -405,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},
@@ -428,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
@@ -439,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];
@@ -492,7 +497,8 @@ initialize_char_syntax (opts)
 
 
 /* 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;
@@ -509,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;
@@ -527,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)
@@ -536,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 = (U_CHAR*)
+  pfile->token_buffer = (U_CHAR *)
     xrealloc(pfile->token_buffer, pfile->token_buffer_size);
   CPP_SET_WRITTEN (pfile, old_written);
 }
@@ -609,7 +615,6 @@ make_assertion (pfile, option, str)
      char *option;
      U_CHAR *str;
 {
-  cpp_buffer *ip;
   struct directive *kt;
   U_CHAR *buf, *p, *q;
 
@@ -641,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
@@ -775,8 +782,8 @@ path_include (pfile, path)
 }
 \f
 void
-init_parse_options (opts)
-     struct cpp_options *opts;
+cpp_options_init (opts)
+     cpp_options *opts;
 {
   bzero ((char *) opts, sizeof *opts);
   opts->in_fname = NULL;
@@ -785,7 +792,6 @@ init_parse_options (opts)
   /* 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;
@@ -793,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;
 
@@ -828,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)
@@ -849,52 +856,18 @@ file_cleanup (pbuf, pfile)
   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)
@@ -929,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);
@@ -939,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 ' ';
            }
@@ -950,6 +923,7 @@ skip_comment (pfile, linep)
 }     
 
 /* Skip whitespace \-newline and comments.  Does not macro-expand.  */
+
 void
 cpp_skip_hspace (pfile)
      cpp_reader *pfile;
@@ -986,9 +960,9 @@ cpp_skip_hspace (pfile)
 }
 
 /* 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;
 {
@@ -1013,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':
@@ -1071,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;
@@ -1117,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);
@@ -1129,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;
 
@@ -1203,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;
@@ -1245,7 +1223,7 @@ collect_expansion (pfile, buf, limit, 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 (limit < buf)
     abort ();
@@ -1261,7 +1239,7 @@ collect_expansion (pfile, buf, limit, nargs, arglist)
      leading and trailing newline-marker and final null.  */
   maxsize = (sizeof (DEFINITION)
             + (limit - p) + 5);
-  /* Occurrences of '@' get doubled, so allocate extra space for them. */
+  /* Occurrences of '@' get doubled, so allocate extra space for them.  */
   while (p < limit)
     if (*p++ == '@')
       maxsize++;
@@ -1274,7 +1252,7 @@ collect_expansion (pfile, buf, limit, nargs, arglist)
   p = buf;
 
   /* Add one initial space escape-marker to prevent accidental
-     token-pasting (often removed by macroexpand). */
+     token-pasting (often removed by macroexpand).  */
   *exp_p++ = '@';
   *exp_p++ = ' ';
 
@@ -1310,7 +1288,10 @@ collect_expansion (pfile, buf, limit, 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 '#':
@@ -1335,7 +1316,8 @@ collect_expansion (pfile, buf, limit, 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
@@ -1396,7 +1378,8 @@ collect_expansion (pfile, buf, limit, 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) {
@@ -1505,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;
@@ -1536,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;
@@ -1566,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;
@@ -1594,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);
@@ -1610,7 +1594,7 @@ create_definition (buf, limit, pfile, predefinition)
 
     ++bp;                      /* skip paren */
     SKIP_WHITE_SPACE (bp);
-    /* now everything from bp before limit is the definition. */
+    /* now everything from bp before limit is the definition.  */
     defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
     defn->rest_args = rest_args;
 
@@ -1657,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 *) "";
   }
@@ -1693,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;
@@ -1708,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;
@@ -1722,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) {
@@ -1818,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.  */
@@ -1870,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)
@@ -1884,26 +1870,27 @@ struct argdata {
   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 = CPP_BUFFER (pfile);
   if (buf == pfile->buffer_stack)
-    fatal ("macro or `#include' recursion too deep");
+    {
+      cpp_fatal (pfile, "%s: macro or `#include' recursion too deep",
+                buf->fname);
+      return NULL;
+    }
   buf--;
   bzero ((char *) buf, sizeof (cpp_buffer));
   CPP_BUFFER (pfile) = buf;
-#else
-  register cpp_buffer *buf = (cpp_buffer*) xmalloc (sizeof(cpp_buffer));
-  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;
@@ -1913,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)
@@ -1941,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)
        {
@@ -1990,6 +1969,8 @@ 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;
@@ -2024,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)
@@ -2063,9 +2044,9 @@ 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;
 {
@@ -2111,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;
@@ -2156,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); 
@@ -2228,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: ;
@@ -2290,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;
@@ -2328,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 */
@@ -2345,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;
@@ -2359,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++;
 
@@ -2399,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 */
@@ -2413,7 +2407,7 @@ special_symbol (hp, pfile)
        adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
 
        buf = (char *) alloca (10);
-       sprintf (buf, "%d", line);
+       sprintf (buf, "%ld", line);
       }
       break;
 
@@ -2442,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 ";
@@ -2493,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)
@@ -2601,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 '=':
@@ -2689,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;
@@ -2797,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);
@@ -2852,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);
                        }
@@ -2940,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)
                {
@@ -3007,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++)
        {
@@ -3031,7 +3009,7 @@ macroexpand (pfile, hp)
   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.
@@ -3050,6 +3028,8 @@ 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;
 
@@ -3097,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;
@@ -3113,7 +3093,7 @@ get_directive_token (pfile)
    The input is normally in part of the output_buffer following
    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)
@@ -3140,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;
@@ -3148,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)
@@ -3182,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;
@@ -3268,8 +3256,8 @@ 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
@@ -3428,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) {
@@ -3464,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);
       }
@@ -3474,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);
@@ -3517,7 +3505,8 @@ do_include (pfile, keyword, unused1, unused2)
 #endif
     
     /* Actually process the file */
-    cpp_push_buffer (pfile, NULL, 0);
+    if (cpp_push_buffer (pfile, NULL, 0) == NULL)
+      return 0;
     if (finclude (pfile, f, fname, is_system_include (pfile, fname),
                  searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
       {
@@ -3594,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;
@@ -3671,8 +3661,8 @@ delete_assertion (hp)
       tail = next;
     }
 
-  /* make sure that the bucket chain header that
-     the deleted guy was on points to the right thing afterwards. */
+  /* 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;
 
@@ -3685,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;
@@ -3754,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.  */
@@ -3824,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;
       }
@@ -3914,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);
@@ -3935,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;
 }
 
@@ -3955,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;
@@ -3973,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)
@@ -3988,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;
 }
@@ -4150,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;
@@ -4160,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);
@@ -4186,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;
@@ -4294,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;
@@ -4411,7 +4404,7 @@ 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)
       {
@@ -4590,9 +4583,8 @@ validate_else (pfile, directive)
 }
 
 /* Get the next token, and add it to the text in pfile->token_buffer.
-   Return the kind of token we got. */
+   Return the kind of token we got.  */
   
-
 enum cpp_token
 cpp_get_token (pfile)
      cpp_reader *pfile;
@@ -4620,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) result.
-                But the #line refers to the file we will pop to. */
+                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;
@@ -4659,7 +4652,7 @@ cpp_get_token (pfile)
                                   "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.  */
@@ -4684,7 +4677,7 @@ cpp_get_token (pfile)
            {
 #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
@@ -4724,8 +4717,8 @@ 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++) = '/';
@@ -4823,7 +4816,7 @@ cpp_get_token (pfile)
                  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++;
                    }
@@ -4887,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 ();
@@ -4895,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;
                    }
@@ -5031,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;
@@ -5108,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;
@@ -5154,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) {
@@ -5178,7 +5173,7 @@ cpp_get_token (pfile)
            /* 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. */
+              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] == ' ')
@@ -5235,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;
@@ -5251,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)
@@ -5270,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)
@@ -5415,7 +5414,8 @@ read_filename_string (ch, f)
   return alloc;
 }
 
-/* This structure holds a linked list of file name maps, one per directory. */
+/* 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;
@@ -5512,65 +5512,68 @@ open_include_file (pfile, filename, searchptr)
      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 (pfile,
-                                          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 (pfile, 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);
 }
@@ -5594,14 +5597,14 @@ 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 (file_size_and_mode (f, &st_mode, &st_size) < 0)
+  if (fstat (f, &st) < 0)
     {
       cpp_perror_with_name (pfile, fname);
       close (f);
@@ -5620,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;
@@ -5631,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;
 
@@ -5655,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;
   }
 
@@ -5705,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;
 {
@@ -5737,6 +5753,8 @@ push_parse_file (pfile, fname)
   /* Do partial setup of input buffer for the sake of generating
      early #line directives (when -g is in effect).  */
   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;
@@ -5821,7 +5839,7 @@ 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. */
+  /* First reverse the list.  */
   opts->pending = nreverse_pending (opts->pending);
 
   for (pend = opts->pending;  pend;  pend = pend->next)
@@ -5849,8 +5867,8 @@ push_parse_file (pfile, fname)
 
   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)
       {
@@ -5894,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++;
@@ -5960,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)
@@ -5999,9 +6018,10 @@ push_parse_file (pfile, fname)
          if (fd < 0)
            {
              cpp_perror_with_name (pfile, pend->arg);
-             return FAILURE_EXIT_CODE;
+             return 0;
            }
-         cpp_push_buffer (pfile, NULL, 0);
+         if (!cpp_push_buffer (pfile, NULL, 0))
+             return 0;
          finclude (pfile, fd, pend->arg, 0, NULL_PTR);
          cpp_scan_buffer (pfile);
        }
@@ -6021,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",
@@ -6080,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
@@ -6100,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
@@ -6164,15 +6185,16 @@ push_parse_file (pfile, fname)
          if (fd < 0)
            {
              cpp_perror_with_name (pfile, pend->arg);
-             return FAILURE_EXIT_CODE;
+             return 0;
            }
-         cpp_push_buffer (pfile, NULL, 0);
+         if (!cpp_push_buffer (pfile, NULL, 0))
+           return 0;
          finclude (pfile, fd, pend->arg, 0, NULL_PTR);
        }
     }
   pfile->no_record_file--;
 
-  /* Free the pending list. */
+  /* Free the pending list.  */
   for (pend = opts->pending;  pend; )
     {
       struct cpp_pending *next = pend->next;
@@ -6195,18 +6217,18 @@ push_parse_file (pfile, fname)
 #endif
   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 ((char *) pfile, sizeof (cpp_reader));
   pfile->get_token = cpp_get_token;
 
   pfile->token_buffer_size = 200;
-  pfile->token_buffer = (U_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;
@@ -6240,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;
@@ -6263,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
@@ -6271,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];
        }
@@ -6292,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));
@@ -6330,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);
@@ -6365,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);
@@ -6385,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;
@@ -6400,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 = "";
@@ -6418,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;
@@ -6432,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;
@@ -6442,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"))
@@ -6485,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"))
@@ -6530,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
@@ -6558,6 +6599,9 @@ cpp_handle_options (pfile, argc, argv)
            case 'D':
              opts->dump_macros = dump_definitions;
              break;
+           case 'I':
+             opts->dump_includes = 1;
+             break;
            }
          }
        }
@@ -6585,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;
@@ -6597,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];
 
@@ -6631,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;
@@ -6670,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;
@@ -6693,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.  */
@@ -6740,13 +6798,14 @@ 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. */
+/* Free resources used by PFILE.
+   This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology).  */
 
 void
 cpp_cleanup (pfile)
@@ -7152,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.  */
 
@@ -7180,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
@@ -7200,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;
 {
@@ -7209,7 +7269,8 @@ savestring (input)
   return output;
 }
 \f
-/* Initialize PMARK to remember the current position of PFILE. */
+/* Initialize PMARK to remember the current position of PFILE.  */
+
 void
 parse_set_mark (pmark, pfile)
      struct parse_marker *pmark;
@@ -7222,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)
@@ -7244,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)
@@ -7258,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;
 }
 
@@ -7427,7 +7489,7 @@ cpp_pedwarn_with_file_and_line (pfile, file, line, msg, arg1, arg2, arg3)
               msg, arg1, arg2, arg3);
 }
 
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+/* This defines "errno" properly for VMS, and gives us EACCES.  */
 #include <errno.h>
 #ifndef errno
 extern int errno;
@@ -7436,11 +7498,7 @@ extern int errno;
 #ifndef VMS
 #ifndef HAVE_STRERROR
 extern int sys_nerr;
-#if defined(bsd4_4)
-extern const char *const sys_errlist[];
-#else
 extern char *sys_errlist[];
-#endif
 #else  /* HAVE_STRERROR */
 char *strerror ();
 #endif
@@ -7448,9 +7506,8 @@ char *strerror ();
 char *strerror (int,...);
 #endif
 
-/*
- * my_strerror - return the descriptive text associated with an `errno' code.
- */
+/* my_strerror - return the descriptive text associated with an
+   `errno' code.  */
 
 char *
 my_strerror (errnum)