OSDN Git Service

* gcc.c (convert_filename): Handle null filename argument.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 312af6d..d269395 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,5 +1,5 @@
 /* Compiler driver program that can handle many languages.
-   Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -32,63 +32,17 @@ Once it knows which kind of compilation to perform, the procedure for
 compilation is specified by a string called a "spec".  */
 \f
 #include "config.h"
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
 #include "system.h"
 #include <signal.h>
-#include <sys/stat.h>
 
-#include "gansidecl.h"
 #include "obstack.h"
-
-
-/* ??? Need to find a GCC header to put these in.  */
-extern int pexecute PROTO ((const char *, char * const *, const char *,
-                           const char *, char **, char **, int));
-extern int pwait PROTO ((int, int *, int));
-extern char *update_path PROTO((char *, char *));
-extern void set_std_prefix PROTO((char *, int));
-/* Flag arguments to pexecute.  */
-#define PEXECUTE_FIRST   1
-#define PEXECUTE_LAST    2
-#define PEXECUTE_SEARCH  4
-#define PEXECUTE_VERBOSE 8
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
+#include "intl.h"
+#include "prefix.h"
 
 #ifdef VMS
 #define exit __posix_exit
 #endif
 
-#ifdef USG
-#define vfork fork
-#endif /* USG */
-
-/* Test if something is a normal file.  */
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-/* Test if something is a directory.  */
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
 /* By default there is no special suffix for executables.  */
 #ifdef EXECUTABLE_SUFFIX
 #define HAVE_EXECUTABLE_SUFFIX
@@ -117,17 +71,8 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0};
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
-#endif
-
-extern char *choose_temp_base PROTO((void));
-
-#ifndef HAVE_STRERROR
-extern int sys_nerr;
-extern char *sys_errlist[];
-#else
-extern char *strerror();
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
 #endif
 
 #ifndef HAVE_KILL
@@ -163,6 +108,11 @@ static int print_multi_directory;
 
 static int print_multi_lib;
 
+/* Flag saying to print the command line options understood by gcc and its
+   sub-processes.  */
+
+static int print_help_list;
+
 /* Flag indicating whether we should print the command and arguments */
 
 static int verbose_flag;
@@ -220,8 +170,8 @@ static struct compiler *lookup_compiler PROTO((char *, size_t, char *));
 static char *build_search_list PROTO((struct path_prefix *, char *, int));
 static void putenv_from_prefixes PROTO((struct path_prefix *, char *));
 static char *find_a_file       PROTO((struct path_prefix *, char *, int));
-static void add_prefix         PROTO((struct path_prefix *, char *, char *,
-                                      int, int, int *));
+static void add_prefix         PROTO((struct path_prefix *, const char *,
+                                      const char *, int, int, int *));
 static char *skip_whitespace   PROTO((char *));
 static void record_temp_file   PROTO((char *, int, int));
 static void delete_if_ordinary PROTO((char *));
@@ -230,9 +180,8 @@ static void delete_failure_queue PROTO((void));
 static void clear_failure_queue PROTO((void));
 static int check_live_switch   PROTO((int, int));
 static char *handle_braces     PROTO((char *));
-static char *save_string       PROTO((char *, int));
-static char *concat            PVPROTO((char *, ...));
-static int do_spec             PROTO((char *));
+static char *save_string       PROTO((const char *, int));
+extern int do_spec             PROTO((char *));
 static int do_spec_1           PROTO((char *, int, char *));
 static char *find_file         PROTO((char *));
 static int is_directory                PROTO((char *, char *, int));
@@ -243,28 +192,28 @@ static int used_arg               PROTO((char *, int));
 static int default_arg         PROTO((char *, int));
 static void set_multilib_dir   PROTO((void));
 static void print_multilib_info        PROTO((void));
-static void pfatal_with_name   PROTO((char *));
+static void pfatal_with_name   PROTO((char *)) ATTRIBUTE_NORETURN;
 static void perror_with_name   PROTO((char *));
-static void pfatal_pexecute    PROTO((char *, char *));
-#ifdef HAVE_VPRINTF
-static void fatal              PVPROTO((char *, ...));
+static void pfatal_pexecute    PROTO((char *, char *)) ATTRIBUTE_NORETURN;
+static void fatal              PVPROTO((char *, ...)) ATTRIBUTE_NORETURN;
 static void error              PVPROTO((char *, ...));
-#else
-/* We must not provide any prototype here, even if ANSI C.  */
-static void fatal              PROTO(());
-static void error              PROTO(());
-#endif
+static void fatal              PVPROTO((char *, ...))
+  ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1;
+static void error              PVPROTO((char *, ...)) ATTRIBUTE_PRINTF_1;
+static void notice             PVPROTO((char *, ...));
+static void display_help       PROTO((void));
 
-void fancy_abort ();
-char *xmalloc ();
-char *xrealloc ();
+void fancy_abort               PROTO((void)) ATTRIBUTE_NORETURN;
 
 #ifdef LANG_SPECIFIC_DRIVER
-#ifdef HAVE_VPRINTF
-extern void lang_specific_driver PROTO ((void (*) (char *, ...), int *, char ***, int *));
-#else
-extern void lang_specific_driver PROTO ((void (*) (), int *, char ***, int *));
-#endif
+/* Called before processing to change/add/remove arguments. */
+extern void lang_specific_driver PROTO ((void (*) PVPROTO((char *, ...)), int *, char ***, int *));
+
+/* Called before linking.  Returns 0 on success and -1 on failure. */
+extern int lang_specific_pre_link ();
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+extern int lang_specific_extra_outfiles;
 #endif
 \f
 /* Specs are strings containing lines, each of which (if not blank)
@@ -285,12 +234,30 @@ or with constant text in a single argument.
  %b     substitute the basename of the input file being processed.
        This is the substring up to (and not including) the last period
        and not including the directory.
- %g     substitute the temporary-file-name-base.  This is a string chosen
-       once per compilation.  Different temporary file names are made by
-       concatenation of constant strings on the end, as in `%g.s'.
-       %g also has the same effect of %d.
- %u    like %g, but make the temporary file name unique.
- %U    returns the last file name generated with %u.
+ %gSUFFIX
+       substitute a file name that has suffix SUFFIX and is chosen
+       once per compilation, and mark the argument a la %d.  To reduce
+       exposure to denial-of-service attacks, the file name is now
+       chosen in a way that is hard to predict even when previously
+       chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
+       might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
+       the regexp "[.A-Za-z]*" or the special string "%O", which is
+       treated exactly as if %O had been pre-processed.  Previously, %g
+       was simply substituted with a file name chosen once per compilation,
+       without regard to any appended suffix (which was therefore treated
+       just like ordinary text), making such attacks more likely to succeed.
+ %uSUFFIX
+       like %g, but generates a new temporary file name even if %uSUFFIX
+       was already seen.
+ %USUFFIX
+       substitutes the last file name generated with %uSUFFIX, generating a
+       new one if there is no such last file name.  In the absence of any
+       %uSUFFIX, this is just like %gSUFFIX, except they don't share
+       the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
+       would involve the generation of two distinct file names, one
+       for each `%g.s' and another for each `%U.s'.  Previously, %U was
+       simply substituted with a file name chosen for the previous %u,
+       without regard to any appended suffix.
  %d    marks the argument containing or following the %d as a
        temporary file name, so that that file will be deleted if CC exits
        successfully.  Unlike %g, this contributes no text to the argument.
@@ -307,7 +274,13 @@ or with constant text in a single argument.
        Input files whose names have no recognized suffix are not compiled
        at all, but they are included among the output files, so they will
        be linked.
- %O    substitutes the suffix for object files.
+ %O    substitutes the suffix for object files.  Note that this is
+       handled specially when it immediately follows %g, %u, or %U,
+       because of the need for those to form complete file names.  The
+       handling is such that %O is treated exactly as if it had already
+       been substituted, except that %g, %u, and %U do not currently
+       support additional SUFFIX characters following %O as they would
+       following, for example, `.o'.
  %p    substitutes the standard macro predefinitions for the
        current target machine.  Use this when running cpp.
  %P    like %p, but puts `__' before and after the name of each macro.
@@ -331,7 +304,7 @@ or with constant text in a single argument.
         This allows config.h to specify part of the spec for running as.
  %A    process ASM_FINAL_SPEC as a spec.  A capital A is actually
        used here.  This can be used to run a post-processor after the
-       assembler has done it's job.
+       assembler has done its job.
  %D    Dump out a -L option for each directory in startfile_prefixes.
        If multilib_dir is set, extra entries are generated with it affixed.
  %l     process LINK_SPEC as a spec.
@@ -366,6 +339,8 @@ or with constant text in a single argument.
  %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
  %{.S:X} substitutes X, but only if processing a file with suffix S.
  %{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
+ %{S|P:X} substitutes X if either -S or -P was given to CC.  This may be
+         combined with ! and . as above binding stronger than the OR.
  %(Spec) processes a specification defined in a specs file as *Spec:
  %[Spec] as above, but put __ around -D arguments
 
@@ -379,8 +354,9 @@ constructs.  If another value of -O or the negated form of a -f, -m, or
 value is ignored, except with {S*} where S is just one letter; this
 passes all matching options.
 
-The character | is used to indicate that a command should be piped to
-the following command, but only if -pipe is specified.
+The character | at the beginning of the predicate text is used to indicate
+that a command should be piped to the following command, but only if -pipe
+is specified.
 
 Note that it is built into CC which switches take arguments and which
 do not.  You might think it would be useful to generalize this to
@@ -546,6 +522,18 @@ static struct user_specs *user_specs_head, *user_specs_tail;
 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
 #endif
 \f
+
+#ifdef HAVE_EXECUTABLE_SUFFIX
+/* This defines which switches stop a full compilation.  */
+#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
+  ((CHAR) == 'c' || (CHAR) == 'S')
+
+#ifndef SWITCH_CURTAILS_COMPILATION
+#define SWITCH_CURTAILS_COMPILATION(CHAR) \
+  DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
+#endif
+#endif
+
 /* Record the mapping from file suffixes for compilation specs.  */
 
 struct compiler
@@ -580,72 +568,94 @@ static struct compiler default_compilers[] =
      were not present when we built the driver, we will hit these copies
      and be given a more meaningful error than "file not used since
      linking is not done".  */
-  {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}}, {".c++", {"#C++"}},
-  {".C", {"#C++"}}, {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
+  {".m", {"#Objective-C"}},
+  {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}},
+  {".c++", {"#C++"}}, {".C", {"#C++"}},
+  {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
   {".f", {"#Fortran"}}, {".for", {"#Fortran"}}, {".F", {"#Fortran"}},
   {".fpp", {"#Fortran"}},
   {".p", {"#Pascal"}}, {".pas", {"#Pascal"}},
   /* Next come the entries for C.  */
   {".c", {"@c"}},
   {"@c",
-   {"cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+   {
+#if USE_CPPLIB
+     "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
+       %{C} %{v} %{A*} %{I*} %{P} %I\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
        %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-       %{ansi:-trigraphs -D__STRICT_ANSI__}\
-       %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+       %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+       %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
+        %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
+      %{!E:%{!M:%{!MM:cc1 %i %1 \
+                  %{std*} %{nostdinc*} %{A*} %{I*} %I\
+                  %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
+                  %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+                  -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
+                 %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+                 %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
+                  %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+                  %{H} %C %{D*} %{U*} %{i*} %Z\
+                  %{ftraditional:-traditional}\
+                  %{traditional-cpp:-traditional}\
+                 %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
+                 %{aux-info*} %{Qn:-fno-ident}\
+                 %{--help:--help}\
+                 %{g*} %{O*} %{W*} %{w} %{pedantic*}\
+                 %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+                 %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
+                  %{!S:as %a %Y\
+                    %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
+                     %{!pipe:%g.s} %A\n }}}}"
+  }},
+#else /* ! USE_CPPLIB */
+    "cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
+       %{C} %{v} %{A*} %{I*} %{P} %I\
+       %{C:%{!E:%eGNU C does not support -C without using -E}}\
+       %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+        -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
+       %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+       %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
+        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+        %{traditional} %{ftraditional:-traditional}\
+        %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
-    "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
+   "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
                   %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
-                  %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+                  %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
                   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
-                  %{aux-info*}\
+                  %{aux-info*} %{Qn:-fno-ident}\
+                  %{--help:--help} \
                   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
                   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
               %{!S:as %a %Y\
                      %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
-                      %{!pipe:%g.s} %A\n }}}}"}},
+                      %{!pipe:%g.s} %A\n }}}}"
+  }},
+#endif /* ! USE_CPPLIB */
   {"-",
-   {"%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+   {"%{E:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
+       %{C} %{v} %{A*} %{I*} %{P} %I\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
        %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-       %{ansi:-trigraphs -D__STRICT_ANSI__}\
-       %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+       %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+       %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}}\
     %{!E:%e-E required when input is from standard input}"}},
-  {".m", {"@objective-c"}},
-  {"@objective-c",
-   {"cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
-       %{C:%{!E:%eGNU C does not support -C without using -E}}\
-       %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
-        -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-        %{ansi:-trigraphs -D__STRICT_ANSI__}\
-       %{!undef:%{!ansi:%p} %P} %{trigraphs}\
-        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-        %{traditional} %{ftraditional:-traditional}\
-        %{traditional-cpp:-traditional}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
-        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
-    "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
-                  %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a*}\
-                  %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
-                  %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
-                  -lang-objc %{gen-decls} \
-                  %{aux-info*}\
-                  %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
-                  %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
-              %{!S:as %a %Y\
-                     %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
-                      %{!pipe:%g.s} %A\n }}}}"}},
   {".h", {"@c-header"}},
   {"@c-header",
    {"%{!E:%eCompilation of header file requested} \
@@ -653,19 +663,20 @@ static struct compiler default_compilers[] =
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
         %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-        %{ansi:-trigraphs -D__STRICT_ANSI__}\
-       %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+       %{std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+       %{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}"}},
   {".i", {"@cpp-output"}},
   {"@cpp-output",
    {"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
-                       %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
+                       %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
                        %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
-                       %{aux-info*}\
+                       %{aux-info*} %{Qn:-fno-ident}\
                        %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
                        %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
                     %{!S:as %a %Y\
@@ -685,6 +696,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
     "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
@@ -708,6 +720,12 @@ static int n_default_compilers
 /* We want %{T*} after %{L*} and %D so that it can be used to specify linker
    scripts which exist in user specified directories, or in standard
    directories.  */
+#ifdef LINK_COMMAND_SPEC
+/* Provide option to override link_command_spec from machine specific
+   configuration files.  */
+static char *link_command_spec = 
+       LINK_COMMAND_SPEC;
+#else
 #ifdef LINK_LIBGCC_SPECIAL
 /* Don't generate -L options.  */
 static char *link_command_spec = "\
@@ -733,6 +751,7 @@ static char *link_command_spec = "\
                        %{T*}\
                        \n }}}}}}";
 #endif
+#endif
 
 /* A vector of options to give to the linker.
    These options are accumulated by %x,
@@ -778,6 +797,8 @@ struct option_map option_map[] =
    {"--ansi", "-ansi", 0},
    {"--assemble", "-S", 0},
    {"--assert", "-A", "a"},
+   {"--classpath", "-fclasspath=", "aj"},
+   {"--CLASSPATH", "-fCLASSPATH=", "aj"},
    {"--comments", "-C", 0},
    {"--compile", "-c", 0},
    {"--debug", "-g", "oj"},
@@ -810,6 +831,7 @@ struct option_map option_map[] =
    {"--no-warnings", "-w", 0},
    {"--optimize", "-O", "oj"},
    {"--output", "-o", "a"},
+   {"--output-class-directory", "-foutput-class-dir=", "ja"},
    {"--pedantic", "-pedantic", 0},
    {"--pedantic-errors", "-pedantic-errors", 0},
    {"--pipe", "-pipe", 0},
@@ -830,6 +852,7 @@ struct option_map option_map[] =
    {"--silent", "-q", 0},
    {"--specs", "-specs=", "aj"},
    {"--static", "-static", 0},
+   {"--std", "-std=", "aj"},
    {"--symbolic", "-symbolic", 0},
    {"--target", "-b", "a"},
    {"--trace-includes", "-H", 0},
@@ -856,7 +879,7 @@ translate_options (argcp, argvp)
      int *argcp;
      char ***argvp;
 {
-  int i, j, k;
+  int i;
   int argc = *argcp;
   char **argv = *argvp;
   char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
@@ -870,6 +893,7 @@ translate_options (argcp, argvp)
       /* Translate -- options.  */
       if (argv[i][0] == '-' && argv[i][1] == '-')
        {
+         size_t j;
          /* Find a mapping that applies to this option.  */
          for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
            {
@@ -887,6 +911,7 @@ translate_options (argcp, argvp)
 
                  if (arglen < optlen)
                    {
+                     size_t k;
                      for (k = j + 1;
                           k < sizeof (option_map) / sizeof (option_map[0]);
                           k++)
@@ -1009,7 +1034,7 @@ translate_options (argcp, argvp)
 }
 \f
 char *
-my_strerror(e)
+xstrerror(e)
      int e;
 {
 #ifdef HAVE_STRERROR
@@ -1018,15 +1043,13 @@ my_strerror(e)
 
 #else
 
-  static char buffer[30];
   if (!e)
-    return "cannot access";
+    return "errno = 0";
 
   if (e > 0 && e < sys_nerr)
     return sys_errlist[e];
 
-  sprintf (buffer, "Unknown error %d", e);
-  return buffer;
+  return "errno = ?";
 #endif
 }
 \f
@@ -1101,7 +1124,16 @@ static struct spec_list static_specs[] = {
 };
 
 #ifdef EXTRA_SPECS             /* additional specs needed */
-static struct spec_list extra_specs[] = { EXTRA_SPECS };
+/* Structure to keep track of just the first two args of a spec_list.
+   That is all that the EXTRA_SPECS macro gives us. */
+struct spec_list_1
+{
+  char *name;
+  char *ptr;
+};
+
+static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+static struct spec_list * extra_specs = (struct spec_list *)0;
 #endif
 
 /* List of dynamically allocates specs that have been defined so far.  */
@@ -1122,12 +1154,20 @@ init_spec ()
     return;                    /* already initialized */
 
   if (verbose_flag)
-    fprintf (stderr, "Using builtin specs.\n");
+    notice ("Using builtin specs.\n");
 
 #ifdef EXTRA_SPECS
-  for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
+  extra_specs = (struct spec_list *)
+    xmalloc (sizeof(struct spec_list) *
+            (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
+  bzero ((PTR) extra_specs, sizeof(struct spec_list) *
+        (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
+  
+  for (i = (sizeof(extra_specs_1) / sizeof(extra_specs_1[0])) - 1; i >= 0; i--)
     {
       sl = &extra_specs[i];
+      sl->name = extra_specs_1[i].name;
+      sl->ptr = extra_specs_1[i].ptr;
       sl->next = next;
       sl->name_len = strlen (sl->name);
       sl->ptr_spec = &sl->ptr;
@@ -1193,13 +1233,13 @@ set_spec (name, spec)
     }
 
   old_spec = *(sl->ptr_spec);
-  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE (spec[1]))
+  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
                     ? concat (old_spec, spec + 1, NULL_PTR)
                     : save_string (spec, strlen (spec)));
 
 #ifdef DEBUG_SPECS
   if (verbose_flag)
-    fprintf (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+    notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
 #endif
 
   /* Free the old spec */
@@ -1223,7 +1263,13 @@ static int argbuf_length;
 
 static int argbuf_index;
 
+/* We want this on by default all the time now.  */
+#define MKTEMP_EACH_FILE
+
 #ifdef MKTEMP_EACH_FILE
+
+extern char *make_temp_file PROTO((char *));
+
 /* This is the list of suffixes and codes (%g/%u/%U) and the associated
    temp file.  */
 
@@ -1237,6 +1283,7 @@ static struct temp_name {
 } *temp_names;
 #endif
 
+
 /* Number of commands executed so far.  */
 
 static int execution_count;
@@ -1390,7 +1437,7 @@ read_specs (filename, main_p)
   register char *p;
 
   if (verbose_flag)
-    fprintf (stderr, "Reading specs from %s\n", filename);
+    notice ("Reading specs from %s\n", filename);
 
   /* Open and stat the file.  */
   desc = open (filename, O_RDONLY, 0);
@@ -1442,8 +1489,8 @@ read_specs (filename, main_p)
                p1++;
 
              if (*p1++ != '<' || p[-2] != '>')
-               fatal ("specs %%include syntax malformed after %d characters",
-                      p1 - buffer + 1);
+               fatal ("specs %%include syntax malformed after %ld characters",
+                      (long) (p1 - buffer + 1));
 
              p[-2] = '\0';
              new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
@@ -1460,15 +1507,15 @@ read_specs (filename, main_p)
              while (*p1 == ' ' || *p1 == '\t') p1++;
 
              if (*p1++ != '<' || p[-2] != '>')
-               fatal ("specs %%include syntax malformed after %d characters",
-                      p1 - buffer + 1);
+               fatal ("specs %%include syntax malformed after %ld characters",
+                      (long) (p1 - buffer + 1));
 
              p[-2] = '\0';
              new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
              if (new_filename)
                read_specs (new_filename, FALSE);
              else if (verbose_flag)
-               fprintf (stderr, "Could not find specs file %s\n", p1);
+               notice ("Could not find specs file %s\n", p1);
              continue;
            }
          else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
@@ -1483,35 +1530,35 @@ read_specs (filename, main_p)
              while (*p1 == ' ' || *p1 == '\t')
                p1++;
 
-             if (! ISALPHA (*p1))
-               fatal ("specs %%rename syntax malformed after %d characters",
-                      p1 - buffer);
+             if (! ISALPHA ((unsigned char)*p1))
+               fatal ("specs %%rename syntax malformed after %ld characters",
+                      (long) (p1 - buffer));
 
              p2 = p1;
-             while (*p2 && !ISSPACE (*p2))
+             while (*p2 && !ISSPACE ((unsigned char)*p2))
                p2++;
 
              if (*p2 != ' ' && *p2 != '\t')
-               fatal ("specs %%rename syntax malformed after %d characters",
-                      p2 - buffer);
+               fatal ("specs %%rename syntax malformed after %ld characters",
+                      (long) (p2 - buffer));
 
              name_len = p2 - p1;
              *p2++ = '\0';
              while (*p2 == ' ' || *p2 == '\t')
                p2++;
 
-             if (! ISALPHA (*p2))
-               fatal ("specs %%rename syntax malformed after %d characters",
-                      p2 - buffer);
+             if (! ISALPHA ((unsigned char)*p2))
+               fatal ("specs %%rename syntax malformed after %ld characters",
+                      (long) (p2 - buffer));
 
              /* Get new spec name */
              p3 = p2;
-             while (*p3 && !ISSPACE (*p3))
+             while (*p3 && !ISSPACE ((unsigned char)*p3))
                p3++;
 
              if (p3 != p-1)
-               fatal ("specs %%rename syntax malformed after %d characters",
-                      p3 - buffer);
+               fatal ("specs %%rename syntax malformed after %ld characters",
+                      (long) (p3 - buffer));
              *p3 = '\0';
 
              for (sl = specs; sl; sl = sl->next)
@@ -1526,9 +1573,9 @@ read_specs (filename, main_p)
 
              if (verbose_flag)
                {
-                 fprintf (stderr, "rename spec %s to %s\n", p1, p2);
+                 notice ("rename spec %s to %s\n", p1, p2);
 #ifdef DEBUG_SPECS
-                 fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+                 notice ("spec is '%s'\n\n", *(sl->ptr_spec));
 #endif
                }
 
@@ -1541,8 +1588,8 @@ read_specs (filename, main_p)
              continue;
            }
          else
-           fatal ("specs unknown %% command after %d characters",
-                  p1 - buffer);
+           fatal ("specs unknown %% command after %ld characters",
+                  (long) (p1 - buffer));
        }
 
       /* Find the colon that should end the suffix.  */
@@ -1552,7 +1599,8 @@ read_specs (filename, main_p)
 
       /* The colon shouldn't be missing.  */
       if (*p1 != ':')
-       fatal ("specs file malformed after %d characters", p1 - buffer);
+       fatal ("specs file malformed after %ld characters",
+              (long) (p1 - buffer));
 
       /* Skip back over trailing whitespace.  */
       p2 = p1;
@@ -1564,11 +1612,12 @@ read_specs (filename, main_p)
       /* Find the next line.  */
       p = skip_whitespace (p1 + 1);
       if (p[1] == 0)
-       fatal ("specs file malformed after %d characters", p - buffer);
+       fatal ("specs file malformed after %ld characters",
+              (long) (p - buffer));
 
       p1 = p;
-      /* Find next blank line.  */
-      while (*p1 && !(*p1 == '\n' && p1[1] == '\n'))
+      /* Find next blank line or end of string.  */
+      while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
        p1++;
 
       /* Specs end at the blank line and do not include the newline.  */
@@ -1801,7 +1850,7 @@ putenv (str)
   /* Add a new environment variable */
   environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
   *environ = str;
-  bcopy ((char *) old_environ, (char *) (environ + 1),
+  memcpy ((char *) (environ + 1), (char *) old_environ,
         sizeof (char *) * (num_envs+1));
 
 #endif /* VMS */
@@ -1900,6 +1949,26 @@ find_a_file (pprefix, name, mode)
   struct prefix_list *pl;
   int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
 
+#ifdef DEFAULT_ASSEMBLER
+  if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) {
+    name = DEFAULT_ASSEMBLER;
+    len = strlen(name)+1;
+    temp = xmalloc (len);
+    strcpy (temp, name);
+    return temp;
+  }
+#endif
+
+#ifdef DEFAULT_LINKER
+  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) {
+    name = DEFAULT_LINKER;
+    len = strlen(name)+1;
+    temp = xmalloc (len);
+    strcpy (temp, name);
+    return temp;
+  }
+#endif
+
   if (machine_suffix)
     len += strlen (machine_suffix);
 
@@ -1912,7 +1981,7 @@ find_a_file (pprefix, name, mode)
       || (DIR_SEPARATOR == '\\' && name[1] == ':'
          && (name[2] == DIR_SEPARATOR || name[2] == '/')))
     {
-      if (access (name, mode))
+      if (access (name, mode) == 0)
        {
          strcpy (temp, name);
          return temp;
@@ -2032,8 +2101,8 @@ find_a_file (pprefix, name, mode)
 static void
 add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
      struct path_prefix *pprefix;
-     char *prefix;
-     char *component;
+     const char *prefix;
+     const char *component;
      int first;
      int require_machine_suffix;
      int *warn;
@@ -2142,7 +2211,7 @@ execute ()
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
       {                                /* each command.  */
-#if defined (__MSDOS__) || (defined (_WIN32) && defined (__CYGWIN32_)) || defined (OS2) || defined (VMS)
+#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
         fatal ("-pipe not supported");
 #endif
        argbuf[i] = 0;  /* termination of command args.  */
@@ -2160,6 +2229,10 @@ execute ()
 
   if (verbose_flag)
     {
+      /* For help listings, put a blank line between sub-processes.  */
+      if (print_help_list)
+       fputc ('\n', stderr);
+      
       /* Print each piped command as a separate line.  */
       for (i = 0; i < n_commands ; i++)
        {
@@ -2175,7 +2248,7 @@ execute ()
        }
       fflush (stderr);
 #ifdef DEBUG
-      fprintf (stderr, "\nGo ahead? (y or n) ");
+      notice ("\nGo ahead? (y or n) ");
       fflush (stderr);
       i = getchar ();
       if (i != '\n')
@@ -2263,7 +2336,7 @@ execute ()
    is a null-terminated vector containing the following arguments.
    The `live_cond' field is 1 if the switch is true in a conditional spec,
    -1 if false (overridden by a later switch), and is initialized to zero.
-   The `valid' field is nonzero if any spec has looked at this switch;
+   The `validated' field is nonzero if any spec has looked at this switch;
    if it remains zero at the end of the run, it must be meaningless.  */
 
 struct switchstr
@@ -2271,7 +2344,7 @@ struct switchstr
   char *part1;
   char **args;
   int live_cond;
-  int valid;
+  int validated;
 };
 
 static struct switchstr *switches;
@@ -2320,7 +2393,12 @@ convert_filename (name, do_exe)
      int do_exe;
 {
   int i;
-  int len = strlen (name);
+  int len;
+
+  if (name == NULL)
+    return NULL;
+  
+  len = strlen (name);
 
 #ifdef HAVE_OBJECT_SUFFIX
   /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj".  */
@@ -2357,6 +2435,110 @@ convert_filename (name, do_exe)
 }
 #endif
 \f
+/* Display the command line switches accepted by gcc.  */
+static void
+display_help ()
+{
+  printf ("Usage: %s [options] file...\n", programname);
+  printf ("Options:\n");
+
+  printf ("  --help                   Display this information\n");
+  if (! verbose_flag)
+    printf ("  (Use '-v --help' to display command line options of sub-processes)\n");
+  printf ("  -dumpspecs               Display all of the built in spec strings\n");
+  printf ("  -dumpversion             Display the version of the compiler\n");
+  printf ("  -dumpmachine             Display the compiler's target processor\n");
+  printf ("  -print-search-dirs       Display the directories in the compiler's search path\n");
+  printf ("  -print-libgcc-file-name  Display the name of the compiler's companion library\n");
+  printf ("  -print-file-name=<lib>   Display the full path to library <lib>\n");
+  printf ("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n");
+  printf ("  -print-multi-directory   Display the root directory for versions of libgcc\n");
+  printf ("  -print-multi-lib         Display the mapping between command line options and\n");
+  printf ("                            multiple library search directories\n");
+  printf ("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n");
+  printf ("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n");
+  printf ("  -Wl,<options>            Pass comma-separated <options> on to the linker\n");
+  printf ("  -Xlinker <arg>           Pass <arg> on to the linker\n");
+  printf ("  -save-temps              Do not delete intermediate files\n");
+  printf ("  -pipe                    Use pipes rather than intermediate files\n");
+  printf ("  -specs=<file>            Override builtin specs with the contents of <file>\n");
+  printf ("  -std=<standard>          Assume that the input sources are for <standard>\n");
+  printf ("  -B <directory>           Add <directory> to the compiler's search paths\n");
+  printf ("  -b <machine>             Run gcc for target <machine>, if installed\n");
+  printf ("  -V <version>             Run gcc version number <version>, if installed\n");
+  printf ("  -v                       Display the programs invoked by the compiler\n");
+  printf ("  -E                       Preprocess only; do not compile, assemble or link\n");
+  printf ("  -S                       Compile only; do not assemble or link\n");
+  printf ("  -c                       Compile and assemble, but do not link\n");
+  printf ("  -o <file>                Place the output into <file>\n");
+  printf ("  -x <language>            Specify the language of the following input files\n");
+  printf ("                            Permissable languages include: c c++ assembler none\n");
+  printf ("                            'none' means revert to the default behaviour of\n");
+  printf ("                            guessing the language based on the file's extension\n");
+
+  printf ("\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n");
+  printf ("the various sub-processes invoked by %s.  In order to pass other options\n",
+         programname);
+  printf ("on to these processes the -W<letter> options must be used.\n");
+
+  /* The rest of the options are displayed by invocations of the various
+     sub-processes.  */
+}
+
+static void                                                            
+add_preprocessor_option (option, len)                                  
+     char * option;                                                    
+     int    len;                                                       
+{                                                                      
+  n_preprocessor_options++;                                                    
+                                                                       
+  if (! preprocessor_options)                                          
+    preprocessor_options                                                       
+      = (char **) xmalloc (n_preprocessor_options * sizeof (char *));  
+  else                                                                 
+    preprocessor_options                                                       
+      = (char **) xrealloc (preprocessor_options,                              
+                           n_preprocessor_options * sizeof (char *));  
+                                                                       
+  preprocessor_options [n_preprocessor_options - 1] = save_string (option, len);  
+}
+     
+static void                                                            
+add_assembler_option (option, len)                                     
+     char * option;                                                    
+     int    len;                                                       
+{                                                                      
+  n_assembler_options++;                                                       
+                                                                       
+  if (! assembler_options)                                             
+    assembler_options                                                  
+      = (char **) xmalloc (n_assembler_options * sizeof (char *));     
+  else                                                                 
+    assembler_options                                                  
+      = (char **) xrealloc (assembler_options,                         
+                           n_assembler_options * sizeof (char *));     
+                                                                       
+  assembler_options [n_assembler_options - 1] = save_string (option, len);  
+}
+     
+static void                                                            
+add_linker_option (option, len)                                        
+     char * option;                                                    
+     int    len;                                                       
+{                                                                      
+  n_linker_options++;                                                  
+                                                                       
+  if (! linker_options)                                                
+    linker_options                                                     
+      = (char **) xmalloc (n_linker_options * sizeof (char *));        
+  else                                                                 
+    linker_options                                                     
+      = (char **) xrealloc (linker_options,                            
+                           n_linker_options * sizeof (char *));        
+                                                                       
+  linker_options [n_linker_options - 1] = save_string (option, len);  
+}
+\f
 /* Create the vector `switches' and its contents.
    Store its length in `n_switches'.  */
 
@@ -2373,7 +2555,7 @@ process_command (argc, argv)
   int have_o = 0;
   int lang_n_infiles = 0;
 
-  GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
+  GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
 
   n_switches = 0;
   n_infiles = 0;
@@ -2396,7 +2578,7 @@ process_command (argc, argv)
   if (gcc_exec_prefix)
     {
       int len = strlen (gcc_exec_prefix);
-      if (len > sizeof ("/lib/gcc-lib/")-1
+      if (len > (int) sizeof ("/lib/gcc-lib/")-1
          && (gcc_exec_prefix[len-1] == '/'
              || gcc_exec_prefix[len-1] == DIR_SEPARATOR))
        {
@@ -2416,7 +2598,7 @@ process_command (argc, argv)
   /* COMPILER_PATH and LIBRARY_PATH have values
      that are lists of directory names with colons.  */
 
-  GET_ENVIRONMENT (temp, "COMPILER_PATH");
+  GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
   if (temp)
     {
       char *startp, *endp;
@@ -2450,7 +2632,7 @@ process_command (argc, argv)
        }
     }
 
-  GET_ENVIRONMENT (temp, "LIBRARY_PATH");
+  GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
   if (temp && *cross_compile == '0')
     {
       char *startp, *endp;
@@ -2483,7 +2665,7 @@ process_command (argc, argv)
     }
 
   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
-  GET_ENVIRONMENT (temp, "LPATH");
+  GET_ENV_PATH_LIST (temp, "LPATH");
   if (temp && *cross_compile == '0')
     {
       char *startp, *endp;
@@ -2547,6 +2729,19 @@ process_command (argc, argv)
          printf ("%s\n", spec_machine);
          exit  (0);
        }
+      else if (strcmp (argv[i], "-fhelp") == 0)
+       {
+         /* translate_options () has turned --help into -fhelp.  */
+         print_help_list = 1;
+
+         /* We will be passing a dummy file on to the sub-processes.  */
+         n_infiles++;
+         n_switches++;
+         
+         add_preprocessor_option ("--help", 6);
+         add_assembler_option ("--help", 6);
+         add_linker_option ("--help", 6);
+       }
       else if (! strcmp (argv[i], "-print-search-dirs"))
        print_search_dirs = 1;
       else if (! strcmp (argv[i], "-print-libgcc-file-name"))
@@ -2564,60 +2759,34 @@ process_command (argc, argv)
          int prev, j;
          /* Pass the rest of this option to the assembler.  */
 
-         n_assembler_options++;
-         if (!assembler_options)
-           assembler_options
-             = (char **) xmalloc (n_assembler_options * sizeof (char **));
-         else
-           assembler_options
-             = (char **) xrealloc (assembler_options,
-                                   n_assembler_options * sizeof (char **));
-
          /* Split the argument at commas.  */
          prev = 4;
          for (j = 4; argv[i][j]; j++)
            if (argv[i][j] == ',')
              {
-               assembler_options[n_assembler_options - 1]
-                 = save_string (argv[i] + prev, j - prev);
-               n_assembler_options++;
-               assembler_options
-                 = (char **) xrealloc (assembler_options,
-                                       n_assembler_options * sizeof (char **));
+               add_assembler_option (argv[i] + prev, j - prev);
                prev = j + 1;
              }
+         
          /* Record the part after the last comma.  */
-         assembler_options[n_assembler_options - 1] = argv[i] + prev;
+         add_assembler_option (argv[i] + prev, j - prev);
        }
       else if (! strncmp (argv[i], "-Wp,", 4))
        {
          int prev, j;
          /* Pass the rest of this option to the preprocessor.  */
 
-         n_preprocessor_options++;
-         if (!preprocessor_options)
-           preprocessor_options
-             = (char **) xmalloc (n_preprocessor_options * sizeof (char **));
-         else
-           preprocessor_options
-             = (char **) xrealloc (preprocessor_options,
-                                   n_preprocessor_options * sizeof (char **));
-
          /* Split the argument at commas.  */
          prev = 4;
          for (j = 4; argv[i][j]; j++)
            if (argv[i][j] == ',')
              {
-               preprocessor_options[n_preprocessor_options - 1]
-                 = save_string (argv[i] + prev, j - prev);
-               n_preprocessor_options++;
-               preprocessor_options
-                 = (char **) xrealloc (preprocessor_options,
-                                       n_preprocessor_options * sizeof (char **));
+               add_preprocessor_option (argv[i] + prev, j - prev);
                prev = j + 1;
              }
+         
          /* Record the part after the last comma.  */
-         preprocessor_options[n_preprocessor_options - 1] = argv[i] + prev;
+         add_preprocessor_option (argv[i] + prev, j - prev);
        }
       else if (argv[i][0] == '+' && argv[i][1] == 'e')
        /* The +e options to the C++ front-end.  */
@@ -2768,21 +2937,21 @@ process_command (argc, argv)
                char *v = compiler_version;
 
                /* Ignore leading non-digits.  i.e. "foo-" in "foo-2.7.2".  */
-               while (! isdigit (*v))
+               while (! ISDIGIT (*v))
                  v++;
 
                if (v > compiler_version && v[-1] != '-')
                  fatal ("invalid version number format");
 
                /* Set V after the first period.  */
-               while (isdigit (*v))
+               while (ISDIGIT (*v))
                  v++;
 
                if (*v != '.')
                  fatal ("invalid version number format");
 
                v++;
-               while (isdigit (*v))
+               while (ISDIGIT (*v))
                  v++;
 
                if (*v != 0 && *v != ' ' && *v != '.' && *v != '-')
@@ -2790,6 +2959,7 @@ process_command (argc, argv)
              }
              break;
 
+           case 'S':
            case 'c':
              if (p[1] == 0)
                {
@@ -2801,10 +2971,40 @@ process_command (argc, argv)
 
            case 'o':
              have_o = 1;
+#if defined(HAVE_EXECUTABLE_SUFFIX)
+             if (! have_c)
+               {
+                 int skip;
+                 
+                 /* Forward scan, just in case -S or -c is specified
+                    after -o.  */
+                 int j = i + 1;
+                 if (p[1] == 0)
+                   ++j;
+                 while (j < argc)
+                   {
+                     if (argv[j][0] == '-')
+                       {
+                         if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
+                             && argv[j][2] == 0)
+                           {
+                             have_c = 1;
+                             break;
+                           }
+                         else if (skip = SWITCH_TAKES_ARG (argv[j][1]))
+                           j += skip - (argv[j][2] != 0);
+                         else if (skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))
+                           j += skip;
+                       }
+                     j++;
+                   }
+               }
+#endif
 #if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
-             argv[i] = convert_filename (argv[i], 1);
              if (p[1] == 0)
-               argv[i+1] = convert_filename (argv[i+1], 1);
+               argv[i+1] = convert_filename (argv[i+1], ! have_c);
+             else
+               argv[i] = convert_filename (argv[i], ! have_c);
 #endif
              goto normal_switch;
 
@@ -2922,6 +3122,25 @@ process_command (argc, argv)
        ;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        ;
+      else if (strcmp (argv[i], "-fhelp") == 0)
+       {
+         if (verbose_flag)
+           {
+             /* Create a dummy input file, so that we can pass --help on to
+                the various sub-processes.  */
+             infiles[n_infiles].language = "c";
+             infiles[n_infiles++].name   = "help-dummy";
+             
+             /* Preserve the --help switch so that it can be caught by the
+                cc1 spec string.  */
+             switches[n_switches].part1     = "--help";
+             switches[n_switches].args      = 0;
+             switches[n_switches].live_cond = 0;
+             switches[n_switches].validated     = 0;
+             
+             n_switches++;
+           }
+       }
       else if (argv[i][0] == '+' && argv[i][1] == 'e')
        {
          /* Compensate for the +e options to the C++ front-end;
@@ -2932,7 +3151,7 @@ process_command (argc, argv)
          switches[n_switches].part1 = &argv[i][0];
          switches[n_switches].args = 0;
          switches[n_switches].live_cond = 0;
-         switches[n_switches].valid = 0;
+         switches[n_switches].validated = 0;
          n_switches++;
        }
       else if (strncmp (argv[i], "-Wl,", 4) == 0)
@@ -3031,15 +3250,15 @@ process_command (argc, argv)
            switches[n_switches].args = 0;
 
          switches[n_switches].live_cond = 0;
-         switches[n_switches].valid = 0;
+         switches[n_switches].validated = 0;
          /* This is always valid, since gcc.c itself understands it.  */
          if (!strcmp (p, "save-temps"))
-           switches[n_switches].valid = 1;
+           switches[n_switches].validated = 1;
           else
             {
               char ch = switches[n_switches].part1[0];
               if (ch == 'V' || ch == 'b' || ch == 'B')
-                switches[n_switches].valid = 1;
+                switches[n_switches].validated = 1;
             }
          n_switches++;
        }
@@ -3078,9 +3297,9 @@ process_command (argc, argv)
    sans all directory names, and basename_length is the number
    of characters starting there excluding the suffix .c or whatever.  */
 
-static char *input_filename;
+char *input_filename;
 static int input_file_number;
-static size_t input_filename_length;
+size_t input_filename_length;
 static int basename_length;
 static char *input_basename;
 static char *input_suffix;
@@ -3110,7 +3329,7 @@ static int input_from_pipe;
 /* Process the spec SPEC and run the commands specified therein.
    Returns 0 if the spec is successfully processed; -1 if failed.  */
 
-static int
+int
 do_spec (spec)
      char *spec;
 {
@@ -3195,7 +3414,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            if (i < n_switches)
              {
                input_from_pipe = 1;
-               switches[i].valid = 1;
+               switches[i].validated = 1;
                break;
              }
            else
@@ -3381,7 +3600,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case 'e':
-           /* {...:%efoo} means report an error with `foo' as error message
+           /* %efoo means report an error with `foo' as error message
               and don't execute any more commands for this file.  */
            {
              char *q = p;
@@ -3390,7 +3609,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              buf = (char *) alloca (p - q + 1);
              strncpy (buf, q, p - q);
              buf[p - q] = 0;
-             error ("%s", buf);
+             error (buf);
              return -1;
            }
            break;
@@ -3411,16 +3630,30 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                   That matters for the names of object files.
                   In 2.4, do something about that.  */
                struct temp_name *t;
+               int suffix_length;
                char *suffix = p;
-               while (*p == '.' || ISALPHA (*p)
-                      || (p[0] == '%' && p[1] == 'O'))
-                 p++;
+
+               if (p[0] == '%' && p[1] == 'O')
+                 {
+                   p += 2;
+                   /* We don't support extra suffix characters after %O.  */
+                   if (*p == '.' || ISALPHA ((unsigned char)*p))
+                     abort ();
+                   suffix = OBJECT_SUFFIX;
+                   suffix_length = strlen (OBJECT_SUFFIX);
+                 }
+               else
+                 {
+                   while (*p == '.' || ISALPHA ((unsigned char)*p))
+                     p++;
+                   suffix_length = p - suffix;
+                 }
 
                /* See if we already have an association of %g/%u/%U and
                   suffix.  */
                for (t = temp_names; t; t = t->next)
-                 if (t->length == p - suffix
-                     && strncmp (t->suffix, suffix, p - suffix) == 0
+                 if (t->length == suffix_length
+                     && strncmp (t->suffix, suffix, suffix_length) == 0
                      && t->unique == (c != 'g'))
                    break;
 
@@ -3433,10 +3666,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        t->next = temp_names;
                        temp_names = t;
                      }
-                   t->length = p - suffix;
-                   t->suffix = save_string (suffix, p - suffix);
+                   t->length = suffix_length;
+                   t->suffix = save_string (suffix, suffix_length);
                    t->unique = (c != 'g');
-                   temp_filename = choose_temp_base ();
+                   temp_filename = make_temp_file (t->suffix);
                    temp_filename_length = strlen (temp_filename);
                    t->filename = temp_filename;
                    t->filename_length = temp_filename_length;
@@ -3491,9 +3724,16 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case 'o':
-           for (i = 0; i < n_infiles; i++)
-             store_arg (outfiles[i], 0, 0);
-           break;
+           {
+             int max = n_infiles;
+#ifdef LANG_SPECIFIC_DRIVER
+             max += lang_specific_extra_outfiles;
+#endif
+             for (i = 0; i < max; i++)
+               if (outfiles[i])
+                 store_arg (outfiles[i], 0, 0);
+             break;
+           }
 
          case 'O':
            obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
@@ -3546,16 +3786,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                  }
 
              /* This option is new; add it.  */
-             n_linker_options++;
-             if (!linker_options)
-               linker_options
-                 = (char **) xmalloc (n_linker_options * sizeof (char **));
-             else
-               linker_options
-                 = (char **) xrealloc (linker_options,
-                                       n_linker_options * sizeof (char **));
-
-             linker_options[n_linker_options - 1] = string;
+             add_linker_option (string, strlen (string));
            }
            break;
 
@@ -3701,7 +3932,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      *x++ = *y++;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+                         || (*(y+1) != '_'
+                             && ! ISUPPER ((unsigned char)*(y+1))))
                        {
                          /* Stick __ at front of macro name.  */
                          *x++ = '_';
@@ -3743,7 +3975,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      y += 2;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+                         || (*(y+1) != '_'
+                             && ! ISUPPER ((unsigned char)*(y+1))))
                        {
                          /* Stick -D__ at front of macro name.  */
                          *x++ = '-';
@@ -3827,8 +4060,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
               to add and use their own specs.
               %[...] modifies -D options the way %P does;
               %(...) uses the spec unmodified.  */
-         case '(':
          case '[':
+           error ("Warning: use of obsolete %%[ operator in specs");
+         case '(':
            {
              char *name = p;
              struct spec_list *sl;
@@ -3845,8 +4079,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                  {
                    name = *(sl->ptr_spec);
 #ifdef DEBUG_SPECS
-                   fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
-                            c, sl->name, (c == '(') ? ')' : ']', name);
+                   notice ("Processing spec %c%s%c, which is '%s'\n",
+                           c, sl->name, (c == '(') ? ')' : ']', name);
 #endif
                    break;
                  }
@@ -3975,11 +4209,10 @@ static char *
 handle_braces (p)
      register char *p;
 {
-  register char *q;
-  char *filter;
+  char *filter, *body = NULL, *endbody;
   int pipe_p = 0;
-  int negate = 0;
-  int suffix = 0;
+  int negate;
+  int suffix;
   int include_blanks = 1;
 
   if (*p == '^')
@@ -3992,6 +4225,9 @@ handle_braces (p)
        This is used in %{|!pipe:...}.  */
     pipe_p = 1, ++p;
 
+next_member:
+  negate = suffix = 0;
+
   if (*p == '!')
     /* A `!' after the open-brace negates the condition:
        succeed if the specified switch is not present.  */
@@ -4008,39 +4244,49 @@ handle_braces (p)
     }
 
   filter = p;
-  while (*p != ':' && *p != '}') p++;
-  if (*p != '}')
+  while (*p != ':' && *p != '}' && *p != '|') p++;
+
+  if (*p == '|' && pipe_p)
+    abort ();
+
+  if (!body)
     {
-      register int count = 1;
-      q = p + 1;
-      while (count > 0)
-       {
-         if (*q == '{')
-           count++;
-         else if (*q == '}')
-           count--;
-         else if (*q == 0)
-           abort ();
-         q++;
+      if (*p != '}')
+        {
+         register int count = 1;
+         register char *q = p;
+
+         while (*q++ != ':') continue;
+         body = q;
+         
+         while (count > 0)
+           {
+             if (*q == '{')
+               count++;
+             else if (*q == '}')
+               count--;
+             else if (*q == 0)
+               abort ();
+             q++;
+           }
+         endbody = q;
        }
+      else
+       body = p, endbody = p+1;
     }
-  else
-    q = p + 1;
 
   if (suffix)
     {
       int found = (input_suffix != 0
-                  && strlen (input_suffix) == p - filter
+                  && (long) strlen (input_suffix) == (long)(p - filter)
                   && strncmp (input_suffix, filter, p - filter) == 0);
 
-      if (p[0] == '}')
+      if (body[0] == '}')
        abort ();
 
       if (negate != found
-         && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
+         && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
        return 0;
-
-      return q;
     }
   else if (p[-1] == '*' && p[0] == '}')
     {
@@ -4063,11 +4309,11 @@ handle_braces (p)
       if (p[-1] == '*' && !negate)
        {
          int substitution;
-         char *r = p;
+         char *r = body;
 
          /* First see whether we have %*.  */
          substitution = 0;
-         while (r < q)
+         while (r < endbody)
            {
              if (*r == '%' && r[1] == '*')
                substitution = 1;
@@ -4081,7 +4327,7 @@ handle_braces (p)
                 in the text that follows the colon.  */
 
              unsigned hard_match_len = p - filter - 1;
-             char *string = save_string (p + 1, q - p - 2);
+             char *string = save_string (body, endbody - body - 1);
 
              for (i = 0; i < n_switches; i++)
                if (!strncmp (switches[i].part1, filter, hard_match_len)
@@ -4092,7 +4338,10 @@ handle_braces (p)
                    give_switch (i, 1, 1);
                  }
 
-             return q;
+             /* We didn't match.  Try again.  */
+             if (*p++ == '|')
+               goto next_member;
+             return endbody;
            }
        }
 
@@ -4126,7 +4375,7 @@ handle_braces (p)
            }
        }
 
-      /* If it is as desired (present for %{s...}, absent for %{-s...})
+      /* If it is as desired (present for %{s...}, absent for %{!s...})
         then substitute either the switch or the specified
         conditional text.  */
       if (present != negate)
@@ -4137,7 +4386,8 @@ handle_braces (p)
            }
          else
            {
-             if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
+             if (do_spec_1 (save_string (body, endbody - body - 1),
+                            0, NULL_PTR) < 0)
                return 0;
            }
        }
@@ -4146,10 +4396,15 @@ handle_braces (p)
          /* Here if a %{|...} conditional fails: output a minus sign,
             which means "standard output" or "standard input".  */
          do_spec_1 ("-", 0, NULL_PTR);
+         return endbody;
        }
     }
 
-  return q;
+  /* We didn't match; try again.  */
+  if (*p++ == '|')
+    goto next_member;
+
+  return endbody;
 }
 \f
 /* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
@@ -4186,7 +4441,7 @@ check_live_switch (switchnum, prefix_length)
        for (i = switchnum + 1; i < n_switches; i++)
          if (switches[i].part1[0] == 'O')
            {
-             switches[switchnum].valid = 1;
+             switches[switchnum].validated = 1;
              switches[switchnum].live_cond = -1;
              return 0;
            }
@@ -4200,7 +4455,7 @@ check_live_switch (switchnum, prefix_length)
            if (switches[i].part1[0] == name[0]
                && ! strcmp (&switches[i].part1[1], &name[4]))
            {
-             switches[switchnum].valid = 1;
+             switches[switchnum].validated = 1;
              switches[switchnum].live_cond = -1;
              return 0;
            }
@@ -4215,7 +4470,7 @@ check_live_switch (switchnum, prefix_length)
                && switches[i].part1[3] == '-'
                && !strcmp (&switches[i].part1[4], &name[1]))
            {
-             switches[switchnum].valid = 1;
+             switches[switchnum].validated = 1;
              switches[switchnum].live_cond = -1;
              return 0;
            }
@@ -4263,7 +4518,7 @@ give_switch (switchnum, omit_first_word, include_blanks)
     }
 
   do_spec_1 (" ", 0, NULL_PTR);
-  switches[switchnum].valid = 1;
+  switches[switchnum].validated = 1;
 }
 \f
 /* Search for a file named NAME trying various prefixes including the
@@ -4323,8 +4578,8 @@ is_directory (path1, path2, linker)
   /* Construct the path from the two parts.  Ensure the string ends with "/.".
      The resulting path will be a directory even if the given path is a
      symbolic link.  */
-  bcopy (path1, path, len1);
-  bcopy (path2, path + len1, len2);
+  memcpy (path, path1, len1);
+  memcpy (path + len1, path2, len2);
   cp = path + len1 + len2;
   if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR)
     *cp++ = DIR_SEPARATOR;
@@ -4377,6 +4632,12 @@ main (argc, argv)
   while (p != argv[0] && p[-1] != '/' && p[-1] != DIR_SEPARATOR) --p;
   programname = p;
 
+#ifdef HAVE_LC_MESSAGES
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, localedir);
+  textdomain (PACKAGE);
+
   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
     signal (SIGINT, fatal_error);
 #ifdef SIGHUP
@@ -4447,8 +4708,10 @@ main (argc, argv)
 
   /* Choose directory for temp files.  */
 
+#ifndef MKTEMP_EACH_FILE
   temp_filename = choose_temp_base ();
   temp_filename_length = strlen (temp_filename);
+#endif
 
   /* Make a table of what switches there are (switches, n_switches).
      Make a table of specified input files (infiles, n_infiles).
@@ -4465,7 +4728,7 @@ main (argc, argv)
                  sizeof ("COLLECT_GCC_OPTIONS=")-1);
 
     first_time = TRUE;
-    for (i = 0; i < n_switches; i++)
+    for (i = 0; (int)i < n_switches; i++)
       {
        char **args;
        char *p, *q;
@@ -4636,8 +4899,8 @@ main (argc, argv)
 
   /* Warn about any switches that no pass was interested in.  */
 
-  for (i = 0; i < n_switches; i++)
-    if (! switches[i].valid)
+  for (i = 0; (int)i < n_switches; i++)
+    if (! switches[i].validated)
       error ("unrecognized option `-%s'", switches[i].part1);
 
   /* Obey some of the options.  */
@@ -4678,6 +4941,23 @@ main (argc, argv)
       exit (0);
     }
 
+  if (print_help_list)
+    {
+      display_help ();
+
+      if (! verbose_flag)
+       {
+         printf ("\nReport bugs to egcs-bugs@egcs.cygnus.com.\n");
+         printf ("Please see the file BUGS (included with the sources) first.\n");
+         
+         exit (0);
+       }
+
+      /* We do not exit here.  Instead we have created a fake input file
+        called 'help-dummy' which needs to be compiled, and we pass this
+        on the the various sub-processes, along with the --help switch.  */
+    }
+  
   if (verbose_flag)
     {
       int n;
@@ -4691,10 +4971,10 @@ main (argc, argv)
 
       if (! strncmp (version_string, compiler_version, n)
          && compiler_version[n] == 0)
-       fprintf (stderr, "gcc version %s\n", version_string);
+       notice ("gcc version %s\n", version_string);
       else
-       fprintf (stderr, "gcc driver version %s executing gcc version %s\n",
-                version_string, compiler_version);
+       notice ("gcc driver version %s executing gcc version %s\n",
+               version_string, compiler_version);
 
       if (n_infiles == 0)
        exit (0);
@@ -4706,15 +4986,19 @@ main (argc, argv)
   /* Make a place to record the compiler output file names
      that correspond to the input files.  */
 
-  outfiles = (char **) xmalloc (n_infiles * sizeof (char *));
-  bzero ((char *) outfiles, n_infiles * sizeof (char *));
+  i = n_infiles;
+#ifdef LANG_SPECIFIC_DRIVER
+  i += lang_specific_extra_outfiles;
+#endif
+  outfiles = (char **) xmalloc (i * sizeof (char *));
+  bzero ((char *) outfiles, i * sizeof (char *));
 
   /* Record which files were specified explicitly as link input.  */
 
   explicit_link_files = xmalloc (n_infiles);
   bzero (explicit_link_files, n_infiles);
 
-  for (i = 0; i < n_infiles; i++)
+  for (i = 0; (int)i < n_infiles; i++)
     {
       register struct compiler *cp = 0;
       int this_file_error = 0;
@@ -4802,6 +5086,17 @@ main (argc, argv)
       clear_failure_queue ();
     }
 
+#ifdef LANG_SPECIFIC_DRIVER
+  if (error_count == 0)
+    {
+      /* Make sure INPUT_FILE_NUMBER points to first available open
+        slot.  */
+      input_file_number = n_infiles;
+      if (lang_specific_pre_link ())
+       error_count++;
+    }
+#endif
+
   /* Run ld to link all the compiler output files.  */
 
   if (error_count == 0)
@@ -4834,7 +5129,7 @@ main (argc, argv)
      complain about input files to be given to the linker.  */
 
   if (! linker_was_run && error_count == 0)
-    for (i = 0; i < n_infiles; i++)
+    for (i = 0; (int)i < n_infiles; i++)
       if (explicit_link_files[i])
        error ("%s: linker input file unused since linking not done",
               outfiles[i]);
@@ -4845,6 +5140,12 @@ main (argc, argv)
     delete_failure_queue ();
   delete_temp_files ();
 
+  if (print_help_list)
+    {
+      printf ("\nReport bugs to egcs-bugs@egcs.cygnus.com.\n");
+      printf ("Please see the file BUGS (included with the sources) first.\n");
+    }
+  
   exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
   /* NOTREACHED */
   return 0;
@@ -4920,85 +5221,35 @@ lookup_compiler (name, length, language)
   return 0;
 }
 \f
-char *
+PTR
 xmalloc (size)
-     unsigned size;
+  size_t size;
 {
-  register char *value = (char *) malloc (size);
+  register PTR value = (PTR) malloc (size);
   if (value == 0)
     fatal ("virtual memory exhausted");
   return value;
 }
 
-char *
-xrealloc (ptr, size)
-     char *ptr;
-     unsigned size;
+PTR
+xrealloc (old, size)
+  PTR old;
+  size_t size;
 {
-  register char *value = (char *) realloc (ptr, size);
-  if (value == 0)
+  register PTR ptr;
+  if (old)
+    ptr = (PTR) realloc (old, size);
+  else
+    ptr = (PTR) malloc (size);
+  if (ptr == 0)
     fatal ("virtual memory exhausted");
-  return value;
-}
-
-/* This function is based on the one in libiberty.  */
-
-static char *
-concat VPROTO((char *first, ...))
-{
-  register int length;
-  register char *newstr;
-  register char *end;
-  register char *arg;
-  va_list args;
-#ifndef __STDC__
-  char *first;
-#endif
-
-  /* First compute the size of the result and get sufficient memory.  */
-
-  VA_START (args, first);
-#ifndef __STDC__
-  first = va_arg (args, char *);
-#endif
-
-  arg = first;
-  length = 0;
-
-  while (arg != 0)
-    {
-      length += strlen (arg);
-      arg = va_arg (args, char *);
-    }
-
-  newstr = (char *) xmalloc (length + 1);
-  va_end (args);
-
-  /* Now copy the individual pieces to the result string.  */
-
-  VA_START (args, first);
-#ifndef __STDC__
-  first = va_arg (args, char *);
-#endif
-
-  end = newstr;
-  arg = first;
-  while (arg != 0)
-    {
-      while (*arg)
-       *end++ = *arg++;
-      arg = va_arg (args, char *);
-    }
-  *end = '\000';
-  va_end (args);
-
-  return (newstr);
+  return ptr;
 }
 
 static char *
 save_string (s, len)
-     char *s;
-     int len;
+  const char *s;
+  int len;
 {
   register char *result = xmalloc (len + 1);
 
@@ -5011,14 +5262,16 @@ static void
 pfatal_with_name (name)
      char *name;
 {
-  fatal ("%s: %s", name, my_strerror (errno));
+  perror_with_name (name);
+  delete_temp_files ();
+  exit (1);
 }
 
 static void
 perror_with_name (name)
      char *name;
 {
-  error ("%s: %s", name, my_strerror (errno));
+  error ("%s: %s", name, xstrerror (errno));
 }
 
 static void
@@ -5026,17 +5279,19 @@ pfatal_pexecute (errmsg_fmt, errmsg_arg)
      char *errmsg_fmt;
      char *errmsg_arg;
 {
-  int save_errno = errno;
-
   if (errmsg_arg)
     {
+      int save_errno = errno;
+
       /* Space for trailing '\0' is in %s.  */
       char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
       sprintf (msg, errmsg_fmt, errmsg_arg);
       errmsg_fmt = msg;
+
+      errno = save_errno;
     }
 
-  fatal ("%s: %s", errmsg_fmt, my_strerror (save_errno));
+  pfatal_with_name (errmsg_fmt);
 }
 
 /* More 'friendly' abort that prints the line and file.
@@ -5048,26 +5303,24 @@ fancy_abort ()
   fatal ("Internal gcc abort.");
 }
 \f
-#ifdef HAVE_VPRINTF
-
 /* Output an error message and exit */
 
 static void
-fatal VPROTO((char *format, ...))
+fatal VPROTO((char *msgid, ...))
 {
-#ifndef __STDC__
-  char *format;
+#ifndef ANSI_PROTOTYPES
+  char *msgid;
 #endif
   va_list ap;
 
-  VA_START (ap, format);
+  VA_START (ap, msgid);
 
-#ifndef __STDC__
-  format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, char *);
 #endif
 
   fprintf (stderr, "%s: ", programname);
-  vfprintf (stderr, format, ap);
+  vfprintf (stderr, _(msgid), ap);
   va_end (ap);
   fprintf (stderr, "\n");
   delete_temp_files ();
@@ -5075,47 +5328,43 @@ fatal VPROTO((char *format, ...))
 }
 
 static void
-error VPROTO((char *format, ...))
+error VPROTO((char *msgid, ...))
 {
-#ifndef __STDC__
-  char *format;
+#ifndef ANSI_PROTOTYPES
+  char *msgid;
 #endif
   va_list ap;
 
-  VA_START (ap, format);
+  VA_START (ap, msgid);
 
-#ifndef __STDC__
-  format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, char *);
 #endif
 
   fprintf (stderr, "%s: ", programname);
-  vfprintf (stderr, format, ap);
+  vfprintf (stderr, _(msgid), ap);
   va_end (ap);
 
   fprintf (stderr, "\n");
 }
 
-#else /* not HAVE_VPRINTF */
-
 static void
-fatal (msg, arg1, arg2)
-     char *msg, *arg1, *arg2;
+notice VPROTO((char *msgid, ...))
 {
-  error (msg, arg1, arg2);
-  delete_temp_files ();
-  exit (1);
-}
+#ifndef ANSI_PROTOTYPES
+  char *msgid;
+#endif
+  va_list ap;
 
-static void
-error (msg, arg1, arg2)
-     char *msg, *arg1, *arg2;
-{
-  fprintf (stderr, "%s: ", programname);
-  fprintf (stderr, msg, arg1, arg2);
-  fprintf (stderr, "\n");
-}
+  VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  msgid = va_arg (ap, char *);
+#endif
 
-#endif /* not HAVE_VPRINTF */
+  vfprintf (stderr, _(msgid), ap);
+  va_end (ap);
+}
 
 \f
 static void
@@ -5188,7 +5437,7 @@ validate_switches (start)
       --p;
       for (i = 0; i < n_switches; i++)
        if (!strncmp (switches[i].part1, filter, p - filter))
-         switches[i].valid = 1;
+         switches[i].validated = 1;
     }
   else
     {
@@ -5197,7 +5446,7 @@ validate_switches (start)
        {
          if (!strncmp (switches[i].part1, filter, p - filter)
              && switches[i].part1[p - filter] == 0)
-           switches[i].valid = 1;
+           switches[i].validated = 1;
        }
     }
 }