gansidecl.h: Prepend a "G" to the macro wrapping this file (to distinguish it from...
[platform/upstream/gcc.git] / gcc / cccp.c
index 2a92acb..e3568da 100644 (file)
@@ -1,5 +1,5 @@
 /* C Compatible Compiler Preprocessor (CCCP)
-   Copyright (C) 1986, 87, 89, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc.
    Written by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
 
@@ -16,212 +16,59 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+Boston, MA 02111-1307, USA. */
 
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them.   Help stamp out software-hoarding!  */
-\f
-typedef unsigned char U_CHAR;
-
-#ifdef EMACS
-#define NO_SHORTNAMES
-#include "../src/config.h"
-#ifdef open
-#undef open
-#undef read
-#undef write
-#endif /* open */
-#endif /* EMACS */
-
-/* The macro EMACS is defined when cpp is distributed as part of Emacs,
-   for the sake of machines with limited C compilers.  */
-#ifndef EMACS
 #include "config.h"
-#endif /* not EMACS */
-
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
-#endif
-
-#include "pcp.h"
 
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
+#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)
 
-/* By default, the suffix for object files is ".o".  */
-#ifdef OBJECT_SUFFIX
-#define HAVE_OBJECT_SUFFIX
-#else
-#define OBJECT_SUFFIX ".o"
-#endif
+#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 <sys/types.h>
+#include "system.h"
 #include <sys/stat.h>
-#include <ctype.h>
-#include <stdio.h>
 #include <signal.h>
 
-/* The following symbols should be autoconfigured:
-       HAVE_FCNTL_H
-       HAVE_SYS_TIME_H
-       STDC_HEADERS
-       TIME_WITH_SYS_TIME
-   In the mean time, we'll get by with approximations based
-   on existing GCC configuration symbols.  */
-
-#ifdef POSIX
-# ifndef STDC_HEADERS
-# define STDC_HEADERS 1
-# endif
-#endif /* defined (POSIX) */
-
-#if defined (POSIX) || (defined (USG) && !defined (VMS))
-# ifndef HAVE_FCNTL_H
-# define HAVE_FCNTL_H 1
-# endif
-#endif
-
-#ifndef RLIMIT_STACK
-# include <time.h>
-#else
-# if TIME_WITH_SYS_TIME
-#  include <sys/time.h>
-#  include <time.h>
-# else
-#  if HAVE_SYS_TIME_H
-#   include <sys/time.h>
-#  else
-#   include <time.h>
-#  endif
-# endif
+#ifdef HAVE_SYS_RESOURCE_H
 # include <sys/resource.h>
 #endif
 
-#if HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
+typedef unsigned char U_CHAR;
 
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
+#include "pcp.h"
 
-#include <errno.h>
+#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
+#include <locale.h>
+#endif /* MULTIBYTE_CHARS */
 
-#if HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *getenv ();
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
 #endif
 
-#if STDC_HEADERS
-# include <string.h>
-# ifndef bcmp
-# define bcmp(a, b, n) memcmp (a, b, n)
-# endif
-# ifndef bcopy
-# define bcopy(s, d, n) memcpy (d, s, n)
-# endif
-# ifndef bzero
-# define bzero(d, n) memset (d, 0, n)
-# endif
-#else /* !STDC_HEADERS */
-char *index ();
-char *rindex ();
-
-# if !defined (BSTRING) && (defined (USG) || defined (VMS))
-
-#  ifndef bcmp
-#  define bcmp my_bcmp
-static int
-my_bcmp (a, b, n)
-     register char *a;
-     register char *b;
-     register unsigned n;
-{
-   while (n-- > 0)
-     if (*a++ != *b++)
-       return 1;
-
-   return 0;
-}
-#  endif /* !defined (bcmp) */
-
-#  ifndef bcopy
-#  define bcopy my_bcopy
-static void
-my_bcopy (s, d, n)
-     register char *s;
-     register char *d;
-     register unsigned n;
-{
-  while (n-- > 0)
-    *d++ = *s++;
-}
-#  endif /* !defined (bcopy) */
-
-#  ifndef bzero
-#  define bzero my_bzero
-static void
-my_bzero (b, length)
-     register char *b;
-     register unsigned length;
-{
-  while (length-- > 0)
-    *b++ = 0;
-}
-#  endif /* !defined (bzero) */
-
-# endif /* !defined (BSTRING) && (defined (USG) || defined (VMS)) */
-#endif /* ! STDC_HEADERS */
-
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-# define __attribute__(x)
+#ifndef STANDARD_INCLUDE_DIR
+# define STANDARD_INCLUDE_DIR "/usr/include"
 #endif
 
-#ifndef PROTO
-# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#  define PROTO(ARGS) ARGS
-# else
-#  define PROTO(ARGS) ()
-# endif
+/* By default, colon separates directories in a path.  */
+#ifndef PATH_SEPARATOR
+# define PATH_SEPARATOR ':'
 #endif
 
-#if defined (__STDC__) && defined (HAVE_VPRINTF)
-# include <stdarg.h>
-# define VA_START(va_list, var) va_start (va_list, var)
-# define PRINTF_ALIST(msg) char *msg, ...
-# define PRINTF_DCL(msg)
-# define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (__printf__, m, n)))
+/* By default, the suffix for object files is ".o".  */
+#ifdef OBJECT_SUFFIX
+# define HAVE_OBJECT_SUFFIX
 #else
-# include <varargs.h>
-# define VA_START(va_list, var) va_start (va_list)
-# define PRINTF_ALIST(msg) msg, va_alist
-# define PRINTF_DCL(msg) char *msg; va_dcl
-# define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (__printf__, m, n)))
-# define vfprintf(file, msg, args) \
-    { \
-      char *a0 = va_arg(args, char *); \
-      char *a1 = va_arg(args, char *); \
-      char *a2 = va_arg(args, char *); \
-      char *a3 = va_arg(args, char *); \
-      fprintf (file, msg, a0, a1, a2, a3); \
-    }
-#endif
-
-#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)
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
+# define OBJECT_SUFFIX ".o"
 #endif
 
 /* VMS-specific definitions */
 #ifdef VMS
 #include <descrip.h>
+#include <ssdef.h>
+#include <syidef.h>
 #define open(fname,mode,prot)  VMS_open (fname,mode,prot)
 #define fopen(fname,mode)      VMS_fopen (fname,mode)
 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
@@ -230,7 +77,7 @@ static int VMS_fstat (), VMS_stat ();
 static int VMS_open ();
 static FILE *VMS_fopen ();
 static FILE *VMS_freopen ();
-static void hack_vms_include_specification ();
+static int 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 */
@@ -241,10 +88,6 @@ static void hack_vms_include_specification ();
 #define INO_T_EQ(a, b) 0
 #endif
 
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
 #undef MIN
 #undef MAX
 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
@@ -258,12 +101,10 @@ static void hack_vms_include_specification ();
 #  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)
+#  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))
+#  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
@@ -288,24 +129,6 @@ static void hack_vms_include_specification ();
 #define INO_T_HASH(a) (a)
 #endif
 
-/* Define a generic NULL if one hasn't already been defined.  */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef GENERIC_PTR
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define GENERIC_PTR void *
-#else
-#define GENERIC_PTR char *
-#endif
-#endif
-
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR) 0)
-#endif
-
 #ifndef INCLUDE_LEN_FUDGE
 #define INCLUDE_LEN_FUDGE 0
 #endif
@@ -314,22 +137,8 @@ static void hack_vms_include_specification ();
 
 extern char *version_string;
 extern char *update_path PROTO((char *, char *));
-#ifndef VMS
-#ifndef HAVE_STRERROR
-extern int sys_nerr;
-extern char *sys_errlist[];
-#else  /* HAVE_STRERROR */
-char *strerror ();
-#endif
-#else  /* VMS */
-char *strerror (int,...);
-#endif
 HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
-HOST_WIDE_INT parse_c_expression PROTO((char *));
-
-#ifndef errno
-extern int errno;
-#endif
+HOST_WIDE_INT parse_c_expression PROTO((char *, int));
 \f
 /* Name under which this program was invoked.  */
 
@@ -412,7 +221,7 @@ static enum {dump_none, dump_only, dump_names, dump_definitions}
 static int debug_output = 0;
 
 /* Nonzero means pass #include lines through to the output,
-   even if they are ifdeffed out.  */
+   even if they are ifdefed out.  */
 static int dump_includes;
 
 /* Nonzero indicates special processing used by the pcp program.  The
@@ -466,7 +275,7 @@ static int warn_trigraphs;
 
 /* Nonzero means warn if undefined identifiers are evaluated in an #if.  */
 
-int warn_undef;
+static int warn_undef;
 
 /* Nonzero means warn if #import is used.  */
 
@@ -490,6 +299,9 @@ int c89;
 
 static int no_output;
 
+/* Nonzero means we should look for header.gcc files that remap file names.  */
+static int remap;
+
 /* Nonzero means this file was included with a -imacros or -include
    command line and should not be recorded as an include file.  */
 
@@ -515,6 +327,8 @@ static struct file_buf {
   char *fname;
   /* Filename specified with #line directive.  */
   char *nominal_fname;
+  /* The length of nominal_fname, which may contain embedded NULs.  */
+  size_t nominal_fname_len;
   /* Include file description.  */
   struct include_file *inc;
   /* Record where in the search path this file was found.
@@ -606,7 +420,6 @@ static struct default_include {
   = {
     /* Pick up GNU C++ specific include files.  */
     { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
-    { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 },
 #ifdef CROSS_COMPILE
     /* This is the dir for fixincludes.  Put it just before
        the files that we fix.  */
@@ -753,6 +566,7 @@ struct definition {
   U_CHAR *expansion;
   int line;                    /* Line number of definition */
   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 {
     struct reflist *next;
@@ -912,6 +726,8 @@ char * wchar_type = WCHAR_TYPE;
 #ifndef USER_LABEL_PREFIX
 #define USER_LABEL_PREFIX ""
 #endif
+char * user_label_prefix = USER_LABEL_PREFIX;
+#undef USER_LABEL_PREFIX
 
 /* The string value for __REGISTER_PREFIX__ */
 
@@ -975,7 +791,8 @@ struct directive {
   enum node_type type;         /* Code which describes which directive.  */
 };
 
-#define IS_INCLUDE_DIRECTIVE_TYPE(t) (T_INCLUDE <= (t) && (t) <= T_IMPORT)
+#define IS_INCLUDE_DIRECTIVE_TYPE(t) \
+((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT)
 
 /* These functions are declared to return int instead of void since they
    are going to be placed in the table and some old compilers have trouble with
@@ -1057,6 +874,7 @@ static char *out_fname;
 struct if_stack {
   struct if_stack *next;       /* for chaining to the next stack frame */
   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 */
@@ -1085,6 +903,7 @@ 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));
 
 int main PROTO((int, char **));
 
@@ -1124,7 +943,7 @@ static void record_control_macro PROTO((struct include_file *, 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 *, U_CHAR *, FILE_BUF *));
+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 *));
@@ -1156,7 +975,7 @@ static void validate_else PROTO((U_CHAR *, 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 *));
+static char *quote_string PROTO((char *, char *, size_t));
 static U_CHAR *skip_paren_group PROTO((FILE_BUF *));
 
 /* Last arg to output_line_directive.  */
@@ -1168,13 +987,13 @@ static void macroexpand PROTO((HASHNODE *, FILE_BUF *));
 struct argdata;
 static char *macarg PROTO((struct argdata *, int));
 
-static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, int *, int *, int *, int));
+static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int));
 
 static int discard_comments PROTO((U_CHAR *, int, int));
 
 static int change_newlines PROTO((U_CHAR *, int));
 
-char *my_strerror PROTO((int));
+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 *));
@@ -1186,7 +1005,7 @@ 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_3((char *, int, char *, ...));
+static void pedwarn_with_file_and_line PRINTF_PROTO_4((char *, size_t, int, char *, ...));
 
 static void print_containing_files PROTO((void));
 
@@ -1206,7 +1025,7 @@ static void dump_arg_n PROTO((DEFINITION *, int, FILE *));
 static void initialize_char_syntax PROTO((void));
 static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *));
 
-static void make_definition PROTO((char *, FILE_BUF *));
+static void make_definition PROTO((char *));
 static void make_undef PROTO((char *, FILE_BUF *));
 
 static void make_assertion PROTO((char *, char *));
@@ -1214,6 +1033,7 @@ static void make_assertion PROTO((char *, 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 int quote_string_for_make PROTO((char *, char *));
 static void deps_output PROTO((char *, int));
 
 static void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn));
@@ -1227,6 +1047,7 @@ 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));
 \f
 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
    retrying if necessary.  If MAX_READ_LEN is defined, read at most
@@ -1297,6 +1118,101 @@ safe_write (desc, ptr, len)
     len -= written;
   }
 }
+
+/* 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 ()
+{
+  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 ("  -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");
+  printf ("  -isystem <dir>            Add <dir> to the start of the system include paths\n");
+  printf ("  -idirafter <dir>          Add <dir> to the end of the system include paths\n");
+  printf ("  -I <dir>                  Add <dir> to the end of the main include paths\n");
+  printf ("  -nostdinc                 Do not search the system include directories\n");
+  printf ("  -nostdinc++               Do not search the system include directories for C++\n");
+  printf ("  -o <file>                 Put output into <file>\n");
+  printf ("  -pedantic                 Issue all warnings demanded by strict ANSI C\n");
+  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-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-chill               Assume that the input sources are in Chill\n");
+  printf ("  -+                        Allow parsing of C++ style features\n");
+  printf ("  -w                        Inhibit warning messages\n");
+  printf ("  -Wtrigraphs               Warn if trigraphs are encountered\n");
+  printf ("  -Wno-trigraphs            Do not warn about trigraphs\n");
+  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 ("  -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 ("  -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");
+  printf ("  -Wno-error                Do not treat warnings as errors\n");
+  printf ("  -Wall                     Enable all preprocessor warnings\n");
+  printf ("  -M                        Generate make dependencies\n");
+  printf ("  -MM                       As -M, but ignore system header files\n");
+  printf ("  -MD                       As -M, but put output in a .d file\n");
+  printf ("  -MMD                      As -MD, but ignore system header files\n");
+  printf ("  -MG                       Treat missing header file as generated files\n");
+  printf ("  -g                        Include #define and #undef directives in the output\n");
+  printf ("  -D<macro>                 Define a <macro> with string '1' as its value\n");
+  printf ("  -D<macro>=<val>           Define a <macro> with <val> as its value\n");
+  printf ("  -A<question> (<answer>)   Assert the <answer> to <question>\n");
+  printf ("  -U<macro>                 Undefine <macro> \n");
+  printf ("  -u or -undef              Do not predefine any macros\n");
+  printf ("  -v                        Display the version number\n");
+  printf ("  -H                        Print the name of header files as they are used\n");
+  printf ("  -C                        Do not discard comments\n");
+  printf ("  -dM                       Display a list of macro definitions active at end\n");
+  printf ("  -dD                       Preserve macro definitions in output\n");
+  printf ("  -dN                       As -dD except that only the names are preserved\n");
+  printf ("  -dI                       Include #include directives in the output\n");
+  printf ("  -ifoutput                 Describe skipped code blocks in output \n");
+  printf ("  -P                        Do not generate #line directives\n");
+  printf ("  -$                        Do not include '$' in identifiers\n");
+  printf ("  -remap                    Remap file names when including files.\n");
+  printf ("  -h or --help              Display this information\n");
+}
 \f
 int
 main (argc, argv)
@@ -1338,7 +1254,7 @@ main (argc, argv)
   /* Target-name to write with the dependency information.  */
   char *deps_target = 0;
 
-#ifdef RLIMIT_STACK
+#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
   /* Get rid of any avoidable limit on stack size.  */
   {
     struct rlimit rlim;
@@ -1349,7 +1265,7 @@ main (argc, argv)
     rlim.rlim_cur = rlim.rlim_max;
     setrlimit (RLIMIT_STACK, &rlim);
   }
-#endif /* RLIMIT_STACK defined */
+#endif
 
 #ifdef SIGPIPE
   signal (SIGPIPE, pipe_closed);
@@ -1392,12 +1308,21 @@ main (argc, argv)
   bzero ((char *) pend_assertions, argc * sizeof (char *));
   bzero ((char *) pend_includes, argc * sizeof (char *));
 
+#ifdef MULTIBYTE_CHARS
+  /* Change to the native locale for multibyte conversions.  */
+  setlocale (LC_CTYPE, "");
+  literal_codeset = getenv ("LANG");
+#endif
+
   /* Process switches and find input file name.  */
 
   for (i = 1; i < argc; i++) {
     if (argv[i][0] != '-') {
       if (out_fname != NULL)
-       fatal ("Usage: %s [switches] input output", argv[0]);
+       {
+         print_help ();
+         fatal ("Too many arguments");
+       }
       else if (in_fname != NULL)
        out_fname = argv[i];
       else
@@ -1407,16 +1332,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[i] = argv[++i]);
+           simplify_filename (pend_includes[temp] = 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[i] = argv[++i]);
+           simplify_filename (pend_files[temp] = argv[++i]);
        }
        if (!strcmp (argv[i], "-iprefix")) {
          if (i + 1 == argc)
@@ -1601,6 +1530,13 @@ main (argc, argv)
          }
        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
@@ -1673,6 +1609,13 @@ main (argc, argv)
          debug_output = 1;
        break;
 
+      case '-':
+       if (strcmp (argv[i], "--help") != 0)
+         return i;
+       print_help ();
+       exit (0);
+       break;
+
       case 'v':
        fprintf (stderr, "GNU CPP version %s", version_string);
 #ifdef TARGET_VERSION
@@ -1775,6 +1718,11 @@ main (argc, argv)
          no_precomp = 1;
        break;
 
+      case 'r':
+       if (!strcmp (argv[i], "-remap"))
+         remap = 1;
+       break;
+
       case 'u':
        /* Sun compiler passes undocumented switch "-undef".
           Let's assume it means to inhibit the predefined symbols.  */
@@ -1802,7 +1750,7 @@ main (argc, argv)
   /* Some people say that CPATH should replace the standard include dirs,
      but that seems pointless: it comes before them, so it overrides them
      anyway.  */
-  cp = getenv ("CPATH");
+  GET_ENV_PATH_LIST (cp, "CPATH");
   if (cp && ! no_standard_includes)
     path_include (cp);
 
@@ -1819,6 +1767,7 @@ main (argc, argv)
   if (in_fname == NULL)
     in_fname = "";
   fp->nominal_fname = fp->fname = in_fname;
+  fp->nominal_fname_len = strlen (in_fname);
   fp->lineno = 0;
 
   /* In C++, wchar_t is a distinct basic type, and we can expect
@@ -1835,6 +1784,63 @@ main (argc, argv)
 
   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;
@@ -1849,7 +1855,7 @@ main (argc, argv)
          *p++= 0;
        if (debug_output)
          output_line_directive (fp, &outbuf, 0, same_file);
-       make_definition (q, &outbuf);
+       make_definition (q);
        while (*p == ' ' || *p == '\t')
          p++;
       } else if (p[0] == '-' && p[1] == 'A') {
@@ -1914,7 +1920,7 @@ main (argc, argv)
     if (pend_defs[i]) {
       if (debug_output)
         output_line_directive (fp, &outbuf, 0, same_file);
-      make_definition (pend_defs[i], &outbuf);
+      make_definition (pend_defs[i]);
     }
     if (pend_assertions[i])
       make_assertion (pend_assertion_options[i], pend_assertions[i]);
@@ -1928,16 +1934,16 @@ main (argc, argv)
     switch ((objc << 1) + cplusplus)
       {
       case 0:
-       epath = getenv ("C_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
        break;
       case 1:
-       epath = getenv ("CPLUS_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
        break;
       case 2:
-       epath = getenv ("OBJC_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
        break;
       case 3:
-       epath = getenv ("OBJCPLUS_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
        break;
       }
     /* If the environment var for this language is set,
@@ -2183,6 +2189,7 @@ main (argc, argv)
   if (fstat (f, &st) != 0)
     pfatal_with_name (in_fname);
   fp->nominal_fname = fp->fname = in_fname;
+  fp->nominal_fname_len = strlen (in_fname);
   fp->lineno = 1;
   fp->system_header_p = 0;
   /* JF all this is mine about reading pipes and ttys */
@@ -2212,8 +2219,11 @@ main (argc, argv)
   } else {
     /* Read a file whose size we can determine in advance.
        For the sake of VMS, st.st_size is just an upper bound.  */
-    fp->buf = (U_CHAR *) xmalloc (st.st_size + 2);
-    fp->length = safe_read (f, (char *) fp->buf, st.st_size);
+    size_t s = (size_t) st.st_size;
+    if (s != st.st_size || s + 2 < s)
+      memory_full ();
+    fp->buf = (U_CHAR *) xmalloc (s + 2);
+    fp->length = safe_read (f, (char *) fp->buf, s);
     if (fp->length < 0) goto perror;
   }
   fp->bufp = fp->buf;
@@ -2558,10 +2568,10 @@ get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
   if ((linsize >= 7) && !bcmp (ibp, "VARARGS", 7)) {
     *cmdlen = 7;
     ibp += 7; linsize -= 7;
-    if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS";
+    if ((linsize == 0) || ! ISDIGIT (*ibp)) return "VARARGS";
 
     /* OK, read a number */
-    for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr);
+    for (numptr = *argstart = ibp; (numptr < limit) && ISDIGIT (*numptr);
         numptr++);
     *arglen = numptr - *argstart;
     return "VARARGS";
@@ -2777,9 +2787,27 @@ do { ip = &instack[indepth];             \
              bp += 2;
            else if (*bp == '/' && bp[1] == '*') {
              bp += 2;
-             while (!(*bp == '*' && bp[1] == '/'))
-               bp++;
-             bp += 2;
+             while (1)
+               {
+                 if (*bp == '*')
+                   {
+                     if (bp[1] == '/')
+                       {
+                         bp += 2;
+                         break;
+                       }
+                   }
+                 else
+                   {
+#ifdef MULTIBYTE_CHARS
+                     int length;
+                     length = local_mblen (bp, limit - bp);
+                     if (length > 1)
+                       bp += (length - 1);
+#endif
+                   }
+                 bp++;
+               }
            }
            /* There is no point in trying to deal with C++ // comments here,
               because if there is one, then this # must be part of the
@@ -2855,9 +2883,11 @@ do { ip = &instack[indepth];             \
 
       /* Handle any pending identifier;
         but the L in L'...' or L"..." is not an identifier.  */
-      if (ident_length
-         && ! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
-       goto specialchar;
+      if (ident_length) {
+       if (! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
+         goto specialchar;
+       ident_length = hash = 0;
+      }
 
       start_line = ip->lineno;
 
@@ -2876,9 +2906,11 @@ do { ip = &instack[indepth];             \
          if (!traditional) {
            error_with_line (line_for_error (start_line),
                             "unterminated string or character constant");
-           error_with_line (multiline_string_line,
-                            "possible real start of unterminated constant");
-           multiline_string_line = 0;
+           if (multiline_string_line) {
+             error_with_line (multiline_string_line,
+                              "possible real start of unterminated constant");
+             multiline_string_line = 0;
+           }
          }
          break;
        }
@@ -2907,20 +2939,25 @@ do { ip = &instack[indepth];            \
          break;
 
        case '\\':
-         if (ibp >= limit)
-           break;
          if (*ibp == '\n') {
-           /* Backslash newline is replaced by nothing at all,
-              but keep the line counts correct.  */
-           --obp;
+           /* Backslash newline is replaced by nothing at all, but
+              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)
+             *obp++ = '\n';
+           else
+             --obp;
            ++ibp;
            ++ip->lineno;
          } else {
            /* ANSI stupidly requires that in \\ the second \
               is *not* prevented from combining with a newline.  */
-           while (*ibp == '\\' && ibp[1] == '\n') {
-             ibp += 2;
-             ++ip->lineno;
+           if (!ip->macro) {
+             while (*ibp == '\\' && ibp[1] == '\n') {
+               ibp += 2;
+               ++ip->lineno;
+             }
            }
            *obp++ = *ibp++;
          }
@@ -2931,20 +2968,37 @@ do { ip = &instack[indepth];            \
          if (ibp[-1] == c)
            goto while2end;
          break;
+#ifdef MULTIBYTE_CHARS
+       default:
+         {
+           int length;
+           --ibp;
+           length = local_mblen (ibp, limit - ibp);
+           if (length > 0)
+             {
+               --obp;
+               bcopy (ibp, obp, length);
+               obp += length;
+               ibp += length;
+             }
+           else
+             ++ibp;
+         }
+         break;
+#endif
        }
       }
     while2end:
       break;
 
     case '/':
+      if (ip->macro != 0)
+       goto randomchar;
       if (*ibp == '\\' && ibp[1] == '\n')
        newline_fix (ibp);
-
       if (*ibp != '*'
          && !(cplusplus_comments && *ibp == '/'))
        goto randomchar;
-      if (ip->macro != 0)
-       goto randomchar;
       if (ident_length)
        goto specialchar;
 
@@ -2960,24 +3014,39 @@ do { ip = &instack[indepth];            \
          U_CHAR *before_bp = ibp;
 
          while (++ibp < limit) {
-           if (*ibp == '\n') {
-             if (ibp[-1] != '\\') {
+           if (*ibp == '\n')
+             {
                if (put_out_comments) {
                  bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
                  obp += ibp - before_bp;
                }
                break;
              }
-             if (warn_comments)
-               warning ("multiline `//' comment");
-             ++ip->lineno;
-             /* Copy the newline into the output buffer, in order to
-                avoid the pain of a #line every time a multiline comment
-                is seen.  */
-             if (!put_out_comments)
-               *obp++ = '\n';
-             ++op->lineno;
-           }
+           if (*ibp == '\\')
+             {
+               if (ibp + 1 < limit && ibp[1] == '\n')
+                 {
+                   if (warn_comments)
+                     warning ("multiline `//' comment");
+                   ++ip->lineno;
+                   /* Copy the newline into the output buffer, in order to
+                      avoid the pain of a #line every time a multiline comment
+                      is seen.  */
+                   if (!put_out_comments)
+                     *obp++ = '\n';
+                   ++op->lineno;
+                   ++ibp;
+                 }
+             }
+           else
+             {
+#ifdef MULTIBYTE_CHARS
+               int length;
+               length = local_mblen (ibp, limit - ibp);
+               if (length > 1)
+                 ibp += (length - 1);
+#endif
+             }
          }
          break;
        }
@@ -3066,6 +3135,16 @@ do { ip = &instack[indepth];             \
              goto limit_reached;
            }
            break;
+#ifdef MULTIBYTE_CHARS
+         default:
+           {
+             int length;
+             length = local_mblen (ibp, limit - ibp);
+             if (length > 1)
+               ibp += (length - 1);
+           }
+           break;
+#endif
          }
        }
       comment_end:
@@ -3095,9 +3174,11 @@ do { ip = &instack[indepth];             \
 
       if (ident_length == 0) {
        for (;;) {
-         while (ibp[0] == '\\' && ibp[1] == '\n') {
-           ++ip->lineno;
-           ibp += 2;
+         if (!ip->macro) {
+           while (ibp[0] == '\\' && ibp[1] == '\n') {
+             ++ip->lineno;
+             ibp += 2;
+           }
          }
          c = *ibp++;
          if (!is_idchar[c] && c != '.') {
@@ -3108,9 +3189,11 @@ do { ip = &instack[indepth];             \
          /* A sign can be part of a preprocessing number
             if it follows an `e' or `p'.  */
          if (c == 'e' || c == 'E' || c == 'p' || c == 'P') {
-           while (ibp[0] == '\\' && ibp[1] == '\n') {
-             ++ip->lineno;
-             ibp += 2;
+           if (!ip->macro) {
+             while (ibp[0] == '\\' && ibp[1] == '\n') {
+               ++ip->lineno;
+               ibp += 2;
+             }
            }
            if (*ibp == '+' || *ibp == '-') {
              *obp++ = *ibp++;
@@ -3370,35 +3453,6 @@ randomchar:
                      old_iln = ip->lineno;
                      old_oln = op->lineno;
                    }
-                   /* A comment: copy it unchanged or discard it.  */
-                   else if (*ibp == '/' && ibp[1] == '*') {
-                     if (put_out_comments) {
-                       *obp++ = '/';
-                       *obp++ = '*';
-                     } else if (! traditional) {
-                       *obp++ = ' ';
-                     }
-                     ibp += 2;
-                     while (ibp + 1 != limit
-                            && !(ibp[0] == '*' && ibp[1] == '/')) {
-                       /* We need not worry about newline-marks,
-                          since they are never found in comments.  */
-                       if (*ibp == '\n') {
-                         /* Newline in a file.  Count it.  */
-                         ++ip->lineno;
-                         ++op->lineno;
-                       }
-                       if (put_out_comments)
-                         *obp++ = *ibp++;
-                       else
-                         ibp++;
-                     }
-                     ibp += 2;
-                     if (put_out_comments) {
-                       *obp++ = '*';
-                       *obp++ = '/';
-                     }
-                   }
                    else if (is_space[*ibp]) {
                      *obp++ = *ibp++;
                      if (ibp[-1] == '\n') {
@@ -3425,6 +3479,100 @@ randomchar:
                        }
                      }
                    }
+                   else if (ip->macro)
+                     break;
+                   else if (*ibp == '/') {
+                     /* If a comment, copy it unchanged or discard it.  */
+                     if (ibp[1] == '\\' && ibp[2] == '\n')
+                       newline_fix (ibp + 1);
+                     if (ibp[1] == '*') {
+                       if (put_out_comments) {
+                         *obp++ = '/';
+                         *obp++ = '*';
+                       } else if (! traditional) {
+                         *obp++ = ' ';
+                       }
+                       for (ibp += 2; ibp < limit; ibp++) {
+                         /* We need not worry about newline-marks,
+                            since they are never found in comments.  */
+                         if (ibp[0] == '*') {
+                           if (ibp[1] == '\\' && ibp[2] == '\n')
+                             newline_fix (ibp + 1);
+                           if (ibp[1] == '/') {
+                             ibp += 2;
+                             if (put_out_comments) {
+                               *obp++ = '*';
+                               *obp++ = '/';
+                             }
+                             break;
+                           }
+                         }
+                         else if (*ibp == '\n') {
+                           /* Newline in a file.  Count it.  */
+                           ++ip->lineno;
+                           ++op->lineno;
+                         }
+                         else
+                           {
+#ifdef MULTIBYTE_CHARS
+                             int length;
+                             length = local_mblen (ibp, limit - ibp);
+                             if (length > 1)
+                               {
+                                 if (put_out_comments)
+                                   {
+                                     bcopy (ibp, obp, length - 1);
+                                     obp += length - 1;
+                                   }
+                                 ibp += (length - 1);
+                               }
+#endif
+                           }
+                         if (put_out_comments)
+                           *obp++ = *ibp;
+                       }
+                     } else if (ibp[1] == '/' && cplusplus_comments) {
+                       if (put_out_comments) {
+                         *obp++ = '/';
+                         *obp++ = '/';
+                       } else if (! traditional) {
+                         *obp++ = ' ';
+                       }
+                       for (ibp += 2; ; ibp++)
+                         {
+                           if (*ibp == '\n')
+                             break;
+                           if (*ibp == '\\' && ibp[1] == '\n')
+                             {
+                               if (put_out_comments)
+                                 *obp++ = *ibp++;
+                             }
+                           else
+                             {
+#ifdef MULTIBYTE_CHARS
+                               int length;
+                               length = local_mblen (ibp, limit - ibp);
+                               if (length > 1)
+                                 {
+                                   if (put_out_comments)
+                                     {
+                                       bcopy (ibp, obp, length - 1);
+                                       obp += length - 1;
+                                     }
+                                   ibp += (length - 1);
+                                 }
+#endif
+                             }
+                           if (put_out_comments)
+                             *obp++ = *ibp;
+                         }
+                     } else
+                       break;
+                   }
+                   else if (ibp[0] == '\\' && ibp[1] == '\n') {
+                     ibp += 2;
+                     ++ip->lineno;
+                   }
                    else break;
                  }
                  if (*ibp != '(') {
@@ -3585,6 +3733,7 @@ expand_to_temp_buffer (buf, limit, output_marks, assertions)
   ip = &instack[indepth];
   ip->fname = 0;
   ip->nominal_fname = 0;
+  ip->nominal_fname_len = 0;
   ip->inc = 0;
   ip->system_header_p = 0;
   ip->macro = 0;
@@ -3651,8 +3800,11 @@ handle_directive (ip, op)
       if (*bp != ' ' && *bp != '\t' && pedantic)
        pedwarn ("%s in preprocessing directive", char_name[*bp]);
       bp++;
-    } else if (*bp == '/' && (bp[1] == '*'
-                             || (cplusplus_comments && bp[1] == '/'))) {
+    } else if (*bp == '/') {
+      if (bp[1] == '\\' && bp[2] == '\n')
+       newline_fix (bp + 1);
+      if (! (bp[1] == '*' || (cplusplus_comments && bp[1] == '/')))
+       break;
       ip->bufp = bp + 2;
       skip_to_end_of_comment (ip, &ip->lineno, 0);
       bp = ip->bufp;
@@ -3770,8 +3922,25 @@ handle_directive (ip, op)
          }
          break;
 
+       case '"':
+         /* "..." is special for #include.  */
+         if (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) {
+           while (bp < limit && *bp != '\n') {
+             if (*bp == '"') {
+               bp++;
+               break;
+             }
+             if (*bp == '\\' && bp[1] == '\n') {
+               ip->lineno++;
+               copy_directive = 1;
+               bp++;
+             }
+             bp++;
+           }
+           break;
+         }
+         /* Fall through.  */
        case '\'':
-       case '\"':
          bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, &copy_directive, &unterminated);
          /* Don't bother calling the directive if we already got an error
             message due to unterminated string.  Skip everything and pretend
@@ -3937,13 +4106,7 @@ handle_directive (ip, op)
                = skip_quoted_string (xp - 1, bp, ip->lineno,
                                      NULL_PTR, NULL_PTR, NULL_PTR);
              while (xp != bp1)
-               if (*xp == '\\') {
-                 if (*++xp != '\n')
-                   *cp++ = '\\';
-                 else
-                   xp++;
-               } else
-                 *cp++ = *xp++;
+               *cp++ = *xp++;
            }
            break;
 
@@ -3980,7 +4143,7 @@ handle_directive (ip, op)
         directives through.  */
 
       if (!no_output && already_output == 0
-         && (kt->type == T_DEFINE ? dump_names <= dump_macros
+         && (kt->type == T_DEFINE ? (int) dump_names <= (int) dump_macros
              : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
              : kt->type == T_PRAGMA)) {
         int len;
@@ -4080,16 +4243,14 @@ special_symbol (hp, op)
   case T_FILE:
   case T_BASE_FILE:
     {
-      char *string;
-      if (hp->type == T_FILE)
-       string = ip->nominal_fname;
-      else
-       string = instack[0].nominal_fname;
+      FILE_BUF *p = hp->type == T_FILE ? ip : &instack[0];
+      char *string = p->nominal_fname;
 
       if (string)
        {
-         buf = (char *) alloca (3 + 4 * strlen (string));
-         quote_string (buf, string);
+         size_t string_len = p->nominal_fname_len;
+         buf = (char *) alloca (3 + 4 * string_len);
+         quote_string (buf, string, string_len);
        }
       else
        buf = "\"\"";
@@ -4129,7 +4290,7 @@ special_symbol (hp, op)
     break;
 
   case T_USER_LABEL_PREFIX_TYPE:
-    buf = USER_LABEL_PREFIX;
+    buf = user_label_prefix;
     break;
 
   case T_REGISTER_PREFIX_TYPE:
@@ -4307,10 +4468,15 @@ get_filename:
       FILE_BUF *fp;
       /* Copy the operand text, concatenating the strings.  */
       {
-       while (fin != limit) {
-         while (fin != limit && *fin != '\"')
-           *fend++ = *fin++;
-         fin++;
+       for (;;) {
+         for (;;) {
+           if (fin == limit)
+             goto invalid_include_file_name;
+           *fend = *fin++;
+           if (*fend == '"')
+             break;
+           fend++;
+         }
          if (fin == limit)
            break;
          /* If not at the end, there had better be another string.  */
@@ -4338,11 +4504,22 @@ get_filename:
            /* 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) + strlen (nam)));
+                  alloca (sizeof (struct file_name_list)
+                          + fp->nominal_fname_len));
            strcpy (dsp->fname, nam);
            simplify_filename (dsp->fname);
            nam = base_name (dsp->fname);
            *nam = 0;
+#ifdef VMS
+           /* for hack_vms_include_specification(), a local
+              dir specification must start with "./" on VMS.  */
+           if (nam == dsp->fname)
+             {    
+               *nam++ = '.';
+               *nam++ = '/';
+               *nam = 0;
+             }
+#endif
            /* But for efficiency's sake, do not insert the dir
               if it matches the search list's first dir.  */
            dsp->next = search_start;
@@ -4378,8 +4555,10 @@ get_filename:
      * code from case '<' is repeated here) and generates a warning.
      * (Note: macro expansion of `xyz' takes precedence.)
      */
-    if (retried && isalpha(*(U_CHAR *) (--fbeg))) {
-      while (fin != limit && (!isspace(*fin)))
+    /* Note: The argument of ISALPHA() can be evaluated twice, so do
+       the pre-decrement outside of the macro. */
+    if (retried && (--fin, ISALPHA(*(U_CHAR *) (fin)))) {
+      while (fin != limit && (!ISSPACE(*fin)))
        *fend++ = *fin++;
       warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
       vaxc_include = 1;
@@ -4393,16 +4572,18 @@ get_filename:
 #endif
 
   fail:
-    if (retried) {
-      error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
-      return 0;
-    } else {
+    if (! retried) {
       /* 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;
       trybuf = expand_to_temp_buffer (buf, limit, 1, 0);
+      if (errors != errors_before_expansion) {
+       free (trybuf.buf);
+       goto invalid_include_file_name;
+      }
       src = trybuf.buf;
       buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
       limit = buf;
@@ -4426,9 +4607,13 @@ get_filename:
       }
       *limit = 0;
       free (trybuf.buf);
-      retried++;
+      retried = 1;
       goto get_filename;
     }
+
+  invalid_include_file_name:
+    error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
+    return 0;
   }
 
   /* For #include_next, skip in the search path
@@ -4493,26 +4678,41 @@ get_filename:
          }
       }
 
-      strcpy (fname, searchptr->fname);
-      strcat (fname, fbeg);
 #ifdef VMS
       /* Change this 1/2 Unix 1/2 VMS file specification into a
          full VMS file specification */
-      if (searchptr->fname[0]) {
-       /* Fix up the filename */
-       hack_vms_include_specification (fname, vaxc_include);
-      } else {
-       /* This is a normal VMS filespec, so use it unchanged.  */
-       strcpy (fname, fbeg);
-       /* if it's '#include filename', add the missing .h */
-       if (vaxc_include && index(fname,'.')==NULL) {
-         strcat (fname, ".h");
+      if (searchptr->fname[0])
+       {
+         strcpy (fname, searchptr->fname);
+         if (fname[strlen (fname) - 1] == ':')
+           {
+             char *slashp;
+             slashp = strchr (fbeg, '/');
+
+             /* start at root-dir of logical device if no path given.  */
+             if (slashp == 0)
+               strcat (fname, "[000000]");
+           }
+         strcat (fname, fbeg);
+
+         /* Fix up the filename */
+         hack_vms_include_specification (fname, vaxc_include);
        }
-      }
-#endif /* VMS */
-      f = open_include_file (fname, searchptr, importing, &inc);
-      if (f != -1) {
-       if (bypass_slot && searchptr != first_bracket_include) {
+      else
+       {
+         /* This is a normal VMS filespec, so use it unchanged.  */
+         strcpy (fname, fbeg);
+         /* if it's '#include filename', add the missing .h */
+         if (vaxc_include && index(fname,'.')==NULL)
+           strcat (fname, ".h");
+       }
+#else
+      strcpy (fname, searchptr->fname);
+      strcat (fname, fbeg);
+#endif /* VMS */
+      f = open_include_file (fname, searchptr, importing, &inc);
+      if (f != -1) {
+       if (bypass_slot && searchptr != first_bracket_include) {
          /* This is the first time we found this include file,
             and we found it after first_bracket_include.
             Record its location so that we can bypass to here next time.  */
@@ -4622,8 +4822,7 @@ get_filename:
     if (pcfbuf) {
       pcfname = xmalloc (strlen (pcftry) + 1);
       strcpy (pcfname, pcftry);
-      pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) pcfbuflimit,
-                 (U_CHAR *) fname, op);
+      pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) fname, op);
     }
     else
       finclude (f, inc, op, is_system_include (fname), searchptr);
@@ -4667,7 +4866,7 @@ base_name (fname)
   char *s = fname;
   char *p;
 #if defined (__MSDOS__) || defined (_WIN32)
-  if (isalpha (s[0]) && s[1] == ':') s += 2;
+  if (ISALPHA (s[0]) && s[1] == ':') s += 2;
 #endif
 #ifdef VMS
   if ((p = rindex (s, ':'))) s = p + 1;        /* Skip device.  */
@@ -4690,11 +4889,14 @@ absolute_filename (filename)
      char *filename;
 {
 #if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN32__))
-  if (isalpha (filename[0]) && filename[1] == ':') filename += 2;
+  if (ISALPHA (filename[0]) && filename[1] == ':') filename += 2;
 #endif
 #if defined (__CYGWIN32__)
   /* At present, any path that begins with a drive spec is absolute.  */
-  if (isalpha (filename[0]) && filename[1] == ':') return 1;
+  if (ISALPHA (filename[0]) && filename[1] == ':') return 1;
+#endif
+#ifdef VMS
+  if (index (filename, ':') != 0) return 1;
 #endif
   if (filename[0] == '/') return 1;
 #ifdef DIR_SEPARATOR
@@ -4709,7 +4911,7 @@ absolute_filename (filename)
 
    Do only the simplifications allowed by Posix.
    It is OK to miss simplifications on non-Posix hosts,
-   since this merely leads to suboptimial results.  */
+   since this merely leads to suboptimal results.  */
 
 static size_t
 simplify_filename (filename)
@@ -4745,9 +4947,12 @@ simplify_filename (filename)
   to0 = to;
 
   for (;;) {
+#ifndef VMS
     if (from[0] == '.' && from[1] == '/')
       from += 2;
-    else {
+    else
+#endif
+      {
       /* Copy this component and trailing /, if any.  */
       while ((*to++ = *from++) != '/') {
        if (!to[-1]) {
@@ -4926,7 +5131,7 @@ open_include_file (filename, searchptr, importing, pinc)
      U_CHAR *importing;
      struct include_file **pinc;
 {
-  char *fname = remap_include_file (filename, searchptr);
+  char *fname = remap ? remap_include_file (filename, searchptr) : filename;
   int fd = -2;
 
   /* Look up FNAME in include_hashtab.  */
@@ -4945,7 +5150,16 @@ open_include_file (filename, searchptr, importing, pinc)
     fd = open (fname, O_RDONLY, 0);
 
     if (fd < 0)
-      return fd;
+      {
+#ifdef VMS
+       /* if #include <dir/file> fails, try again with hacked spec.  */
+       if (!hack_vms_include_specification (fname, 0))
+         return fd;
+       fd = open (fname, O_RDONLY, 0);
+       if (fd < 0)
+#endif
+         return fd;
+      }
 
     if (!inc) {
       /* FNAME was not in include_hashtab; insert a new entry.  */
@@ -4985,7 +5199,7 @@ open_include_file (filename, searchptr, importing, pinc)
   return fd;
 }
 
-/* Return the remapped name of the the include file FILENAME.
+/* Return the remapped name of the include file FILENAME.
    SEARCHPTR is the directory being tried from the include file path.  */
 
 static char *
@@ -5082,6 +5296,7 @@ finclude (f, inc, op, system_header_p, dirptr)
   fp = &instack[indepth + 1];
   bzero ((char *) fp, sizeof (FILE_BUF));
   fp->nominal_fname = fp->fname = fname;
+  fp->nominal_fname_len = strlen (fname);
   fp->inc = inc;
   fp->length = 0;
   fp->lineno = 1;
@@ -5090,12 +5305,15 @@ finclude (f, inc, op, system_header_p, dirptr)
   fp->dir = dirptr;
 
   if (S_ISREG (inc->st.st_mode)) {
-    fp->buf = (U_CHAR *) xmalloc (inc->st.st_size + 2);
+    size_t s = (size_t) inc->st.st_size;
+    if (s != inc->st.st_size || s + 2 < s)
+      memory_full ();
+    fp->buf = (U_CHAR *) xmalloc (s + 2);
     fp->bufp = fp->buf;
 
-    /* Read the file contents, knowing that inc->st.st_size is an upper bound
+    /* Read the file contents, knowing that s is an upper bound
        on the number of bytes we can read.  */
-    fp->length = safe_read (f, (char *) fp->buf, inc->st.st_size);
+    fp->length = safe_read (f, (char *) fp->buf, s);
     if (fp->length < 0) goto nope;
   }
   else if (S_ISDIR (inc->st.st_mode)) {
@@ -5198,7 +5416,7 @@ static char *
 check_precompiled (pcf, st, fname, limit)
      int pcf;
      struct stat *st;
-     char *fname;
+     char *fname ATTRIBUTE_UNUSED;
      char **limit;
 {
   int length = 0;
@@ -5210,8 +5428,11 @@ check_precompiled (pcf, st, fname, limit)
 
   if (S_ISREG (st->st_mode))
     {
-      buf = xmalloc (st->st_size + 2);
-      length = safe_read (pcf, buf, st->st_size);
+      size_t s = (size_t) st->st_size;
+      if (s != st->st_size || s + 2 < s)
+       memory_full ();
+      buf = xmalloc (s + 2);
+      length = safe_read (pcf, buf, s);
       if (length < 0)
        goto nope;
     }
@@ -5308,8 +5529,8 @@ check_preconditions (prec)
    in.  OP is the main output buffer.  */
 
 static void
-pcfinclude (buf, limit, name, op)
-     U_CHAR *buf, *limit, *name;
+pcfinclude (buf, name, op)
+     U_CHAR *buf, *name;
      FILE_BUF *op;
 {
   FILE_BUF tmpbuf;
@@ -5463,7 +5684,8 @@ write_output ()
                                     line_directive_len *= 2);
        sprintf (line_directive, "\n# %d ", next_string->lineno);
        strcpy (quote_string (line_directive + strlen (line_directive),
-                             (char *) next_string->filename),
+                             (char *) next_string->filename,
+                             strlen ((char *) next_string->filename)),
                "\n");
        safe_write (fileno (stdout), line_directive, strlen (line_directive));
        safe_write (fileno (stdout),
@@ -5545,6 +5767,7 @@ create_definition (buf, limit, op)
   int sym_length;              /* and how long it is */
   int line = instack[indepth].lineno;
   char *file = instack[indepth].nominal_fname;
+  size_t file_len = instack[indepth].nominal_fname_len;
   int rest_args = 0;
 
   DEFINITION *defn;
@@ -5594,8 +5817,10 @@ create_definition (buf, limit, op)
       while (is_idchar[*bp]) {
        bp++;
        /* do we have a "special" rest-args extension here? */
-       if (limit - bp > REST_EXTENSION_LENGTH
+       if (limit - bp > (long) REST_EXTENSION_LENGTH
            && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
+         if (pedantic && !instack[indepth].system_header_p)
+           pedwarn ("ANSI C does not allow macro with variable arguments");
          rest_args = 1;
          temp->rest_args = 1;
          break;
@@ -5692,6 +5917,7 @@ create_definition (buf, limit, op)
 
   defn->line = line;
   defn->file = file;
+  defn->file_len = file_len;
 
   /* OP is null if this is a predefinition */
   defn->predefined = !op;
@@ -5752,7 +5978,9 @@ do_define (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->line,
+         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.  */
@@ -5811,7 +6039,8 @@ compare_defs (d1, d2)
 
   if (d1->nargs != d2->nargs)
     return 1;
-  if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
+  if (pedantic
+      && strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
     return 1;
   for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
        a1 = a1->next, a2 = a2->next) {
@@ -6026,7 +6255,7 @@ collect_expansion (buf, end, nargs, arglist)
       }
     } else {
       /* In -traditional mode, recognize arguments inside strings and
-        and character constants, and ignore special properties of #.
+        character constants, and ignore special properties of #.
         Arguments inside strings are considered "stringified", but no
         extra quote marks are supplied.  */
       switch (c) {
@@ -6071,6 +6300,25 @@ collect_expansion (buf, end, nargs, arglist)
       }
     }
 
+#ifdef MULTIBYTE_CHARS
+    /* Handle multibyte characters inside string and character literals.  */
+    if (expected_delimiter != '\0')
+      {
+       int length;
+       --p;
+       length = local_mblen (p, limit - p);
+       if (length > 1)
+         {
+           --exp_p;
+           bcopy (p, exp_p, length);
+           p += length;
+           exp_p += length;
+           continue;
+         }
+       ++p;
+      }
+#endif
+
     /* Handle the start of a symbol.  */
     if (is_idchar[c] && nargs > 0) {
       U_CHAR *id_beg = p - 1;
@@ -6183,8 +6431,8 @@ collect_expansion (buf, end, nargs, arglist)
 static int
 do_assert (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
-     FILE_BUF *op;
-     struct directive *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 */
@@ -6260,8 +6508,8 @@ do_assert (buf, limit, op, keyword)
 static int
 do_unassert (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
-     FILE_BUF *op;
-     struct directive *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 */
@@ -6538,7 +6786,7 @@ assertion_install (name, len, hash)
   return hp;
 }
 
-/* Find the most recent hash node for name name (ending with first
+/* Find the most recent hash node for name "name" (ending with first
    non-identifier char) installed by install
 
    If LEN is >= 0, it is the length of the name.
@@ -6592,7 +6840,7 @@ static int
 do_line (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   register U_CHAR *bp;
   FILE_BUF *ip = &instack[indepth];
@@ -6607,7 +6855,7 @@ do_line (buf, limit, op, keyword)
   bp = tem.buf;
   SKIP_WHITE_SPACE (bp);
 
-  if (!isdigit (*bp)) {
+  if (!ISDIGIT (*bp)) {
     error ("invalid format `#line' directive");
     return 0;
   }
@@ -6622,7 +6870,7 @@ do_line (buf, limit, op, keyword)
     pedwarn ("line number out of range in `#line' directive");
 
   /* skip over the line number.  */
-  while (isdigit (*bp))
+  while (ISDIGIT (*bp))
     bp++;
 
 #if 0 /* #line 10"foo.c" is supposed to be allowed.  */
@@ -6664,7 +6912,7 @@ do_line (buf, limit, op, keyword)
        break;
 
       case '\"':
-       p[-1] = 0;
+       *--p = 0;
        goto fname_done;
       }
   fname_done:
@@ -6710,6 +6958,7 @@ do_line (buf, limit, op, keyword)
       if (hp->length == fname_length &&
          bcmp (hp->value.cpval, fname, fname_length) == 0) {
        ip->nominal_fname = hp->value.cpval;
+       ip->nominal_fname_len = fname_length;
        break;
       }
     if (hp == 0) {
@@ -6718,9 +6967,9 @@ do_line (buf, limit, op, keyword)
       hp->next = *hash_bucket;
       *hash_bucket = hp;
 
-      hp->length = fname_length;
       ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
-      bcopy (fname, hp->value.cpval, fname_length);
+      ip->nominal_fname_len = hp->length = fname_length;
+      bcopy (fname, hp->value.cpval, fname_length + 1);
     }
   } else if (*bp) {
     error ("invalid format `#line' directive");
@@ -6780,8 +7029,8 @@ do_undef (buf, limit, op, keyword)
 static int
 do_error (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
-     FILE_BUF *op;
-     struct directive *keyword;
+     FILE_BUF *op ATTRIBUTE_UNUSED;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   int length = limit - buf;
   U_CHAR *copy = (U_CHAR *) alloca (length + 1);
@@ -6799,14 +7048,18 @@ do_error (buf, limit, op, keyword)
 static int
 do_warning (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
-     FILE_BUF *op;
-     struct directive *keyword;
+     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);
+
+  if (pedantic && !instack[indepth].system_header_p)
+    pedwarn ("ANSI C does not allow `#warning'");
+
   /* 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);
@@ -6834,7 +7087,7 @@ static int
 do_ident (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   FILE_BUF trybuf;
   int len;
@@ -6863,9 +7116,9 @@ do_ident (buf, limit, op, keyword)
 
 static int
 do_pragma (buf, limit, op, keyword)
-     U_CHAR *buf, *limit;
-     FILE_BUF *op;
-     struct directive *keyword;
+     U_CHAR *buf, *limit ATTRIBUTE_UNUSED;
+     FILE_BUF *op ATTRIBUTE_UNUSED;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   SKIP_WHITE_SPACE (buf);
   if (!strncmp ((char *) buf, "once", 4)) {
@@ -6934,9 +7187,9 @@ nope:
 
 static int
 do_sccs (buf, limit, op, keyword)
-     U_CHAR *buf, *limit;
-     FILE_BUF *op;
-     struct directive *keyword;
+     U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
+     FILE_BUF *op ATTRIBUTE_UNUSED;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   if (pedantic)
     pedwarn ("ANSI C does not allow `#sccs'");
@@ -6960,7 +7213,7 @@ static int
 do_if (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   HOST_WIDE_INT value;
   FILE_BUF *ip = &instack[indepth];
@@ -6977,7 +7230,7 @@ static int
 do_elif (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   HOST_WIDE_INT value;
   FILE_BUF *ip = &instack[indepth];
@@ -6989,9 +7242,12 @@ do_elif (buf, limit, op, keyword)
     if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
       error ("`#elif' after `#else'");
       fprintf (stderr, " (matches line %d", if_stack->lineno);
-      if (if_stack->fname != NULL && ip->fname != NULL
-         && strcmp (if_stack->fname, ip->nominal_fname) != 0)
-       fprintf (stderr, ", file %s", if_stack->fname);
+      if (! (if_stack->fname_len == ip->nominal_fname_len
+            && !bcmp (if_stack->fname, ip->nominal_fname,
+                      if_stack->fname_len))) {
+       fprintf (stderr, ", file ");
+       eprint_string (if_stack->fname, if_stack->fname_len);
+      }
       fprintf (stderr, ")\n");
     }
     if_stack->type = T_ELIF;
@@ -7031,7 +7287,8 @@ eval_if_expression (buf, length)
   delete_macro (save_defined); /* clean up special symbol */
 
   temp_obuf.buf[temp_obuf.length] = '\n';
-  value = parse_c_expression ((char *) temp_obuf.buf);
+  value = parse_c_expression ((char *) temp_obuf.buf,
+                             warn_undef && !instack[indepth].system_header_p);
 
   free (temp_obuf.buf);
 
@@ -7098,7 +7355,7 @@ do_xifdef (buf, limit, op, keyword)
     HASHNODE *hp;
 
     if (! traditional) {
-      if (isdigit (buf[0]))
+      if (ISDIGIT (buf[0]))
        pedwarn ("`#%s' argument starts with a digit", keyword->name);
       else if (end != limit)
        pedwarn ("garbage at end of `#%s' argument", keyword->name);
@@ -7150,6 +7407,7 @@ conditional_skip (ip, skip, type, control_macro, op)
 
   temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
   temp->fname = ip->nominal_fname;
+  temp->fname_len = ip->nominal_fname_len;
   temp->lineno = ip->lineno;
   temp->next = if_stack;
   temp->control_macro = control_macro;
@@ -7186,6 +7444,7 @@ skip_if_group (ip, any, op)
   /* Save info about where the group starts.  */
   U_CHAR *beg_of_group = bp;
   int beg_lineno = ip->lineno;
+  int skipping_include_directive = 0;
 
   if (output_conditionals && op != 0) {
     char *ptr = "#failed\n";
@@ -7214,22 +7473,49 @@ skip_if_group (ip, any, op)
        bp = skip_to_end_of_comment (ip, &ip->lineno, 0);
       }
       break;
+    case '<':
+      if (skipping_include_directive) {
+       while (bp < endb && *bp != '>' && *bp != '\n') {
+         if (*bp == '\\' && bp[1] == '\n') {
+           ip->lineno++;
+           bp++;
+         }
+         bp++;
+       }
+      }
+      break;
     case '\"':
+      if (skipping_include_directive) {
+       while (bp < endb && *bp != '\n') {
+         if (*bp == '"') {
+           bp++;
+           break;
+         }
+         if (*bp == '\\' && bp[1] == '\n') {
+           ip->lineno++;
+           bp++;
+         }
+         bp++;
+       }
+       break;
+      }
+      /* Fall through.  */
     case '\'':
       bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno,
                               NULL_PTR, NULL_PTR);
       break;
     case '\\':
-      /* Char after backslash loses its special meaning.  */
-      if (bp < endb) {
-       if (*bp == '\n')
-         ++ip->lineno;         /* But do update the line-count.  */
+      /* Char after backslash loses its special meaning in some cases.  */
+      if (*bp == '\n') {
+       ++ip->lineno;
+       bp++;
+      } else if (traditional && bp < endb)
        bp++;
-      }
       break;
     case '\n':
       ++ip->lineno;
       beg_of_line = bp;
+      skipping_include_directive = 0;
       break;
     case '%':
       if (beg_of_line == 0 || traditional)
@@ -7259,9 +7545,27 @@ skip_if_group (ip, any, op)
            bp += 2;
          else if (*bp == '/' && bp[1] == '*') {
            bp += 2;
-           while (!(*bp == '*' && bp[1] == '/'))
-             bp++;
-           bp += 2;
+           while (1)
+             {
+               if (*bp == '*')
+                 {
+                   if (bp[1] == '/')
+                     {
+                       bp += 2;
+                       break;
+                     }
+                 }
+               else
+                 {
+#ifdef MULTIBYTE_CHARS
+                   int length;
+                   length = local_mblen (bp, endb - bp);
+                   if (length > 1)
+                     bp += (length - 1);
+#endif
+                 }
+               bp++;
+             }
          }
          /* There is no point in trying to deal with C++ // comments here,
             because if there is one, then this # must be part of the
@@ -7291,6 +7595,8 @@ skip_if_group (ip, any, op)
        else if (*bp == '\\' && bp[1] == '\n')
          bp += 2;
        else if (*bp == '/') {
+         if (bp[1] == '\\' && bp[2] == '\n')
+           newline_fix (bp + 1);
          if (bp[1] == '*') {
            for (bp += 2; ; bp++) {
              if (*bp == '\n')
@@ -7298,20 +7604,42 @@ skip_if_group (ip, any, op)
              else if (*bp == '*') {
                if (bp[-1] == '/' && warn_comments)
                  warning ("`/*' within comment");
+               if (bp[1] == '\\' && bp[2] == '\n')
+                 newline_fix (bp + 1);
                if (bp[1] == '/')
                  break;
              }
+             else
+               {
+#ifdef MULTIBYTE_CHARS
+                 int length;
+                 length = local_mblen (bp, endb - bp);
+                 if (length > 1)
+                   bp += (length - 1);
+#endif
+               }
            }
            bp += 2;
          } else if (bp[1] == '/' && cplusplus_comments) {
            for (bp += 2; ; bp++) {
-             if (*bp == '\n') {
-               if (bp[-1] != '\\')
-                 break;
-               if (warn_comments)
-                 warning ("multiline `//' comment");
-               ip->lineno++;
-             }
+             if (*bp == '\n')
+               break;
+             if (*bp == '\\' && bp[1] == '\n')
+               {
+                 if (warn_comments)
+                   warning ("multiline `//' comment");
+                 ip->lineno++;
+                 bp++;
+               }
+             else
+               {
+#ifdef MULTIBYTE_CHARS
+                 int length;
+                 length = local_mblen (bp, endb - bp);
+                 if (length > 1)
+                   bp += (length - 1);
+#endif
+               }
            }
          } else
            break;
@@ -7392,6 +7720,7 @@ skip_if_group (ip, any, op)
            if_stack = temp;
            temp->lineno = ip->lineno;
            temp->fname = ip->nominal_fname;
+           temp->fname_len = ip->nominal_fname_len;
            temp->type = kt->type;
            break;
          case T_ELSE:
@@ -7418,7 +7747,13 @@ skip_if_group (ip, any, op)
            free (temp);
            break;
 
-          default:
+         case T_INCLUDE:
+         case T_INCLUDE_NEXT:
+         case T_IMPORT:
+           skipping_include_directive = 1;
+           break;
+
+         default:
            break;
          }
          break;
@@ -7466,7 +7801,7 @@ static int
 do_else (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   FILE_BUF *ip = &instack[indepth];
 
@@ -7487,8 +7822,12 @@ do_else (buf, limit, op, keyword)
     if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
       error ("`#else' after `#else'");
       fprintf (stderr, " (matches line %d", if_stack->lineno);
-      if (strcmp (if_stack->fname, ip->nominal_fname) != 0)
-       fprintf (stderr, ", file %s", if_stack->fname);
+      if (! (if_stack->fname_len == ip->nominal_fname_len
+            && !bcmp (if_stack->fname, ip->nominal_fname,
+                      if_stack->fname_len))) {
+       fprintf (stderr, ", file ");
+       eprint_string (if_stack->fname, if_stack->fname_len);
+      }
       fprintf (stderr, ")\n");
     }
     if_stack->type = T_ELSE;
@@ -7509,7 +7848,7 @@ static int
 do_endif (buf, limit, op, keyword)
      U_CHAR *buf, *limit;
      FILE_BUF *op;
-     struct directive *keyword;
+     struct directive *keyword ATTRIBUTE_UNUSED;
 {
   if (pedantic) {
     SKIP_WHITE_SPACE (buf);
@@ -7596,6 +7935,15 @@ validate_else (p, limit)
              break;
            }
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (p, limit - p);
+             if (length > 1)
+               p += (length - 1);
+#endif
+           }
        }
       }
       else if (cplusplus_comments && p[1] == '/')
@@ -7639,16 +7987,37 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
   }
   if (cplusplus_comments && bp[-1] == '/') {
     for (; bp < limit; bp++) {
-      if (*bp == '\n') {
-       if (bp[-1] != '\\')
-         break;
-       if (!nowarn && warn_comments)
-         warning ("multiline `//' comment");
-       if (line_counter)
-         ++*line_counter;
-       if (op)
-         ++op->lineno;
-      }
+      if (*bp == '\n')
+       break;
+      if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
+       {
+         if (!nowarn && warn_comments)
+           warning ("multiline `//' comment");
+         if (line_counter)
+           ++*line_counter;
+         if (op)
+           {
+             ++op->lineno;
+             *op->bufp++ = *bp;
+           }
+         ++bp;
+       }
+      else
+       {
+#ifdef MULTIBYTE_CHARS
+         int length;
+         length = local_mblen (bp, limit - bp);
+         if (length > 1)
+           {
+             if (op)
+               {
+                 bcopy (bp, op->bufp, length - 1);
+                 op->bufp += (length - 1);
+               }
+             bp += (length - 1);
+           }
+#endif
+       }
       if (op)
        *op->bufp++ = *bp;
     }
@@ -7686,6 +8055,23 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
        return bp;
       }
       break;
+#ifdef MULTIBYTE_CHARS
+    default:
+      {
+       int length;
+       bp--;
+       length = local_mblen (bp, limit - bp);
+       if (length <= 0)
+         length = 1;
+       if (op)
+         {
+           op->bufp--;
+           bcopy (bp, op->bufp, length);
+           op->bufp += length;
+         }
+       bp += length;
+      }
+#endif
     }
   }
 
@@ -7742,10 +8128,11 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
          ++*count_newlines;
        bp += 2;
       }
-      if (*bp == '\n' && count_newlines) {
+      if (*bp == '\n') {
        if (backslash_newlines_p)
          *backslash_newlines_p = 1;
-       ++*count_newlines;
+       if (count_newlines)
+         ++*count_newlines;
       }
       bp++;
     } else if (c == '\n') {
@@ -7775,25 +8162,38 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
       }
     } else if (c == match)
       break;
+#ifdef MULTIBYTE_CHARS
+    {
+      int length;
+      --bp;
+      length = local_mblen (bp, limit - bp);
+      if (length <= 0)
+       length = 1;
+      bp += length;
+    }
+#endif
   }
   return bp;
 }
 
 /* Place into DST a quoted string representing the string SRC.
+   SRCLEN is the length of SRC; SRC may contain null bytes.
    Return the address of DST's terminating null.  */
 
 static char *
-quote_string (dst, src)
+quote_string (dst, src, srclen)
      char *dst, *src;
+     size_t srclen;
 {
   U_CHAR c;
+  char *srclim = src + srclen;
 
   *dst++ = '\"';
-  for (;;)
+  while (src != srclim)
     switch ((c = *src++))
       {
       default:
-        if (isprint (c))
+        if (ISPRINT (c))
          *dst++ = c;
        else
          {
@@ -7807,12 +8207,11 @@ quote_string (dst, src)
        *dst++ = '\\';
        *dst++ = c;
        break;
-      
-      case '\0':
-       *dst++ = '\"';
-       *dst = '\0';
-       return dst;
       }
+      
+  *dst++ = '\"';
+  *dst = '\0';
+  return dst;
 }
 
 /* Skip across a group of balanced parens, starting from IP->bufp.
@@ -7911,10 +8310,10 @@ output_line_directive (ip, op, conditional, file_change)
     ip->bufp++;
   }
 
-  line_directive_buf = (char *) alloca (4 * strlen (ip->nominal_fname) + 100);
+  line_directive_buf = (char *) alloca (4 * ip->nominal_fname_len + 100);
   sprintf (line_directive_buf, "# %d ", ip->lineno);
   line_end = quote_string (line_directive_buf + strlen (line_directive_buf),
-                          ip->nominal_fname);
+                          ip->nominal_fname, ip->nominal_fname_len);
   if (file_change != same_file) {
     *line_end++ = ' ';
     *line_end++ = file_change == enter_file ? '1' : '2';
@@ -8179,29 +8578,30 @@ macroexpand (hp, op)
          for (; i < arglen; i++) {
            c = arg->raw[i];
 
-           /* Special markers Newline Space
-              generate nothing for a stringified argument.  */
-           if (c == '\n' && arg->raw[i+1] != '\n') {
-             i++;
-             continue;
-           }
+           if (! in_string) {
+             /* Special markers Newline Space
+                generate nothing for a stringified argument.  */
+             if (c == '\n' && arg->raw[i+1] != '\n') {
+               i++;
+               continue;
+             }
 
-           /* Internal sequences of whitespace are replaced by one space
-              except within an string or char token.  */
-           if (! in_string
-               && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) {
-             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];
+             /* 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];
+               }
+               i--;
+               c = ' ';
              }
-             i--;
-             c = ' ';
            }
 
            if (escaped)
@@ -8209,9 +8609,23 @@ macroexpand (hp, op)
            else {
              if (c == '\\')
                escaped = 1;
-             if (in_string) {
+             else if (in_string) {
                if (c == in_string)
                  in_string = 0;
+               else
+                 {
+#ifdef MULTIBYTE_CHARS
+                   int length;
+                   length = local_mblen (arg->raw + i, arglen - i);
+                   if (length > 1)
+                     {
+                       bcopy (arg->raw + i, xbuf + totlen, length);
+                       i += length - 1;
+                       totlen += length;
+                       continue;
+                     }
+#endif
+                 }
              } else if (c == '\"' || c == '\'')
                in_string = c;
            }
@@ -8219,12 +8633,10 @@ macroexpand (hp, op)
            /* Escape these chars */
            if (c == '\"' || (in_string && c == '\\'))
              xbuf[totlen++] = '\\';
-           if (isprint (c))
-             xbuf[totlen++] = c;
-           else {
-             sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c);
-             totlen += 4;
-           }
+           /* We used to output e.g. \008 for control characters here,
+              but this doesn't conform to the C Standard.
+              Just output the characters as-is.  */
+           xbuf[totlen++] = c;
          }
          if (!traditional)
            xbuf[totlen++] = '\"'; /* insert ending quote */
@@ -8340,6 +8752,7 @@ macroexpand (hp, op)
 
     ip2->fname = 0;
     ip2->nominal_fname = 0;
+    ip2->nominal_fname_len = 0;
     ip2->inc = 0;
     /* This may not be exactly correct, but will give much better error
        messages for nested macro calls than using a line number of zero.  */
@@ -8378,7 +8791,7 @@ macarg (argptr, rest_args)
 
   /* 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,
+  U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro,
                        &paren, &newlines, &comments, rest_args);
 
   /* If we find the end of the argument at this level,
@@ -8416,7 +8829,7 @@ macarg (argptr, rest_args)
       ip = &instack[--indepth];
       newlines = 0;
       comments = 0;
-      bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren,
+      bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren,
                    &newlines, &comments, rest_args);
       final_start = bufsize;
       bufsize += bp - ip->bufp;
@@ -8479,8 +8892,6 @@ macarg (argptr, rest_args)
 #endif
       if (c == '\"' || c == '\\') /* escape these chars */
        totlen++;
-      else if (!isprint (c))
-       totlen += 3;
     }
     argptr->stringified_length = totlen;
   }
@@ -8488,6 +8899,7 @@ macarg (argptr, rest_args)
 }
 \f
 /* Scan text from START (inclusive) up to LIMIT (exclusive),
+   taken from the expansion of MACRO,
    counting parens in *DEPTHPTR,
    and return if reach LIMIT
    or before a `)' that would make *DEPTHPTR negative
@@ -8501,9 +8913,10 @@ macarg (argptr, rest_args)
    Set *COMMENTS to 1 if a comment is seen.  */
 
 static U_CHAR *
-macarg1 (start, limit, depthptr, newlines, comments, rest_args)
+macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
      U_CHAR *start;
      register U_CHAR *limit;
+     struct hashnode *macro;
      int *depthptr, *newlines, *comments;
      int rest_args;
 {
@@ -8520,18 +8933,15 @@ macarg1 (start, limit, depthptr, newlines, comments, rest_args)
       break;
     case '\\':
       /* Traditionally, backslash makes following char not special.  */
-      if (bp + 1 < limit && traditional)
-       {
-         bp++;
-         /* But count source lines anyway.  */
-         if (*bp == '\n')
-           ++*newlines;
-       }
+      if (traditional && bp + 1 < limit && bp[1] != '\n')
+       bp++;
       break;
     case '\n':
       ++*newlines;
       break;
     case '/':
+      if (macro)
+       break;
       if (bp[1] == '\\' && bp[2] == '\n')
        newline_fix (bp + 1);
       if (bp[1] == '*') {
@@ -8549,17 +8959,39 @@ macarg1 (start, limit, depthptr, newlines, comments, rest_args)
              break;
            }
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (bp, limit - bp);
+             if (length > 1)
+               bp += (length - 1);
+#endif
+           }
        }
       } else if (bp[1] == '/' && cplusplus_comments) {
        *comments = 1;
        for (bp += 2; bp < limit; bp++) {
          if (*bp == '\n') {
            ++*newlines;
-           if (bp[-1] != '\\')
-             break;
-           if (warn_comments)
-             warning ("multiline `//' comment");
+           break;
          }
+         if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
+           {
+             ++*newlines;
+             if (warn_comments)
+               warning ("multiline `//' comment");
+             ++bp;
+           }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (bp, limit - bp);
+             if (length > 1)
+               bp += (length - 1);
+#endif
+           }
        }
       }
       break;
@@ -8572,14 +9004,26 @@ macarg1 (start, limit, depthptr, newlines, comments, rest_args)
            bp++;
            if (*bp == '\n')
              ++*newlines;
-           while (*bp == '\\' && bp[1] == '\n') {
-             bp += 2;
+           if (!macro) {
+             while (*bp == '\\' && bp[1] == '\n') {
+               bp += 2;
+               ++*newlines;
+             }
            }
          } else if (*bp == '\n') {
            ++*newlines;
            if (quotec == '\'')
              break;
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (bp, limit - bp);
+             if (length > 1)
+               bp += (length - 1);
+#endif
+           }
        }
       }
       break;
@@ -8657,8 +9101,22 @@ discard_comments (start, length, newlines)
        /* Comments are equivalent to spaces.  */
        obp[-1] = ' ';
        ibp++;
-       while (ibp < limit && (*ibp != '\n' || ibp[-1] == '\\'))
-         ibp++;
+       while (ibp < limit)
+         {
+           if (*ibp == '\n')
+             break;
+           if (*ibp == '\\' && ibp + 1 < limit && ibp[1] == '\n')
+             ibp++;
+           else
+             {
+#ifdef MULTIBYTE_CHARS
+               int length = local_mblen (ibp, limit - ibp);
+               if (length > 1)
+                 ibp += (length - 1);
+#endif
+             }
+           ibp++;
+         }
        break;
       }
       if (ibp[0] != '*' || ibp + 1 >= limit)
@@ -8669,16 +9127,24 @@ discard_comments (start, length, newlines)
        obp--;
       else
        obp[-1] = ' ';
-      ibp++;
-      while (ibp + 1 < limit) {
-       if (ibp[0] == '*'
-           && ibp[1] == '\\' && ibp[2] == '\n')
-         newline_fix (ibp + 1);
-       if (ibp[0] == '*' && ibp[1] == '/')
-         break;
-       ibp++;
+      while (++ibp < limit) {
+       if (ibp[0] == '*') {
+         if (ibp[1] == '\\' && ibp[2] == '\n')
+           newline_fix (ibp + 1);
+         if (ibp[1] == '/') {
+           ibp += 2;
+           break;
+         }
+       }
+       else
+         {
+#ifdef MULTIBYTE_CHARS
+           int length = local_mblen (ibp, limit - ibp);
+           if (length > 1)
+             ibp += (length - 1);
+#endif
+         }
       }
-      ibp += 2;
       break;
 
     case '\'':
@@ -8692,13 +9158,39 @@ discard_comments (start, length, newlines)
          *obp++ = c = *ibp++;
          if (c == quotec)
            break;
-         if (c == '\n' && quotec == '\'')
-           break;
-         if (c == '\\' && ibp < limit) {
-           while (*ibp == '\\' && ibp[1] == '\n')
-             ibp += 2;
-           *obp++ = *ibp++;
+         if (c == '\n')
+           {
+             if (quotec == '\'')
+               break;
+           }
+         else if (c == '\\') {
+           if (ibp < limit && *ibp == '\n') {
+             ibp++;
+             obp--;
+           } else {
+             while (*ibp == '\\' && ibp[1] == '\n')
+               ibp += 2;
+             if (ibp < limit)
+               *obp++ = *ibp++;
+           }
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             ibp--;
+             length = local_mblen (ibp, limit - ibp);
+             if (length > 1)
+               {
+                 obp--;
+                 bcopy (ibp, obp, length);
+                 ibp += length;
+                 obp += length;
+               }
+             else
+               ibp++;
+#endif
+           }
        }
       }
       break;
@@ -8750,8 +9242,30 @@ change_newlines (start, length)
          *obp++ = c = *ibp++;
          if (c == quotec)
            break;
-         if (c == '\n' && quotec == '\'')
-           break;
+         else if (c == '\\' && ibp < limit && *ibp == '\n')
+           *obp++ = *ibp++;
+         else if (c == '\n')
+           {
+             if (quotec == '\'')
+               break;
+           }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             ibp--;
+             length = local_mblen (ibp, limit - ibp);
+             if (length > 1)
+               {
+                 obp--;
+                 bcopy (ibp, obp, length);
+                 ibp += length;
+                 obp += length;
+               }
+             else
+               ibp++;
+#endif
+           }
        }
       }
       break;
@@ -8764,7 +9278,7 @@ change_newlines (start, length)
 /* my_strerror - return the descriptive text associated with an
    `errno' code.  */
 
-char *
+static char *
 my_strerror (errnum)
      int errnum;
 {
@@ -8796,12 +9310,19 @@ my_strerror (errnum)
 /* error - print error message and increment count of errors.  */
 
 void
-error (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+error VPROTO ((char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msg;
+#endif
   va_list args;
 
   VA_START (args, msg);
+
+#ifndef ANSI_PROTOTYPES
+  msg = va_arg (args, char *);
+#endif
+
   verror (msg, args);
   va_end (args);
 }
@@ -8822,8 +9343,10 @@ verror (msg, args)
       break;
     }
 
-  if (ip != NULL)
-    fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
+  if (ip != NULL) {
+    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fprintf (stderr, ":%d: ", ip->lineno);
+  }
   vfprintf (stderr, msg, args);
   fprintf (stderr, "\n");
   errors++;
@@ -8835,6 +9358,7 @@ static void
 error_from_errno (name)
      char *name;
 {
+  int e = errno;
   int i;
   FILE_BUF *ip = NULL;
 
@@ -8846,10 +9370,12 @@ error_from_errno (name)
       break;
     }
 
-  if (ip != NULL)
-    fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
+  if (ip != NULL) {
+    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fprintf (stderr, ":%d: ", ip->lineno);
+  }
 
-  fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
+  fprintf (stderr, "%s: %s\n", name, my_strerror (e));
 
   errors++;
 }
@@ -8857,12 +9383,19 @@ error_from_errno (name)
 /* Print error message but don't count it.  */
 
 void
-warning (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+warning VPROTO ((char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msg;
+#endif
   va_list args;
 
   VA_START (args, msg);
+
+#ifndef ANSI_PROTOTYPES
+  msg = va_arg (args, char *);
+#endif
+
   vwarning (msg, args);
   va_end (args);
 }
@@ -8889,25 +9422,31 @@ vwarning (msg, args)
       break;
     }
 
-  if (ip != NULL)
-    fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
+  if (ip != NULL) {
+    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fprintf (stderr, ":%d: ", ip->lineno);
+  }
   fprintf (stderr, "warning: ");
   vfprintf (stderr, msg, args);
   fprintf (stderr, "\n");
 }
 
 static void
-#if defined (__STDC__) && defined (HAVE_VPRINTF)
-error_with_line (int line, PRINTF_ALIST (msg))
-#else
-error_with_line (line, PRINTF_ALIST (msg))
-     int line;
-     PRINTF_DCL (msg)
-#endif
+error_with_line VPROTO ((int line, char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  int line;
+  char * msg;
+#endif
   va_list args;
 
   VA_START (args, msg);
+
+#ifndef ANSI_PROTOTYPES
+  line = va_arg (args, int);
+  msg = va_arg (args, char *);
+#endif
+
   verror_with_line (line, msg, args);
   va_end (args);
 }
@@ -8929,25 +9468,31 @@ verror_with_line (line, msg, args)
       break;
     }
 
-  if (ip != NULL)
-    fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
+  if (ip != NULL) {
+    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fprintf (stderr, ":%d: ", line);
+  }
   vfprintf (stderr, msg, args);
   fprintf (stderr, "\n");
   errors++;
 }
 
 static void
-#if defined (__STDC__) && defined (HAVE_VPRINTF)
-warning_with_line (int line, PRINTF_ALIST (msg))
-#else
-warning_with_line (line, PRINTF_ALIST (msg))
-     int line;
-     PRINTF_DCL (msg)
-#endif
+warning_with_line VPROTO ((int line, char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  int line;
+  char * msg;
+#endif
   va_list args;
 
   VA_START (args, msg);
+
+#ifndef ANSI_PROTOTYPES
+  line = va_arg (args, int);
+  msg = va_arg (args, char *);
+#endif
+
   vwarning_with_line (line, msg, args);
   va_end (args);
 }
@@ -8975,8 +9520,10 @@ vwarning_with_line (line, msg, args)
       break;
     }
 
-  if (ip != NULL)
-    fprintf (stderr, line ? "%s:%d: " : "%s: ", ip->nominal_fname, line);
+  if (ip != NULL) {
+    eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+    fprintf (stderr, line ? ":%d: " : ": ", line);
+  }
   fprintf (stderr, "warning: ");
   vfprintf (stderr, msg, args);
   fprintf (stderr, "\n");
@@ -8985,12 +9532,19 @@ vwarning_with_line (line, msg, args)
 /* Print an error message and maybe count it.  */
 
 void
-pedwarn (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+pedwarn VPROTO ((char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msg;
+#endif
   va_list args;
 
   VA_START (args, msg);
+#ifndef ANSI_PROTOTYPES
+  msg = va_arg (args, char *);
+#endif
   if (pedantic_errors)
     verror (msg, args);
   else
@@ -8999,17 +9553,21 @@ pedwarn (PRINTF_ALIST (msg))
 }
 
 void
-#if defined (__STDC__) && defined (HAVE_VPRINTF)
-pedwarn_with_line (int line, PRINTF_ALIST (msg))
-#else
-pedwarn_with_line (line, PRINTF_ALIST (msg))
-     int line;
-     PRINTF_DCL (msg)
-#endif
+pedwarn_with_line VPROTO ((int line, char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  int line;
+  char * msg;
+#endif
   va_list args;
 
   VA_START (args, msg);
+#ifndef ANSI_PROTOTYPES
+  line = va_arg (args, int);
+  msg = va_arg (args, char *);
+#endif
   if (pedantic_errors)
     verror_with_line (line, msg, args);
   else
@@ -9021,26 +9579,38 @@ pedwarn_with_line (line, PRINTF_ALIST (msg))
    giving specified file name and line number, not current.  */
 
 static void
-#if defined (__STDC__) && defined (HAVE_VPRINTF)
-pedwarn_with_file_and_line (char *file, int line, PRINTF_ALIST (msg))
-#else
-pedwarn_with_file_and_line (file, line, PRINTF_ALIST (msg))
-     char *file;
-     int line;
-     PRINTF_DCL (msg)
+pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line,
+                                   char * msg, ...))
+{
+#ifndef ANSI_PROTOTYPES
+  char *file;
+  size_t file_len;
+  int line;
+  char * msg;
 #endif
-{
   va_list args;
 
   if (!pedantic_errors && inhibit_warnings)
     return;
-  if (file != NULL)
-    fprintf (stderr, "%s:%d: ", file, line);
+
+  VA_START (args, msg);
+#ifndef ANSI_PROTOTYPES
+  file = va_arg (args, char *);
+  file_len = va_arg (args, size_t);
+  line = va_arg (args, int);
+  msg = va_arg (args, char *);
+#endif
+  if (file) {
+    eprint_string (file, file_len);
+    fprintf (stderr, ":%d: ", line);
+  }
   if (pedantic_errors)
     errors++;
   if (!pedantic_errors)
     fprintf (stderr, "warning: ");
-  VA_START (args, msg);
+
   vfprintf (stderr, msg, args);
   va_end (args);
   fprintf (stderr, "\n");
@@ -9082,7 +9652,9 @@ print_containing_files ()
        fprintf (stderr, ",\n                ");
       }
 
-      fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno);
+      fprintf (stderr, " from ");
+      eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+      fprintf (stderr, ":%d", ip->lineno);
     }
   if (! first)
     fprintf (stderr, ":\n");
@@ -9219,7 +9791,7 @@ install (name, len, type, value, hash)
 }
 
 /*
- * find the most recent hash node for name name (ending with first
+ * find the most recent hash node for name "name" (ending with first
  * non-identifier char) installed by install
  *
  * If LEN is >= 0, it is the length of the name.
@@ -9637,9 +10209,8 @@ initialize_builtins (inp, outp)
  */
 
 static void
-make_definition (str, op)
+make_definition (str)
      char *str;
-     FILE_BUF *op;
 {
   FILE_BUF *ip;
   struct directive *kt;
@@ -9683,10 +10254,7 @@ make_definition (str, op)
        if (unterminated)
          return;
        while (p != p1)
-         if (*p == '\\' && p[1] == '\n')
-           p += 2;
-         else
-           *q++ = *p++;
+         *q++ = *p++;
       } else if (*p == '\\' && p[1] == '\n')
        p += 2;
       /* Change newline chars into newline-markers.  */
@@ -9704,6 +10272,7 @@ make_definition (str, op)
   
   ip = &instack[++indepth];
   ip->nominal_fname = ip->fname = "*Initialization*";
+  ip->nominal_fname_len = strlen (ip->nominal_fname);
 
   ip->buf = ip->bufp = buf;
   ip->length = strlen ((char *) buf);
@@ -9733,6 +10302,7 @@ make_undef (str, op)
 
   ip = &instack[++indepth];
   ip->nominal_fname = ip->fname = "*undef*";
+  ip->nominal_fname_len = strlen (ip->nominal_fname);
 
   ip->buf = ip->bufp = (U_CHAR *) str;
   ip->length = strlen (str);
@@ -9789,6 +10359,7 @@ make_assertion (option, str)
   
   ip = &instack[++indepth];
   ip->nominal_fname = ip->fname = "*Initialization*";
+  ip->nominal_fname_len = strlen (ip->nominal_fname);
 
   ip->buf = ip->bufp = buf;
   ip->length = strlen ((char *) buf);
@@ -9847,11 +10418,16 @@ new_include_prefix (prev_file_name, component, prefix, name)
     len = simplify_filename (dir->fname);
 
     /* Convert directory name to a prefix.  */
-    if (dir->fname[len - 1] != DIR_SEPARATOR) {
+    if (len && dir->fname[len - 1] != DIR_SEPARATOR) {
       if (len == 1 && dir->fname[len - 1] == '.')
        len = 0;
       else
+#ifdef VMS
+       /* must be '/', hack_vms_include_specification triggers on it.  */
+       dir->fname[len++] = '/';
+#else
        dir->fname[len++] = DIR_SEPARATOR;
+#endif
       dir->fname[len] = 0;
     }
 
@@ -9939,6 +10515,67 @@ append_include_chain (first, last)
   last_include = last;
 }
 \f
+/* Place into DST a representation of the file named SRC that is suitable
+   for `make'.  Do not null-terminate DST.  Return its length.  */
+static int
+quote_string_for_make (dst, src)
+     char *dst;
+     char *src;
+{
+  char *p = src;
+  int i = 0;
+  for (;;)
+    {
+      char c = *p++;
+      switch (c)
+       {
+       case '\0':
+       case ' ':
+       case '\t':
+         {
+           /* GNU make uses a weird quoting scheme for white space.
+              A space or tab preceded by 2N+1 backslashes represents
+              N backslashes followed by space; a space or tab
+              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;
+           for (q = p - 1; src < q && q[-1] == '\\';  q--)
+             {
+               if (dst)
+                 dst[i] = '\\';
+               i++;
+             }
+         }
+         if (!c)
+           return i;
+         if (dst)
+           dst[i] = '\\';
+         i++;
+         goto ordinary_char;
+         
+       case '$':
+         if (dst)
+           dst[i] = c;
+         i++;
+         /* Fall through.  This can mishandle things like "$(" but
+            there's no easy fix.  */
+       default:
+       ordinary_char:
+         /* This can mishandle characters in the string "\0\n%*?[\\~";
+            exactly which chars are mishandled depends on the `make' version.
+            We know of no portable solution for this;
+            even GNU make 3.76.1 doesn't solve the problem entirely.
+            (Also, '\0' is mishandled due to our calling conventions.)  */
+         if (dst)
+           dst[i] = c;
+         i++;
+         break;
+       }
+    }
+}
+
+
 /* Add output to `deps_buffer' for the -M switch.
    STRING points to the text to be output.
    SPACER is ':' for targets, ' ' for dependencies.  */
@@ -9948,7 +10585,7 @@ deps_output (string, spacer)
      char *string;
      int spacer;
 {
-  int size = strlen (string);
+  int size = quote_string_for_make ((char *) 0, string);
 
   if (size == 0)
     return;
@@ -9965,15 +10602,15 @@ deps_output (string, spacer)
       spacer = 0;
   }
 
-  if (deps_size + size + 8 > deps_allocated_size) {
-    deps_allocated_size = (deps_size + size + 50) * 2;
+  if (deps_size + 2 * size + 8 > deps_allocated_size) {
+    deps_allocated_size = (deps_size + 2 * size + 50) * 2;
     deps_buffer = xrealloc (deps_buffer, deps_allocated_size);
   }
   if (spacer == ' ') {
     deps_buffer[deps_size++] = ' ';
     deps_column++;
   }
-  bcopy (string, &deps_buffer[deps_size], size);
+  quote_string_for_make (&deps_buffer[deps_size], string);
   deps_size += size;
   deps_column += size;
   if (spacer == ':') {
@@ -9984,13 +10621,20 @@ deps_output (string, spacer)
 }
 \f
 static void
-fatal (PRINTF_ALIST (msg))
-     PRINTF_DCL (msg)
+fatal VPROTO ((char * msg, ...))
 {
+#ifndef ANSI_PROTOTYPES
+  char * msg;
+#endif
   va_list args;
 
   fprintf (stderr, "%s: ", progname);
   VA_START (args, msg);
+#ifndef ANSI_PROTOTYPES
+  msg = va_arg (args, char *);
+#endif
   vfprintf (stderr, msg, args);
   va_end (args);
   fprintf (stderr, "\n");
@@ -10010,8 +10654,7 @@ static void
 perror_with_name (name)
      char *name;
 {
-  fprintf (stderr, "%s: ", progname);
-  fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
+  fprintf (stderr, "%s: %s: %s\n", progname, name, my_strerror (errno));
   errors++;
 }
 
@@ -10032,7 +10675,7 @@ pfatal_with_name (name)
 static void
 pipe_closed (signo)
      /* If this is missing, some compilers complain.  */
-     int signo;
+     int signo ATTRIBUTE_UNUSED;
 {
   fatal ("output pipe has been closed");
 }
@@ -10089,31 +10732,84 @@ savestring (input)
 \f
 #ifdef VMS
 
-/* Under VMS we need to fix up the "include" specification filename so
-   that everything following the 1st slash is changed into its correct
-   VMS file specification.  */
+/* Under VMS we need to fix up the "include" specification filename.
 
-static void
-hack_vms_include_specification (fname, vaxc_include)
-     char *fname;
+   Rules for possible conversions
+
+       fullname                tried paths
+
+       name                    name
+       ./dir/name              [.dir]name
+       /dir/name               dir:name
+       /name                   [000000]name, name
+       dir/name                dir:[000000]name, dir:name, dir/name
+       dir1/dir2/name          dir1:[dir2]name, dir1:[000000.dir2]name
+       path:/name              path:[000000]name, path:name
+       path:/dir/name          path:[000000.dir]name, path:[dir]name
+       path:dir/name           path:[dir]name
+       [path]:[dir]name        [path.dir]name
+       path/[dir]name          [path.dir]name
+
+   The path:/name input is constructed when expanding <> includes.
+
+   return 1 if name was changed, 0 else.  */
+
+static int
+hack_vms_include_specification (fullname, vaxc_include)
+     char *fullname;
      int vaxc_include;
 {
-  register char *cp, *cp1, *cp2;
-  int f, check_filename_before_returning;
+  register char *basename, *unixname, *local_ptr, *first_slash;
+  int f, check_filename_before_returning, must_revert;
   char Local[512];
 
   check_filename_before_returning = 0;
+  must_revert = 0;
+  /* See if we can find a 1st slash. If not, there's no path information.  */
+  first_slash = index (fullname, '/');
+  if (first_slash == 0)
+    return 0;                          /* Nothing to do!!! */
+
+  /* construct device spec if none given.  */
+
+  if (index (fullname, ':') == 0)
+    {
+
+      /* If fullname has a slash, take it as device spec.  */
+
+      if (first_slash == fullname)
+       {
+         first_slash = index (fullname+1, '/');        /* 2nd slash ? */
+         if (first_slash)
+           *first_slash = ':';                         /* make device spec  */
+         for (basename = fullname; *basename != 0; basename++)
+           *basename = *(basename+1);                  /* remove leading slash  */
+       }
+      else if ((first_slash[-1] != '.')                /* keep ':/', './' */
+           && (first_slash[-1] != ':')
+           && (first_slash[-1] != ']'))        /* or a vms path  */
+       {
+         *first_slash = ':';
+       }
+      else if ((first_slash[1] == '[')         /* skip './' in './[dir'  */
+           && (first_slash[-1] == '.'))
+       fullname += 2;
+    }
+
+  /* Get part after first ':' (basename[-1] == ':')
+     or last '/' (basename[-1] == '/').  */
 
-  cp = base_name (fname);
+  basename = base_name (fullname);
 
   /*
    * Check if we have a vax-c style '#include filename'
    * and add the missing .h
    */
-  if (vaxc_include && !index (cp,'.'))
-    strcat (cp, ".h");
 
-  cp2 = Local;                 /* initialize */
+  if (vaxc_include && !index (basename,'.'))
+    strcat (basename, ".h");
+
+  local_ptr = Local;                   /* initialize */
 
   /* We are trying to do a number of things here.  First of all, we are
      trying to hammer the filenames into a standard format, such that later
@@ -10126,112 +10822,195 @@ hack_vms_include_specification (fname, vaxc_include)
      If no device is specified, then the first directory name is taken to be
      a device name (or a rooted logical).  */
 
-  /* See if we found that 1st slash */
-  if (cp == 0) return;         /* Nothing to do!!! */
-  if (*cp != '/') return;      /* Nothing to do!!! */
-  /* Point to the UNIX filename part (which needs to be fixed!) */
-  cp1 = cp+1;
+  /* Point to the UNIX filename part (which needs to be fixed!)
+     but skip vms path information.
+     [basename != fullname since first_slash != 0].  */
+
+  if ((basename[-1] == ':')            /* vms path spec.  */
+      || (basename[-1] == ']')
+      || (basename[-1] == '>'))
+    unixname = basename;
+  else
+    unixname = fullname;
+
+  if (*unixname == '/')
+    unixname++;
+
   /* If the directory spec is not rooted, we can just copy
-     the UNIX filename part and we are done */
-  if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) {
-    if (cp[-2] != '.') {
-      /*
-       * The VMS part ends in a `]', and the preceding character is not a `.'.
-       * We strip the `]', and then splice the two parts of the name in the
-       * usual way.  Given the default locations for include files in cccp.c,
-       * we will only use this code if the user specifies alternate locations
-       * with the /include (-I) switch on the command line.  */
-      cp -= 1;                 /* Strip "]" */
-      cp1--;                   /* backspace */
-    } else {
-      /*
-       * The VMS part has a ".]" at the end, and this will not do.  Later
-       * processing will add a second directory spec, and this would be a syntax
-       * error.  Thus we strip the ".]", and thus merge the directory specs.
-       * We also backspace cp1, so that it points to a '/'.  This inhibits the
-       * generation of the 000000 root directory spec (which does not belong here
-       * in this case).
-       */
-      cp -= 2;                 /* Strip ".]" */
-      cp1--; };                        /* backspace */
-  } else {
+     the UNIX filename part and we are done.  */
 
-    /* We drop in here if there is no VMS style directory specification yet.
-     * If there is no device specification either, we make the first dir a
-     * device and try that.  If we do not do this, then we will be essentially
-     * searching the users default directory (as if they did a #include "asdf.h").
-     *
-     * Then all we need to do is to push a '[' into the output string. Later
-     * processing will fill this in, and close the bracket.
-     */
-    if (cp[-1] != ':') *cp2++ = ':'; /* dev not in spec.  take first dir */
-    *cp2++ = '[';              /* Open the directory specification */
-  }
+  if (((basename - fullname) > 1)
+     && (  (basename[-1] == ']')
+        || (basename[-1] == '>')))
+    {
+      if (basename[-2] != '.')
+       {
+
+       /* The VMS part ends in a `]', and the preceding character is not a `.'.
+          -> PATH]:/name (basename = '/name', unixname = 'name')
+          We strip the `]', and then splice the two parts of the name in the
+          usual way.  Given the default locations for include files in cccp.c,
+          we will only use this code if the user specifies alternate locations
+          with the /include (-I) switch on the command line.  */
+
+         basename -= 1;        /* Strip "]" */
+         unixname--;           /* backspace */
+       }
+      else
+       {
+
+       /* The VMS part has a ".]" at the end, and this will not do.  Later
+          processing will add a second directory spec, and this would be a syntax
+          error.  Thus we strip the ".]", and thus merge the directory specs.
+          We also backspace unixname, so that it points to a '/'.  This inhibits the
+          generation of the 000000 root directory spec (which does not belong here
+          in this case).  */
+
+         basename -= 2;        /* Strip ".]" */
+         unixname--;           /* backspace */
+       }
+    }
+
+  else
+
+    {
+
+      /* We drop in here if there is no VMS style directory specification yet.
+         If there is no device specification either, we make the first dir a
+         device and try that.  If we do not do this, then we will be essentially
+         searching the users default directory (as if they did a #include "asdf.h").
+        
+         Then all we need to do is to push a '[' into the output string. Later
+         processing will fill this in, and close the bracket.  */
+
+      if ((unixname != fullname)       /* vms path spec found.  */
+        && (basename[-1] != ':'))
+       *local_ptr++ = ':';             /* dev not in spec.  take first dir */
+
+      *local_ptr++ = '[';              /* Open the directory specification */
+    }
+
+    if (unixname == fullname)          /* no vms dir spec.  */
+      {
+       must_revert = 1;
+       if ((first_slash != 0)          /* unix dir spec.  */
+           && (*unixname != '/')       /* not beginning with '/'  */
+           && (*unixname != '.'))      /* or './' or '../'  */
+         *local_ptr++ = '.';           /* dir is local !  */
+      }
 
   /* at this point we assume that we have the device spec, and (at least
      the opening "[" for a directory specification.  We may have directories
-     specified already */
+     specified already.
 
-  /* If there are no other slashes then the filename will be
+     If there are no other slashes then the filename will be
      in the "root" directory.  Otherwise, we need to add
      directory specifications.  */
-  if (index (cp1, '/') == 0) {
-    /* Just add "000000]" as the directory string */
-    strcpy (cp2, "000000]");
-    cp2 += strlen (cp2);
-    check_filename_before_returning = 1; /* we might need to fool with this later */
-  } else {
-    /* As long as there are still subdirectories to add, do them.  */
-    while (index (cp1, '/') != 0) {
-      /* If this token is "." we can ignore it */
-      if ((cp1[0] == '.') && (cp1[1] == '/')) {
-       cp1 += 2;
-       continue;
-      }
-      /* Add a subdirectory spec. Do not duplicate "." */
-      if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<')
-       *cp2++ = '.';
-      /* If this is ".." then the spec becomes "-" */
-      if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) {
-       /* Add "-" and skip the ".." */
-       *cp2++ = '-';
-       cp1 += 3;
-       continue;
-      }
-      /* Copy the subdirectory */
-      while (*cp1 != '/') *cp2++= *cp1++;
-      cp1++;                   /* Skip the "/" */
+
+  if (index (unixname, '/') == 0)
+    {
+      /* if no directories specified yet and none are following.  */
+      if (local_ptr[-1] == '[')
+       {
+         /* Just add "000000]" as the directory string */
+         strcpy (local_ptr, "000000]");
+         local_ptr += strlen (local_ptr);
+         check_filename_before_returning = 1; /* we might need to fool with this later */
+       }
+    }
+  else
+    {
+
+      /* As long as there are still subdirectories to add, do them.  */
+      while (index (unixname, '/') != 0)
+       {
+         /* If this token is "." we can ignore it
+              if it's not at the beginning of a path.  */
+         if ((unixname[0] == '.') && (unixname[1] == '/'))
+           {
+             /* remove it at beginning of path.  */
+             if (  ((unixname == fullname)             /* no device spec  */
+                   && (fullname+2 != basename))        /* starts with ./ */
+                                                       /* or  */
+                || ((basename[-1] == ':')              /* device spec  */
+                   && (unixname-1 == basename)))       /* and ./ afterwards  */
+               *local_ptr++ = '.';                     /* make '[.' start of path.  */
+             unixname += 2;
+             continue;
+           }
+
+         /* Add a subdirectory spec. Do not duplicate "." */
+         if (  local_ptr[-1] != '.'
+            && local_ptr[-1] != '['
+            && local_ptr[-1] != '<')
+           *local_ptr++ = '.';
+
+         /* If this is ".." then the spec becomes "-" */
+         if (  (unixname[0] == '.')
+            && (unixname[1] == '.')
+            && (unixname[2] == '/'))
+           {
+             /* Add "-" and skip the ".." */
+             if ((local_ptr[-1] == '.')
+                 && (local_ptr[-2] == '['))
+               local_ptr--;                    /* prevent [.-  */
+             *local_ptr++ = '-';
+             unixname += 3;
+             continue;
+           }
+
+         /* Copy the subdirectory */
+         while (*unixname != '/')
+           *local_ptr++= *unixname++;
+
+         unixname++;                   /* Skip the "/" */
+       }
+
+      /* Close the directory specification */
+      if (local_ptr[-1] == '.')                /* no trailing periods */
+       local_ptr--;
+
+      if (local_ptr[-1] == '[')                /* no dir needed */
+       local_ptr--;
+      else
+       *local_ptr++ = ']';
     }
-    /* Close the directory specification */
-    if (cp2[-1] == '.')                /* no trailing periods */
-      cp2--;
-    *cp2++ = ']';
-  }
-  /* Now add the filename */
-  while (*cp1) *cp2++ = *cp1++;
-  *cp2 = 0;
+
+  /* Now add the filename.  */
+
+  while (*unixname)
+    *local_ptr++ = *unixname++;
+  *local_ptr = 0;
+
   /* Now append it to the original VMS spec.  */
-  strcpy (cp, Local);
+
+  strcpy ((must_revert==1)?fullname:basename, Local);
 
   /* If we put a [000000] in the filename, try to open it first. If this fails,
      remove the [000000], and return that name.  This provides flexibility
      to the user in that they can use both rooted and non-rooted logical names
      to point to the location of the file.  */
 
-  if (check_filename_before_returning) {
-    f = open (fname, O_RDONLY, 0666);
-    if (f >= 0) {
-      /* The file name is OK as it is, so return it as is.  */
-      close (f);
-      return;
+  if (check_filename_before_returning)
+    {
+      f = open (fullname, O_RDONLY, 0666);
+      if (f >= 0)
+       {
+         /* The file name is OK as it is, so return it as is.  */
+         close (f);
+         return 1;
+       }
+
+      /* The filename did not work.  Try to remove the [000000] from the name,
+        and return it.  */
+
+      basename = index (fullname, '[');
+      local_ptr = index (fullname, ']') + 1;
+      strcpy (basename, local_ptr);            /* this gets rid of it */
+
     }
-    /* The filename did not work.  Try to remove the [000000] from the name,
-       and return it.  */
-    cp = index (fname, '[');
-    cp2 = index (fname, ']') + 1;
-    strcpy (cp, cp2);          /* this gets rid of it */
-  }
-  return;
+
+  return 1;
 }
 #endif /* VMS */
 \f
@@ -10251,10 +11030,11 @@ VMS_freopen (fname, type, oldfile)
      char *type;
      FILE *oldfile;
 {
+#undef freopen /* Get back the real freopen routine.  */
   if (strcmp (type, "w") == 0)
-    return decc$freopen (fname, type, oldfile,
+    return freopen (fname, type, oldfile,
                         "mbc=16", "deq=64", "fop=tef", "shr=nil");
-  return decc$freopen (fname, type, oldfile, "mbc=16");
+  return freopen (fname, type, oldfile, "mbc=16");
 }
 
 static FILE *
@@ -10262,10 +11042,11 @@ VMS_fopen (fname, type)
      char *fname;
      char *type;
 {
+#undef fopen   /* Get back the real fopen routine.  */
   /* The gcc-vms-1.42 distribution's header files prototype fopen with two
      fixed arguments, which matches ANSI's specification but not VAXCRTL's
      pre-ANSI implementation.  This hack circumvents the mismatch problem.  */
-  FILE *(*vmslib_fopen)() = (FILE *(*)()) decc$fopen;
+  FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen;
 
   if (*type == 'w')
     return (*vmslib_fopen) (fname, type, "mbc=32",
@@ -10280,14 +11061,15 @@ VMS_open (fname, flags, prot)
      int flags;
      int prot;
 {
-  return decc$open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
+#undef open    /* Get back the real open routine.  */
+  return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
 }
 \f
 /* more VMS hackery */
 #include <fab.h>
 #include <nam.h>
 
-extern unsigned long sys$parse(), sys$search();
+extern unsigned long SYS$PARSE(), SYS$SEARCH();
 
 /* Work around another library bug.  If a file is located via a searchlist,
    and if the device it's on is not the same device as the one specified
@@ -10301,13 +11083,14 @@ extern unsigned long sys$parse(), sys$search();
    bad enough, but then compounding the problem by reporting the reason for
    failure as "normal successful completion."  */
 
+#undef fstat   /* Get back to the library version.  */
 
 static int
 VMS_fstat (fd, statbuf)
      int fd;
      struct stat *statbuf;
 {
-  int result = decc$fstat (fd, statbuf);
+  int result = fstat (fd, statbuf);
 
   if (result < 0)
     {
@@ -10333,8 +11116,8 @@ VMS_stat (name, statbuf)
     {
       struct FAB fab;
       struct NAM nam;
-      char exp_nam[NAM$C_MAXRSS+1],  /* expanded name buffer for sys$parse */
-          res_nam[NAM$C_MAXRSS+1];  /* resultant name buffer for sys$search */
+      char exp_nam[NAM$C_MAXRSS+1],  /* expanded name buffer for SYS$PARSE */
+          res_nam[NAM$C_MAXRSS+1];  /* resultant name buffer for SYS$SEARCH */
 
       fab = cc$rms_fab;
       fab.fab$l_fna = (char *) name;
@@ -10344,9 +11127,9 @@ VMS_stat (name, statbuf)
       nam.nam$l_esa = exp_nam,  nam.nam$b_ess = sizeof exp_nam - 1;
       nam.nam$l_rsa = res_nam,  nam.nam$b_rss = sizeof res_nam - 1;
       nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL;
-      if (sys$parse (&fab) & 1)
+      if (SYS$PARSE (&fab) & 1)
        {
-         if (sys$search (&fab) & 1)
+         if (SYS$SEARCH (&fab) & 1)
            {
              res_nam[nam.nam$b_rsl] = '\0';
              result = stat (res_nam, statbuf);
@@ -10354,7 +11137,7 @@ VMS_stat (name, statbuf)
          /* Clean up searchlist context cached by the system.  */
          nam.nam$b_nop = NAM$M_SYNCHK;
          fab.fab$l_fna = 0,  fab.fab$b_fns = 0;
-         (void) sys$parse (&fab);
+         (void) SYS$PARSE (&fab);
        }
     }