OSDN Git Service

X
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index ac0b36c..a7eb71e 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -32,12 +32,6 @@ 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"
 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 "system.h"
 #include <signal.h>
 #include <sys/stat.h>
@@ -75,11 +69,6 @@ extern void set_std_prefix PROTO((char *, int));
 #define exit __posix_exit
 #endif
 
 #define exit __posix_exit
 #endif
 
-/* Define O_RDONLY if the system hasn't defined it for us.  */
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
 #ifdef USG
 #define vfork fork
 #endif /* USG */
 #ifdef USG
 #define vfork fork
 #endif /* USG */
@@ -122,18 +111,11 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0};
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
 #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)
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
 #endif
 
 #endif
 
-extern char *choose_temp_base PROTO((void));
-
-#ifndef HAVE_STRERROR
-extern int sys_nerr;
-extern char *sys_errlist[];
-#else
-extern char *strerror();
-#endif
+extern char *my_strerror PROTO((int));
 
 #ifndef HAVE_KILL
 #define kill(p,s) raise(s)
 
 #ifndef HAVE_KILL
 #define kill(p,s) raise(s)
@@ -168,6 +150,11 @@ static int print_multi_directory;
 
 static int print_multi_lib;
 
 
 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;
 /* Flag indicating whether we should print the command and arguments */
 
 static int verbose_flag;
@@ -237,7 +224,7 @@ 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 char *handle_braces     PROTO((char *));
 static char *save_string       PROTO((char *, int));
 static char *concat            PVPROTO((char *, ...));
-static int do_spec             PROTO((char *));
+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));
 static int do_spec_1           PROTO((char *, int, char *));
 static char *find_file         PROTO((char *));
 static int is_directory                PROTO((char *, char *, int));
@@ -248,24 +235,26 @@ 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 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 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 *, ...));
 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 display_help       PROTO((void));
 
 
-void fancy_abort ();
+void fancy_abort               PROTO((void)) ATTRIBUTE_NORETURN;
 char *xmalloc ();
 char *xrealloc ();
 
 #ifdef LANG_SPECIFIC_DRIVER
 char *xmalloc ();
 char *xrealloc ();
 
 #ifdef LANG_SPECIFIC_DRIVER
-extern void lang_specific_driver PROTO ((void (*) (), int *, char ***));
+/* 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)
 #endif
 \f
 /* Specs are strings containing lines, each of which (if not blank)
@@ -286,12 +275,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.
  %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.
  %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.
@@ -308,7 +315,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.
        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.
  %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.
@@ -332,7 +345,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
         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.
  %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.
@@ -367,6 +380,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: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
 
  %(Spec) processes a specification defined in a specs file as *Spec:
  %[Spec] as above, but put __ around -D arguments
 
@@ -380,8 +395,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.
 
 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
 
 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
@@ -477,6 +493,10 @@ proper position among the other output files.  */
 #endif
 #endif
 
 #endif
 #endif
 
+#ifndef LINKER_NAME
+#define LINKER_NAME "collect2"
+#endif
+
 static char *cpp_spec = CPP_SPEC;
 static char *cpp_predefines = CPP_PREDEFINES;
 static char *cc1_spec = CC1_SPEC;
 static char *cpp_spec = CPP_SPEC;
 static char *cpp_predefines = CPP_PREDEFINES;
 static char *cc1_spec = CC1_SPEC;
@@ -490,6 +510,7 @@ static char *libgcc_spec = LIBGCC_SPEC;
 static char *endfile_spec = ENDFILE_SPEC;
 static char *startfile_spec = STARTFILE_SPEC;
 static char *switches_need_spaces = SWITCHES_NEED_SPACES;
 static char *endfile_spec = ENDFILE_SPEC;
 static char *startfile_spec = STARTFILE_SPEC;
 static char *switches_need_spaces = SWITCHES_NEED_SPACES;
+static char *linker_name_spec = LINKER_NAME;
 
 /* Some compilers have limits on line lengths, and the multilib_select
    and/or multilib_matches strings can be very long, so we build them at
 
 /* Some compilers have limits on line lengths, and the multilib_select
    and/or multilib_matches strings can be very long, so we build them at
@@ -542,6 +563,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
 #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
 /* Record the mapping from file suffixes for compilation specs.  */
 
 struct compiler
@@ -584,7 +617,43 @@ static struct compiler default_compilers[] =
   /* Next come the entries for C.  */
   {".c", {"@c"}},
   {"@c",
   /* 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:89} %{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} \
+        %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 \
+                  -lang-c%{ansi:89} %{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:-trigraphs -D__STRICT_ANSI__}\
+                  %{!undef:%{!ansi:%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*}\
+                 %{--help:--help} \
+                 %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+                 %{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:89} %{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\
        %{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\
@@ -593,18 +662,22 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
         %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",
        %{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} \
                   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
                   %{aux-info*}\
                   %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
                   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
                   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
                   %{aux-info*}\
+                  %{--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}\
                   %{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\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
   {"-",
    {"%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
@@ -615,6 +688,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
         %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}"}},
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}}\
     %{!E:%e-E required when input is from standard input}"}},
@@ -629,6 +703,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
         %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:cc1obj %{!pipe:%g.i} %1 \
        %{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 \
@@ -654,6 +729,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
         %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"}},
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}"}},
   {".i", {"@cpp-output"}},
@@ -681,6 +757,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
         %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\
        %{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\
@@ -704,11 +781,17 @@ 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.  */
 /* 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 = "\
 %{!fsyntax-only: \
 #ifdef LINK_LIBGCC_SPECIAL
 /* Don't generate -L options.  */
 static char *link_command_spec = "\
 %{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
                        %{static:} %{L*} %o\
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
                        %{static:} %{L*} %o\
@@ -720,7 +803,7 @@ static char *link_command_spec = "\
 /* Use -L.  */
 static char *link_command_spec = "\
 %{!fsyntax-only: \
 /* Use -L.  */
 static char *link_command_spec = "\
 %{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
                        %{static:} %{L*} %D %o\
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
                        %{static:} %{L*} %D %o\
@@ -729,6 +812,7 @@ static char *link_command_spec = "\
                        %{T*}\
                        \n }}}}}}";
 #endif
                        %{T*}\
                        \n }}}}}}";
 #endif
+#endif
 
 /* A vector of options to give to the linker.
    These options are accumulated by %x,
 
 /* A vector of options to give to the linker.
    These options are accumulated by %x,
@@ -774,6 +858,8 @@ struct option_map option_map[] =
    {"--ansi", "-ansi", 0},
    {"--assemble", "-S", 0},
    {"--assert", "-A", "a"},
    {"--ansi", "-ansi", 0},
    {"--assemble", "-S", 0},
    {"--assert", "-A", "a"},
+   {"--classpath", "-fclasspath=", "aj"},
+   {"--CLASSPATH", "-fCLASSPATH=", "aj"},
    {"--comments", "-C", 0},
    {"--compile", "-c", 0},
    {"--debug", "-g", "oj"},
    {"--comments", "-C", 0},
    {"--compile", "-c", 0},
    {"--debug", "-g", "oj"},
@@ -852,7 +938,7 @@ translate_options (argcp, argvp)
      int *argcp;
      char ***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 *));
   int argc = *argcp;
   char **argv = *argvp;
   char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
@@ -866,6 +952,7 @@ translate_options (argcp, argvp)
       /* Translate -- options.  */
       if (argv[i][0] == '-' && argv[i][1] == '-')
        {
       /* 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++)
            {
          /* Find a mapping that applies to this option.  */
          for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
            {
@@ -883,6 +970,7 @@ translate_options (argcp, argvp)
 
                  if (arglen < optlen)
                    {
 
                  if (arglen < optlen)
                    {
+                     size_t k;
                      for (k = j + 1;
                           k < sizeof (option_map) / sizeof (option_map[0]);
                           k++)
                      for (k = j + 1;
                           k < sizeof (option_map) / sizeof (option_map[0]);
                           k++)
@@ -1093,10 +1181,20 @@ static struct spec_list static_specs[] = {
   INIT_STATIC_SPEC ("multilib_defaults",       &multilib_defaults),
   INIT_STATIC_SPEC ("multilib_extra",          &multilib_extra),
   INIT_STATIC_SPEC ("multilib_matches",                &multilib_matches),
   INIT_STATIC_SPEC ("multilib_defaults",       &multilib_defaults),
   INIT_STATIC_SPEC ("multilib_extra",          &multilib_extra),
   INIT_STATIC_SPEC ("multilib_matches",                &multilib_matches),
+  INIT_STATIC_SPEC ("linker",                  &linker_name_spec),
 };
 
 #ifdef EXTRA_SPECS             /* additional specs needed */
 };
 
 #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.  */
 #endif
 
 /* List of dynamically allocates specs that have been defined so far.  */
@@ -1120,9 +1218,17 @@ init_spec ()
     fprintf (stderr, "Using builtin specs.\n");
 
 #ifdef EXTRA_SPECS
     fprintf (stderr, "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 = &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;
       sl->next = next;
       sl->name_len = strlen (sl->name);
       sl->ptr_spec = &sl->ptr;
@@ -1188,7 +1294,7 @@ set_spec (name, spec)
     }
 
   old_spec = *(sl->ptr_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)));
 
                     ? concat (old_spec, spec + 1, NULL_PTR)
                     : save_string (spec, strlen (spec)));
 
@@ -1218,7 +1324,13 @@ static int argbuf_length;
 
 static int argbuf_index;
 
 
 static int argbuf_index;
 
+/* We want this on by default all the time now.  */
+#define MKTEMP_EACH_FILE
+
 #ifdef 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.  */
 
 /* This is the list of suffixes and codes (%g/%u/%U) and the associated
    temp file.  */
 
@@ -1230,8 +1342,11 @@ static struct temp_name {
   int filename_length; /* strlen (filename).  */
   struct temp_name *next;
 } *temp_names;
   int filename_length; /* strlen (filename).  */
   struct temp_name *next;
 } *temp_names;
+#else
+extern char *choose_temp_base PROTO((void));
 #endif
 
 #endif
 
+
 /* Number of commands executed so far.  */
 
 static int execution_count;
 /* Number of commands executed so far.  */
 
 static int execution_count;
@@ -1478,12 +1593,12 @@ read_specs (filename, main_p)
              while (*p1 == ' ' || *p1 == '\t')
                p1++;
 
              while (*p1 == ' ' || *p1 == '\t')
                p1++;
 
-             if (! ISALPHA (*p1))
+             if (! ISALPHA ((unsigned char)*p1))
                fatal ("specs %%rename syntax malformed after %d characters",
                       p1 - buffer);
 
              p2 = p1;
                fatal ("specs %%rename syntax malformed after %d characters",
                       p1 - buffer);
 
              p2 = p1;
-             while (*p2 && !ISSPACE (*p2))
+             while (*p2 && !ISSPACE ((unsigned char)*p2))
                p2++;
 
              if (*p2 != ' ' && *p2 != '\t')
                p2++;
 
              if (*p2 != ' ' && *p2 != '\t')
@@ -1495,13 +1610,13 @@ read_specs (filename, main_p)
              while (*p2 == ' ' || *p2 == '\t')
                p2++;
 
              while (*p2 == ' ' || *p2 == '\t')
                p2++;
 
-             if (! ISALPHA (*p2))
+             if (! ISALPHA ((unsigned char)*p2))
                fatal ("specs %%rename syntax malformed after %d characters",
                       p2 - buffer);
 
              /* Get new spec name */
              p3 = p2;
                fatal ("specs %%rename syntax malformed after %d characters",
                       p2 - buffer);
 
              /* Get new spec name */
              p3 = p2;
-             while (*p3 && !ISSPACE (*p3))
+             while (*p3 && !ISSPACE ((unsigned char)*p3))
                p3++;
 
              if (p3 != p-1)
                p3++;
 
              if (p3 != p-1)
@@ -1562,8 +1677,8 @@ read_specs (filename, main_p)
        fatal ("specs file malformed after %d characters", p - buffer);
 
       p1 = p;
        fatal ("specs file malformed after %d characters", 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.  */
        p1++;
 
       /* Specs end at the blank line and do not include the newline.  */
@@ -1796,7 +1911,7 @@ putenv (str)
   /* Add a new environment variable */
   environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
   *environ = 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 */
         sizeof (char *) * (num_envs+1));
 
 #endif /* VMS */
@@ -1895,6 +2010,26 @@ find_a_file (pprefix, name, mode)
   struct prefix_list *pl;
   int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
 
   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);
 
   if (machine_suffix)
     len += strlen (machine_suffix);
 
@@ -1907,7 +2042,7 @@ find_a_file (pprefix, name, mode)
       || (DIR_SEPARATOR == '\\' && name[1] == ':'
          && (name[2] == DIR_SEPARATOR || name[2] == '/')))
     {
       || (DIR_SEPARATOR == '\\' && name[1] == ':'
          && (name[2] == DIR_SEPARATOR || name[2] == '/')))
     {
-      if (access (name, mode))
+      if (access (name, mode) == 0)
        {
          strcpy (temp, name);
          return temp;
        {
          strcpy (temp, name);
          return temp;
@@ -2130,6 +2265,7 @@ execute ()
   commands[0].prog = argbuf[0]; /* first command.  */
   commands[0].argv = &argbuf[0];
   string = find_a_file (&exec_prefixes, commands[0].prog, X_OK);
   commands[0].prog = argbuf[0]; /* first command.  */
   commands[0].argv = &argbuf[0];
   string = find_a_file (&exec_prefixes, commands[0].prog, X_OK);
+
   if (string)
     commands[0].argv[0] = string;
 
   if (string)
     commands[0].argv[0] = string;
 
@@ -2154,6 +2290,10 @@ execute ()
 
   if (verbose_flag)
     {
 
   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++)
        {
       /* Print each piped command as a separate line.  */
       for (i = 0; i < n_commands ; i++)
        {
@@ -2284,6 +2424,11 @@ static struct infile *infiles;
 
 static int n_infiles;
 
 
 static int n_infiles;
 
+/* This counts the number of libraries added by LANG_SPECIFIC_DRIVER, so that
+   we can tell if there were any user supplied any files or libraries.  */
+
+static int added_libraries;
+
 /* And a vector of corresponding output files is made up later.  */
 
 static char **outfiles;
 /* And a vector of corresponding output files is made up later.  */
 
 static char **outfiles;
@@ -2346,6 +2491,109 @@ convert_filename (name, do_exe)
 }
 #endif
 \f
 }
 #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 ("  -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'.  */
 
 /* Create the vector `switches' and its contents.
    Store its length in `n_switches'.  */
 
@@ -2362,10 +2610,11 @@ process_command (argc, argv)
   int have_o = 0;
   int lang_n_infiles = 0;
 
   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;
 
   n_switches = 0;
   n_infiles = 0;
+  added_libraries = 0;
 
   /* Figure compiler version from version string.  */
 
 
   /* Figure compiler version from version string.  */
 
@@ -2384,7 +2633,7 @@ process_command (argc, argv)
   if (gcc_exec_prefix)
     {
       int len = strlen (gcc_exec_prefix);
   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))
        {
          && (gcc_exec_prefix[len-1] == '/'
              || gcc_exec_prefix[len-1] == DIR_SEPARATOR))
        {
@@ -2404,7 +2653,7 @@ process_command (argc, argv)
   /* COMPILER_PATH and LIBRARY_PATH have values
      that are lists of directory names with colons.  */
 
   /* 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;
   if (temp)
     {
       char *startp, *endp;
@@ -2438,7 +2687,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;
   if (temp && *cross_compile == '0')
     {
       char *startp, *endp;
@@ -2471,7 +2720,7 @@ process_command (argc, argv)
     }
 
   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
     }
 
   /* 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;
   if (temp && *cross_compile == '0')
     {
       char *startp, *endp;
@@ -2508,7 +2757,7 @@ process_command (argc, argv)
 
 #ifdef LANG_SPECIFIC_DRIVER
   /* Do language-specific adjustment/addition of flags.  */
 
 #ifdef LANG_SPECIFIC_DRIVER
   /* Do language-specific adjustment/addition of flags.  */
-  lang_specific_driver (fatal, &argc, &argv);
+  lang_specific_driver (fatal, &argc, &argv, &added_libraries);
 #endif
 
   /* Scan argv twice.  Here, the first time, just count how many switches
 #endif
 
   /* Scan argv twice.  Here, the first time, just count how many switches
@@ -2527,7 +2776,7 @@ process_command (argc, argv)
        }
       else if (! strcmp (argv[i], "-dumpversion"))
        {
        }
       else if (! strcmp (argv[i], "-dumpversion"))
        {
-         printf ("%s\n", version_string);
+         printf ("%s\n", spec_version);
          exit (0);
        }
       else if (! strcmp (argv[i], "-dumpmachine"))
          exit (0);
        }
       else if (! strcmp (argv[i], "-dumpmachine"))
@@ -2535,6 +2784,19 @@ process_command (argc, argv)
          printf ("%s\n", spec_machine);
          exit  (0);
        }
          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"))
       else if (! strcmp (argv[i], "-print-search-dirs"))
        print_search_dirs = 1;
       else if (! strcmp (argv[i], "-print-libgcc-file-name"))
@@ -2552,60 +2814,34 @@ process_command (argc, argv)
          int prev, j;
          /* Pass the rest of this option to the assembler.  */
 
          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] == ',')
              {
          /* 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;
              }
                prev = j + 1;
              }
+         
          /* Record the part after the last comma.  */
          /* 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.  */
 
        }
       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] == ',')
              {
          /* 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;
              }
                prev = j + 1;
              }
+         
          /* Record the part after the last comma.  */
          /* 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.  */
        }
       else if (argv[i][0] == '+' && argv[i][1] == 'e')
        /* The +e options to the C++ front-end.  */
@@ -2746,8 +2982,39 @@ process_command (argc, argv)
                spec_version = p + 1;
              compiler_version = spec_version;
              warn_std_ptr = &warn_std;
                spec_version = p + 1;
              compiler_version = spec_version;
              warn_std_ptr = &warn_std;
+
+             /* Validate the version number.  Use the same checks
+                done when inserting it into a spec.
+
+                The format of the version string is
+                ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?  */
+             {
+               char *v = compiler_version;
+
+               /* Ignore leading non-digits.  i.e. "foo-" in "foo-2.7.2".  */
+               while (! ISDIGIT (*v))
+                 v++;
+
+               if (v > compiler_version && v[-1] != '-')
+                 fatal ("invalid version number format");
+
+               /* Set V after the first period.  */
+               while (ISDIGIT (*v))
+                 v++;
+
+               if (*v != '.')
+                 fatal ("invalid version number format");
+
+               v++;
+               while (ISDIGIT (*v))
+                 v++;
+
+               if (*v != 0 && *v != ' ' && *v != '.' && *v != '-')
+                 fatal ("invalid version number format");
+             }
              break;
 
              break;
 
+           case 'S':
            case 'c':
              if (p[1] == 0)
                {
            case 'c':
              if (p[1] == 0)
                {
@@ -2759,10 +3026,40 @@ process_command (argc, argv)
 
            case 'o':
              have_o = 1;
 
            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)
 #if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
-             argv[i] = convert_filename (argv[i], 1);
              if (p[1] == 0)
              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;
 
 #endif
              goto normal_switch;
 
@@ -2784,7 +3081,7 @@ process_command (argc, argv)
     }
 
   if (have_c && have_o && lang_n_infiles > 1)
     }
 
   if (have_c && have_o && lang_n_infiles > 1)
-    fatal ("cannot specify -o with -c and multiple compilations");
+    fatal ("cannot specify -o with -c or -S and multiple compilations");
 
   /* Set up the search paths before we go looking for config files.  */
 
 
   /* Set up the search paths before we go looking for config files.  */
 
@@ -2880,6 +3177,25 @@ process_command (argc, argv)
        ;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        ;
        ;
       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].valid     = 0;
+             
+             n_switches++;
+           }
+       }
       else if (argv[i][0] == '+' && argv[i][1] == 'e')
        {
          /* Compensate for the +e options to the C++ front-end;
       else if (argv[i][0] == '+' && argv[i][1] == 'e')
        {
          /* Compensate for the +e options to the C++ front-end;
@@ -2901,23 +3217,23 @@ process_command (argc, argv)
          for (j = 4; argv[i][j]; j++)
            if (argv[i][j] == ',')
              {
          for (j = 4; argv[i][j]; j++)
            if (argv[i][j] == ',')
              {
-               infiles[n_infiles].language = 0;
+               infiles[n_infiles].language = "*";
                infiles[n_infiles++].name
                  = save_string (argv[i] + prev, j - prev);
                prev = j + 1;
              }
          /* Record the part after the last comma.  */
                infiles[n_infiles++].name
                  = save_string (argv[i] + prev, j - prev);
                prev = j + 1;
              }
          /* Record the part after the last comma.  */
-         infiles[n_infiles].language = 0;
+         infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[i] + prev;
        }
       else if (strcmp (argv[i], "-Xlinker") == 0)
        {
          infiles[n_infiles++].name = argv[i] + prev;
        }
       else if (strcmp (argv[i], "-Xlinker") == 0)
        {
-         infiles[n_infiles].language = 0;
+         infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[++i];
        }
       else if (strncmp (argv[i], "-l", 2) == 0)
        {
          infiles[n_infiles++].name = argv[++i];
        }
       else if (strncmp (argv[i], "-l", 2) == 0)
        {
-         infiles[n_infiles].language = 0;
+         infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[i];
        }
       else if (strcmp (argv[i], "-specs") == 0)
          infiles[n_infiles++].name = argv[i];
        }
       else if (strcmp (argv[i], "-specs") == 0)
@@ -3036,9 +3352,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.  */
 
    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 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;
 static int basename_length;
 static char *input_basename;
 static char *input_suffix;
@@ -3068,7 +3384,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.  */
 
 /* 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;
 {
 do_spec (spec)
      char *spec;
 {
@@ -3369,16 +3685,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;
                   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;
                char *suffix = p;
-               while (*p == '.' || ISALPHA (*p)
-                      || (p[0] == '%' && p[1] == 'O'))
-                 p++;
+
+               if (p[0] == '%' && p[1] == 'O')
+                 {
+                   /* We don't support extra suffix characters after %O.  */
+                   if (*p == '.' || ISALPHA ((unsigned char)*p))
+                     abort ();
+                   suffix = OBJECT_SUFFIX;
+                   suffix_length = strlen (OBJECT_SUFFIX);
+                   p += 2;
+                 }
+               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)
 
                /* 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;
 
                      && t->unique == (c != 'g'))
                    break;
 
@@ -3391,10 +3721,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        t->next = temp_names;
                        temp_names = t;
                      }
                        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');
                    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;
                    temp_filename_length = strlen (temp_filename);
                    t->filename = temp_filename;
                    t->filename_length = temp_filename_length;
@@ -3449,9 +3779,16 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case 'o':
            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));
 
          case 'O':
            obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
@@ -3504,16 +3841,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                  }
 
              /* This option is new; add it.  */
                  }
 
              /* 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;
 
            }
            break;
 
@@ -3659,7 +3987,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      *x++ = *y++;
 
                      if (*y != '_'
                      *x++ = *y++;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+                         || (*(y+1) != '_'
+                             && ! ISUPPER ((unsigned char)*(y+1))))
                        {
                          /* Stick __ at front of macro name.  */
                          *x++ = '_';
                        {
                          /* Stick __ at front of macro name.  */
                          *x++ = '_';
@@ -3701,7 +4030,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      y += 2;
 
                      if (*y != '_'
                      y += 2;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+                         || (*(y+1) != '_'
+                             && ! ISUPPER ((unsigned char)*(y+1))))
                        {
                          /* Stick -D__ at front of macro name.  */
                          *x++ = '-';
                        {
                          /* Stick -D__ at front of macro name.  */
                          *x++ = '-';
@@ -3785,8 +4115,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.  */
               to add and use their own specs.
               %[...] modifies -D options the way %P does;
               %(...) uses the spec unmodified.  */
-         case '(':
          case '[':
          case '[':
+           error ("Warning: use of obsolete %%[ operator in specs");
+         case '(':
            {
              char *name = p;
              struct spec_list *sl;
            {
              char *name = p;
              struct spec_list *sl;
@@ -3822,13 +4153,12 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      char *x = (char *) alloca (strlen (name) * 2 + 1);
                      char *buf = x;
                      char *y = name;
                      char *x = (char *) alloca (strlen (name) * 2 + 1);
                      char *buf = x;
                      char *y = name;
+                     int flag = 0;
 
                      /* Copy all of NAME into BUF, but put __ after
                         every -D and at the end of each arg,  */
                      while (1)
                        {
 
                      /* Copy all of NAME into BUF, but put __ after
                         every -D and at the end of each arg,  */
                      while (1)
                        {
-                         int flag;
-
                          if (! strncmp (y, "-D", 2))
                            {
                              *x++ = '-';
                          if (! strncmp (y, "-D", 2))
                            {
                              *x++ = '-';
@@ -3934,11 +4264,10 @@ static char *
 handle_braces (p)
      register char *p;
 {
 handle_braces (p)
      register char *p;
 {
-  register char *q;
-  char *filter;
+  char *filter, *body = NULL, *endbody;
   int pipe_p = 0;
   int pipe_p = 0;
-  int negate = 0;
-  int suffix = 0;
+  int negate;
+  int suffix;
   int include_blanks = 1;
 
   if (*p == '^')
   int include_blanks = 1;
 
   if (*p == '^')
@@ -3951,6 +4280,9 @@ handle_braces (p)
        This is used in %{|!pipe:...}.  */
     pipe_p = 1, ++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.  */
   if (*p == '!')
     /* A `!' after the open-brace negates the condition:
        succeed if the specified switch is not present.  */
@@ -3967,39 +4299,49 @@ handle_braces (p)
     }
 
   filter = 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
 
   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);
 
                   && strncmp (input_suffix, filter, p - filter) == 0);
 
-      if (p[0] == '}')
+      if (body[0] == '}')
        abort ();
 
       if (negate != found
        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 0;
-
-      return q;
     }
   else if (p[-1] == '*' && p[0] == '}')
     {
     }
   else if (p[-1] == '*' && p[0] == '}')
     {
@@ -4022,11 +4364,11 @@ handle_braces (p)
       if (p[-1] == '*' && !negate)
        {
          int substitution;
       if (p[-1] == '*' && !negate)
        {
          int substitution;
-         char *r = p;
+         char *r = body;
 
          /* First see whether we have %*.  */
          substitution = 0;
 
          /* First see whether we have %*.  */
          substitution = 0;
-         while (r < q)
+         while (r < endbody)
            {
              if (*r == '%' && r[1] == '*')
                substitution = 1;
            {
              if (*r == '%' && r[1] == '*')
                substitution = 1;
@@ -4040,7 +4382,7 @@ handle_braces (p)
                 in the text that follows the colon.  */
 
              unsigned hard_match_len = p - filter - 1;
                 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)
 
              for (i = 0; i < n_switches; i++)
                if (!strncmp (switches[i].part1, filter, hard_match_len)
@@ -4051,7 +4393,10 @@ handle_braces (p)
                    give_switch (i, 1, 1);
                  }
 
                    give_switch (i, 1, 1);
                  }
 
-             return q;
+             /* We didn't match.  Try again.  */
+             if (*p++ == '|')
+               goto next_member;
+             return endbody;
            }
        }
 
            }
        }
 
@@ -4085,7 +4430,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)
         then substitute either the switch or the specified
         conditional text.  */
       if (present != negate)
@@ -4096,7 +4441,8 @@ handle_braces (p)
            }
          else
            {
            }
          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;
            }
        }
                return 0;
            }
        }
@@ -4105,10 +4451,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);
          /* 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
 }
 \f
 /* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
@@ -4282,8 +4633,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.  */
   /* 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;
   cp = path + len1 + len2;
   if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR)
     *cp++ = DIR_SEPARATOR;
@@ -4406,8 +4757,10 @@ main (argc, argv)
 
   /* Choose directory for temp files.  */
 
 
   /* Choose directory for temp files.  */
 
+#ifndef MKTEMP_EACH_FILE
   temp_filename = choose_temp_base ();
   temp_filename_length = strlen (temp_filename);
   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).
 
   /* Make a table of what switches there are (switches, n_switches).
      Make a table of specified input files (infiles, n_infiles).
@@ -4424,7 +4777,7 @@ main (argc, argv)
                  sizeof ("COLLECT_GCC_OPTIONS=")-1);
 
     first_time = TRUE;
                  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;
       {
        char **args;
        char *p, *q;
@@ -4528,7 +4881,15 @@ main (argc, argv)
         as a unit.  If GCC_EXEC_PREFIX is defined, base
         standard_startfile_prefix on that as well.  */
       if (*standard_startfile_prefix == '/'
         as a unit.  If GCC_EXEC_PREFIX is defined, base
         standard_startfile_prefix on that as well.  */
       if (*standard_startfile_prefix == '/'
-         || *standard_startfile_prefix == DIR_SEPARATOR)
+         || *standard_startfile_prefix == DIR_SEPARATOR
+         || *standard_startfile_prefix == '$'
+#ifdef __MSDOS__
+         /* Check for disk name on MS-DOS-based systems.  */
+          || (standard_startfile_prefix[1] == ':'
+             && (standard_startfile_prefix[2] == DIR_SEPARATOR
+                 || standard_startfile_prefix[2] == '/'))
+#endif
+         )
        add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
                    0, 0, NULL_PTR);
       else
        add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
                    0, 0, NULL_PTR);
       else
@@ -4587,7 +4948,7 @@ main (argc, argv)
 
   /* Warn about any switches that no pass was interested in.  */
 
 
   /* Warn about any switches that no pass was interested in.  */
 
-  for (i = 0; i < n_switches; i++)
+  for (i = 0; (int)i < n_switches; i++)
     if (! switches[i].valid)
       error ("unrecognized option `-%s'", switches[i].part1);
 
     if (! switches[i].valid)
       error ("unrecognized option `-%s'", switches[i].part1);
 
@@ -4629,6 +4990,23 @@ main (argc, argv)
       exit (0);
     }
 
       exit (0);
     }
 
+  if (print_help_list)
+    {
+      display_help ();
+
+      if (! verbose_flag)
+       {
+         printf ("\nReport bugs to egcs-bugs@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;
   if (verbose_flag)
     {
       int n;
@@ -4651,21 +5029,25 @@ main (argc, argv)
        exit (0);
     }
 
        exit (0);
     }
 
-  if (n_infiles == 0)
+  if (n_infiles == added_libraries)
     fatal ("No input files");
 
   /* Make a place to record the compiler output file names
      that correspond to the input files.  */
 
     fatal ("No input files");
 
   /* 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);
 
 
   /* 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;
     {
       register struct compiler *cp = 0;
       int this_file_error = 0;
@@ -4753,12 +5135,30 @@ main (argc, argv)
       clear_failure_queue ();
     }
 
       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)
     {
       int tmp = execution_count;
 
   /* Run ld to link all the compiler output files.  */
 
   if (error_count == 0)
     {
       int tmp = execution_count;
 
+      /* We'll use ld if we can't find collect2. */
+      if (! strcmp (linker_name_spec, "collect2"))
+       {
+         char *s = find_a_file (&exec_prefixes, "collect2", X_OK);
+         if (s == NULL)
+           linker_name_spec = "ld";
+       }
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
         for collect.  */
       putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
         for collect.  */
       putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
@@ -4778,7 +5178,7 @@ main (argc, argv)
      complain about input files to be given to the linker.  */
 
   if (! linker_was_run && error_count == 0)
      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]);
       if (explicit_link_files[i])
        error ("%s: linker input file unused since linking not done",
               outfiles[i]);
@@ -4789,6 +5189,12 @@ main (argc, argv)
     delete_failure_queue ();
   delete_temp_files ();
 
     delete_failure_queue ();
   delete_temp_files ();
 
+  if (print_help_list)
+    {
+      printf ("\nReport bugs to egcs-bugs@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;
   exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
   /* NOTREACHED */
   return 0;
@@ -4796,7 +5202,7 @@ main (argc, argv)
 
 /* Find the proper compilation spec for the file name NAME,
    whose length is LENGTH.  LANGUAGE is the specified language,
 
 /* Find the proper compilation spec for the file name NAME,
    whose length is LENGTH.  LANGUAGE is the specified language,
-   or 0 if none specified.  */
+   or 0 if this file is to be passed to the linker.  */
 
 static struct compiler *
 lookup_compiler (name, length, language)
 
 static struct compiler *
 lookup_compiler (name, length, language)
@@ -4806,19 +5212,19 @@ lookup_compiler (name, length, language)
 {
   struct compiler *cp;
 
 {
   struct compiler *cp;
 
-  /* Look for the language, if one is spec'd.  */
+  /* If this was specified by the user to be a linker input, indicate that. */
+  if (language != 0 && language[0] == '*')
+    return 0;
+
+  /* Otherwise, look for the language, if one is spec'd.  */
   if (language != 0)
     {
       for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
   if (language != 0)
     {
       for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
-       {
-         if (language != 0)
-           {
-             if (cp->suffix[0] == '@'
-                 && !strcmp (cp->suffix + 1, language))
-               return cp;
-           }
-       }
+       if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
+         return cp;
+
       error ("language %s not recognized", language);
       error ("language %s not recognized", language);
+      return 0;
     }
 
   /* Look for a suffix.  */
     }
 
   /* Look for a suffix.  */
@@ -4826,23 +5232,24 @@ lookup_compiler (name, length, language)
     {
       if (/* The suffix `-' matches only the file name `-'.  */
          (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
     {
       if (/* The suffix `-' matches only the file name `-'.  */
          (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
-         ||
-         (strlen (cp->suffix) < length
-          /* See if the suffix matches the end of NAME.  */
+         || (strlen (cp->suffix) < length
+             /* See if the suffix matches the end of NAME.  */
 #ifdef OS2
 #ifdef OS2
-          && (!strcmp (cp->suffix,
-                       name + length - strlen (cp->suffix))
-           || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
-            && !strcasecmp (cp->suffix,
-                         name + length - strlen (cp->suffix)))))
+             && ((!strcmp (cp->suffix,
+                          name + length - strlen (cp->suffix))
+                  || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+                 && !strcasecmp (cp->suffix,
+                                 name + length - strlen (cp->suffix)))
 #else
 #else
-          && !strcmp (cp->suffix,
-                      name + length - strlen (cp->suffix))))
+             && !strcmp (cp->suffix,
+                         name + length - strlen (cp->suffix))
 #endif
 #endif
+        ))
        {
          if (cp->spec[0][0] == '@')
            {
              struct compiler *new;
        {
          if (cp->spec[0][0] == '@')
            {
              struct compiler *new;
+
              /* An alias entry maps a suffix to a language.
                 Search for the language; pass 0 for NAME and LENGTH
                 to avoid infinite recursion if language not found.
              /* An alias entry maps a suffix to a language.
                 Search for the language; pass 0 for NAME and LENGTH
                 to avoid infinite recursion if language not found.
@@ -4854,6 +5261,7 @@ lookup_compiler (name, length, language)
                     (char *) new->spec, sizeof new->spec);
              return new;
            }
                     (char *) new->spec, sizeof new->spec);
              return new;
            }
+
          /* A non-alias entry: return it.  */
          return cp;
        }
          /* A non-alias entry: return it.  */
          return cp;
        }
@@ -4968,6 +5376,8 @@ pfatal_pexecute (errmsg_fmt, errmsg_arg)
      char *errmsg_fmt;
      char *errmsg_arg;
 {
      char *errmsg_fmt;
      char *errmsg_arg;
 {
+  int save_errno = errno;
+
   if (errmsg_arg)
     {
       /* Space for trailing '\0' is in %s.  */
   if (errmsg_arg)
     {
       /* Space for trailing '\0' is in %s.  */
@@ -4976,7 +5386,7 @@ pfatal_pexecute (errmsg_fmt, errmsg_arg)
       errmsg_fmt = msg;
     }
 
       errmsg_fmt = msg;
     }
 
-  fatal ("%s: %s", errmsg_fmt, my_strerror (errno));
+  fatal ("%s: %s", errmsg_fmt, my_strerror (save_errno));
 }
 
 /* More 'friendly' abort that prints the line and file.
 }
 
 /* More 'friendly' abort that prints the line and file.
@@ -4988,8 +5398,6 @@ fancy_abort ()
   fatal ("Internal gcc abort.");
 }
 \f
   fatal ("Internal gcc abort.");
 }
 \f
-#ifdef HAVE_VPRINTF
-
 /* Output an error message and exit */
 
 static void
 /* Output an error message and exit */
 
 static void
@@ -5034,29 +5442,6 @@ error VPROTO((char *format, ...))
 
   fprintf (stderr, "\n");
 }
 
   fprintf (stderr, "\n");
 }
-
-#else /* not HAVE_VPRINTF */
-
-static void
-fatal (msg, arg1, arg2)
-     char *msg, *arg1, *arg2;
-{
-  error (msg, arg1, arg2);
-  delete_temp_files ();
-  exit (1);
-}
-
-static void
-error (msg, arg1, arg2)
-     char *msg, *arg1, *arg2;
-{
-  fprintf (stderr, "%s: ", programname);
-  fprintf (stderr, msg, arg1, arg2);
-  fprintf (stderr, "\n");
-}
-
-#endif /* not HAVE_VPRINTF */
-
 \f
 static void
 validate_all_switches ()
 \f
 static void
 validate_all_switches ()