OSDN Git Service

* Makefile.in ($(srcdir)/c-parse.y: c-parse.in): Enclose the whole
[pf3gnuchains/gcc-fork.git] / gcc / cccp.c
index fbea643..9a02333 100644 (file)
@@ -1,5 +1,6 @@
 /* C Compatible Compiler Preprocessor (CCCP)
-   Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000 Free Software Foundation, Inc.
    Written by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
 
@@ -20,15 +21,7 @@ Boston, MA 02111-1307, USA. */
 
 #include "config.h"
 
-#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)
-
-#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
-#define PRINTF_PROTO_2(ARGS) PRINTF_PROTO(ARGS, 2, 3)
-#define PRINTF_PROTO_3(ARGS) PRINTF_PROTO(ARGS, 3, 4)
-#define PRINTF_PROTO_4(ARGS) PRINTF_PROTO(ARGS, 4, 5)
-
 #include "system.h"
-#include <sys/stat.h>
 #include <signal.h>
 
 #ifdef HAVE_SYS_RESOURCE_H
@@ -37,8 +30,10 @@ Boston, MA 02111-1307, USA. */
 
 typedef unsigned char U_CHAR;
 
-#include "gansidecl.h"
 #include "pcp.h"
+#include "intl.h"
+#include "prefix.h"
+#include "version.h"
 
 #ifdef MULTIBYTE_CHARS
 #include "mbchar.h"
@@ -53,11 +48,6 @@ typedef unsigned char U_CHAR;
 # define STANDARD_INCLUDE_DIR "/usr/include"
 #endif
 
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-# define PATH_SEPARATOR ':'
-#endif
-
 /* By default, the suffix for object files is ".o".  */
 #ifdef OBJECT_SUFFIX
 # define HAVE_OBJECT_SUFFIX
@@ -74,54 +64,25 @@ typedef unsigned char U_CHAR;
 #define fopen(fname,mode)      VMS_fopen (fname,mode)
 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
 #define fstat(fd,stbuf)                VMS_fstat (fd,stbuf)
+#define fwrite(ptr,size,nitems,stream) VMS_fwrite (ptr,size,nitems,stream)
 static int VMS_fstat (), VMS_stat ();
 static int VMS_open ();
 static FILE *VMS_fopen ();
 static FILE *VMS_freopen ();
-static int hack_vms_include_specification ();
+static size_t VMS_fwrite ();
+static void hack_vms_include_specification ();
 #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
 #define INO_T_HASH(a) 0
 #define INCLUDE_LEN_FUDGE 12   /* leave room for VMS syntax conversion */
 #endif /* VMS */
 
-/* Windows does not natively support inodes, and neither does MSDOS.  */
-#if (defined (_WIN32) && ! defined (CYGWIN32)) || defined (__MSDOS__)
+/* Windows does not natively support inodes, and neither does MSDOS. 
+   Cygwin's emulation can generate non-unique inodes, so don't use it. */
+#if (defined (_WIN32) && ! defined (_UWIN)) \
+  || defined (__MSDOS__)
 #define INO_T_EQ(a, b) 0
 #endif
 
-#undef MIN
-#undef MAX
-#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.
-   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
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
 #ifndef INO_T_EQ
 #define INO_T_EQ(a, b) ((a) == (b))
 #endif
@@ -136,14 +97,12 @@ static int hack_vms_include_specification ();
 
 /* External declarations.  */
 
-extern char *version_string;
-extern char *update_path PROTO((char *, char *));
-HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
-HOST_WIDE_INT parse_c_expression PROTO((char *, int));
+HOST_WIDEST_INT parse_escape PARAMS ((char **, HOST_WIDEST_INT));
+HOST_WIDEST_INT parse_c_expression PARAMS ((char *, int));
 \f
 /* Name under which this program was invoked.  */
 
-static char *progname;
+static const char *progname;
 
 /* Nonzero means use extra default include directories for C++.  */
 
@@ -278,6 +237,10 @@ static int warn_trigraphs;
 
 static int warn_undef;
 
+/* Nonzero means warn if we find white space where it doesn't belong.  */
+
+static int warn_white_space;
+
 /* Nonzero means warn if #import is used.  */
 
 static int warn_import = 1;
@@ -294,6 +257,10 @@ int traditional;
 
 int c89;
 
+/* Nonzero for the 1999 C Standard.  */
+
+int c99;
+
 /* Nonzero causes output not to be done,
    but directives such as #define that have side effects
    are still obeyed.  */
@@ -325,9 +292,9 @@ static int multiline_string_line = 0;
    and for expanding macro arguments.  */
 #define INPUT_STACK_MAX 400
 static struct file_buf {
-  char *fname;
+  const char *fname;
   /* Filename specified with #line directive.  */
-  char *nominal_fname;
+  const char *nominal_fname;
   /* The length of nominal_fname, which may contain embedded NULs.  */
   size_t nominal_fname_len;
   /* Include file description.  */
@@ -408,54 +375,55 @@ struct file_name_list
 /* -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 */
+  const char *fname;           /* The name of the directory.  */
+  const 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
                                   C++.  */
+  int included;                 /* Set if the directory is acceptable.  */
 } include_defaults_array[]
 #ifdef INCLUDE_DEFAULTS
   = INCLUDE_DEFAULTS;
 #else
   = {
     /* Pick up GNU C++ specific include files.  */
-    { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
+    { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
 #ifdef CROSS_COMPILE
     /* This is the dir for fixincludes.  Put it just before
        the files that we fix.  */
-    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+    { GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
     /* For cross-compilation, this dir name is generated
        automatically in Makefile.in.  */
-    { CROSS_INCLUDE_DIR, "GCC", 0, 0 },
+    { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 },
 #ifdef TOOL_INCLUDE_DIR
     /* This is another place that the target system's headers might be.  */
-    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
+    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0, 0 },
 #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, 0, 1 },
+    { LOCAL_INCLUDE_DIR, 0, 0, 1, 0 },
 #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, "BINUTILS", 0, 0 },
+    { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0, 0 },
 #endif
     /* This is the dir for fixincludes.  Put it just before
        the files that we fix.  */
-    { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+    { GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
     /* Some systems have an extra dir of include files.  */
 #ifdef SYSTEM_INCLUDE_DIR
-    { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
+    { SYSTEM_INCLUDE_DIR, 0, 0, 0, 0 },
 #endif
 #ifndef STANDARD_INCLUDE_COMPONENT
 #define STANDARD_INCLUDE_COMPONENT 0
 #endif
-    { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
+    { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 0 },
 #endif /* not CROSS_COMPILE */
-    { 0, 0, 0, 0 }
+    { 0, 0, 0, 0, 0 }
     };
 #endif /* no INCLUDE_DEFAULTS */
 
@@ -496,7 +464,7 @@ struct include_file {
      was seen in this include file, or #import was applied to the file.
      Otherwise, if it is nonzero, it is a macro name.
      Don't include the file again if that macro is defined.  */
-  U_CHAR *control_macro;
+  const U_CHAR *control_macro;
   /* Nonzero if the dependency on this include file has been output.  */
   int deps_output;
   struct stat st;
@@ -523,7 +491,7 @@ typedef struct macrodef MACRODEF;
 struct macrodef
 {
   struct definition *defn;
-  U_CHAR *symnam;
+  const U_CHAR *symnam;
   int symlen;
 };
 \f
@@ -566,7 +534,7 @@ struct definition {
                                /* came from the command line */
   U_CHAR *expansion;
   int line;                    /* Line number of definition */
-  char *file;                  /* File of definition */
+  const char *file;            /* File of definition */
   size_t file_len;             /* Length of file (which can contain NULs) */
   char rest_args;              /* Nonzero if last arg. absorbs the rest */
   struct reflist {
@@ -593,7 +561,7 @@ struct definition {
 /* different kinds of things that can appear in the value field
    of a hash node.  Actually, this may be useless now.  */
 union hashval {
-  char *cpval;
+  const char *cpval;
   DEFINITION *defn;
   KEYDEF *keydef;
 };
@@ -613,6 +581,11 @@ union hashval {
 static char rest_extension[] = "...";
 #define REST_EXTENSION_LENGTH  (sizeof (rest_extension) - 1)
 
+/* This is the implicit parameter name when using variable number of
+   parameters for macros using the ISO C 99 extension.  */
+static char va_args_name[] = "__VA_ARGS__";
+#define VA_ARGS_NAME_LENGTH    (sizeof (va_args_name) - 1)
+
 /* The structure of a node in the hash table.  The hash table
    has entries for all tokens defined by #define directives (type T_MACRO),
    plus some special tokens like __LINE__ (these each have their own
@@ -659,6 +632,7 @@ enum node_type {
  T_DISABLED,   /* macro temporarily turned off for rescan */
  T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
  T_PCSTRING,   /* precompiled string (hashval is KEYDEF *) */
+ T_POISON,     /* defined with `#pragma poison' */
  T_UNUSED      /* Used for something not defined.  */
  };
 
@@ -688,13 +662,6 @@ static HASHNODE *hashtab[HASHSIZE];
 #define HASHSTEP(old, c) ((old << 2) + c)
 #define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
 
-/* Symbols to predefine.  */
-
-#ifdef CPP_PREDEFINES
-static char *predefs = CPP_PREDEFINES;
-#else
-static char *predefs = "";
-#endif
 \f
 /* We let tm.h override the types used here, to handle trivial differences
    such as the choice of unsigned int or long unsigned int for size_t.
@@ -719,7 +686,7 @@ static char *predefs = "";
 #ifndef WCHAR_TYPE
 #define WCHAR_TYPE "int"
 #endif
-char * wchar_type = WCHAR_TYPE;
+static const char * wchar_type = WCHAR_TYPE;
 #undef WCHAR_TYPE
 
 /* The string value for __USER_LABEL_PREFIX__ */
@@ -727,6 +694,8 @@ char * wchar_type = WCHAR_TYPE;
 #ifndef USER_LABEL_PREFIX
 #define USER_LABEL_PREFIX ""
 #endif
+static const char * user_label_prefix = USER_LABEL_PREFIX;
+#undef USER_LABEL_PREFIX
 
 /* The string value for __REGISTER_PREFIX__ */
 
@@ -781,12 +750,12 @@ static int assertions_flag;
 \f
 /* `struct directive' defines one #-directive, including how to handle it.  */
 
-#define DO_PROTO PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *))
+#define DO_PROTO PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *))
 
 struct directive {
   int length;                  /* Length of name */
   int (*func) DO_PROTO;        /* Function to handle directive */
-  char *name;                  /* Name of directive */
+  const char *name;            /* Name of directive */
   enum node_type type;         /* Code which describes which directive.  */
 };
 
@@ -813,7 +782,6 @@ static int do_sccs DO_PROTO;
 #endif
 static int do_unassert DO_PROTO;
 static int do_undef DO_PROTO;
-static int do_warning DO_PROTO;
 static int do_xifdef DO_PROTO;
 
 /* Here is the actual list of #-directives, most-often-used first.  */
@@ -832,7 +800,7 @@ static struct directive directive_table[] = {
   {  6, do_include, "import", T_IMPORT},
   {  5, do_undef, "undef", T_UNDEF},
   {  5, do_error, "error", T_ERROR},
-  {  7, do_warning, "warning", T_WARNING},
+  {  7, do_error, "warning", T_WARNING},
 #ifdef SCCS_DIRECTIVE
   {  4, do_sccs, "sccs", T_SCCS},
 #endif
@@ -855,8 +823,6 @@ U_CHAR is_idstart[256];
 static U_CHAR is_hor_space[256];
 /* table to tell if c is horizontal or vertical space.  */
 U_CHAR is_space[256];
-/* names of some characters */
-static char *char_name[256];
 
 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
@@ -864,20 +830,24 @@ static char *char_name[256];
 static int errors = 0;                 /* Error counter for exit code */
 
 /* Name of output file, for error messages.  */
-static char *out_fname;
+static const char *out_fname;
 
+/* Nonzero to ignore \ in string constants.  Use to treat #line 1 "A:\file.h
+   as a non-form feed.  If you want it to be a form feed, you must use
+   # 1 "\f".  */
+static int ignore_escape_flag = 1;
 
 /* Stack of conditionals currently in progress
    (including both successful and failing conditionals).  */
 
 struct if_stack {
   struct if_stack *next;       /* for chaining to the next stack frame */
-  char *fname;         /* copied from input when frame is made */
+  const char *fname;           /* copied from input when frame is made */
   size_t fname_len;            /* similarly */
   int lineno;                  /* similarly */
   int if_succeeded;            /* true if a leg of this if-group
                                    has been passed through rescan */
-  U_CHAR *control_macro;       /* For #ifndef at start of file,
+  const U_CHAR *control_macro; /* For #ifndef at start of file,
                                   this is the macro name tested.  */
   enum node_type type;         /* type of last directive seen in this group */
 };
@@ -900,153 +870,165 @@ static int deps_column;
    so don't look for #include "foo" the source-file directory.  */
 static int ignore_srcdir;
 \f
-static int safe_read PROTO((int, char *, int));
-static void safe_write PROTO((int, char *, int));
-static void eprint_string PROTO((char *, size_t));
+static int safe_read PARAMS ((int, char *, int));
+static void safe_write PARAMS ((int, const char *, int));
 
-int main PROTO((int, char **));
+int main PARAMS ((int, char **));
 
-static void path_include PROTO((char *));
+static void path_include PARAMS ((char *));
 
-static U_CHAR *index0 PROTO((U_CHAR *, int, size_t));
+static const U_CHAR *index0 PARAMS ((const U_CHAR *, int, size_t));
 
-static void trigraph_pcp PROTO((FILE_BUF *));
+static void trigraph_pcp PARAMS ((FILE_BUF *));
+static void check_white_space PARAMS ((FILE_BUF *));
 
-static void newline_fix PROTO((U_CHAR *));
-static void name_newline_fix PROTO((U_CHAR *));
+static void newline_fix PARAMS ((U_CHAR *));
+static void name_newline_fix PARAMS ((U_CHAR *));
 
-static char *get_lintcmd PROTO((U_CHAR *, U_CHAR *, U_CHAR **, int *, int *));
+static const char *get_lintcmd PARAMS ((const U_CHAR *, const U_CHAR *,
+                                       const U_CHAR **, int *, int *));
 
-static void rescan PROTO((FILE_BUF *, int));
+static void rescan PARAMS ((FILE_BUF *, int));
 
-static FILE_BUF expand_to_temp_buffer PROTO((U_CHAR *, U_CHAR *, int, int));
+static FILE_BUF expand_to_temp_buffer PARAMS ((const U_CHAR *, const U_CHAR *,
+                                              int, int));
 
-static int handle_directive PROTO((FILE_BUF *, FILE_BUF *));
+static int handle_directive PARAMS ((FILE_BUF *, FILE_BUF *));
 
-static struct tm *timestamp PROTO((void));
-static void special_symbol PROTO((HASHNODE *, FILE_BUF *));
+static struct tm *timestamp PARAMS ((void));
+static void special_symbol PARAMS ((HASHNODE *, FILE_BUF *));
 
-static int is_system_include PROTO((char *));
-static char *base_name PROTO((char *));
-static int absolute_filename PROTO((char *));
-static size_t simplify_filename PROTO((char *));
+static int is_system_include PARAMS ((const char *));
+static char *base_name PARAMS ((const char *));
+static int absolute_filename PARAMS ((const char *));
+static size_t simplify_filename PARAMS ((char *));
 
-static char *read_filename_string PROTO((int, FILE *));
-static struct file_name_map *read_name_map PROTO((char *));
-static int open_include_file PROTO((char *, struct file_name_list *, U_CHAR *, struct include_file **));
-static char *remap_include_file PROTO((char *, struct file_name_list *));
-static int lookup_ino_include PROTO((struct include_file *));
+static char *read_filename_string PARAMS ((int, FILE *));
+static struct file_name_map *read_name_map PARAMS ((const char *));
+static int open_include_file PARAMS ((char *, struct file_name_list *,
+                                     const U_CHAR *, struct include_file **));
+static char *remap_include_file PARAMS ((char *, struct file_name_list *));
+static int lookup_ino_include PARAMS ((struct include_file *));
 
-static void finclude PROTO((int, struct include_file *, FILE_BUF *, int, struct file_name_list *));
-static void record_control_macro PROTO((struct include_file *, U_CHAR *));
+static void finclude PARAMS ((int, struct include_file *, FILE_BUF *, int,
+                             struct file_name_list *));
+static void record_control_macro PARAMS ((struct include_file *,
+                                         const U_CHAR *));
 
-static char *check_precompiled PROTO((int, struct stat *, char *, char **));
-static int check_preconditions PROTO((char *));
-static void pcfinclude PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
-static void pcstring_used PROTO((HASHNODE *));
-static void write_output PROTO((void));
-static void pass_thru_directive PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *));
+static char *check_precompiled PARAMS ((int, struct stat *, const char *,
+                                       const char **));
+static int check_preconditions PARAMS ((const char *));
+static void pcfinclude PARAMS ((U_CHAR *, const U_CHAR *, FILE_BUF *));
+static void pcstring_used PARAMS ((HASHNODE *));
+static void write_output PARAMS ((void));
+static void pass_thru_directive PARAMS ((const U_CHAR *, const U_CHAR *,
+                                        FILE_BUF *, struct directive *));
 
-static MACRODEF create_definition PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
+static MACRODEF create_definition PARAMS ((const U_CHAR *, const U_CHAR *,
+                                          FILE_BUF *));
 
-static int check_macro_name PROTO((U_CHAR *, char *));
-static int compare_defs PROTO((DEFINITION *, DEFINITION *));
-static int comp_def_part PROTO((int, U_CHAR *, int, U_CHAR *, int, int));
+static int check_macro_name PARAMS ((const U_CHAR *, int));
+static int compare_defs PARAMS ((DEFINITION *, DEFINITION *));
+static int comp_def_part PARAMS ((int, const U_CHAR *, int, const U_CHAR *,
+                                 int, int));
 
-static DEFINITION *collect_expansion  PROTO((U_CHAR *, U_CHAR *, int, struct arglist *));
+static DEFINITION *collect_expansion  PARAMS ((const U_CHAR *, const U_CHAR *,
+                                              int, struct arglist *));
 
-int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
-static int compare_token_lists PROTO((struct arglist *, struct arglist *));
+int check_assertion PARAMS ((const U_CHAR *, int, int, struct arglist *));
+static int compare_token_lists PARAMS ((struct arglist *, struct arglist *));
 
-static struct arglist *read_token_list PROTO((U_CHAR **, U_CHAR *, int *));
-static void free_token_list PROTO((struct arglist *));
+static struct arglist *read_token_list PARAMS ((const U_CHAR **,
+                                               const U_CHAR *, int *));
+static void free_token_list PARAMS ((struct arglist *));
 
-static ASSERTION_HASHNODE *assertion_install PROTO((U_CHAR *, int, int));
-static ASSERTION_HASHNODE *assertion_lookup PROTO((U_CHAR *, int, int));
-static void delete_assertion PROTO((ASSERTION_HASHNODE *));
+static ASSERTION_HASHNODE *assertion_install PARAMS ((const U_CHAR *, int, int));
+static ASSERTION_HASHNODE *assertion_lookup PARAMS ((const U_CHAR *, int, int));
+static void delete_assertion PARAMS ((ASSERTION_HASHNODE *));
 
-static void do_once PROTO((void));
+static void do_once PARAMS ((void));
 
-static HOST_WIDE_INT eval_if_expression PROTO((U_CHAR *, int));
-static void conditional_skip PROTO((FILE_BUF *, int, enum node_type, U_CHAR *, FILE_BUF *));
-static void skip_if_group PROTO((FILE_BUF *, int, FILE_BUF *));
-static void validate_else PROTO((U_CHAR *, U_CHAR *));
+static HOST_WIDEST_INT eval_if_expression PARAMS ((const U_CHAR *, int));
+static void conditional_skip PARAMS ((FILE_BUF *, int, enum node_type,
+                                     const U_CHAR *, FILE_BUF *));
+static void skip_if_group PARAMS ((FILE_BUF *, int, FILE_BUF *));
+static void validate_else PARAMS ((const U_CHAR *, const U_CHAR *));
 
-static U_CHAR *skip_to_end_of_comment PROTO((FILE_BUF *, int *, int));
-static U_CHAR *skip_quoted_string PROTO((U_CHAR *, U_CHAR *, int, int *, int *, int *));
-static char *quote_string PROTO((char *, char *, size_t));
-static U_CHAR *skip_paren_group PROTO((FILE_BUF *));
+static U_CHAR *skip_to_end_of_comment PARAMS ((FILE_BUF *, int *, int));
+static U_CHAR *skip_quoted_string PARAMS ((const U_CHAR *, const U_CHAR *,
+                                          int, int *, int *, int *));
+static char *quote_string PARAMS ((char *, const char *, size_t));
+static U_CHAR *skip_paren_group PARAMS ((FILE_BUF *));
 
 /* Last arg to output_line_directive.  */
 enum file_change_code {same_file, enter_file, leave_file};
-static void output_line_directive PROTO((FILE_BUF *, FILE_BUF *, int, enum file_change_code));
+static void output_line_directive PARAMS ((FILE_BUF *, FILE_BUF *, int, enum file_change_code));
 
-static void macroexpand PROTO((HASHNODE *, FILE_BUF *));
+static void macroexpand PARAMS ((HASHNODE *, FILE_BUF *));
 
 struct argdata;
-static char *macarg PROTO((struct argdata *, int));
+static int macarg PARAMS ((struct argdata *, int));
 
-static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int));
+static U_CHAR *macarg1 PARAMS ((U_CHAR *, const U_CHAR *, struct hashnode *, int *, int *, int *, int));
 
-static int discard_comments PROTO((U_CHAR *, int, int));
+static int discard_comments PARAMS ((U_CHAR *, int, int));
 
-static int change_newlines PROTO((U_CHAR *, int));
+static void change_newlines PARAMS ((struct argdata *));
 
-static char *my_strerror PROTO((int));
-void error PRINTF_PROTO_1((char *, ...));
-static void verror PROTO((char *, va_list));
-static void error_from_errno PROTO((char *));
-void warning PRINTF_PROTO_1((char *, ...));
-static void vwarning PROTO((char *, va_list));
-static void error_with_line PRINTF_PROTO_2((int, char *, ...));
-static void verror_with_line PROTO((int, char *, va_list));
-static void vwarning_with_line PROTO((int, char *, va_list));
-static void warning_with_line PRINTF_PROTO_2((int, char *, ...));
-void pedwarn PRINTF_PROTO_1((char *, ...));
-void pedwarn_with_line PRINTF_PROTO_2((int, char *, ...));
-static void pedwarn_with_file_and_line PRINTF_PROTO_4((char *, size_t, int, char *, ...));
+static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
+static void vnotice PARAMS ((const char *, va_list));
+void error PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void verror PARAMS ((const char *, va_list));
+static void error_from_errno PARAMS ((const char *));
+void warning PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
+static void vwarning PARAMS ((const char *, va_list));
+static void error_with_line PARAMS ((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void verror_with_line PARAMS ((int, const char *, va_list));
+static void vwarning_with_line PARAMS ((int, const char *, va_list));
+static void warning_with_line PARAMS ((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+void pedwarn PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void pedwarn_with_line PARAMS ((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void pedwarn_with_file_and_line PARAMS ((const char *, size_t, int, const char *, ...)) ATTRIBUTE_PRINTF_4;
+static void pedwarn_strange_white_space PARAMS ((int));
 
-static void print_containing_files PROTO((void));
+static void print_containing_files PARAMS ((void));
 
-static int line_for_error PROTO((int));
-static int grow_outbuf PROTO((FILE_BUF *, int));
+static int line_for_error PARAMS ((int));
+static int grow_outbuf PARAMS ((FILE_BUF *, int));
 
-static HASHNODE *install PROTO((U_CHAR *, int, enum node_type, char *, int));
-HASHNODE *lookup PROTO((U_CHAR *, int, int));
-static void delete_macro PROTO((HASHNODE *));
-static int hashf PROTO((U_CHAR *, int, int));
+static HASHNODE *install PARAMS ((const U_CHAR *, int, enum node_type,
+                                 const char *, int));
+HASHNODE *lookup PARAMS ((const U_CHAR *, int, int));
+static void delete_macro PARAMS ((HASHNODE *));
+static int hashf PARAMS ((const U_CHAR *, int, int));
 
-static void dump_single_macro PROTO((HASHNODE *, FILE *));
-static void dump_all_macros PROTO((void));
-static void dump_defn_1 PROTO((U_CHAR *, int, int, FILE *));
-static void dump_arg_n PROTO((DEFINITION *, int, FILE *));
+static void dump_single_macro PARAMS ((HASHNODE *, FILE *));
+static void dump_all_macros PARAMS ((void));
+static void dump_defn_1 PARAMS ((const U_CHAR *, int, int, FILE *));
+static void dump_arg_n PARAMS ((DEFINITION *, int, FILE *));
 
-static void initialize_char_syntax PROTO((void));
-static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *));
+static void initialize_char_syntax PARAMS ((void));
+static void initialize_builtins PARAMS ((FILE_BUF *, FILE_BUF *));
 
-static void make_definition PROTO((char *));
-static void make_undef PROTO((char *, FILE_BUF *));
+static void make_definition PARAMS ((char *));
+static void make_undef PARAMS ((char *, FILE_BUF *));
 
-static void make_assertion PROTO((char *, char *));
+static void make_assertion PARAMS ((const char *, const char *));
 
-static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, char *, char *, char *));
-static void append_include_chain PROTO((struct file_name_list *, struct file_name_list *));
+static struct file_name_list *new_include_prefix PARAMS ((struct file_name_list *, const char *, const char *, const char *));
+static void append_include_chain PARAMS ((struct file_name_list *, struct file_name_list *));
 
-static int quote_string_for_make PROTO((char *, char *));
-static void deps_output PROTO((char *, int));
+static int quote_string_for_make PARAMS ((char *, const char *));
+static void deps_output PARAMS ((const char *, int));
 
-static void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn));
-void fancy_abort PROTO((void)) __attribute__ ((noreturn));
-static void perror_with_name PROTO((char *));
-static void pfatal_with_name PROTO((char *)) __attribute__ ((noreturn));
-static void pipe_closed PROTO((int)) __attribute__ ((noreturn));
+void fatal PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
+static void perror_with_name PARAMS ((const char *));
+static void pfatal_with_name PARAMS ((const char *)) ATTRIBUTE_NORETURN;
+static void pipe_closed PARAMS ((int)) ATTRIBUTE_NORETURN;
 
-static void memory_full PROTO((void)) __attribute__ ((noreturn));
-GENERIC_PTR xmalloc PROTO((size_t));
-static GENERIC_PTR xrealloc PROTO((GENERIC_PTR, size_t));
-static GENERIC_PTR xcalloc PROTO((size_t, size_t));
-static char *savestring PROTO((char *));
-static void print_help PROTO((void));
+static void memory_full PARAMS ((void)) ATTRIBUTE_NORETURN;
+static void print_help PARAMS ((void));
 \f
 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
    retrying if necessary.  If MAX_READ_LEN is defined, read at most
@@ -1093,7 +1075,7 @@ safe_read (desc, ptr, len)
 static void
 safe_write (desc, ptr, len)
      int desc;
-     char *ptr;
+     const char *ptr;
      int len;
 {
   int wcount, written;
@@ -1118,33 +1100,6 @@ safe_write (desc, ptr, len)
   }
 }
 
-/* Print a string to stderr, with extra handling in case it contains
-   embedded NUL characters.  Any present are written as is.
-
-   Using fwrite for this purpose produces undesireable results on VMS
-   when stderr happens to be a record oriented file, such as a batch log
-   file, rather than a stream oriented one.  */
-
-static void
-eprint_string (string, length)
-     char *string;
-     size_t length;
-{
-  size_t segment_length;
-
-  do {
-    fprintf(stderr, "%s", string);
-    length -= (segment_length = strlen(string));
-    if (length > 0)
-      {
-       fputc('\0', stderr);
-       length -= 1;
-       /* Advance past the portion which has already been printed.  */
-       string += segment_length + 1;
-      }
-  } while (length > 0);
-}
-
 \f
 static void
 print_help ()
@@ -1152,7 +1107,7 @@ print_help ()
   printf ("Usage: %s [switches] input output\n", progname);
   printf ("Switches:\n");
   printf ("  -include <file>           Include the contents of <file> before other files\n");
-  printf ("  -imacros <file>           Accept definition of marcos in <file>\n");
+  printf ("  -imacros <file>           Accept definition of macros in <file>\n");
   printf ("  -iprefix <path>           Specify <path> as a prefix for next two options\n");
   printf ("  -iwithprefix <dir>        Add <dir> to the end of the system include paths\n");
   printf ("  -iwithprefixbefore <dir>  Add <dir> to the end of the main include paths\n");
@@ -1166,12 +1121,16 @@ print_help ()
   printf ("  -traditional              Follow K&R pre-processor behaviour\n");
   printf ("  -trigraphs                Support ANSI C trigraphs\n");
   printf ("  -lang-c                   Assume that the input sources are in C\n");
-  printf ("  -lang-c89                 Assume that the input sources are in C89\n");
+  printf ("  -lang-c89                 Assume that the input is C89; depricated\n");
   printf ("  -lang-c++                 Assume that the input sources are in C++\n");
   printf ("  -lang-objc                Assume that the input sources are in ObjectiveC\n");
   printf ("  -lang-objc++              Assume that the input sources are in ObjectiveC++\n");
   printf ("  -lang-asm                 Assume that the input sources are in assembler\n");
+  printf ("  -lang-fortran            Assume that the input sources are in Fortran\n");
   printf ("  -lang-chill               Assume that the input sources are in Chill\n");
+  printf ("  -std=<std name>           Specify the conformance standard; one of:\n");
+  printf ("                            gnu89, gnu99, c89, c99, iso9899:1990,\n");
+  printf ("                            iso9899:199409, iso9899:1999\n");
   printf ("  -+                        Allow parsing of C++ style features\n");
   printf ("  -w                        Inhibit warning messages\n");
   printf ("  -Wtrigraphs               Warn if trigraphs are encountered\n");
@@ -1179,10 +1138,10 @@ print_help ()
   printf ("  -Wcomment{s}              Warn if one comment starts inside another\n");
   printf ("  -Wno-comment{s}           Do not warn about comments\n");
   printf ("  -Wtraditional             Warn if a macro argument is/would be turned into\n");
-  printf ("                             a string if -tradtional is specified\n");
+  printf ("                             a string if -traditional is specified\n");
   printf ("  -Wno-traditional          Do not warn about stringification\n");
   printf ("  -Wundef                   Warn if an undefined macro is used by #if\n");
-  printf ("  -Wno-undef                Do not warn about testing udefined macros\n");
+  printf ("  -Wno-undef                Do not warn about testing undefined macros\n");
   printf ("  -Wimport                  Warn about the use of the #import directive\n");
   printf ("  -Wno-import               Do not warn about the use of #import\n");
   printf ("  -Werror                   Treat all warnings as errors\n");
@@ -1219,21 +1178,21 @@ main (argc, argv)
      char **argv;
 {
   struct stat st;
-  char *in_fname;
+  const char *in_fname;
   char *cp;
   int f, i;
   FILE_BUF *fp;
-  char **pend_files = (char **) xmalloc (argc * sizeof (char *));
-  char **pend_defs = (char **) xmalloc (argc * sizeof (char *));
-  char **pend_undefs = (char **) xmalloc (argc * sizeof (char *));
-  char **pend_assertions = (char **) xmalloc (argc * sizeof (char *));
-  char **pend_includes = (char **) xmalloc (argc * sizeof (char *));
+
+  char **pend_files;
+  char **pend_defs;
+  char **pend_undefs;
+  char **pend_assertions;
+  char **pend_includes;
 
   /* Record the option used with each element of pend_assertions.
      This is preparation for supporting more than one option for making
      an assertion.  */
-  char **pend_assertion_options = (char **) xmalloc (argc * sizeof (char *));
-  int inhibit_predefs = 0;
+  const char **pend_assertion_options;
   int no_standard_includes = 0;
   int no_standard_cplusplus_includes = 0;
   int missing_newline = 0;
@@ -1247,7 +1206,7 @@ main (argc, argv)
      This is 0 if deps are being written to stdout.  */
   char *deps_file = 0;
   /* Fopen file mode to open deps_file with.  */
-  char *deps_mode = "a";
+  const char *deps_mode = "a";
   /* Stream on which to print the dependency information.  */
   FILE *deps_stream = 0;
   /* Target-name to write with the dependency information.  */
@@ -1270,13 +1229,20 @@ main (argc, argv)
   signal (SIGPIPE, pipe_closed);
 #endif
 
+#ifdef HAVE_LC_MESSAGES
+  setlocale (LC_MESSAGES, "");
+#endif
+  (void) bindtextdomain (PACKAGE, localedir);
+  (void) textdomain (PACKAGE);
+
   progname = base_name (argv[0]);
 
 #ifdef VMS
   {
     /* Remove extension from PROGNAME.  */
     char *p;
-    char *s = progname = savestring (progname);
+    char *s = xstrdup (progname);
+    progname = s;
 
     if ((p = rindex (s, ';')) != 0) *p = '\0'; /* strip version number */
     if ((p = rindex (s, '.')) != 0             /* strip type iff ".exe" */
@@ -1288,6 +1254,16 @@ main (argc, argv)
   }
 #endif
 
+  /* Do not invoke xmalloc before this point, since locale and
+     progname need to be set first, in case a diagnostic is issued.  */
+     
+  pend_files = (char **) xmalloc (argc * sizeof (char *));
+  pend_defs = (char **) xmalloc ((2 * argc) * sizeof (char *));
+  pend_undefs = (char **) xmalloc (argc * sizeof (char *));
+  pend_assertions = (char **) xmalloc (argc * sizeof (char *));
+  pend_includes = (char **) xmalloc (argc * sizeof (char *));
+  pend_assertion_options = (const char **) xmalloc (argc * sizeof (char *));
+
   in_fname = NULL;
   out_fname = NULL;
 
@@ -1302,7 +1278,7 @@ main (argc, argv)
   cplusplus_comments = 1;
 
   bzero ((char *) pend_files, argc * sizeof (char *));
-  bzero ((char *) pend_defs, argc * sizeof (char *));
+  bzero ((char *) pend_defs, (2 * argc) * sizeof (char *));
   bzero ((char *) pend_undefs, argc * sizeof (char *));
   bzero ((char *) pend_assertions, argc * sizeof (char *));
   bzero ((char *) pend_includes, argc * sizeof (char *));
@@ -1331,20 +1307,20 @@ main (argc, argv)
 
       case 'i':
        if (!strcmp (argv[i], "-include")) {
-         int temp = i;
-
          if (i + 1 == argc)
            fatal ("Filename missing after `-include' option");
-         else
-           simplify_filename (pend_includes[temp] = argv[++i]);
+         else {
+           i++;
+           simplify_filename (pend_includes[i] = argv[i]);
+         }
        }
        if (!strcmp (argv[i], "-imacros")) {
-         int temp = i;
-
          if (i + 1 == argc)
            fatal ("Filename missing after `-imacros' option");
-         else
-           simplify_filename (pend_files[temp] = argv[++i]);
+         else {
+           i++;
+           simplify_filename (pend_files[i] = argv[i]);
+         }
        }
        if (!strcmp (argv[i], "-iprefix")) {
          if (i + 1 == argc)
@@ -1378,7 +1354,7 @@ main (argc, argv)
          if (include_prefix != 0)
            prefix = include_prefix;
          else {
-           prefix = savestring (GCC_INCLUDE_DIR);
+           prefix = xstrdup (GCC_INCLUDE_DIR);
            /* Remove the `include' from /usr/local/lib/gcc.../include.  */
            if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
              prefix[strlen (prefix) - 7] = 0;
@@ -1403,7 +1379,7 @@ main (argc, argv)
          if (include_prefix != 0)
            prefix = include_prefix;
          else {
-           prefix = savestring (GCC_INCLUDE_DIR);
+           prefix = xstrdup (GCC_INCLUDE_DIR);
            /* Remove the `include' from /usr/local/lib/gcc.../include.  */
            if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
              prefix[strlen (prefix) - 7] = 0;
@@ -1470,18 +1446,24 @@ main (argc, argv)
 
       case 'l':
        if (! strcmp (argv[i], "-lang-c"))
-         cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 0;
-       if (! strcmp (argv[i], "-lang-c89"))
-         cplusplus = 0, cplusplus_comments = 0, c89 = 1, objc = 0;
-       if (! strcmp (argv[i], "-lang-c++"))
-         cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 0;
-       if (! strcmp (argv[i], "-lang-objc"))
-         cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 1;
-       if (! strcmp (argv[i], "-lang-objc++"))
-         cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 1;
-       if (! strcmp (argv[i], "-lang-asm"))
+         cplusplus = 0, cplusplus_comments = 1, c89 = 0, c99 = 1, objc = 0;
+       else if (! strcmp (argv[i], "-lang-c89"))
+         {
+           cplusplus = 0, cplusplus_comments = 0, c89 = 1, c99 = 0, objc = 0;
+           no_trigraphs = 0;
+           pend_defs[2*i] = "__STRICT_ANSI__";
+         }
+       else if (! strcmp (argv[i], "-lang-c++"))
+         cplusplus = 1, cplusplus_comments = 1, c89 = 0, c99 = 0, objc = 0;
+       else if (! strcmp (argv[i], "-lang-objc"))
+         cplusplus = 0, cplusplus_comments = 1, c89 = 0, c99 = 0, objc = 1;
+       else if (! strcmp (argv[i], "-lang-objc++"))
+         cplusplus = 1, cplusplus_comments = 1, c89 = 0, c99 = 0, objc = 1;
+       else if (! strcmp (argv[i], "-lang-asm"))
          lang_asm = 1;
-       if (! strcmp (argv[i], "-lint"))
+       else if (! strcmp (argv[i], "-lang-fortran"))
+         /* Doesn't actually do anything.  */ ;
+       else if (! strcmp (argv[i], "-lint"))
          for_lint = 1;
        break;
 
@@ -1489,6 +1471,43 @@ main (argc, argv)
        cplusplus = 1, cplusplus_comments = 1;
        break;
 
+      case 's':
+       if (!strcmp (argv[i], "-std=gnu89"))
+         {
+           cplusplus = 0, cplusplus_comments = 0, c89 = 1, c99 = 0, objc = 0;
+         }
+       else if (!strcmp (argv[i], "-std=gnu9x")
+                || !strcmp (argv[i], "-std=gnu99"))
+         {
+           cplusplus = 0, cplusplus_comments = 1, c89 = 0, c99 = 1, objc = 0;
+           pend_defs[2*i+1] = "__STDC_VERSION__=199901L";
+         }
+       else if (!strcmp (argv[i], "-std=iso9899:1990")
+                || !strcmp (argv[i], "-std=c89"))
+         {
+           cplusplus = 0, cplusplus_comments = 0, c89 = 1, c99 = 0, objc = 0;
+           no_trigraphs = 0;
+           pend_defs[2*i] = "__STRICT_ANSI__";
+         }
+       else if (!strcmp (argv[i], "-std=iso9899:199409"))
+         {
+           cplusplus = 0, cplusplus_comments = 0, c89 = 1, c99 = 0, objc = 0;
+           no_trigraphs = 0;
+           pend_defs[2*i] = "__STRICT_ANSI__";
+           pend_defs[2*i+1] = "__STDC_VERSION__=199409L";
+         }
+        else if (!strcmp (argv[i], "-std=iso9899:199x")
+                || !strcmp (argv[i], "-std=iso9899:1999")
+                || !strcmp (argv[i], "-std=c9x")
+                || !strcmp (argv[i], "-std=c99"))
+         {
+           cplusplus = 0, cplusplus_comments = 1, c89 = 0, c99 = 1, objc = 0;
+           no_trigraphs = 0;
+           pend_defs[2*i] = "__STRICT_ANSI__";
+           pend_defs[2*i+1] = "__STDC_VERSION__=199901L";
+         }
+       break;
+
       case 'w':
        inhibit_warnings = 1;
        break;
@@ -1510,6 +1529,10 @@ main (argc, argv)
          warn_stringify = 1;
        else if (!strcmp (argv[i], "-Wno-traditional"))
          warn_stringify = 0;
+       else if (!strcmp (argv[i], "-Wwhite-space"))
+         warn_white_space = 1;
+       else if (!strcmp (argv[i], "-Wno-white-space"))
+         warn_white_space = 0;
        else if (!strcmp (argv[i], "-Wundef"))
          warn_undef = 1;
        else if (!strcmp (argv[i], "-Wno-undef"))
@@ -1526,9 +1549,17 @@ main (argc, argv)
          {
            warn_trigraphs = 1;
            warn_comments = 1;
+           warn_white_space = 1;
          }
        break;
 
+      case 'f':
+       if (!strcmp (argv[i], "-fleading-underscore"))
+         user_label_prefix = "_";
+       else if (!strcmp (argv[i], "-fno-leading-underscore"))
+         user_label_prefix = "";
+       break;
+
       case 'M':
        /* The style of the choices here is a bit mixed.
           The chosen scheme is a hybrid of keeping all options in one string
@@ -1609,7 +1640,7 @@ main (argc, argv)
        break;
 
       case 'v':
-       fprintf (stderr, "GNU CPP version %s", version_string);
+       notice ("GNU CPP version %s", version_string);
 #ifdef TARGET_VERSION
        TARGET_VERSION;
 #endif
@@ -1623,11 +1654,11 @@ main (argc, argv)
 
       case 'D':
        if (argv[i][2] != 0)
-         pend_defs[i] = argv[i] + 2;
+         pend_defs[2*i] = argv[i] + 2;
        else if (i + 1 == argc)
          fatal ("Macro name missing after -D option");
        else
-         i++, pend_defs[i] = argv[i];
+         i++, pend_defs[2*i] = argv[i];
        break;
 
       case 'A':
@@ -1647,9 +1678,8 @@ main (argc, argv)
               on the command line.  That way we can get rid of any
               that were passed automatically in from GCC.  */
            int j;
-           inhibit_predefs = 1;
            for (j = 0; j < i; j++)
-             pend_defs[j] = pend_assertions[j] = 0;
+             pend_defs[2*j] = pend_assertions[j] = 0;
          } else {
            pend_assertions[i] = p;
            pend_assertion_options[i] = "-A";
@@ -1684,15 +1714,15 @@ main (argc, argv)
       case 'I':                        /* Add directory to path for includes.  */
        {
          struct file_name_list *dirtmp;
+         char *dir = argv[i][2] ? argv[i] + 2 : argv[++i];
 
-         if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) {
+         if (! ignore_srcdir && dir && !strcmp (dir, "-")) {
            ignore_srcdir = 1;
            /* Don't use any preceding -I directories for #include <...>.  */
            first_bracket_include = 0;
          }
          else {
-           dirtmp = new_include_prefix (last_include, NULL_PTR, "",
-                                        argv[i][2] ? argv[i] + 2 : argv[++i]);
+           dirtmp = new_include_prefix (last_include, NULL_PTR, "", dir);
            append_include_chain (dirtmp, dirtmp);
          }
        }
@@ -1715,12 +1745,6 @@ main (argc, argv)
          remap = 1;
        break;
 
-      case 'u':
-       /* Sun compiler passes undocumented switch "-undef".
-          Let's assume it means to inhibit the predefined symbols.  */
-       inhibit_predefs = 1;
-       break;
-
       case '\0': /* JF handle '-' as file name meaning stdin or stdout */
        if (in_fname == NULL) {
          in_fname = "";
@@ -1762,144 +1786,10 @@ main (argc, argv)
   fp->nominal_fname_len = strlen (in_fname);
   fp->lineno = 0;
 
-  /* In C++, wchar_t is a distinct basic type, and we can expect
-     __wchar_t to be defined by cc1plus.  */
-  if (cplusplus)
-    wchar_type = "__wchar_t";
-
   /* Install __LINE__, etc.  Must follow initialize_char_syntax
      and option processing.  */
   initialize_builtins (fp, &outbuf);
 
-  /* Do standard #defines and assertions
-     that identify system and machine type.  */
-
-  if (!inhibit_predefs) {
-    char *p = (char *) alloca (strlen (predefs) + 1);
-
-#ifdef VMS
-    struct dsc$descriptor_s lcl_name;
-    struct item_list {
-      unsigned short length;  /* input length */
-      unsigned short code;    /* item code */   
-      unsigned long dptr;     /* data ptr */
-      unsigned long lptr;     /* output length ptr */
-    };
-
-    unsigned long syi_length;
-    char syi_data[16];
-
-    struct item_list items[] = {
-      { 16, SYI$_VERSION, 0, 0 },
-      { 0, 0, 0, 0 }
-    };
-
-    items[0].dptr = (unsigned long)syi_data;
-    items[0].lptr = (unsigned long)(&syi_length);
-
-    if (SYS$GETSYIW (0, 0, 0, items, NULL, NULL, NULL, NULL) == SS$_NORMAL)
-      {
-       unsigned long vms_version_value;
-       char *vers;
-
-       vers = syi_data;
-       vms_version_value = 0;
-
-       if (*vers == 'V')
-         vers++;
-       if (ISDIGIT (*vers))
-         {
-           vms_version_value = (*vers - '0') * 10000000;
-         }
-       vers++;
-       if (*vers == '.')
-         {
-           vers++;
-           if (ISDIGIT (*vers))
-             {
-               vms_version_value += (*vers - '0') * 100000;
-             }
-         }
-
-       if (vms_version_value > 0)
-         {
-           char versbuf[32];
-
-           sprintf (versbuf, "__VMS_VER=%08ld", vms_version_value);
-           if (debug_output)
-             output_line_directive (fp, &outbuf, 0, same_file);
-           make_definition (versbuf);
-         }
-      }
-#endif
-
-    strcpy (p, predefs);
-    while (*p) {
-      char *q;
-      while (*p == ' ' || *p == '\t')
-       p++;
-      /* Handle -D options.  */ 
-      if (p[0] == '-' && p[1] == 'D') {
-       q = &p[2];
-       while (*p && *p != ' ' && *p != '\t')
-         p++;
-       if (*p != 0)
-         *p++= 0;
-       if (debug_output)
-         output_line_directive (fp, &outbuf, 0, same_file);
-       make_definition (q);
-       while (*p == ' ' || *p == '\t')
-         p++;
-      } else if (p[0] == '-' && p[1] == 'A') {
-       /* Handle -A options (assertions).  */ 
-       char *assertion;
-       char *past_name;
-       char *value;
-       char *past_value;
-       char *termination;
-       int save_char;
-
-       assertion = &p[2];
-       past_name = assertion;
-       /* Locate end of name.  */
-       while (*past_name && *past_name != ' '
-              && *past_name != '\t' && *past_name != '(')
-         past_name++;
-       /* Locate `(' at start of value.  */
-       value = past_name;
-       while (*value && (*value == ' ' || *value == '\t'))
-         value++;
-       if (*value++ != '(')
-         abort ();
-       while (*value && (*value == ' ' || *value == '\t'))
-         value++;
-       past_value = value;
-       /* Locate end of value.  */
-       while (*past_value && *past_value != ' '
-              && *past_value != '\t' && *past_value != ')')
-         past_value++;
-       termination = past_value;
-       while (*termination && (*termination == ' ' || *termination == '\t'))
-         termination++;
-       if (*termination++ != ')')
-         abort ();
-       if (*termination && *termination != ' ' && *termination != '\t')
-         abort ();
-       /* Temporarily null-terminate the value.  */
-       save_char = *termination;
-       *termination = '\0';
-       /* Install the assertion.  */
-       make_assertion ("-A", assertion);
-       *termination = (char) save_char;
-       p = termination;
-       while (*p == ' ' || *p == '\t')
-         p++;
-      } else {
-       abort ();
-      }
-    }
-  }
-
   /* Now handle the command line options.  */
 
   /* Do -U's, -D's and -A's in the order they were seen.  */
@@ -1909,10 +1799,15 @@ main (argc, argv)
         output_line_directive (fp, &outbuf, 0, same_file);
       make_undef (pend_undefs[i], &outbuf);
     }
-    if (pend_defs[i]) {
+    if (pend_defs[2*i]) {
+      if (debug_output)
+        output_line_directive (fp, &outbuf, 0, same_file);
+      make_definition (pend_defs[2*i]);
+    }
+    if (pend_defs[2*i+1]) {
       if (debug_output)
         output_line_directive (fp, &outbuf, 0, same_file);
-      make_definition (pend_defs[i]);
+      make_definition (pend_defs[2*i+1]);
     }
     if (pend_assertions[i])
       make_assertion (pend_assertion_options[i], pend_assertions[i]);
@@ -1958,7 +1853,7 @@ main (argc, argv)
        if (c == PATH_SEPARATOR || !c) {
          endp[-1] = 0;
          include_defaults[num_dirs].fname
-           = startp == endp ? "." : savestring (startp);
+           = startp == endp ? "." : xstrdup (startp);
          endp[-1] = c;
          include_defaults[num_dirs].component = 0;
          include_defaults[num_dirs].cplusplus = cplusplus;
@@ -1970,8 +1865,8 @@ main (argc, argv)
        }
       }
       /* Put the usual defaults back in at the end.  */
-      bcopy ((char *) include_defaults_array,
-            (char *) &include_defaults[num_dirs],
+      bcopy ((const PTR) include_defaults_array,
+            (PTR) &include_defaults[num_dirs],
             sizeof (include_defaults_array));
     }
   }
@@ -1984,7 +1879,7 @@ main (argc, argv)
   if (!no_standard_includes) {
     struct default_include *p = include_defaults;
     char *specd_prefix = include_prefix;
-    char *default_prefix = savestring (GCC_INCLUDE_DIR);
+    char *default_prefix = xstrdup (GCC_INCLUDE_DIR);
     int default_len = 0;
     /* Remove the `include' from /usr/local/lib/gcc.../include.  */
     if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
@@ -2008,6 +1903,7 @@ main (argc, argv)
              append_include_chain (new, new);
              if (first_system_include == 0)
                first_system_include = new;
+             p->included = 1;
            }
          }
        }
@@ -2023,6 +1919,7 @@ main (argc, argv)
          append_include_chain (new, new);
          if (first_system_include == 0)
            first_system_include = new;
+         p->included = 1;
        }
       }
     }
@@ -2036,10 +1933,10 @@ main (argc, argv)
   /* With -v, print the list of dirs to search.  */
   if (verbose) {
     struct file_name_list *p;
-    fprintf (stderr, "#include \"...\" search starts here:\n");
+    notice ("#include \"...\" search starts here:\n");
     for (p = include; p; p = p->next) {
       if (p == first_bracket_include)
-       fprintf (stderr, "#include <...> search starts here:\n");
+       notice ("#include <...> search starts here:\n");
       if (!p->fname[0])
        fprintf (stderr, " .\n");
       else if (!strcmp (p->fname, "/") || !strcmp (p->fname, "//"))
@@ -2048,7 +1945,15 @@ main (argc, argv)
        /* Omit trailing '/'.  */
        fprintf (stderr, " %.*s\n", (int) strlen (p->fname) - 1, p->fname);
     }
-    fprintf (stderr, "End of search list.\n");
+    notice ("End of search list.\n");
+    {
+      struct default_include * d;
+      notice ("The following default directories have been omitted from the search path:\n");
+      for (d = include_defaults; d->fname; d++)
+       if (! d->included)
+         fprintf (stderr, " %s\n", d->fname);
+      notice ("End of omitted list.\n");
+    }
   }
 
   /* -MG doesn't select the form of output and must be specified with one of
@@ -2076,17 +1981,14 @@ main (argc, argv)
     else
       print_deps = 1;
 
-    s = spec;
     /* Find the space before the DEPS_TARGET, if there is one.  */
-    /* This should use index.  (mrs) */
-    while (*s != 0 && *s != ' ') s++;
-    if (*s != 0) {
+    s = index (spec, ' ');
+    if (s) {
       deps_target = s + 1;
       output_file = xmalloc (s - spec + 1);
       bcopy (spec, output_file, s - spec);
       output_file[s - spec] = 0;
-    }
-    else {
+    } else {
       deps_target = 0;
       output_file = spec;
     }
@@ -2147,8 +2049,9 @@ main (argc, argv)
       strcpy (q, OBJECT_SUFFIX);
 
       deps_output (p, ':');
-      deps_output (in_fname, ' ');
     }
+
+    deps_output (in_fname, ' ');
   }
 
   /* Scan the -imacros files before the main input.
@@ -2236,6 +2139,9 @@ main (argc, argv)
   if (!no_trigraphs)
     trigraph_pcp (fp);
 
+  if (warn_white_space)
+    check_white_space (fp);
+
   /* Now that we know the input file is valid, open the output.  */
 
   if (!out_fname || !strcmp (out_fname, ""))
@@ -2349,17 +2255,17 @@ path_include (path)
    If we knew we could use memchr, we could just invoke memchr (S, C, N),
    but unfortunately memchr isn't autoconfigured yet.  */
 
-static U_CHAR *
+static const U_CHAR *
 index0 (s, c, n)
-     U_CHAR *s;
+     const U_CHAR *s;
      int c;
      size_t n;
 {
-  char *p = (char *) s;
+  const char *p = (const char *) s;
   for (;;) {
-    char *q = index (p, c);
+    const char *q = index (p, c);
     if (q)
-      return (U_CHAR *) q;
+      return (const U_CHAR *) q;
     else {
       size_t l = strlen (p);
       if (l == n)
@@ -2384,10 +2290,11 @@ static void
 trigraph_pcp (buf)
      FILE_BUF *buf;
 {
-  register U_CHAR c, *fptr, *bptr, *sptr, *lptr;
+  register U_CHAR c, *bptr;
+  register const U_CHAR *fptr, *sptr, *lptr;
   int len;
 
-  fptr = bptr = sptr = buf->buf;
+  fptr = sptr = bptr = buf->buf;
   lptr = fptr + buf->length;
   while ((sptr = index0 (sptr, '?', (size_t) (lptr - sptr))) != NULL) {
     if (*++sptr != '?')
@@ -2431,7 +2338,7 @@ trigraph_pcp (buf)
     /* BSD doc says bcopy () works right for overlapping strings.  In ANSI
        C, this will be memmove ().  */
     if (bptr != fptr && len > 0)
-      bcopy ((char *) fptr, (char *) bptr, len);
+      bcopy ((const PTR) fptr, (PTR) bptr, len);
 
     bptr += len;
     *bptr++ = c;
@@ -2439,20 +2346,50 @@ trigraph_pcp (buf)
   }
   len = buf->length - (fptr - buf->buf);
   if (bptr != fptr && len > 0)
-    bcopy ((char *) fptr, (char *) bptr, len);
+    bcopy ((const PTR) fptr, (PTR) bptr, len);
   buf->length -= fptr - bptr;
   buf->buf[buf->length] = '\0';
   if (warn_trigraphs && fptr != bptr)
     warning_with_line (0, "%lu trigraph(s) encountered",
                       (unsigned long) (fptr - bptr) / 2);
 }
+
+/* Warn about white space between backslash and end of line.  */
+
+static void
+check_white_space (buf)
+     FILE_BUF *buf;
+{
+  register const U_CHAR *sptr = buf->buf;
+  register const U_CHAR *lptr = sptr + buf->length;
+  register const U_CHAR *nptr;
+  int line = 0;
+
+  nptr = sptr = buf->buf;
+  lptr = sptr + buf->length;
+  for (nptr = sptr;
+       (nptr = index0 (nptr, '\n', (size_t) (lptr - nptr))) != NULL;
+       nptr ++) {
+    register const U_CHAR *p = nptr;
+    line++;
+    for (p = nptr; sptr < p; p--) {
+      if (! is_hor_space[p[-1]]) {
+       if (p[-1] == '\\' && p != nptr)
+         warning_with_line (line, 
+                            "`\\' followed by white space at end of line");
+       break;
+      }
+    }
+  }
+}
 \f
 /* Move all backslash-newline pairs out of embarrassing places.
    Exchange all such pairs following BP
    with any potentially-embarrassing characters that follow them.
    Potentially-embarrassing characters are / and *
    (because a backslash-newline inside a comment delimiter
-   would cause it not to be recognized).  */
+   would cause it not to be recognized).
+   We assume that *BP == '\\'.  */
 
 static void
 newline_fix (bp)
@@ -2461,21 +2398,24 @@ newline_fix (bp)
   register U_CHAR *p = bp;
 
   /* First count the backslash-newline pairs here.  */
-
-  while (p[0] == '\\' && p[1] == '\n')
+  do {
+    if (p[1] != '\n')
+      break;
     p += 2;
+  } while (*p == '\\');
 
   /* What follows the backslash-newlines is not embarrassing.  */
 
   if (*p != '/' && *p != '*')
+    /* What follows the backslash-newlines is not embarrassing.  */
     return;
 
   /* Copy all potentially embarrassing characters
      that follow the backslash-newline pairs
      down to where the pairs originally started.  */
-
-  while (*p == '*' || *p == '/')
+  do
     *bp++ = *p++;
+  while (*p == '*' || *p == '/');
 
   /* Now write the same number of pairs after the embarrassing chars.  */
   while (bp < p) {
@@ -2494,20 +2434,24 @@ name_newline_fix (bp)
   register U_CHAR *p = bp;
 
   /* First count the backslash-newline pairs here.  */
-  while (p[0] == '\\' && p[1] == '\n')
+  do {
+    if (p[1] != '\n')
+      break;
     p += 2;
+  } while (*p == '\\');
 
   /* What follows the backslash-newlines is not embarrassing.  */
 
   if (!is_idchar[*p])
+    /* What follows the backslash-newlines is not embarrassing.  */
     return;
 
   /* Copy all potentially embarrassing characters
      that follow the backslash-newline pairs
      down to where the pairs originally started.  */
-
-  while (is_idchar[*p])
+  do
     *bp++ = *p++;
+  while (is_idchar[*p]);
 
   /* Now write the same number of pairs after the embarrassing chars.  */
   while (bp < p) {
@@ -2526,15 +2470,15 @@ name_newline_fix (bp)
    arglen long.  Note that we don't parse that arg since it will just
    be printed out again.  */
 
-static char *
+static const char *
 get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
-     register U_CHAR *ibp;
-     register U_CHAR *limit;
-     U_CHAR **argstart;                /* point to command arg */
+     register const U_CHAR *ibp;
+     register const U_CHAR *limit;
+     const U_CHAR **argstart;  /* point to command arg */
      int *arglen, *cmdlen;     /* how long they are */
 {
-  HOST_WIDE_INT linsize;
-  register U_CHAR *numptr;     /* temp for arg parsing */
+  HOST_WIDEST_INT linsize;
+  register const U_CHAR *numptr;       /* temp for arg parsing */
 
   *arglen = 0;
 
@@ -2585,7 +2529,7 @@ get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
  * If OUTPUT_MARKS is nonzero, keep Newline markers found in the input
  * and insert them when appropriate.  This is set while scanning macro
  * arguments before substitution.  It is zero when scanning for final output.
- *   There are three types of Newline markers:
+ *   There are two types of Newline markers:
  *   * Newline -  follows a macro name that was not expanded
  *     because it appeared inside an expansion of the same macro.
  *     This marker prevents future expansion of that identifier.
@@ -2736,7 +2680,7 @@ do { ip = &instack[indepth];              \
        if (*ibp == '(') {
          ip->bufp = ibp;
          skip_paren_group (ip);
-         bcopy ((char *) ibp, (char *) obp, ip->bufp - ibp);
+         bcopy ((const PTR) ibp, (PTR) obp, ip->bufp - ibp);
          obp += ip->bufp - ibp;
          ibp = ip->bufp;
        }
@@ -2909,6 +2853,8 @@ do { ip = &instack[indepth];              \
        *obp++ = *ibp;
        switch (*ibp++) {
        case '\n':
+         if (warn_white_space && ip->fname && is_hor_space[ibp[-2]])
+           warning ("white space at end of line in string");
          ++ip->lineno;
          ++op->lineno;
          /* Traditionally, end of line ends a string constant with no error.
@@ -2936,9 +2882,10 @@ do { ip = &instack[indepth];             \
               keep the line counts correct.  But if we are reading
               from a macro, keep the backslash newline, since backslash
               newlines have already been processed.  */
-           if (ip->macro)
+           if (ip->macro) {
              *obp++ = '\n';
-           else
+             ++op->lineno;
+           } else
              --obp;
            ++ibp;
            ++ip->lineno;
@@ -2947,8 +2894,10 @@ do { ip = &instack[indepth];             \
               is *not* prevented from combining with a newline.  */
            if (!ip->macro) {
              while (*ibp == '\\' && ibp[1] == '\n') {
-               ibp += 2;
+               *obp++ = *ibp++;
+               *obp++ = *ibp++;
                ++ip->lineno;
+               ++op->lineno;
              }
            }
            *obp++ = *ibp++;
@@ -2986,7 +2935,7 @@ do { ip = &instack[indepth];              \
     case '/':
       if (ip->macro != 0)
        goto randomchar;
-      if (*ibp == '\\' && ibp[1] == '\n')
+      if (*ibp == '\\')
        newline_fix (ibp);
       if (*ibp != '*'
          && !(cplusplus_comments && *ibp == '/'))
@@ -3009,7 +2958,7 @@ do { ip = &instack[indepth];              \
            if (*ibp == '\n')
              {
                if (put_out_comments) {
-                 bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
+                 bcopy ((const PTR) before_bp, (PTR) obp, ibp - before_bp);
                  obp += ibp - before_bp;
                }
                break;
@@ -3052,9 +3001,10 @@ do { ip = &instack[indepth];             \
 
       /* If this cpp is for lint, we peek inside the comments: */
       if (for_lint) {
-       U_CHAR *argbp;
+       const U_CHAR *argbp;
        int cmdlen, arglen;
-       char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
+       const char *lintcmd =
+         get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
 
        if (lintcmd != NULL) {
          op->bufp = obp;
@@ -3104,7 +3054,7 @@ do { ip = &instack[indepth];              \
          case '*':
            if (ibp[-2] == '/' && warn_comments)
              warning ("`/*' within comment");
-           if (*ibp == '\\' && ibp[1] == '\n')
+           if (*ibp == '\\')
              newline_fix (ibp);
            if (*ibp == '/')
              goto comment_end;
@@ -3143,7 +3093,7 @@ do { ip = &instack[indepth];              \
 
        ibp++;
        if (put_out_comments) {
-         bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
+         bcopy ((const PTR) before_bp, (PTR) obp, ibp - before_bp);
          obp += ibp - before_bp;
        }
       }
@@ -3416,7 +3366,9 @@ randomchar:
 #endif
                
                if (output_marks) {
+                 op->bufp = obp;
                  check_expand (op, limit - ibp + 2);
+                 obp = op->bufp;
                  *obp++ = '\n';
                  *obp++ = '-';
                }
@@ -3475,7 +3427,7 @@ randomchar:
                      break;
                    else if (*ibp == '/') {
                      /* If a comment, copy it unchanged or discard it.  */
-                     if (ibp[1] == '\\' && ibp[2] == '\n')
+                     if (ibp[1] == '\\')
                        newline_fix (ibp + 1);
                      if (ibp[1] == '*') {
                        if (put_out_comments) {
@@ -3488,7 +3440,7 @@ randomchar:
                          /* We need not worry about newline-marks,
                             since they are never found in comments.  */
                          if (ibp[0] == '*') {
-                           if (ibp[1] == '\\' && ibp[2] == '\n')
+                           if (ibp[1] == '\\')
                              newline_fix (ibp + 1);
                            if (ibp[1] == '/') {
                              ibp += 2;
@@ -3638,7 +3590,7 @@ hashcollision:
  ending:
   if (if_stack != ip->if_stack)
     {
-      char *str;
+      const char *str;
 
       switch (if_stack->type)
        {
@@ -3678,7 +3630,8 @@ hashcollision:
  */
 static FILE_BUF
 expand_to_temp_buffer (buf, limit, output_marks, assertions)
-     U_CHAR *buf, *limit;
+     const U_CHAR *buf;
+     const U_CHAR *limit;
      int output_marks, assertions;
 {
   register FILE_BUF *ip;
@@ -3697,7 +3650,7 @@ expand_to_temp_buffer (buf, limit, output_marks, assertions)
 
   buf1 = (U_CHAR *) alloca (length + 1);
   {
-    register U_CHAR *p1 = buf;
+    register const U_CHAR *p1 = buf;
     register U_CHAR *p2 = buf1;
 
     while (p1 != limit)
@@ -3745,9 +3698,6 @@ expand_to_temp_buffer (buf, limit, output_marks, assertions)
   if (indepth != odepth)
     abort ();
 
-  /* Record the output.  */
-  obuf.length = obuf.bufp - obuf.buf;
-
   assertions_flag = save_assertions_flag;
   return obuf;
 }
@@ -3786,14 +3736,16 @@ handle_directive (ip, op)
   /* Record where the directive started.  do_xifdef needs this.  */
   directive_start = bp - 1;
 
+  ignore_escape_flag = 1;
+
   /* Skip whitespace and \-newline.  */
   while (1) {
     if (is_hor_space[*bp]) {
       if (*bp != ' ' && *bp != '\t' && pedantic)
-       pedwarn ("%s in preprocessing directive", char_name[*bp]);
+       pedwarn_strange_white_space (*bp);
       bp++;
     } else if (*bp == '/') {
-      if (bp[1] == '\\' && bp[2] == '\n')
+      if (bp[1] == '\\')
        newline_fix (bp + 1);
       if (! (bp[1] == '*' || (cplusplus_comments && bp[1] == '/')))
        break;
@@ -3814,7 +3766,7 @@ handle_directive (ip, op)
     if (is_idchar[*cp])
       cp++;
     else {
-      if (*cp == '\\' && cp[1] == '\n')
+      if (*cp == '\\')
        name_newline_fix (cp);
       if (is_idchar[*cp])
        cp++;
@@ -3848,6 +3800,7 @@ handle_directive (ip, op)
        pedwarn ("`#' followed by integer");
       after_ident = ident;
       kt = line_directive_table;
+      ignore_escape_flag = 0;
       goto old_linenum;
     }
 
@@ -3891,7 +3844,7 @@ handle_directive (ip, op)
       keep_comments = traditional && kt->type == T_DEFINE;
       /* #import is defined only in Objective C, or when on the NeXT.  */
       if (kt->type == T_IMPORT
-         && !(objc || lookup ((U_CHAR *) "__NeXT__", -1, -1)))
+         && !(objc || lookup ((const U_CHAR *) "__NeXT__", -1, -1)))
        break;
 
       /* Find the end of this directive (first newline not backslashed
@@ -3904,14 +3857,12 @@ handle_directive (ip, op)
        register U_CHAR c = *bp++;
        switch (c) {
        case '\\':
-         if (bp < limit) {
-           if (*bp == '\n') {
-             ip->lineno++;
-             copy_directive = 1;
-             bp++;
-           } else if (traditional)
-             bp++;
-         }
+         if (*bp == '\n') {
+           ip->lineno++;
+           copy_directive = 1;
+           bp++;
+         } else if (traditional && bp < limit)
+           bp++;
          break;
 
        case '"':
@@ -3963,7 +3914,7 @@ handle_directive (ip, op)
          break;
 
        case '/':
-         if (*bp == '\\' && bp[1] == '\n')
+         if (*bp == '\\')
            newline_fix (bp);
          if (*bp == '*'
              || (cplusplus_comments && *bp == '/')) {
@@ -3992,7 +3943,7 @@ handle_directive (ip, op)
        case '\r':
        case '\v':
          if (pedantic)
-           pedwarn ("%s in preprocessing directive", char_name[c]);
+           pedwarn_strange_white_space (c);
          break;
 
        case '\n':
@@ -4012,7 +3963,8 @@ handle_directive (ip, op)
       /* If a directive should be copied through, and -C was given,
         pass it through before removing comments.  */
       if (!no_output && put_out_comments
-         && (kt->type == T_DEFINE ? dump_macros == dump_definitions
+         && ((kt->type == T_DEFINE || kt->type == T_UNDEF)
+             ? dump_macros == dump_definitions
              : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
              : kt->type == T_PRAGMA)) {
         int len;
@@ -4045,12 +3997,13 @@ handle_directive (ip, op)
        register U_CHAR *xp = buf;
        /* Need to copy entire directive into temp buffer before dispatching */
 
-       cp = (U_CHAR *) alloca (bp - buf + 5); /* room for directive plus
-                                                 some slop */
+       /* room for directive plus some slop */
+       cp = (U_CHAR *) alloca (2 * (bp - buf) + 5);
        buf = cp;
 
        /* Copy to the new buffer, deleting comments
-          and backslash-newlines (and whitespace surrounding the latter).  */
+          and backslash-newlines (and whitespace surrounding the latter
+          if outside of char and string constants).  */
 
        while (xp < bp) {
          register U_CHAR c = *xp++;
@@ -4094,11 +4047,33 @@ handle_directive (ip, op)
          case '\'':
          case '\"':
            {
-             register U_CHAR *bp1
+             int backslash_newlines_p = 0;
+
+             register const U_CHAR *bp1
                = skip_quoted_string (xp - 1, bp, ip->lineno,
-                                     NULL_PTR, NULL_PTR, NULL_PTR);
-             while (xp != bp1)
-               *cp++ = *xp++;
+                                     NULL_PTR, &backslash_newlines_p, 
+                                     NULL_PTR);
+             if (backslash_newlines_p)
+               while (xp != bp1)
+                 {
+                   /* With something like:
+
+                        #define X "a\
+                        b"
+
+                      we should still remove the backslash-newline
+                      pair as part of phase two.  */
+                   if (xp[0] == '\\' && xp[1] == '\n')
+                     xp += 2;
+                   else
+                     *cp++ = *xp++;
+                 }
+             else
+               /* This is the same as the loop above, but taking
+                  advantage of the fact that we know there are no
+                  backslash-newline pairs.  */
+               while (xp != bp1)
+                 *cp++ = *xp++;
            }
            break;
 
@@ -4135,7 +4110,8 @@ handle_directive (ip, op)
         directives through.  */
 
       if (!no_output && already_output == 0
-         && (kt->type == T_DEFINE ? (int) dump_names <= (int) dump_macros
+         && ((kt->type == T_DEFINE || kt->type == T_UNDEF)
+             ? (int) dump_names <= (int) dump_macros
              : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
              : kt->type == T_PRAGMA)) {
         int len;
@@ -4164,7 +4140,7 @@ handle_directive (ip, op)
          bcopy (buf, (char *) op->bufp, len);
        }
        op->bufp += len;
-      }                                /* Don't we need a newline or #line? */
+      }
 
       /* Call the appropriate directive handler.  buf now points to
         either the appropriate place in the input buffer, or to
@@ -4186,17 +4162,25 @@ handle_directive (ip, op)
 static struct tm *
 timestamp ()
 {
-  static struct tm *timebuf;
-  if (!timebuf) {
+  static struct tm tmbuf;
+  if (! tmbuf.tm_mday) {
     time_t t = time ((time_t *) 0);
-    timebuf = localtime (&t);
+    struct tm *tm = localtime (&t);
+    if (tm)
+      tmbuf = *tm;
+    else {
+      /* Use 0000-01-01 00:00:00 if local time is not available.  */
+      tmbuf.tm_year = -1900;
+      tmbuf.tm_mday = 1;
+    }
   }
-  return timebuf;
+  return &tmbuf;
 }
 
-static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-                           };
+static const  char * const monthnames[] = {
+  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
 
 /*
  * expand things like __FILE__.  Place the expansion into the output
@@ -4208,7 +4192,7 @@ special_symbol (hp, op)
      HASHNODE *hp;
      FILE_BUF *op;
 {
-  char *buf;
+  const char *buf;
   int i, len;
   int true_indepth;
   FILE_BUF *ip = NULL;
@@ -4236,13 +4220,14 @@ special_symbol (hp, op)
   case T_BASE_FILE:
     {
       FILE_BUF *p = hp->type == T_FILE ? ip : &instack[0];
-      char *string = p->nominal_fname;
+      const char *string = p->nominal_fname;
 
       if (string)
        {
          size_t string_len = p->nominal_fname_len;
-         buf = (char *) alloca (3 + 4 * string_len);
-         quote_string (buf, string, string_len);
+         char *newbuf = (char *) alloca (3 + 4 * string_len);
+         quote_string (newbuf, string, string_len);
+         buf = newbuf;
        }
       else
        buf = "\"\"";
@@ -4251,18 +4236,24 @@ special_symbol (hp, op)
     }
 
   case T_INCLUDE_LEVEL:
-    true_indepth = 0;
-    for (i = indepth; i >= 0; i--)
-      if (instack[i].fname != NULL)
-        true_indepth++;
-
-    buf = (char *) alloca (8); /* Eight bytes ought to be more than enough */
-    sprintf (buf, "%d", true_indepth - 1);
+    {
+      /* Eight bytes ought to be more than enough */
+      char *newbuf =  (char *) alloca (8);
+      true_indepth = 0;
+      for (i = indepth; i >= 0; i--)
+       if (instack[i].fname != NULL)
+         true_indepth++;
+      sprintf (newbuf, "%d", true_indepth - 1);
+      buf = newbuf;
+    }
     break;
 
   case T_VERSION:
-    buf = (char *) alloca (3 + strlen (version_string));
-    sprintf (buf, "\"%s\"", version_string);
+    {
+      char *newbuf = (char *) alloca (3 + strlen (version_string));
+      sprintf (newbuf, "\"%s\"", version_string);
+      buf = newbuf;
+    }
     break;
 
 #ifndef NO_BUILTIN_SIZE_TYPE
@@ -4277,12 +4268,14 @@ special_symbol (hp, op)
     break;
 #endif
 
+#ifndef NO_BUILTIN_WCHAR_TYPE
   case T_WCHAR_TYPE:
     buf = wchar_type;
     break;
+#endif
 
   case T_USER_LABEL_PREFIX_TYPE:
-    buf = USER_LABEL_PREFIX;
+    buf = user_label_prefix;
     break;
 
   case T_REGISTER_PREFIX_TYPE:
@@ -4298,7 +4291,7 @@ special_symbol (hp, op)
 #ifdef STDC_0_IN_SYSTEM_HEADERS
     if (ip->system_header_p
        && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
-       && !lookup ((U_CHAR *) "__STRICT_ANSI__", -1, -1))
+       && !lookup ((const U_CHAR *) "__STRICT_ANSI__", -1, -1))
       buf = "0";
 #endif
     if (pcp_inside_if && pcp_outfile)
@@ -4307,20 +4300,26 @@ special_symbol (hp, op)
     break;
 
   case T_SPECLINE:
-    buf = (char *) alloca (10);
-    sprintf (buf, "%d", ip->lineno);
+    {
+      char *newbuf = (char *) alloca (10);
+      sprintf (newbuf, "%d", ip->lineno);
+      buf = newbuf;
+    }
     break;
 
   case T_DATE:
   case T_TIME:
-    buf = (char *) alloca (20);
-    timebuf = timestamp ();
-    if (hp->type == T_DATE)
-      sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
-             timebuf->tm_mday, timebuf->tm_year + 1900);
-    else
-      sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
-             timebuf->tm_sec);
+    {
+      char *newbuf = (char *) alloca (20);
+      timebuf = timestamp ();
+      if (hp->type == T_DATE)
+       sprintf (newbuf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
+                timebuf->tm_mday, timebuf->tm_year + 1900);
+      else
+       sprintf (newbuf, "\"%02d:%02d:%02d\"", timebuf->tm_hour,
+                timebuf->tm_min, timebuf->tm_sec);
+      buf = newbuf;
+    }
     break;
 
   case T_SPEC_DEFINED:
@@ -4343,7 +4342,12 @@ special_symbol (hp, op)
              || (hp->type == T_MACRO && hp->value.defn->predefined)))
        /* Output a precondition for this macro use.  */
        fprintf (pcp_outfile, "#define %s\n", hp->name);
-      buf = " 1 ";
+      if (hp->type == T_POISON) {
+       error("attempt to use poisoned `%s'.", hp->name);
+       buf = " 0 ";
+      } else {
+       buf = " 1 ";
+      }
     }
     else
       if (pcp_outfile && pcp_inside_if)        {
@@ -4364,6 +4368,11 @@ special_symbol (hp, op)
     }
     break;
 
+  case T_POISON:
+    error("attempt to use poisoned `%s'.", hp->name);
+    buf = " 0 ";       /* Consider poisoned symbol to not be defined */
+    break;
+
 oops:
 
     error ("`defined' without an identifier");
@@ -4393,7 +4402,8 @@ do_include (buf, limit, op, keyword)
      FILE_BUF *op;
      struct directive *keyword;
 {
-  U_CHAR *importing = keyword->type == T_IMPORT ? (U_CHAR *) "" : (U_CHAR *) 0;
+  const U_CHAR *importing =
+    keyword->type == T_IMPORT ? (const U_CHAR *) "" : (const U_CHAR *) 0;
   int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
   static int import_warning = 0;
   char *fname;         /* Dynamically allocated fname buffer */
@@ -4418,7 +4428,7 @@ do_include (buf, limit, op, keyword)
 #endif
   int pcf = -1;
   char *pcfbuf;
-  char *pcfbuflimit;
+  const char *pcfbuflimit;
   int pcfnum;
 
   if (pedantic && !instack[indepth].system_header_p)
@@ -4433,16 +4443,18 @@ do_include (buf, limit, op, keyword)
       && !instack[indepth].system_header_p && !import_warning) {
     import_warning = 1;
     warning ("using `#import' is not recommended");
-    fprintf (stderr, "The fact that a certain header file need not be processed more than once\n");
-    fprintf (stderr, "should be indicated in the header file, not where it is used.\n");
-    fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n");
-    fprintf (stderr, "  #ifndef _FOO_H_INCLUDED\n");
-    fprintf (stderr, "  #define _FOO_H_INCLUDED\n");
-    fprintf (stderr, "  ... <real contents of file> ...\n");
-    fprintf (stderr, "  #endif /* Not _FOO_H_INCLUDED */\n\n");
-    fprintf (stderr, "Then users can use `#include' any number of times.\n");
-    fprintf (stderr, "GNU C automatically avoids processing the file more than once\n");
-    fprintf (stderr, "when it is equipped with such a conditional.\n");
+    notice ("The fact that a certain header file need not be processed more than once\n\
+should be indicated in the header file, not where it is used.\n\
+The best way to do this is with a conditional of this form:\n\
+\n\
+  #ifndef _FOO_H_INCLUDED\n\
+  #define _FOO_H_INCLUDED\n\
+  ... <real contents of file> ...\n\
+  #endif /* Not _FOO_H_INCLUDED */\n\
+\n\
+Then users can use `#include' any number of times.\n\
+GNU C automatically avoids processing the file more than once\n\
+when it is equipped with such a conditional.\n");
   }
 
 get_filename:
@@ -4490,15 +4502,15 @@ get_filename:
       for (fp = &instack[indepth]; fp >= instack; fp--)
        {
          int n;
-         char *nam;
 
-         if ((nam = fp->nominal_fname) != NULL) {
+         if ((fp->nominal_fname) != NULL) {
+           char *nam;
            /* Found a named file.  Figure out dir of the file,
               and put it in front of the search list.  */
            dsp = ((struct file_name_list *)
                   alloca (sizeof (struct file_name_list)
                           + fp->nominal_fname_len));
-           strcpy (dsp->fname, nam);
+           strcpy (dsp->fname, fp->nominal_fname);
            simplify_filename (dsp->fname);
            nam = base_name (dsp->fname);
            *nam = 0;
@@ -4568,9 +4580,10 @@ get_filename:
       /* Expand buffer and then remove any newline markers.
         We can't just tell expand_to_temp_buffer to omit the markers,
         since it would put extra spaces in include file names.  */
-      FILE_BUF trybuf;
       U_CHAR *src;
       int errors_before_expansion = errors;
+      FILE_BUF trybuf;
+
       trybuf = expand_to_temp_buffer (buf, limit, 1, 0);
       if (errors != errors_before_expansion) {
        free (trybuf.buf);
@@ -4589,7 +4602,7 @@ get_filename:
          case '\'':
          case '\"':
            {
-             U_CHAR *src1 = skip_quoted_string (src - 1, trybuf.bufp, 0,
+             const U_CHAR *src1 = skip_quoted_string (src - 1, trybuf.bufp, 0,
                                                 NULL_PTR, NULL_PTR, NULL_PTR);
              while (src != src1)
                *limit++ = *src++;
@@ -4812,8 +4825,7 @@ get_filename:
     
     /* Actually process the file */
     if (pcfbuf) {
-      pcfname = xmalloc (strlen (pcftry) + 1);
-      strcpy (pcfname, pcftry);
+      pcfname = xstrdup (pcftry);
       pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) fname, op);
     }
     else
@@ -4838,7 +4850,7 @@ get_filename:
 
 static int
 is_system_include (filename)
-    register char *filename;
+    register const char *filename;
 {
   struct file_name_list *searchptr;
 
@@ -4853,10 +4865,10 @@ is_system_include (filename)
 
 static char *
 base_name (fname)
-     char *fname;
+     const char *fname;
 {
-  char *s = fname;
-  char *p;
+  const char *s = fname;
+  const char *p;
 #if defined (__MSDOS__) || defined (_WIN32)
   if (ISALPHA (s[0]) && s[1] == ':') s += 2;
 #endif
@@ -4865,25 +4877,26 @@ base_name (fname)
   if ((p = rindex (s, ']'))) s = p + 1;        /* Skip directory.  */
   if ((p = rindex (s, '>'))) s = p + 1;        /* Skip alternate (int'n'l) dir.  */
   if (s != fname)
-    return s;
+    return (char *) s;
 #endif
   if ((p = rindex (s, '/'))) s = p + 1;
 #ifdef DIR_SEPARATOR
   if ((p = rindex (s, DIR_SEPARATOR))) s = p + 1;
 #endif
-  return s;
+  return (char *) s;
 }
 
 /* Yield nonzero if FILENAME is absolute (i.e. not relative).  */
 
 static int
 absolute_filename (filename)
-     char *filename;
+     const char *filename;
 {
-#if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN32__))
+#if defined (__MSDOS__) \
+  || (defined (_WIN32) && !defined (__CYGWIN__) && !defined (_UWIN))
   if (ISALPHA (filename[0]) && filename[1] == ':') filename += 2;
 #endif
-#if defined (__CYGWIN32__)
+#if defined (__CYGWIN__)
   /* At present, any path that begins with a drive spec is absolute.  */
   if (ISALPHA (filename[0]) && filename[1] == ':') return 1;
 #endif
@@ -4897,6 +4910,22 @@ absolute_filename (filename)
   return 0;
 }
 
+/* Returns whether or not a given character is a directory separator.
+   Used by simplify_filename.  */
+static inline int is_dir_separator PARAMS ((int));
+
+static inline
+int
+is_dir_separator(ch)
+     char ch;
+{
+  return (ch == DIR_SEPARATOR)
+#if defined (DIR_SEPARATOR_2)
+          || (ch == DIR_SEPARATOR_2)
+#endif
+         ;
+}
+
 /* Remove unnecessary characters from FILENAME in place,
    to avoid unnecessary filename aliasing.
    Return the length of the resulting string.
@@ -4914,55 +4943,59 @@ simplify_filename (filename)
   char *to0;
 
   /* Remove redundant initial /s.  */
-  if (*from == '/') {
-    *to++ = '/';
-    if (*++from == '/') {
-      if (*++from == '/') {
-       /* 3 or more initial /s are equivalent to 1 /.  */
-       while (*++from == '/')
-         continue;
-      } else {
-       /* On some hosts // differs from /; Posix allows this.  */
-       static int slashslash_vs_slash;
-       if (slashslash_vs_slash == 0) {
-         struct stat s1, s2;
-         slashslash_vs_slash = ((stat ("/", &s1) == 0 && stat ("//", &s2) == 0
-                                 && INO_T_EQ (s1.st_ino, s2.st_ino)
-                                 && s1.st_dev == s2.st_dev)
-                                ? 1 : -1);
-       }
-       if (slashslash_vs_slash < 0)
-         *to++ = '/';
-      }
+  if (is_dir_separator (*from))
+    {
+      *to++ = DIR_SEPARATOR;
+      if (is_dir_separator (*++from))
+        {
+          if (is_dir_separator (*++from))
+            {
+              /* 3 or more initial /s are equivalent to 1 /.  */
+              while (is_dir_separator (*++from))
+                continue;
+            }
+          else
+            {
+             /* On some hosts // differs from /; Posix allows this.  */
+             *to++ = DIR_SEPARATOR;
+            }
+        }
     }
-  }
+
   to0 = to;
 
-  for (;;) {
+  for (;;)
+    {
 #ifndef VMS
-    if (from[0] == '.' && from[1] == '/')
-      from += 2;
-    else
+      if (from[0] == '.' && from[1] == '/')
+        from += 2;
+      else
 #endif
-      {
-      /* Copy this component and trailing /, if any.  */
-      while ((*to++ = *from++) != '/') {
-       if (!to[-1]) {
-         /* Trim . component at end of nonempty name.  */
-         to -= filename <= to - 3 && to[-3] == '/' && to[-2] == '.';
-
-         /* Trim unnecessary trailing /s.  */
-         while (to0 < --to && to[-1] == '/')
-           continue;
-
-         *to = 0;
-         return to - filename;
-       }
-      }
-    }
+        {
+          /* Copy this component and trailing DIR_SEPARATOR, if any.  */
+          while (!is_dir_separator (*to++ = *from++))
+            {
+              if (!to[-1])
+                {
+                  /* Trim . component at end of nonempty name.  */
+                  to -= filename <= to - 3 && to[-3] == DIR_SEPARATOR && to[-2] == '.';
+
+                  /* Trim unnecessary trailing /s.  */
+                  while (to0 < --to && to[-1] == DIR_SEPARATOR)
+                    continue;
+
+                  *to = 0;
+                  return to - filename;
+                }
+            }
+#if defined(DIR_SEPARATOR_2)
+          /* Simplify to one directory separator.  */
+          to[-1] = DIR_SEPARATOR;
+#endif
+        }
 
     /* Skip /s after a /.  */
-    while (*from == '/')
+    while (is_dir_separator (*from))
       from++;
   }
 }
@@ -5022,7 +5055,7 @@ read_filename_string (ch, f)
 
 static struct file_name_map *
 read_name_map (dirname)
-     char *dirname;
+     const char *dirname;
 {
   /* This structure holds a linked list of file name maps, one per
      directory.  */
@@ -5045,7 +5078,7 @@ read_name_map (dirname)
 
   map_list_ptr = ((struct file_name_map_list *)
                  xmalloc (sizeof (struct file_name_map_list)));
-  map_list_ptr->map_list_name = savestring (dirname);
+  map_list_ptr->map_list_name = xstrdup (dirname);
   map_list_ptr->map_list_map = NULL;
 
   dirlen = strlen (dirname);
@@ -5120,7 +5153,7 @@ static int
 open_include_file (filename, searchptr, importing, pinc)
      char *filename;
      struct file_name_list *searchptr;
-     U_CHAR *importing;
+     const U_CHAR *importing;
      struct include_file **pinc;
 {
   char *fname = remap ? remap_include_file (filename, searchptr) : filename;
@@ -5200,7 +5233,7 @@ remap_include_file (filename, searchptr)
      struct file_name_list *searchptr;
 {
   register struct file_name_map *map;
-  register char *from;
+  register const char *from;
 
   if (searchptr)
     {
@@ -5356,6 +5389,9 @@ finclude (f, inc, op, system_header_p, dirptr)
   if (!no_trigraphs)
     trigraph_pcp (fp);
 
+  if (warn_white_space)
+    check_white_space (fp);
+
   output_line_directive (fp, op, 0, enter_file);
   rescan (op, 0);
 
@@ -5386,7 +5422,7 @@ finclude (f, inc, op, system_header_p, dirptr)
 static void
 record_control_macro (inc, macro_name)
      struct include_file *inc;
-     U_CHAR *macro_name;
+     const U_CHAR *macro_name;
 {
   if (!inc->control_macro || inc->control_macro[0])
     inc->control_macro = macro_name;
@@ -5408,8 +5444,8 @@ static char *
 check_precompiled (pcf, st, fname, limit)
      int pcf;
      struct stat *st;
-     char *fname ATTRIBUTE_UNUSED;
-     char **limit;
+     const char *fname ATTRIBUTE_UNUSED;
+     const char **limit;
 {
   int length = 0;
   char *buf;
@@ -5462,10 +5498,10 @@ check_precompiled (pcf, st, fname, limit)
 
 static int 
 check_preconditions (prec)
-     char *prec;
+     const char *prec;
 {
   MACRODEF mdef;
-  char *lineend;
+  const char *lineend;
   
   while (*prec) {
     lineend = index (prec, '\n');
@@ -5478,7 +5514,8 @@ check_preconditions (prec)
       HASHNODE *hp;
       
       prec += 6;
-      mdef = create_definition ((U_CHAR *) prec, (U_CHAR *) lineend, NULL_PTR);
+      mdef = create_definition ((const U_CHAR *) prec,
+                               (const U_CHAR *) lineend, NULL_PTR);
 
       if (mdef.defn == 0)
        abort ();
@@ -5492,7 +5529,7 @@ check_preconditions (prec)
                  || mdef.defn->expansion[1] != ' ')))
        return 0;
     } else if (!strncmp (prec, "undef", 5)) {
-      char *name;
+      const char *name;
       int len;
       
       prec += 5;
@@ -5503,7 +5540,7 @@ check_preconditions (prec)
        prec++;
       len = prec - name;
       
-      if (lookup ((U_CHAR *) name, len, -1))
+      if (lookup ((const U_CHAR *) name, len, -1))
        return 0;
     } else {
       error ("Bad format encountered while reading precompiled file");
@@ -5522,7 +5559,8 @@ check_preconditions (prec)
 
 static void
 pcfinclude (buf, name, op)
-     U_CHAR *buf, *name;
+     U_CHAR *buf;
+     const U_CHAR *name;
      FILE_BUF *op;
 {
   FILE_BUF tmpbuf;
@@ -5556,7 +5594,7 @@ pcfinclude (buf, name, op)
       cp += 4 - ((size_t) cp & 3);
     
     /* Now get the string.  */
-    str = (STRINGDEF *) (GENERIC_PTR) cp;
+    str = (STRINGDEF *) (PTR) cp;
     string_start = cp += sizeof (STRINGDEF);
     
     for (; *cp; cp++)          /* skip the string */
@@ -5569,7 +5607,7 @@ pcfinclude (buf, name, op)
     tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0);
     /* Lineno is already set in the precompiled file */
     str->contents = tmpbuf.buf;
-    str->len = tmpbuf.length;
+    str->len = tmpbuf.bufp - tmpbuf.buf;
     str->writeflag = 0;
     str->filename = name;
     str->output_mark = outbuf.bufp - outbuf.buf;
@@ -5591,8 +5629,9 @@ pcfinclude (buf, name, op)
     else
       /* Otherwise, for each key, */
       for (; nkeys--; free (tmpbuf.buf), cp = endofthiskey + 1) {
-       KEYDEF *kp = (KEYDEF *) (GENERIC_PTR) cp;
+       KEYDEF *kp = (KEYDEF *) (PTR) cp;
        HASHNODE *hp;
+       U_CHAR *bp;
        
        /* It starts with a KEYDEF structure */
        cp += sizeof (KEYDEF);
@@ -5604,20 +5643,19 @@ pcfinclude (buf, name, op)
        
        /* Expand the key, and enter it into the hash table.  */
        tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0);
-       tmpbuf.bufp = tmpbuf.buf;
+       bp = tmpbuf.buf;
        
-       while (is_hor_space[*tmpbuf.bufp])
-         tmpbuf.bufp++;
-       if (!is_idstart[*tmpbuf.bufp]
-           || tmpbuf.bufp == tmpbuf.buf + tmpbuf.length) {
+       while (is_hor_space[*bp])
+         bp++;
+       if (!is_idstart[*bp] || bp == tmpbuf.bufp) {
          str->writeflag = 1;
          continue;
        }
            
-       hp = lookup (tmpbuf.bufp, -1, -1);
+       hp = lookup (bp, -1, -1);
        if (hp == NULL) {
          kp->chain = 0;
-         install (tmpbuf.bufp, -1, T_PCSTRING, (char *) kp, -1);
+         install (bp, -1, T_PCSTRING, (char *) kp, -1);
        }
        else if (hp->type == T_PCSTRING) {
          kp->chain = hp->value.keydef;
@@ -5670,14 +5708,14 @@ write_output ()
     if (next_string
        && cur_buf_loc - outbuf.buf == next_string->output_mark) {
       if (next_string->writeflag) {
-       len = 4 * strlen ((char *) next_string->filename) + 32;
+       len = 4 * strlen ((const char *) next_string->filename) + 32;
        while (len > line_directive_len)
          line_directive = xrealloc (line_directive, 
                                     line_directive_len *= 2);
        sprintf (line_directive, "\n# %d ", next_string->lineno);
        strcpy (quote_string (line_directive + strlen (line_directive),
-                             (char *) next_string->filename,
-                             strlen ((char *) next_string->filename)),
+                             (const char *) next_string->filename,
+                             strlen ((const char *) next_string->filename)),
                "\n");
        safe_write (fileno (stdout), line_directive, strlen (line_directive));
        safe_write (fileno (stdout),
@@ -5705,11 +5743,12 @@ write_output ()
 
 static void
 pass_thru_directive (buf, limit, op, keyword)
-     U_CHAR *buf, *limit;
+     const U_CHAR *buf;
+     const U_CHAR *limit;
      FILE_BUF *op;
      struct directive *keyword;
 {
-  register unsigned keyword_length = keyword->length;
+  register int keyword_length = keyword->length;
 
   check_expand (op, 1 + keyword_length + (limit - buf));
   *op->bufp++ = '#';
@@ -5717,7 +5756,7 @@ pass_thru_directive (buf, limit, op, keyword)
   op->bufp += keyword_length;
   if (limit != buf && buf[0] != ' ')
     *op->bufp++ = ' ';
-  bcopy ((char *) buf, (char *) op->bufp, limit - buf);
+  bcopy ((const PTR) buf, (PTR) op->bufp, limit - buf);
   op->bufp += (limit - buf);
 #if 0
   *op->bufp++ = '\n';
@@ -5740,7 +5779,7 @@ pass_thru_directive (buf, limit, op, keyword)
 
 struct arglist {
   struct arglist *next;
-  U_CHAR *name;
+  const U_CHAR *name;
   int length;
   int argno;
   char rest_args;
@@ -5751,14 +5790,14 @@ struct arglist {
 
 static MACRODEF
 create_definition (buf, limit, op)
-     U_CHAR *buf, *limit;
+     const U_CHAR *buf, *limit;
      FILE_BUF *op;
 {
-  U_CHAR *bp;                  /* temp ptr into input buffer */
-  U_CHAR *symname;             /* remember where symbol name starts */
+  const U_CHAR *bp;            /* temp ptr into input buffer */
+  const U_CHAR *symname;       /* remember where symbol name starts */
   int sym_length;              /* and how long it is */
   int line = instack[indepth].lineno;
-  char *file = instack[indepth].nominal_fname;
+  const char *file = instack[indepth].nominal_fname;
   size_t file_len = instack[indepth].nominal_fname_len;
   int rest_args = 0;
 
@@ -5773,7 +5812,7 @@ create_definition (buf, limit, op)
     bp++;
 
   symname = bp;                        /* remember where it starts */
-  sym_length = check_macro_name (bp, "macro");
+  sym_length = check_macro_name (bp, 0);
   bp += sym_length;
 
   /* Lossage will occur if identifiers or control keywords are broken
@@ -5803,7 +5842,18 @@ create_definition (buf, limit, op)
                 rest_extension);
 
       if (!is_idstart[*bp])
+       {
+         if (c99 && limit - bp > (long) REST_EXTENSION_LENGTH
+             && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)
+           {
+             /* This is the ISO C 99 way to write macros with variable
+                number of arguments.  */
+             rest_args = 1;
+             temp->rest_args = 1;
+           }
+         else
        pedwarn ("invalid character in macro parameter name");
+       }
       
       /* Find the end of the arg name.  */
       while (is_idchar[*bp]) {
@@ -5818,6 +5868,13 @@ create_definition (buf, limit, op)
          break;
        }
       }
+      if (bp == temp->name && rest_args == 1)
+       {
+         /* This is the ISO C 99 style.  */
+         temp->name = (U_CHAR *) va_args_name;
+         temp->length = VA_ARGS_NAME_LENGTH;
+       }
+      else
       temp->length = bp - temp->name;
       if (rest_args == 1)
        bp += REST_EXTENSION_LENGTH;
@@ -5831,7 +5888,9 @@ create_definition (buf, limit, op)
        bp++;
        SKIP_WHITE_SPACE (bp);
        /* A comma at this point can only be followed by an identifier.  */
-       if (!is_idstart[*bp]) {
+       if (!is_idstart[*bp]
+           && !(c99 && limit - bp > (long) REST_EXTENSION_LENGTH
+               &&  bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)) {
          error ("badly punctuated parameter list in `#define'");
          goto nope;
        }
@@ -5845,11 +5904,19 @@ create_definition (buf, limit, op)
 
        for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
          if (temp->length == otemp->length
-             && bcmp (temp->name, otemp->name, temp->length) == 0) {
+             && bcmp (temp->name, otemp->name, temp->length) == 0)
+           {
              error ("duplicate argument name `%.*s' in `#define'",
                     temp->length, temp->name);
              goto nope;
          }
+       if (rest_args == 0 && temp->length == VA_ARGS_NAME_LENGTH
+           && bcmp (temp->name, va_args_name, VA_ARGS_NAME_LENGTH) == 0)
+         {
+           error ("\
+reserved name `%s' used as argument name in `#define'", va_args_name);
+           goto nope;
+         }
       }
     }
 
@@ -5937,6 +6004,7 @@ do_define (buf, limit, op, keyword)
 {
   int hashcode;
   MACRODEF mdef;
+  enum node_type newtype = keyword->type == T_DEFINE ? T_MACRO : T_POISON;
 
   /* If this is a precompiler run (with -pcp) pass thru #define directives.  */
   if (pcp_outfile && op)
@@ -5955,35 +6023,50 @@ do_define (buf, limit, op, keyword)
       /* Redefining a precompiled key is ok.  */
       if (hp->type == T_PCSTRING)
        ok = 1;
+      /* Redefining a poisoned identifier is even worse than `not ok'.  */
+      else if (hp->type == T_POISON)
+        ok = -1;
+      /* Poisoning anything else is not ok.  
+        The poison should always come first.  */
+      else if (newtype == T_POISON)
+       ok = 0;
       /* 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);
       /* Redefining a constant is ok with -D.  */
       else if (hp->type == T_CONST)
         ok = ! done_initializing;
-      /* Print the warning if it's not ok.  */
-      if (!ok) {
-        /* If we are passing through #define and #undef directives, do
-          that for this re-definition now.  */
-        if (debug_output && op)
-         pass_thru_directive (buf, limit, op, keyword);
-
-       pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
-       if (hp->type == T_MACRO)
-         pedwarn_with_file_and_line (hp->value.defn->file,
-                                     hp->value.defn->file_len,
-                                     hp->value.defn->line,
-                                     "this is the location of the previous definition");
-      }
-      /* Replace the old definition.  */
-      hp->type = T_MACRO;
-      hp->value.defn = mdef.defn;
+      
+      /* Print the warning or error if it's not ok.  */
+      if (ok <= 0) 
+       {
+         /* If we are passing through #define and #undef directives, do
+            that for this re-definition now.  */
+         if (debug_output && op)
+           pass_thru_directive (buf, limit, op, keyword);
+         
+         if (hp->type == T_POISON)
+           error ("redefining poisoned `%.*s'", mdef.symlen, mdef.symnam);
+         else
+           pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
+         if (hp->type == T_MACRO)
+           pedwarn_with_file_and_line (hp->value.defn->file,
+                                       hp->value.defn->file_len,
+                                       hp->value.defn->line,
+                                       "this is the location of the previous definition");
+       }
+      if (hp->type != T_POISON)
+       {
+         /* Replace the old definition.  */
+         hp->type = newtype;
+         hp->value.defn = mdef.defn;
+       }
     } else {
       /* If we are passing through #define and #undef directives, do
         that for this new definition now.  */
       if (debug_output && op)
        pass_thru_directive (buf, limit, op, keyword);
-      install (mdef.symnam, mdef.symlen, T_MACRO,
+      install (mdef.symnam, mdef.symlen, newtype,
               (char *) mdef.defn, hashcode);
     }
   }
@@ -5996,14 +6079,14 @@ nope:
 }
 \f
 /* Check a purported macro name SYMNAME, and yield its length.
-   USAGE is the kind of name this is intended for.  */
+   ASSERTION is nonzero if this is really for an assertion name.  */
 
 static int
-check_macro_name (symname, usage)
-     U_CHAR *symname;
-     char *usage;
+check_macro_name (symname, assertion)
+     const U_CHAR *symname;
+     int assertion;
 {
-  U_CHAR *p;
+  const U_CHAR *p;
   int sym_length;
 
   for (p = symname; is_idchar[*p]; p++)
@@ -6011,10 +6094,20 @@ check_macro_name (symname, usage)
   sym_length = p - symname;
   if (sym_length == 0
       || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
-    error ("invalid %s name", usage);
+    {
+      if (assertion)
+       error ("invalid assertion name");
+      else
+       error ("invalid macro name");
+    }
   else if (!is_idstart[*symname]
           || (sym_length == 7 && ! bcmp (symname, "defined", 7)))
-    error ("invalid %s name `%.*s'", usage, sym_length, symname);
+    {
+      if (assertion)
+       error ("invalid assertion name `%.*s'", sym_length, symname);
+      else
+       error ("invalid macro name `%.*s'", sym_length, symname);
+    }
   return sym_length;
 }
 
@@ -6067,12 +6160,12 @@ compare_defs (d1, d2)
 static int
 comp_def_part (first, beg1, len1, beg2, len2, last)
      int first;
-     U_CHAR *beg1, *beg2;
+     const U_CHAR *beg1, *beg2;
      int len1, len2;
      int last;
 {
-  register U_CHAR *end1 = beg1 + len1;
-  register U_CHAR *end2 = beg2 + len2;
+  register const U_CHAR *end1 = beg1 + len1;
+  register const U_CHAR *end2 = beg2 + len2;
   if (first) {
     while (beg1 != end1 && is_space[*beg1]) beg1++;
     while (beg2 != end2 && is_space[*beg2]) beg2++;
@@ -6109,17 +6202,20 @@ have already been deleted from the argument.  */
 
 static DEFINITION *
 collect_expansion (buf, end, nargs, arglist)
-     U_CHAR *buf, *end;
+     const U_CHAR *buf;
+     const U_CHAR *end;
      int nargs;
      struct arglist *arglist;
 {
   DEFINITION *defn;
-  register U_CHAR *p, *limit, *lastp, *exp_p;
+  register const U_CHAR *p;
+  register const U_CHAR *limit;
+  register U_CHAR *lastp, *exp_p;
   struct reflist *endpat = NULL;
   /* Pointer to first nonspace after last ## seen.  */
-  U_CHAR *concat = 0;
+  const U_CHAR *concat = 0;
   /* Pointer to first nonspace after last single-# seen.  */
-  U_CHAR *stringify = 0;
+  const U_CHAR *stringify = 0;
   /* How those tokens were spelled.  */
   enum sharp_token_type concat_sharp_token_type = NO_SHARP_TOKEN;
   enum sharp_token_type stringify_sharp_token_type = NO_SHARP_TOKEN;
@@ -6177,7 +6273,7 @@ collect_expansion (buf, end, nargs, arglist)
        break;
 
       case '\\':
-       if (p < limit && expected_delimiter) {
+       if (expected_delimiter) {
          /* In a string, backslash goes through
             and makes next char ordinary.  */
          *exp_p++ = *p++;
@@ -6187,7 +6283,7 @@ collect_expansion (buf, end, nargs, arglist)
       case '%':
        if (!expected_delimiter && *p == ':') {
          /* %: is not a digraph if preceded by an odd number of '<'s.  */
-         U_CHAR *p0 = p - 1;
+         const U_CHAR *p0 = p - 1;
          while (buf < p0 && p0[-1] == '<')
            p0--;
          if ((p - p0) & 1) {
@@ -6313,7 +6409,7 @@ collect_expansion (buf, end, nargs, arglist)
 
     /* Handle the start of a symbol.  */
     if (is_idchar[c] && nargs > 0) {
-      U_CHAR *id_beg = p - 1;
+      const U_CHAR *id_beg = p - 1;
       int id_len;
 
       --exp_p;
@@ -6369,7 +6465,7 @@ collect_expansion (buf, end, nargs, arglist)
            tpat->argno = arg->argno;
            tpat->nchars = exp_p - lastp;
            {
-             register U_CHAR *p1 = p;
+             register const U_CHAR *p1 = p;
              SKIP_WHITE_SPACE (p1);
              if (p1[0]=='#'
                  ? p1[1]=='#'
@@ -6385,7 +6481,7 @@ collect_expansion (buf, end, nargs, arglist)
 
       /* If this was not a macro arg, copy it into the expansion.  */
       if (! skipped_arg) {
-       register U_CHAR *lim1 = p;
+       register const U_CHAR *lim1 = p;
        p = id_beg;
        while (p != lim1)
          *exp_p++ = *p++;
@@ -6426,8 +6522,8 @@ do_assert (buf, limit, op, keyword)
      FILE_BUF *op ATTRIBUTE_UNUSED;
      struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  U_CHAR *bp;                  /* temp ptr into input buffer */
-  U_CHAR *symname;             /* remember where symbol name starts */
+  const U_CHAR *bp;            /* temp ptr into input buffer */
+  const U_CHAR *symname;       /* remember where symbol name starts */
   int sym_length;              /* and how long it is */
   struct arglist *tokens = NULL;
 
@@ -6440,7 +6536,7 @@ do_assert (buf, limit, op, keyword)
     bp++;
 
   symname = bp;                        /* remember where it starts */
-  sym_length = check_macro_name (bp, "assertion");
+  sym_length = check_macro_name (bp, 1);
   bp += sym_length;
   /* #define doesn't do this, but we should.  */
   SKIP_WHITE_SPACE (bp);
@@ -6503,8 +6599,8 @@ do_unassert (buf, limit, op, keyword)
      FILE_BUF *op ATTRIBUTE_UNUSED;
      struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  U_CHAR *bp;                  /* temp ptr into input buffer */
-  U_CHAR *symname;             /* remember where symbol name starts */
+  const U_CHAR *bp;            /* temp ptr into input buffer */
+  const U_CHAR *symname;       /* remember where symbol name starts */
   int sym_length;              /* and how long it is */
 
   struct arglist *tokens = NULL;
@@ -6519,7 +6615,7 @@ do_unassert (buf, limit, op, keyword)
     bp++;
 
   symname = bp;                        /* remember where it starts */
-  sym_length = check_macro_name (bp, "assertion");
+  sym_length = check_macro_name (bp, 1);
   bp += sym_length;
   /* #define doesn't do this, but we should.  */
   SKIP_WHITE_SPACE (bp);
@@ -6599,7 +6695,7 @@ do_unassert (buf, limit, op, keyword)
 
 int
 check_assertion (name, sym_length, tokens_specified, tokens)
-     U_CHAR *name;
+     const U_CHAR *name;
      int sym_length;
      int tokens_specified;
      struct arglist *tokens;
@@ -6665,12 +6761,12 @@ compare_token_lists (l1, l2)
 
 static struct arglist *
 read_token_list (bpp, limit, error_flag)
-     U_CHAR **bpp;
-     U_CHAR *limit;
+     const U_CHAR **bpp;
+     const U_CHAR *limit;
      int *error_flag;
 {
   struct arglist *token_ptrs = 0;
-  U_CHAR *bp = *bpp;
+  const U_CHAR *bp = *bpp;
   int depth = 1;
 
   *error_flag = 0;
@@ -6678,8 +6774,9 @@ read_token_list (bpp, limit, error_flag)
   /* Loop over the assertion value tokens.  */
   while (depth > 0) {
     struct arglist *temp;
+    U_CHAR *temp2;
     int eofp = 0;
-    U_CHAR *beg = bp;
+    const U_CHAR *beg = bp;
 
     /* Find the end of the token.  */
     if (*bp == '(') {
@@ -6698,9 +6795,10 @@ read_token_list (bpp, limit, error_flag)
        bp++;
 
     temp = (struct arglist *) xmalloc (sizeof (struct arglist));
-    temp->name = (U_CHAR *) xmalloc (bp - beg + 1);
-    bcopy ((char *) beg, (char *) temp->name, bp - beg);
-    temp->name[bp - beg] = 0;
+    temp2 = (U_CHAR *) xmalloc (bp - beg + 1);
+    bcopy ((const PTR) beg, (PTR) temp2, bp - beg);
+    temp2[bp - beg] = 0;
+    temp->name = temp2;
     temp->next = token_ptrs;
     token_ptrs = temp;
     temp->length = bp - beg;
@@ -6734,7 +6832,7 @@ free_token_list (tokens)
 {
   while (tokens) {
     struct arglist *next = tokens->next;
-    free (tokens->name);
+    free ((PTR) tokens->name);
     free (tokens);
     tokens = next;
   }
@@ -6750,13 +6848,14 @@ free_token_list (tokens)
 
 static ASSERTION_HASHNODE *
 assertion_install (name, len, hash)
-     U_CHAR *name;
+     const U_CHAR *name;
      int len;
      int hash;
 {
   register ASSERTION_HASHNODE *hp;
   register int i, bucket;
-  register U_CHAR *p, *q;
+  register U_CHAR *p;
+  register const U_CHAR *q;
 
   i = sizeof (ASSERTION_HASHNODE) + len + 1;
   hp = (ASSERTION_HASHNODE *) xmalloc (i);
@@ -6789,7 +6888,7 @@ assertion_install (name, len, hash)
 
 static ASSERTION_HASHNODE *
 assertion_lookup (name, len, hash)
-     U_CHAR *name;
+     const U_CHAR *name;
      int len;
      int hash;
 {
@@ -6845,6 +6944,7 @@ do_line (buf, limit, op, keyword)
 
   /* Point to macroexpanded line, which is null-terminated now.  */
   bp = tem.buf;
+  limit = tem.bufp;
   SKIP_WHITE_SPACE (bp);
 
   if (!ISDIGIT (*bp)) {
@@ -6887,20 +6987,17 @@ do_line (buf, limit, op, keyword)
     p = bp;
     for (;;)
       switch ((*p++ = *bp++)) {
-      case '\0':
-       error ("invalid format `#line' directive");
-       return 0;
-
       case '\\':
-       {
-         char *bpc = (char *) bp;
-         HOST_WIDE_INT c = parse_escape (&bpc, (HOST_WIDE_INT) (U_CHAR) (-1));
-         bp = (U_CHAR *) bpc;
-         if (c < 0)
-           p--;
-         else
-           p[-1] = c;
-       }
+       if (! ignore_escape_flag)
+         {
+           char *bpc = (char *) bp;
+           HOST_WIDEST_INT c = parse_escape (&bpc, (HOST_WIDEST_INT) (U_CHAR) (-1));
+           bp = (U_CHAR *) bpc;
+           if (c < 0)
+             p--;
+           else
+             p[-1] = c;
+         }
        break;
 
       case '\"':
@@ -6961,7 +7058,7 @@ do_line (buf, limit, op, keyword)
 
       ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
       ip->nominal_fname_len = hp->length = fname_length;
-      bcopy (fname, hp->value.cpval, fname_length + 1);
+      bcopy (fname, ((char *) hp) + sizeof (HASHNODE), fname_length + 1);
     }
   } else if (*bp) {
     error ("invalid format `#line' directive");
@@ -6993,16 +7090,20 @@ do_undef (buf, limit, op, keyword)
     pass_thru_directive (buf, limit, op, keyword);
 
   SKIP_WHITE_SPACE (buf);
-  sym_length = check_macro_name (buf, "macro");
+  sym_length = check_macro_name (buf, 0);
 
   while ((hp = lookup (buf, sym_length, -1)) != NULL) {
     /* If we are generating additional info for debugging (with -g) we
        need to pass through all effective #undef directives.  */
     if (debug_output && op)
       pass_thru_directive (orig_buf, limit, op, keyword);
-    if (hp->type != T_MACRO)
-      warning ("undefining `%s'", hp->name);
-    delete_macro (hp);
+    if (hp->type == T_POISON)
+      error ("cannot undefine poisoned `%s'", hp->name);
+    else {
+      if (hp->type != T_MACRO)
+        warning ("undefining `%s'", hp->name);
+      delete_macro (hp);
+    }
   }
 
   if (pedantic) {
@@ -7014,50 +7115,39 @@ do_undef (buf, limit, op, keyword)
   return 0;
 }
 \f
+
 /* Report an error detected by the program we are processing.
-   Use the text of the line in the error message.
-   (We use error because it prints the filename & line#.)  */
+   Use the text of the line in the error message.  */
 
 static int
 do_error (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op ATTRIBUTE_UNUSED;
-     struct directive *keyword ATTRIBUTE_UNUSED;
+     struct directive *keyword;
 {
   int length = limit - buf;
   U_CHAR *copy = (U_CHAR *) alloca (length + 1);
-  bcopy ((char *) buf, (char *) copy, length);
+  bcopy ((const PTR) buf, (PTR) copy, length);
   copy[length] = 0;
   SKIP_WHITE_SPACE (copy);
-  error ("#error %s", copy);
-  return 0;
-}
 
-/* Report a warning detected by the program we are processing.
-   Use the text of the line in the warning message, then continue.
-   (We use error because it prints the filename & line#.)  */
+  switch (keyword->type) {
+  case T_ERROR:
+    error ("#error %s", copy);
+    break;
 
-static int
-do_warning (buf, limit, op, keyword)
-     U_CHAR *buf, *limit;
-     FILE_BUF *op ATTRIBUTE_UNUSED;
-     struct directive *keyword ATTRIBUTE_UNUSED;
-{
-  int length = limit - buf;
-  U_CHAR *copy = (U_CHAR *) alloca (length + 1);
-  bcopy ((char *) buf, (char *) copy, length);
-  copy[length] = 0;
-  SKIP_WHITE_SPACE (copy);
+  case T_WARNING:
+    if (pedantic && !instack[indepth].system_header_p)
+      pedwarn ("ANSI C does not allow `#warning'");
+    warning ("#warning %s", copy);
+    break;
 
-  if (pedantic && !instack[indepth].system_header_p)
-    pedwarn ("ANSI C does not allow `#warning'");
+  default:
+    abort ();
+  }
 
-  /* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
-     if -pedantic-errors is given, #warning should cause an error.  */
-  pedwarn ("#warning %s", copy);
   return 0;
 }
-
 /* Remember the name of the current file being read from so that we can
    avoid ever including it again.  */
 
@@ -7068,7 +7158,7 @@ do_once ()
 
   for (i = indepth; i >= 0; i--)
     if (instack[i].inc) {
-      record_control_macro (instack[i].inc, (U_CHAR *) "");
+      record_control_macro (instack[i].inc, (const U_CHAR *) "");
       break;
     }
 }
@@ -7096,7 +7186,7 @@ do_ident (buf, limit, op, keyword)
   check_expand (op, 7 + len);
   bcopy ("#ident ", (char *) op->bufp, 7);
   op->bufp += 7;
-  bcopy ((char *) buf, (char *) op->bufp, len);
+  bcopy ((const PTR) buf, (PTR) op->bufp, len);
   op->bufp += len;
 
   free (buf);
@@ -7108,9 +7198,9 @@ do_ident (buf, limit, op, keyword)
 
 static int
 do_pragma (buf, limit, op, keyword)
-     U_CHAR *buf, *limit ATTRIBUTE_UNUSED;
-     FILE_BUF *op ATTRIBUTE_UNUSED;
-     struct directive *keyword ATTRIBUTE_UNUSED;
+     U_CHAR *buf, *limit;
+     FILE_BUF *op;
+     struct directive *keyword;
 {
   SKIP_WHITE_SPACE (buf);
   if (!strncmp ((char *) buf, "once", 4)) {
@@ -7121,6 +7211,29 @@ do_pragma (buf, limit, op, keyword)
     do_once ();
   }
 
+  if (!strncmp ((char *) buf, "poison", 6)) {
+    /* Poison these symbols so that all subsequent usage produces an
+       error message.  */
+    U_CHAR *p = buf + 6;
+
+    SKIP_WHITE_SPACE (p);
+    while (p < limit)
+      {
+       U_CHAR *end = p;
+       
+       while (end < limit && is_idchar[*end])
+         end++;
+       if (end < limit && !is_space[*end])
+         {
+           error ("invalid #pragma poison");
+           return 0;
+         }
+       do_define(p, end, op, keyword);
+       p = end;
+       SKIP_WHITE_SPACE (p);
+      }
+  }
+
   if (!strncmp ((char *) buf, "implementation", 14)) {
     /* Be quiet about `#pragma implementation' for a file only if it hasn't
        been included yet.  */
@@ -7132,8 +7245,9 @@ do_pragma (buf, limit, op, keyword)
       return 0;
 
     fname = p + 1;
-    if ((p = (U_CHAR *) index ((char *) fname, '\"')))
-      *p = '\0';
+    p = skip_quoted_string (p, limit, 0, NULL_PTR, NULL_PTR, NULL_PTR);
+    if (p[-1] == '"')
+      *--p = '\0';
     
     for (h = 0; h < INCLUDE_HASHSIZE; h++) {
       struct include_file *inc;
@@ -7179,7 +7293,8 @@ nope:
 
 static int
 do_sccs (buf, limit, op, keyword)
-     U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
+     U_CHAR *buf ATTRIBUTE_UNUSED;
+     U_CHAR *limit ATTRIBUTE_UNUSED;
      FILE_BUF *op ATTRIBUTE_UNUSED;
      struct directive *keyword ATTRIBUTE_UNUSED;
 {
@@ -7207,7 +7322,7 @@ do_if (buf, limit, op, keyword)
      FILE_BUF *op;
      struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  HOST_WIDE_INT value;
+  HOST_WIDEST_INT value;
   FILE_BUF *ip = &instack[indepth];
 
   value = eval_if_expression (buf, limit - buf);
@@ -7224,7 +7339,7 @@ do_elif (buf, limit, op, keyword)
      FILE_BUF *op;
      struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  HOST_WIDE_INT value;
+  HOST_WIDEST_INT value;
   FILE_BUF *ip = &instack[indepth];
 
   if (if_stack == instack[indepth].if_stack) {
@@ -7238,7 +7353,8 @@ do_elif (buf, limit, op, keyword)
             && !bcmp (if_stack->fname, ip->nominal_fname,
                       if_stack->fname_len))) {
        fprintf (stderr, ", file ");
-       eprint_string (if_stack->fname, if_stack->fname_len);
+       fwrite (if_stack->fname, sizeof if_stack->fname[0],
+               if_stack->fname_len, stderr);
       }
       fprintf (stderr, ")\n");
     }
@@ -7262,23 +7378,23 @@ do_elif (buf, limit, op, keyword)
 /* 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
+static HOST_WIDEST_INT
 eval_if_expression (buf, length)
-     U_CHAR *buf;
+     const U_CHAR *buf;
      int length;
 {
   FILE_BUF temp_obuf;
   HASHNODE *save_defined;
-  HOST_WIDE_INT value;
+  HOST_WIDEST_INT value;
 
-  save_defined = install ((U_CHAR *) "defined", -1, T_SPEC_DEFINED,
+  save_defined = install ((const U_CHAR *) "defined", -1, T_SPEC_DEFINED,
                          NULL_PTR, -1);
   pcp_inside_if = 1;
   temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1);
   pcp_inside_if = 0;
   delete_macro (save_defined); /* clean up special symbol */
 
-  temp_obuf.buf[temp_obuf.length] = '\n';
+  *temp_obuf.bufp = '\n';
   value = parse_c_expression ((char *) temp_obuf.buf,
                              warn_undef && !instack[indepth].system_header_p);
 
@@ -7340,9 +7456,12 @@ do_xifdef (buf, limit, op, keyword)
   if (end == buf) {
     skip = (keyword->type == T_IFDEF);
     if (! traditional)
-      pedwarn (end == limit ? "`#%s' with no argument"
-              : "`#%s' argument starts with punctuation",
-              keyword->name);
+      {
+       if (end == limit)
+         pedwarn ("`#%s' with no argument", keyword->name);
+       else
+         pedwarn ("`#%s' argument starts with punctuation", keyword->name);
+      }
   } else {
     HASHNODE *hp;
 
@@ -7370,10 +7489,14 @@ do_xifdef (buf, limit, op, keyword)
       }
     }
 
+    if ((hp != NULL) && (hp->type == T_POISON)) {
+      error("attempt to use poisoned `%s'.", hp->name);
+      hp = NULL;
+    }
     skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
     if (start_of_file && !skip) {
       control_macro = (U_CHAR *) xmalloc (end - buf + 1);
-      bcopy ((char *) buf, (char *) control_macro, end - buf);
+      bcopy ((const PTR) buf, (PTR) control_macro, end - buf);
       control_macro[end - buf] = 0;
     }
   }
@@ -7392,7 +7515,7 @@ conditional_skip (ip, skip, type, control_macro, op)
      FILE_BUF *ip;
      int skip;
      enum node_type type;
-     U_CHAR *control_macro;
+     const U_CHAR *control_macro;
      FILE_BUF *op;
 {
   IF_STACK_FRAME *temp;
@@ -7439,7 +7562,7 @@ skip_if_group (ip, any, op)
   int skipping_include_directive = 0;
 
   if (output_conditionals && op != 0) {
-    char *ptr = "#failed\n";
+    static const char * const ptr = "#failed\n";
     int len = strlen (ptr);
 
     if (op->bufp > op->buf && op->bufp[-1] != '\n')
@@ -7457,7 +7580,7 @@ skip_if_group (ip, any, op)
   while (bp < endb) {
     switch (*bp++) {
     case '/':                  /* possible comment */
-      if (*bp == '\\' && bp[1] == '\n')
+      if (*bp == '\\')
        newline_fix (bp);
       if (*bp == '*'
          || (cplusplus_comments && *bp == '/')) {
@@ -7587,7 +7710,7 @@ skip_if_group (ip, any, op)
        else if (*bp == '\\' && bp[1] == '\n')
          bp += 2;
        else if (*bp == '/') {
-         if (bp[1] == '\\' && bp[2] == '\n')
+         if (bp[1] == '\\')
            newline_fix (bp + 1);
          if (bp[1] == '*') {
            for (bp += 2; ; bp++) {
@@ -7596,7 +7719,7 @@ skip_if_group (ip, any, op)
              else if (*bp == '*') {
                if (bp[-1] == '/' && warn_comments)
                  warning ("`/*' within comment");
-               if (bp[1] == '\\' && bp[2] == '\n')
+               if (bp[1] == '\\')
                  newline_fix (bp + 1);
                if (bp[1] == '/')
                  break;
@@ -7649,7 +7772,7 @@ skip_if_group (ip, any, op)
        if (is_idchar[*bp])
          bp++;
        else {
-         if (*bp == '\\' && bp[1] == '\n')
+         if (*bp == '\\')
            name_newline_fix (bp);
          if (is_idchar[*bp])
            bp++;
@@ -7764,7 +7887,7 @@ skip_if_group (ip, any, op)
 
  done:
   if (output_conditionals && op != 0) {
-    char *ptr = "#endfailed\n";
+    static const char * const ptr = "#endfailed\n";
     int len = strlen (ptr);
 
     if (op->bufp > op->buf && op->bufp[-1] != '\n')
@@ -7773,7 +7896,7 @@ skip_if_group (ip, any, op)
        op->lineno++;
       }
     check_expand (op, beg_of_line - beg_of_group);
-    bcopy ((char *) beg_of_group, (char *) op->bufp,
+    bcopy ((const PTR) beg_of_group, (PTR) op->bufp,
           beg_of_line - beg_of_group);
     op->bufp += beg_of_line - beg_of_group;
     op->lineno += ip->lineno - beg_lineno;
@@ -7818,7 +7941,8 @@ do_else (buf, limit, op, keyword)
             && !bcmp (if_stack->fname, ip->nominal_fname,
                       if_stack->fname_len))) {
        fprintf (stderr, ", file ");
-       eprint_string (if_stack->fname, if_stack->fname_len);
+       fwrite (if_stack->fname, sizeof if_stack->fname[0],
+               if_stack->fname_len, stderr);
       }
       fprintf (stderr, ")\n");
     }
@@ -7901,8 +8025,8 @@ do_endif (buf, limit, op, keyword)
 
 static void
 validate_else (p, limit)
-     register U_CHAR *p;
-     register U_CHAR *limit;
+     register const U_CHAR *p;
+     register const U_CHAR *limit;
 {
   /* Advance P over whitespace and comments.  */
   while (1) {
@@ -8038,7 +8162,7 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
     case '*':
       if (bp[-2] == '/' && !nowarn && warn_comments)
        warning ("`/*' within comment");
-      if (*bp == '\\' && bp[1] == '\n')
+      if (*bp == '\\')
        newline_fix (bp);
       if (*bp == '/') {
         if (op)
@@ -8081,7 +8205,8 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
    The input stack state is not changed.
 
    If COUNT_NEWLINES is nonzero, it points to an int to increment
-   for each newline passed.
+   for each newline passed; also, warn about any white space
+   just before line end.
 
    If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it
    if we pass a backslash-newline.
@@ -8090,8 +8215,8 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
 
 static U_CHAR *
 skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp)
-     register U_CHAR *bp;
-     register U_CHAR *limit;
+     register const U_CHAR *bp;
+     register const U_CHAR *limit;
      int start_line;
      int *count_newlines;
      int *backslash_newlines_p;
@@ -8137,15 +8262,18 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
       }
       if (match == '\'') {
        error_with_line (line_for_error (start_line),
-                        "unterminated string or character constant");
+                        "unterminated character constant");
        bp--;
        if (eofp)
          *eofp = 1;
        break;
       }
       /* If not traditional, then allow newlines inside strings.  */
-      if (count_newlines)
+      if (count_newlines) {
+       if (warn_white_space && is_hor_space[bp[-2]])
+         warning ("white space at end of line in string");
        ++*count_newlines;
+      }
       if (multiline_string_line == 0) {
        if (pedantic)
          pedwarn_with_line (line_for_error (start_line),
@@ -8165,7 +8293,7 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
     }
 #endif
   }
-  return bp;
+  return (U_CHAR *) bp;
 }
 
 /* Place into DST a quoted string representing the string SRC.
@@ -8174,11 +8302,12 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
 
 static char *
 quote_string (dst, src, srclen)
-     char *dst, *src;
+     char *dst;
+     const char *src;
      size_t srclen;
 {
   U_CHAR c;
-  char *srclim = src + srclen;
+  const char *srclim = src + srclen;
 
   *dst++ = '\"';
   while (src != srclim)
@@ -8327,7 +8456,7 @@ output_line_directive (ip, op, conditional, file_change)
   check_expand (op, len + 1);
   if (op->bufp > op->buf && op->bufp[-1] != '\n')
     *op->bufp++ = '\n';
-  bcopy ((char *) line_directive_buf, (char *) op->bufp, len);
+  bcopy ((const PTR) line_directive_buf, (PTR) op->bufp, len);
   op->bufp += len;
   op->lineno = ip->lineno;
 }
@@ -8335,21 +8464,27 @@ output_line_directive (ip, op, conditional, file_change)
 /* This structure represents one parsed argument in a macro call.
    `raw' points to the argument text as written (`raw_length' is its length).
    `expanded' points to the argument's macro-expansion
-   (its length is `expand_length').
-   `stringified_length' is the length the argument would have
-   if stringified.
+   (its length is `expand_length', and its allocated size is `expand_size').
+   `stringified_length_bound' is an upper bound on the length
+   the argument would have 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.
    `free1' and `free2', if nonzero, point to blocks to be freed
-   when the macro argument data is no longer needed.  */
+   when the macro argument data is no longer needed.
+   `free_ptr', if nonzero, points to a value of instack[i].free_ptr
+   where the raw field points somewhere into this string.  The purpose
+   of this is to hold onto instack[i].buf for macro arguments, even
+   when the element has been popped off the input stack.
+*/
 
 struct argdata {
   U_CHAR *raw, *expanded;
-  int raw_length, expand_length;
-  int stringified_length;
+  int raw_length, expand_length, expand_size;
+  int stringified_length_bound;
   U_CHAR *free1, *free2;
-  char newlines;
+  U_CHAR *free_ptr;
+  int newlines;
   char use_count;
 };
 
@@ -8391,16 +8526,17 @@ macroexpand (hp, op)
   if (nargs >= 0) {
     register int i;
     struct argdata *args;
-    char *parse_error = 0;
+    int parse_error = 0;
 
     args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
 
     for (i = 0; i < nargs; i++) {
       args[i].raw = (U_CHAR *) "";
       args[i].expanded = 0;
-      args[i].raw_length = args[i].expand_length
-       = args[i].stringified_length = 0;
+      args[i].raw_length = args[i].expand_length = args[i].expand_size
+       = args[i].stringified_length_bound = 0;
       args[i].free1 = args[i].free2 = 0;
+      args[i].free_ptr = 0;
       args[i].use_count = 0;
     }
 
@@ -8425,7 +8561,8 @@ macroexpand (hp, op)
       else
        parse_error = macarg (NULL_PTR, 0);
       if (parse_error) {
-       error_with_line (line_for_error (start_line), parse_error);
+       error_with_line (line_for_error (start_line),
+                        "unterminated macro call");
        break;
       }
       i++;
@@ -8433,8 +8570,8 @@ macroexpand (hp, op)
 
     /* If we got one arg but it was just whitespace, call that 0 args.  */
     if (i == 1) {
-      register U_CHAR *bp = args[0].raw;
-      register U_CHAR *lim = bp + args[0].raw_length;
+      register const U_CHAR *bp = args[0].raw;
+      register const U_CHAR *lim = bp + args[0].raw_length;
       /* cpp.texi says for foo ( ) we provide one argument.
         However, if foo wants just 0 arguments, treat this as 0.  */
       if (nargs == 0)
@@ -8491,8 +8628,13 @@ macroexpand (hp, op)
         Also count number of times each arg is used.  */
       xbuf_len = defn->length;
       for (ap = defn->pattern; ap != NULL; ap = ap->next) {
-       if (ap->stringify)
-         xbuf_len += args[ap->argno].stringified_length;
+       if (ap->stringify && args[ap->argno].stringified_length_bound == 0)
+         /* macarg is not called for omitted arguments, as a result
+            stringified_length_bound will be zero.  We need to make
+            enough space for "".  */
+         xbuf_len += 2;
+       else if (ap->stringify)
+         xbuf_len += args[ap->argno].stringified_length_bound;
        else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional)
          /* Add 4 for two newline-space markers to prevent
             token concatenation.  */
@@ -8507,13 +8649,20 @@ macroexpand (hp, op)
                                          1, 0);
 
            args[ap->argno].expanded = obuf.buf;
-           args[ap->argno].expand_length = obuf.length;
+           args[ap->argno].expand_length = obuf.bufp - obuf.buf;
+           args[ap->argno].expand_size = obuf.length;
            args[ap->argno].free2 = obuf.buf;
-         }
 
+           xbuf_len += args[ap->argno].expand_length;
+         } else {
+           /* If the arg appears more than once, its later occurrences
+              may have newline turned into backslash-'n', which is a
+              factor of 2 expansion.  */
+           xbuf_len += 2 * args[ap->argno].expand_length;
+         }
          /* Add 4 for two newline-space markers to prevent
             token concatenation.  */
-         xbuf_len += args[ap->argno].expand_length + 4;
+         xbuf_len += 4;
        }
        if (args[ap->argno].use_count < 10)
          args[ap->argno].use_count++;
@@ -8570,27 +8719,28 @@ macroexpand (hp, op)
          for (; i < arglen; i++) {
            c = arg->raw[i];
 
-           if (! in_string) {
-             /* Special markers Newline Space
+           if (in_string) {
+             /* Generate nothing for backslash-newline in a string.  */
+             if (c == '\\' && arg->raw[i + 1] == '\n') {
+               i++;
+               continue;
+             }
+           } else {
+             /* Special markers
                 generate nothing for a stringified argument.  */
-             if (c == '\n' && arg->raw[i+1] != '\n') {
+             if (c == '\n') {
                i++;
                continue;
              }
 
              /* Internal sequences of whitespace are replaced by one space
-                except within an string or char token.  */
-             if (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c]) {
-               while (1) {
-                 /* Note that Newline Space does occur within whitespace
-                    sequences; consider it part of the sequence.  */
-                 if (c == '\n' && is_space[arg->raw[i+1]])
-                   i += 2;
-                 else if (c != '\n' && is_space[c])
-                   i++;
-                 else break;
-                 c = arg->raw[i];
-               }
+                except within a string or char token.  */
+             if (is_space[c]) {
+               i++;
+               while (is_space[(c = arg->raw[i])])
+                 /* Newline markers can occur within a whitespace sequence;
+                    consider them part of the sequence.  */
+                 i += (c == '\n') + 1;
                i--;
                c = ' ';
              }
@@ -8622,8 +8772,15 @@ macroexpand (hp, op)
                in_string = c;
            }
 
-           /* Escape these chars */
-           if (c == '\"' || (in_string && c == '\\'))
+           /* Escape double-quote, and backslashes in strings.
+              Newlines in strings are best escaped as \n, since
+              otherwise backslash-backslash-newline-newline is
+              mishandled.  The C Standard doesn't allow newlines in
+              strings, so we can escape newlines as we please.  */
+           if (c == '\"'
+               || (in_string
+                   && (c == '\\'
+                       || (c == '\n' ? (c = 'n', 1) : 0))))
              xbuf[totlen++] = '\\';
            /* We used to output e.g. \008 for control characters here,
               but this doesn't conform to the C Standard.
@@ -8633,8 +8790,8 @@ macroexpand (hp, op)
          if (!traditional)
            xbuf[totlen++] = '\"'; /* insert ending quote */
        } else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional) {
-         U_CHAR *p1 = arg->raw;
-         U_CHAR *l1 = p1 + arg->raw_length;
+         const U_CHAR *p1 = arg->raw;
+         const U_CHAR *l1 = p1 + arg->raw_length;
          if (ap->raw_before != 0) {
            while (p1 != l1 && is_space[*p1]) p1++;
            while (p1 != l1 && is_idchar[*p1])
@@ -8656,7 +8813,7 @@ macroexpand (hp, op)
            while (p1 != l1) {
              if (is_space[l1[-1]]) l1--;
              else if (l1[-1] == '-') {
-               U_CHAR *p2 = l1 - 1;
+               const U_CHAR *p2 = l1 - 1;
                /* If a `-' is preceded by an odd number of newlines then it
                   and the last newline are a no-reexpansion marker.  */
                while (p2 != p1 && p2[-1] == '\n') p2--;
@@ -8669,7 +8826,7 @@ macroexpand (hp, op)
            }
          }
 
-         bcopy ((char *) p1, (char *) (xbuf + totlen), l1 - p1);
+         bcopy ((const PTR) p1, (PTR) (xbuf + totlen), l1 - p1);
          totlen += l1 - p1;
          if (!traditional && ap->raw_after == 0) {
            /* Ordinary expanded use of the argument.
@@ -8684,7 +8841,7 @@ macroexpand (hp, op)
            xbuf[totlen++] = '\n';
            xbuf[totlen++] = ' ';
          }
-         bcopy ((char *) arg->expanded, (char *) (xbuf + totlen),
+         bcopy ((const PTR) arg->expanded, (PTR) (xbuf + totlen),
                 arg->expand_length);
          totlen += arg->expand_length;
          if (!traditional) {
@@ -8699,8 +8856,7 @@ macroexpand (hp, op)
            /* Don't bother doing change_newlines for subsequent
               uses of arg.  */
            arg->use_count = 1;
-           arg->expand_length
-             = change_newlines (arg->expanded, arg->expand_length);
+           change_newlines (arg);
          }
        }
 
@@ -8724,6 +8880,18 @@ macroexpand (hp, op)
       xbuf_len = totlen;
 
       for (i = 0; i < nargs; i++) {
+        if (args[i].free_ptr != 0) {
+          U_CHAR *buf = args[i].free_ptr;
+          int d;
+          for (d = indepth; d >= 0; --d) {
+            if (instack[d].buf == buf) {
+              instack[d].free_ptr = buf; /* Give ownership back to instack */
+              goto no_free;
+            }
+          }
+          free (buf); /* buf is not on the stack; must have been popped */
+        no_free:;
+        }
        if (args[i].free1 != 0)
          free (args[i].free1);
        if (args[i].free2 != 0)
@@ -8770,30 +8938,35 @@ macroexpand (hp, op)
    REST_ARGS is passed to macarg1 to make it absorb the rest of the args.
    Return nonzero to indicate a syntax error.  */
 
-static char *
+static int
 macarg (argptr, rest_args)
      register struct argdata *argptr;
      int rest_args;
 {
   FILE_BUF *ip = &instack[indepth];
   int paren = 0;
-  int newlines = 0;
+  int lineno0 = ip->lineno;
   int comments = 0;
-  char *result = 0;
+  int result = 0;
 
   /* Try to parse as much of the argument as exists at this
      input stack level.  */
   U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro,
-                       &paren, &newlines, &comments, rest_args);
+                       &paren, &ip->lineno, &comments, rest_args);
 
   /* If we find the end of the argument at this level,
      set up *ARGPTR to point at it in the input stack.  */
-  if (!(ip->fname != 0 && (newlines != 0 || comments != 0))
+  if (!(ip->fname != 0 && (ip->lineno != lineno0 || comments != 0))
       && bp != ip->buf + ip->length) {
     if (argptr != 0) {
       argptr->raw = ip->bufp;
       argptr->raw_length = bp - ip->bufp;
-      argptr->newlines = newlines;
+      argptr->newlines = ip->lineno - lineno0;
+      /* The next two statements transfer ownership of the the buffer
+        from ip to argptr.  Note that the second statement ensures that
+        a given free_ptr is owned by at most one macro argument. */
+      argptr->free_ptr = ip->free_ptr;
+      ip->free_ptr     = 0;
     }
     ip->bufp = bp;
   } else {
@@ -8802,35 +8975,33 @@ macarg (argptr, rest_args)
        Therefore, we must allocate a temporary buffer and copy
        the macro argument into it.  */
     int bufsize = bp - ip->bufp;
-    int extra = newlines;
+    int extra = ip->lineno - lineno0;
     U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1);
     int final_start = 0;
 
-    bcopy ((char *) ip->bufp, (char *) buffer, bufsize);
+    bcopy ((const PTR) ip->bufp, (PTR) buffer, bufsize);
     ip->bufp = bp;
-    ip->lineno += newlines;
 
     while (bp == ip->buf + ip->length) {
       if (instack[indepth].macro == 0) {
-       result = "unterminated macro call";
+       result = 1;
        break;
       }
       ip->macro->type = T_MACRO;
       if (ip->free_ptr)
        free (ip->free_ptr);
       ip = &instack[--indepth];
-      newlines = 0;
+      lineno0 = ip->lineno;
       comments = 0;
       bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren,
-                   &newlines, &comments, rest_args);
+                   &ip->lineno, &comments, rest_args);
       final_start = bufsize;
       bufsize += bp - ip->bufp;
-      extra += newlines;
+      extra += ip->lineno - lineno0;
       buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1);
-      bcopy ((char *) ip->bufp, (char *) (buffer + bufsize - (bp - ip->bufp)),
+      bcopy ((const PTR) ip->bufp, (PTR) (buffer + bufsize - (bp - ip->bufp)),
             bp - ip->bufp);
       ip->bufp = bp;
-      ip->lineno += newlines;
     }
 
     /* Now, if arg is actually wanted, record its raw form,
@@ -8842,13 +9013,13 @@ macarg (argptr, rest_args)
       argptr->raw = buffer;
       argptr->raw_length = bufsize;
       argptr->free1 = buffer;
-      argptr->newlines = newlines;
-      if ((newlines || comments) && ip->fname != 0)
+      argptr->newlines = ip->lineno - lineno0;
+      if ((argptr->newlines || comments) && ip->fname != 0)
        argptr->raw_length
          = final_start +
            discard_comments (argptr->raw + final_start,
                              argptr->raw_length - final_start,
-                             newlines);
+                             argptr->newlines);
       argptr->raw[argptr->raw_length] = 0;
       if (argptr->raw_length > bufsize + extra)
        abort ();
@@ -8860,7 +9031,7 @@ macarg (argptr, rest_args)
      All this info goes into *ARGPTR.  */
 
   if (argptr != 0) {
-    register U_CHAR *buf, *lim;
+    register const U_CHAR *buf, *lim;
     register int totlen;
 
     buf = argptr->raw;
@@ -8882,10 +9053,10 @@ macarg (argptr, rest_args)
        SKIP_ALL_WHITE_SPACE (buf);
       else
 #endif
-      if (c == '\"' || c == '\\') /* escape these chars */
+      if (c == '\"' || c == '\\' || c == '\n') /* escape these chars */
        totlen++;
     }
-    argptr->stringified_length = totlen;
+    argptr->stringified_length_bound = totlen;
   }
   return result;
 }
@@ -8907,7 +9078,7 @@ macarg (argptr, rest_args)
 static U_CHAR *
 macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
      U_CHAR *start;
-     register U_CHAR *limit;
+     register const U_CHAR *limit;
      struct hashnode *macro;
      int *depthptr, *newlines, *comments;
      int rest_args;
@@ -8934,7 +9105,7 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
     case '/':
       if (macro)
        break;
-      if (bp[1] == '\\' && bp[2] == '\n')
+      if (bp[1] == '\\')
        newline_fix (bp + 1);
       if (bp[1] == '*') {
        *comments = 1;
@@ -8944,7 +9115,7 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
          else if (*bp == '*') {
            if (bp[-1] == '/' && warn_comments)
              warning ("`/*' within comment");
-           if (bp[1] == '\\' && bp[2] == '\n')
+           if (bp[1] == '\\')
              newline_fix (bp + 1);
            if (bp[1] == '/') {
              bp++;
@@ -8991,18 +9162,18 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
     case '\"':
       {
        int quotec;
-       for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) {
+       for (quotec = *bp++; bp < limit && *bp != quotec; bp++) {
          if (*bp == '\\') {
            bp++;
            if (*bp == '\n')
              ++*newlines;
-           if (!macro) {
-             while (*bp == '\\' && bp[1] == '\n') {
-               bp += 2;
-               ++*newlines;
-             }
+           while (*bp == '\\' && bp[1] == '\n') {
+             bp += 2;
+             ++*newlines;
            }
          } else if (*bp == '\n') {
+           if (warn_white_space && is_hor_space[bp[-1]] && ! macro)
+             warning ("white space at end of line in string");
            ++*newlines;
            if (quotec == '\'')
              break;
@@ -9086,7 +9257,7 @@ discard_comments (start, length, newlines)
       break;
 
     case '/':
-      if (*ibp == '\\' && ibp[1] == '\n')
+      if (*ibp == '\\')
        newline_fix (ibp);
       /* Delete any comment.  */
       if (cplusplus_comments && ibp[0] == '/') {
@@ -9121,7 +9292,7 @@ discard_comments (start, length, newlines)
        obp[-1] = ' ';
       while (++ibp < limit) {
        if (ibp[0] == '*') {
-         if (ibp[1] == '\\' && ibp[2] == '\n')
+         if (ibp[1] == '\\')
            newline_fix (ibp + 1);
          if (ibp[1] == '/') {
            ibp += 2;
@@ -9192,18 +9363,19 @@ discard_comments (start, length, newlines)
   return obp - start;
 }
 \f
-/* Turn newlines to spaces in the string of length LENGTH at START,
-   except inside of string constants.
-   The string is copied into itself with its beginning staying fixed.  */
+/* Turn newlines to spaces in the macro argument ARG.
+   Remove backslash-newline from string constants,
+   and turn other newlines in string constants to backslash-'n'.  */
 
-static int
-change_newlines (start, length)
-     U_CHAR *start;
-     int length;
+static void
+change_newlines (arg)
+     struct argdata *arg;
 {
+  U_CHAR *start = arg->expanded;
+  int length = arg->expand_length;
   register U_CHAR *ibp;
   register U_CHAR *obp;
-  register U_CHAR *limit;
+  register const U_CHAR *limit;
   register int c;
 
   ibp = start;
@@ -9264,64 +9436,63 @@ change_newlines (start, length)
     }
   }
 
-  return obp - start;
+  arg->expand_length = obp - arg->expanded;
+
+  if (start != arg->expanded)
+    free (start);
 }
 \f
-/* my_strerror - return the descriptive text associated with an
-   `errno' code.  */
+/* notice - output message to stderr */
 
-static char *
-my_strerror (errnum)
-     int errnum;
+static void
+notice VPARAMS ((const char * msgid, ...))
 {
-  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);
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
 #endif
+  va_list args;
 
-  if (!result)
-    result = "undocumented I/O error";
+  VA_START (args, msgid);
 
-  return result;
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, const char *);
+#endif
+  vnotice (msgid, args);
+  va_end (args);
+}
+
+static void
+vnotice (msgid, args)
+     const char *msgid;
+     va_list args;
+{
+  vfprintf (stderr, _(msgid), args);
 }
 
 /* error - print error message and increment count of errors.  */
 
 void
-error VPROTO ((char * msg, ...))
+error VPARAMS ((const char * msgid, ...))
 {
-#ifndef __STDC__
-  char * msg;
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
 #endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
 
-#ifndef __STDC__
-  msg = va_arg (args, char *);
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, const char *);
 #endif
-
-  verror (msg, args);
+  verror (msgid, args);
   va_end (args);
 }
 
-static void
-verror (msg, args)
-     char *msg;
+void
+verror (msgid, args)
+     const char *msgid;
      va_list args;
 {
   int i;
@@ -9336,10 +9507,11 @@ verror (msg, args)
     }
 
   if (ip != NULL) {
-    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fwrite (ip->nominal_fname, sizeof ip->nominal_fname[0],
+           ip->nominal_fname_len, stderr);
     fprintf (stderr, ":%d: ", ip->lineno);
   }
-  vfprintf (stderr, msg, args);
+  vnotice (msgid, args);
   fprintf (stderr, "\n");
   errors++;
 }
@@ -9348,7 +9520,7 @@ verror (msg, args)
 
 static void
 error_from_errno (name)
-     char *name;
+     const char *name;
 {
   int e = errno;
   int i;
@@ -9363,11 +9535,12 @@ error_from_errno (name)
     }
 
   if (ip != NULL) {
-    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fwrite (ip->nominal_fname, sizeof ip->nominal_fname[0],
+           ip->nominal_fname_len, stderr);
     fprintf (stderr, ":%d: ", ip->lineno);
   }
 
-  fprintf (stderr, "%s: %s\n", name, my_strerror (e));
+  fprintf (stderr, "%s: %s\n", name, xstrerror (e));
 
   errors++;
 }
@@ -9375,26 +9548,26 @@ error_from_errno (name)
 /* Print error message but don't count it.  */
 
 void
-warning VPROTO ((char * msg, ...))
+warning VPARAMS ((const char * msgid, ...))
 {
-#ifndef __STDC__
-  char * msg;
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
 #endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
 
-#ifndef __STDC__
-  msg = va_arg (args, char *);
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, const char *);
 #endif
 
-  vwarning (msg, args);
+  vwarning (msgid, args);
   va_end (args);
 }
 
 static void
-vwarning (msg, args)
-     char *msg;
+vwarning (msgid, args)
+     const char *msgid;
      va_list args;
 {
   int i;
@@ -9415,38 +9588,40 @@ vwarning (msg, args)
     }
 
   if (ip != NULL) {
-    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fwrite (ip->nominal_fname, sizeof ip->nominal_fname[0],
+           ip->nominal_fname_len, stderr);
     fprintf (stderr, ":%d: ", ip->lineno);
   }
-  fprintf (stderr, "warning: ");
-  vfprintf (stderr, msg, args);
+  notice ("warning: ");
+  vnotice (msgid, args);
   fprintf (stderr, "\n");
 }
 
 static void
-error_with_line VPROTO ((int line, char * msg, ...))
+error_with_line VPARAMS ((int line, const char * msgid, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   int line;
-  char * msg;
+  const char * msgid;
 #endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   line = va_arg (args, int);
-  msg = va_arg (args, char *);
+  msgid = va_arg (args, const char *);
 #endif
 
-  verror_with_line (line, msg, args);
+  verror_with_line (line, msgid, args);
   va_end (args);
 }
 
+
 static void
-verror_with_line (line, msg, args)
+verror_with_line (line, msgid, args)
      int line;
-     char *msg;
+     const char *msgid;
      va_list args;
 {
   int i;
@@ -9461,38 +9636,39 @@ verror_with_line (line, msg, args)
     }
 
   if (ip != NULL) {
-    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fwrite (ip->nominal_fname, sizeof ip->nominal_fname[0],
+           ip->nominal_fname_len, stderr);
     fprintf (stderr, ":%d: ", line);
   }
-  vfprintf (stderr, msg, args);
+  vnotice (msgid, args);
   fprintf (stderr, "\n");
   errors++;
 }
 
 static void
-warning_with_line VPROTO ((int line, char * msg, ...))
+warning_with_line VPARAMS ((int line, const char * msgid, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   int line;
-  char * msg;
+  const char * msgid;
 #endif
   va_list args;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   line = va_arg (args, int);
-  msg = va_arg (args, char *);
+  msgid = va_arg (args, const char *);
 #endif
 
-  vwarning_with_line (line, msg, args);
+  vwarning_with_line (line, msgid, args);
   va_end (args);
 }
 
 static void
-vwarning_with_line (line, msg, args)
+vwarning_with_line (line, msgid, args)
      int line;
-     char *msg;
+     const char *msgid;
      va_list args;
 {
   int i;
@@ -9513,57 +9689,61 @@ vwarning_with_line (line, msg, args)
     }
 
   if (ip != NULL) {
-    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
-    fprintf (stderr, line ? ":%d: " : ": ", line);
+    fwrite (ip->nominal_fname, sizeof ip->nominal_fname[0],
+           ip->nominal_fname_len, stderr);
+    if (line)
+      fprintf (stderr, ":%d: ", line);
+    else
+      fputs (": ", stderr);
   }
-  fprintf (stderr, "warning: ");
-  vfprintf (stderr, msg, args);
+  notice ("warning: ");
+  vnotice (msgid, args);
   fprintf (stderr, "\n");
 }
 
 /* Print an error message and maybe count it.  */
 
 void
-pedwarn VPROTO ((char * msg, ...))
+pedwarn VPARAMS ((const char * msgid, ...))
 {
-#ifndef __STDC__
-  char * msg;
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
 #endif
   va_list args;
 
-  VA_START (args, msg);
-#ifndef __STDC__
-  msg = va_arg (args, char *);
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, const char *);
 #endif
+
   if (pedantic_errors)
-    verror (msg, args);
+    verror (msgid, args);
   else
-    vwarning (msg, args);
+    vwarning (msgid, args);
   va_end (args);
 }
 
 void
-pedwarn_with_line VPROTO ((int line, char * msg, ...))
+pedwarn_with_line VPARAMS ((int line, const char * msgid, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   int line;
-  char * msg;
+  const char * msgid;
 #endif
   va_list args;
 
-  VA_START (args, msg);
-#ifndef __STDC__
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
   line = va_arg (args, int);
-  msg = va_arg (args, char *);
+  msgid = va_arg (args, const char *);
 #endif
+
   if (pedantic_errors)
-    verror_with_line (line, msg, args);
+    verror_with_line (line, msgid, args);
   else
-    vwarning_with_line (line, msg, args);
+    vwarning_with_line (line, msgid, args);
   va_end (args);
 }
 
@@ -9571,42 +9751,54 @@ pedwarn_with_line VPROTO ((int line, char * msg, ...))
    giving specified file name and line number, not current.  */
 
 static void
-pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line,
-                                   char * msg, ...))
+pedwarn_with_file_and_line VPARAMS ((const char *file, size_t file_len,
+                                    int line, const char * msgid, ...))
 {
-#ifndef __STDC__
-  char *file;
+#ifndef ANSI_PROTOTYPES
+  const char *file;
   size_t file_len;
   int line;
-  char * msg;
+  const char * msgid;
 #endif
   va_list args;
 
   if (!pedantic_errors && inhibit_warnings)
     return;
 
-  VA_START (args, msg);
+  VA_START (args, msgid);
  
-#ifndef __STDC__
-  file = va_arg (args, char *);
+#ifndef ANSI_PROTOTYPES
+  file = va_arg (args, const char *);
   file_len = va_arg (args, size_t);
   line = va_arg (args, int);
-  msg = va_arg (args, char *);
+  msgid = va_arg (args, const char *);
 #endif
  
   if (file) {
-    eprint_string (file, file_len);
+    fwrite (file, sizeof file[0], file_len, stderr);
     fprintf (stderr, ":%d: ", line);
   }
   if (pedantic_errors)
     errors++;
   if (!pedantic_errors)
-    fprintf (stderr, "warning: ");
-
-  vfprintf (stderr, msg, args);
+    notice ("warning: ");
+  vnotice (msgid, args);
   va_end (args);
   fprintf (stderr, "\n");
 }
+
+static void
+pedwarn_strange_white_space (ch)
+     int ch;
+{
+  switch (ch)
+    {
+    case '\f': pedwarn ("formfeed in preprocessing directive"); break;
+    case '\r': pedwarn ("carriage return in preprocessing directive"); break;
+    case '\v': pedwarn ("vertical tab in preprocessing directive"); break;
+    default: abort ();
+    }
+}
 \f
 /* Print the file names and line numbers of the #include
    directives which led to the current file.  */
@@ -9639,13 +9831,13 @@ print_containing_files ()
       ip = &instack[i];
       if (first) {
        first = 0;
-       fprintf (stderr, "In file included");
+       notice (   "In file included from ");
       } else {
-       fprintf (stderr, ",\n                ");
+       notice (",\n                 from ");
       }
 
-      fprintf (stderr, " from ");
-      eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+      fwrite (ip->nominal_fname, sizeof ip->nominal_fname[0],
+             ip->nominal_fname_len, stderr);
       fprintf (stderr, ":%d", ip->lineno);
     }
   if (! first)
@@ -9713,8 +9905,7 @@ grow_outbuf (obuf, needed)
   if (minsize > obuf->length)
     obuf->length = minsize;
 
-  if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL)
-    memory_full ();
+  p = (U_CHAR *) xrealloc (obuf->buf, obuf->length);
 
   obuf->bufp = p + (obuf->bufp - obuf->buf);
   obuf->buf = p;
@@ -9741,21 +9932,22 @@ grow_outbuf (obuf, needed)
 
 static HASHNODE *
 install (name, len, type, value, hash)
-     U_CHAR *name;
+     const U_CHAR *name;
      int len;
      enum node_type type;
-     char *value;
+     const char *value;
      int hash;
 {
   register HASHNODE *hp;
   register int i, bucket;
-  register U_CHAR *p, *q;
+  register U_CHAR *p;
+  register const U_CHAR *q;
 
   if (len < 0) {
-    p = name;
-    while (is_idchar[*p])
-      p++;
-    len = p - name;
+    q = name;
+    while (is_idchar[*q])
+      q++;
+    len = q - name;
   }
 
   if (hash < 0)
@@ -9795,11 +9987,11 @@ install (name, len, type, value, hash)
 
 HASHNODE *
 lookup (name, len, hash)
-     U_CHAR *name;
+     const U_CHAR *name;
      int len;
      int hash;
 {
-  register U_CHAR *bp;
+  register const U_CHAR *bp;
   register HASHNODE *bucket;
 
   if (len < 0) {
@@ -9870,7 +10062,7 @@ delete_macro (hp)
 
 static int
 hashf (name, len, hashsize)
-     register U_CHAR *name;
+     register const U_CHAR *name;
      register int len;
      int hashsize;
 {
@@ -9994,21 +10186,21 @@ dump_all_macros ()
 
 static void
 dump_defn_1 (base, start, length, of)
-     U_CHAR *base;
+     const U_CHAR *base;
      int start;
      int length;
      FILE *of;
 {
-  U_CHAR *p = base + start;
-  U_CHAR *limit = base + start + length;
+  const U_CHAR *p = base + start;
+  const U_CHAR *limit = base + start + length;
 
   if (traditional)
     fwrite (p, sizeof (*p), length, of);
   else {
     while (p < limit) {
       if (*p == '\"' || *p =='\'') {
-       U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR,
-                                        NULL_PTR, NULL_PTR);
+       const U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR,
+                                              NULL_PTR, NULL_PTR);
        fwrite (p, sizeof (*p), p1 - p, of);
        p = p1;
       } else {
@@ -10057,10 +10249,13 @@ initialize_char_syntax ()
    * refer to them.
    */
   for (i = 'a'; i <= 'z'; i++) {
-    is_idchar[i - 'a' + 'A'] = 1;
-    is_idchar[i] = 1;
-    is_idstart[i - 'a' + 'A'] = 1;
-    is_idstart[i] = 1;
+    /* SKIP EBCIDIC holes, char must be a valid low case char */
+    if (ISLOWER(i)) {
+      is_idchar[TOUPPER(i)] = 1;
+      is_idchar[i] = 1;
+      is_idstart[TOUPPER(i)] = 1;
+      is_idstart[i] = 1;
+    }
   }
   for (i = '0'; i <= '9'; i++)
     is_idchar[i] = 1;
@@ -10082,10 +10277,6 @@ initialize_char_syntax ()
   is_space['\f'] = 1;
   is_space['\n'] = 1;
   is_space['\r'] = 1;
-
-  char_name['\v'] = "vertical tab";
-  char_name['\f'] = "formfeed";
-  char_name['\r'] = "carriage return";
 }
 
 /* Initialize the built-in macros.  */
@@ -10095,36 +10286,36 @@ initialize_builtins (inp, outp)
      FILE_BUF *inp;
      FILE_BUF *outp;
 {
-  install ((U_CHAR *) "__LINE__", -1, T_SPECLINE, NULL_PTR, -1);
-  install ((U_CHAR *) "__DATE__", -1, T_DATE, NULL_PTR, -1);
-  install ((U_CHAR *) "__FILE__", -1, T_FILE, NULL_PTR, -1);
-  install ((U_CHAR *) "__BASE_FILE__", -1, T_BASE_FILE, NULL_PTR, -1);
-  install ((U_CHAR *) "__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, NULL_PTR, -1);
-  install ((U_CHAR *) "__VERSION__", -1, T_VERSION, NULL_PTR, -1);
+  install ((const U_CHAR *) "__LINE__", -1, T_SPECLINE, NULL_PTR, -1);
+  install ((const U_CHAR *) "__DATE__", -1, T_DATE, NULL_PTR, -1);
+  install ((const U_CHAR *) "__FILE__", -1, T_FILE, NULL_PTR, -1);
+  install ((const U_CHAR *) "__BASE_FILE__", -1, T_BASE_FILE, NULL_PTR, -1);
+  install ((const U_CHAR *) "__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, NULL_PTR, -1);
+  install ((const U_CHAR *) "__VERSION__", -1, T_VERSION, NULL_PTR, -1);
 #ifndef NO_BUILTIN_SIZE_TYPE
-  install ((U_CHAR *) "__SIZE_TYPE__", -1, T_SIZE_TYPE, NULL_PTR, -1);
+  install ((const U_CHAR *) "__SIZE_TYPE__", -1, T_SIZE_TYPE, NULL_PTR, -1);
 #endif
 #ifndef NO_BUILTIN_PTRDIFF_TYPE
-  install ((U_CHAR *) "__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, NULL_PTR, -1);
+  install ((const U_CHAR *) "__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, NULL_PTR, -1);
+#endif
+#ifndef NO_BUILTIN_WCHAR_TYPE
+  install ((const U_CHAR *) "__WCHAR_TYPE__", -1, T_WCHAR_TYPE, NULL_PTR, -1);
 #endif
-  install ((U_CHAR *) "__WCHAR_TYPE__", -1, T_WCHAR_TYPE, NULL_PTR, -1);
-  install ((U_CHAR *) "__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE,
+  install ((const U_CHAR *) "__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE,
           NULL_PTR, -1);
-  install ((U_CHAR *) "__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE,
+  install ((const U_CHAR *) "__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE,
           NULL_PTR, -1);
-  install ((U_CHAR *) "__IMMEDIATE_PREFIX__", -1, T_IMMEDIATE_PREFIX_TYPE,
+  install ((const U_CHAR *) "__IMMEDIATE_PREFIX__", -1, T_IMMEDIATE_PREFIX_TYPE,
           NULL_PTR, -1);
-  install ((U_CHAR *) "__TIME__", -1, T_TIME, NULL_PTR, -1);
+  install ((const U_CHAR *) "__TIME__", -1, T_TIME, NULL_PTR, -1);
   if (!traditional) {
-    install ((U_CHAR *) "__STDC__", -1, T_CONST, "1", -1);
-    install ((U_CHAR *) "__STDC_VERSION__", -1, T_CONST, "199409L", -1);
+    install ((const U_CHAR *) "__STDC__", -1, T_CONST, "1", -1);
+    install ((const U_CHAR *) "__STDC_VERSION__", -1, T_CONST, "199409L", -1);
   }
-  if (objc)
-    install ((U_CHAR *) "__OBJC__", -1, T_CONST, "1", -1);
 /*  This is supplied using a -D by the compiler driver
     so that it is present only when truly compiling with GNU C.  */
 /*  install ((U_CHAR *) "__GNUC__", -1, T_CONST, "2", -1);  */
-  install ((U_CHAR *) "__HAVE_BUILTIN_SETJMP__", -1, T_CONST, "1", -1);
+  install ((const U_CHAR *) "__HAVE_BUILTIN_SETJMP__", -1, T_CONST, "1", -1);
 
   if (debug_output)
     {
@@ -10158,10 +10349,12 @@ initialize_builtins (inp, outp)
                           outp, dp);
 #endif
 
+#ifndef NO_BUILTIN_WCHAR_TYPE
       sprintf (directive, " __WCHAR_TYPE__ %s\n", wchar_type);
       output_line_directive (inp, outp, 0, same_file);
       pass_thru_directive (udirective, &udirective[strlen (directive)],
                           outp, dp);
+#endif
 
       sprintf (directive, " __DATE__ \"%s %2d %4d\"\n",
               monthnames[timebuf->tm_mon],
@@ -10241,12 +10434,22 @@ make_definition (str)
     while (*p) {
       if (*p == '\"' || *p == '\'') {
        int unterminated = 0;
-       U_CHAR *p1 = skip_quoted_string (p, p + strlen ((char *) p), 0,
+       const U_CHAR *p1 = skip_quoted_string (p, p + strlen ((char *) p), 0,
                                         NULL_PTR, NULL_PTR, &unterminated);
        if (unterminated)
          return;
-       while (p != p1)
-         *q++ = *p++;
+       while (p != p1) {
+         if (*p == '\\' && p[1] == '\n')
+           p += 2;
+         else if (*p == '\n')
+           {
+             *q++ = '\\';
+             *q++ = 'n';
+             p++;
+           }
+         else
+           *q++ = *p++;
+       }
       } else if (*p == '\\' && p[1] == '\n')
        p += 2;
       /* Change newline chars into newline-markers.  */
@@ -10316,8 +10519,8 @@ make_undef (str, op)
 
 static void
 make_assertion (option, str)
-     char *option;
-     char *str;
+     const char *option;
+     const char *str;
 {
   FILE_BUF *ip;
   struct directive *kt;
@@ -10370,10 +10573,6 @@ make_assertion (option, str)
   --indepth;
 }
 \f
-#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
-#endif
-
 /* The previous include prefix, if any, is PREV_FILE_NAME.
    Translate any pathnames with COMPONENT.
    Allocate a new include prefix whose name is the
@@ -10385,9 +10584,9 @@ make_assertion (option, str)
 static struct file_name_list *
 new_include_prefix (prev_file_name, component, prefix, name)
      struct file_name_list *prev_file_name;
-     char *component;
-     char *prefix;
-     char *name;
+     const char *component;
+     const char *prefix;
+     const char *name;
 {
   if (name == 0)
     fatal ("Directory name missing after command line option");
@@ -10512,9 +10711,9 @@ append_include_chain (first, last)
 static int
 quote_string_for_make (dst, src)
      char *dst;
-     char *src;
+     const char *src;
 {
-  char *p = src;
+  const char *p = src;
   int i = 0;
   for (;;)
     {
@@ -10531,7 +10730,7 @@ quote_string_for_make (dst, src)
               preceded by 2N backslashes represents N backslashes at
               the end of a file name; and backslashes in other
               contexts should not be doubled.  */
-           char *q;
+           const char *q;
            for (q = p - 1; src < q && q[-1] == '\\';  q--)
              {
                if (dst)
@@ -10574,7 +10773,7 @@ quote_string_for_make (dst, src)
 
 static void
 deps_output (string, spacer)
-     char *string;
+     const char *string;
      int spacer;
 {
   int size = quote_string_for_make ((char *) 0, string);
@@ -10612,22 +10811,21 @@ deps_output (string, spacer)
   deps_buffer[deps_size] = 0;
 }
 \f
-static void
-fatal VPROTO ((char * msg, ...))
+void
+fatal VPARAMS ((const char * msgid, ...))
 {
-#ifndef __STDC__
-  char * msg;
+#ifndef ANSI_PROTOTYPES
+  const char * msgid;
 #endif
   va_list args;
 
   fprintf (stderr, "%s: ", progname);
-  VA_START (args, msg);
-#ifndef __STDC__
-  msg = va_arg (args, char *);
+  VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (args, const char *);
 #endif
-  vfprintf (stderr, msg, args);
+  vnotice (msgid, args);
   va_end (args);
   fprintf (stderr, "\n");
   exit (FATAL_EXIT_CODE);
@@ -10644,15 +10842,15 @@ fancy_abort ()
 
 static void
 perror_with_name (name)
-     char *name;
+     const char *name;
 {
-  fprintf (stderr, "%s: %s: %s\n", progname, name, my_strerror (errno));
+  fprintf (stderr, "%s: %s: %s\n", progname, name, xstrerror (errno));
   errors++;
 }
 
 static void
 pfatal_with_name (name)
-     char *name;
+     const char *name;
 {
   perror_with_name (name);
 #ifdef VMS
@@ -10677,50 +10875,6 @@ memory_full ()
 {
   fatal ("Memory exhausted.");
 }
-
-
-GENERIC_PTR
-xmalloc (size)
-     size_t size;
-{
-  register GENERIC_PTR ptr = (GENERIC_PTR) malloc (size);
-  if (!ptr)
-    memory_full ();
-  return ptr;
-}
-
-static GENERIC_PTR
-xrealloc (old, size)
-     GENERIC_PTR old;
-     size_t size;
-{
-  register GENERIC_PTR ptr = (GENERIC_PTR) realloc (old, size);
-  if (!ptr)
-    memory_full ();
-  return ptr;
-}
-
-static GENERIC_PTR
-xcalloc (number, size)
-     size_t number, size;
-{
-  register size_t total = number * size;
-  register GENERIC_PTR ptr = (GENERIC_PTR) malloc (total);
-  if (!ptr)
-    memory_full ();
-  bzero (ptr, total);
-  return ptr;
-}
-
-static char *
-savestring (input)
-     char *input;
-{
-  size_t size = strlen (input);
-  char *output = xmalloc (size + 1);
-  strcpy (output, input);
-  return output;
-}
 \f
 #ifdef VMS
 
@@ -11135,4 +11289,25 @@ VMS_stat (name, statbuf)
 
   return result;
 }
+
+static size_t
+VMS_fwrite (ptr, size, nitems, stream)
+     void const *ptr;
+     size_t size;
+     size_t nitems;
+     FILE *stream;
+{
+  /* VMS fwrite has undesirable results
+     if STREAM happens to be a record oriented file.
+     Work around this problem by writing each character individually.  */
+  char const *p = ptr;
+  size_t bytes = size * nitems;
+  char *lim = p + bytes;
+
+  while (p < lim)
+    if (putc (*p++, stream) == EOF)
+      return 0;
+
+  return bytes;
+}
 #endif /* VMS */