OSDN Git Service

fix SIGCHLD handling
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 696dbd0..7fb57ef 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,6 +1,6 @@
 /* Compiler driver program that can handle many languages.
-   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 
-   1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -32,7 +32,6 @@ CC recognizes how to compile each input file by suffixes in the file names.
 Once it knows which kind of compilation to perform, the procedure for
 compilation is specified by a string called a "spec".  */
 
-
 #include "config.h"
 #include "system.h"
 #include <signal.h>
@@ -74,7 +73,7 @@ extern int getrusage PARAMS ((int, struct rusage *));
 #endif /* DIR_UP */
 #endif /* VMS */
 
-static char dir_separator_str[] = {DIR_SEPARATOR, 0};
+static char dir_separator_str[] = { DIR_SEPARATOR, 0 };
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
@@ -101,6 +100,9 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0};
    to the calling program.  */
 static int pass_exit_codes;
 
+/* Definition of string containing the arguments given to configure.  */
+#include "configargs.h"
+
 /* Flag saying to print the directories gcc will search through looking for
    programs, libraries, etc.  */
 
@@ -134,6 +136,10 @@ static int print_help_list;
 
 static int verbose_flag;
 
+/* Flag indicating to print target specific command line options. */
+
+static int target_help_flag;
+
 /* Flag indicating whether we should report subprocess execution times
    (if this is supported by the system - see pexecute.c).  */
 
@@ -165,6 +171,21 @@ static const char *cross_compile = "1";
 static const char *cross_compile = "0";
 #endif
 
+#ifdef MODIFY_TARGET_NAME
+
+/* Information on how to alter the target name based on a command-line
+   switch.  The only case we support now is simply appending or deleting a
+   string to or from the end of the first part of the configuration name.  */
+
+struct modify_target
+{
+  const char *sw;
+  enum add_del {ADD, DELETE} add_del;
+  const char *str;
+}
+modify_target[] = MODIFY_TARGET_NAME;
+#endif
 /* The number of errors that have occurred; the link phase will not be
    run if this is non-zero.  */
 static int error_count = 0;
@@ -210,7 +231,7 @@ static int access_check             PARAMS ((const char *, int));
 static char *find_a_file       PARAMS ((struct path_prefix *, const char *, int));
 static void add_prefix         PARAMS ((struct path_prefix *, const char *,
                                         const char *, int, int, int *));
-static void translate_options  PARAMS ((int *, const char ***));
+static void translate_options  PARAMS ((int *, const char *const **));
 static char *skip_whitespace   PARAMS ((char *));
 static void record_temp_file   PARAMS ((const char *, int, int));
 static void delete_if_ordinary PARAMS ((const char *));
@@ -242,12 +263,14 @@ static void display_help  PARAMS ((void));
 static void add_preprocessor_option    PARAMS ((const char *, int));
 static void add_assembler_option       PARAMS ((const char *, int));
 static void add_linker_option          PARAMS ((const char *, int));
-static void process_command            PARAMS ((int, const char **));
+static void process_command            PARAMS ((int, const char *const *));
 static int execute                     PARAMS ((void));
-static void unused_prefix_warnings     PARAMS ((struct path_prefix *));
 static void clear_args                 PARAMS ((void));
 static void fatal_error                        PARAMS ((int));
 static void set_input                  PARAMS ((const char *));
+static void init_gcc_specs              PARAMS ((struct obstack *,
+                                                const char *,
+                                                const char *));
 \f
 /* Specs are strings containing lines, each of which (if not blank)
 is made up of a program name, and arguments separated by spaces.
@@ -267,6 +290,7 @@ 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    same as %b, but include the file suffix (text after the last period).
  %gSUFFIX
        substitute a file name that has suffix SUFFIX and is chosen
        once per compilation, and mark the argument a la %d.  To reduce
@@ -291,6 +315,16 @@ or with constant text in a single argument.
        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.
+ %jSUFFIX
+        substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
+        writable, and if save-temps is off; otherwise, substitute the name
+        of a temporary file, just like %u.  This temporary file is not
+        meant for communication between processes, but rather as a junk
+        disposal mechanism.
+ %.SUFFIX
+        substitutes .SUFFIX for the suffixes of a matched switch's args when
+        it is subsequently output with %*. SUFFIX is terminated by the next
+        space or %.
  %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.
@@ -326,6 +360,7 @@ or with constant text in a single argument.
        and substitute the full name found.
  %eSTR  Print STR as an error message.  STR is terminated by a newline.
         Use this when inconsistent options are detected.
+ %nSTR  Print STR as an notice.  STR is terminated by a newline.
  %x{OPTION}    Accumulate an option for %X.
  %X    Output the accumulated linker options specified by compilations.
  %Y    Output the accumulated assembler options specified by compilations.
@@ -346,10 +381,12 @@ or with constant text in a single argument.
  %l     process LINK_SPEC as a spec.
  %L     process LIB_SPEC as a spec.
  %G     process LIBGCC_SPEC as a spec.
+ %M     output multilib_dir with directory separators replaced with "_";
+       if multilib_dir is not set or is ".", output "".
  %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
  %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
  %c    process SIGNED_CHAR_SPEC as a spec.
- %C     process CPP_SPEC as a spec.  A capital C is actually used here.
+ %C     process CPP_SPEC as a spec.
  %1    process CC1_SPEC as a spec.
  %2    process CC1PLUS_SPEC as a spec.
  %|    output "-" if the input for the current command is coming from a pipe.
@@ -360,18 +397,22 @@ or with constant text in a single argument.
        If that switch was not specified, this substitutes nothing.
        Here S is a metasyntactic variable.
  %{S*}  substitutes all the switches specified to CC whose names start
-       with -S.  This is used for -o, -D, -I, etc; switches that take
+       with -S.  This is used for -o, -I, etc; switches that take
        arguments.  CC considers `-o foo' as being one switch whose
        name starts with `o'.  %{o*} would substitute this text,
        including the space; thus, two arguments would be generated.
  %{^S*} likewise, but don't put a blank between a switch and any args.
+ %{S*&T*} likewise, but preserve order of S and T options (the order
+       of S and T in the spec is not significant).  Can be any number
+       of ampersand-separated variables; for each the wild card is
+       optional.  Useful for CPP as %{D*&U*&A*}.
  %{S*:X} substitutes X if one or more switches whose names start with -S are
        specified to CC.  Note that the tail part of the -S option
        (i.e. the part matched by the `*') will be substituted for each
        occurrence of %* within X.
- %{<S}  remove all occurences of S from the command line.
+ %{<S}  remove all occurences of -S from the command line.
         Note - this option is position dependent.  % commands in the
-        spec string before this option will see S, % commands in the
+        spec string before this option will see -S, % commands in the
         spec string after this option will not.
  %{S:X} substitutes X, but only if the -S switch was given to CC.
  %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
@@ -496,6 +537,33 @@ proper position among the other output files.  */
 #define LINKER_NAME "collect2"
 #endif
 
+/* Here is the spec for running the linker, after compiling all files.  */
+
+/* -u* was put back because both BSD and SysV seem to support it.  */
+/* %{static:} simply prevents an error message if the target machine
+   doesn't handle -static.  */
+/* 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.  */
+#ifndef LINK_COMMAND_SPEC
+#define LINK_COMMAND_SPEC "\
+%{!fsyntax-only:%{!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*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
+    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
+#endif
+
+#ifndef LINK_LIBGCC_SPEC
+# ifdef LINK_LIBGCC_SPECIAL
+/* Don't generate -L options for startfile prefix list.  */
+#  define LINK_LIBGCC_SPEC ""
+# else
+/* Do generate them.  */
+#  define LINK_LIBGCC_SPEC "%D"
+# endif
+#endif
+
 static const char *cpp_spec = CPP_SPEC;
 static const char *cpp_predefines = CPP_PREDEFINES;
 static const char *cc1_spec = CC1_SPEC;
@@ -510,6 +578,54 @@ static const char *endfile_spec = ENDFILE_SPEC;
 static const char *startfile_spec = STARTFILE_SPEC;
 static const char *switches_need_spaces = SWITCHES_NEED_SPACES;
 static const char *linker_name_spec = LINKER_NAME;
+static const char *link_command_spec = LINK_COMMAND_SPEC;
+static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
+
+/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
+   There should be no need to override these in target dependent files,
+   but we need to copy them to the specs file so that newer versions
+   of the GCC driver can correctly drive older tool chains with the
+   appropriate -B options.  */
+
+static const char *trad_capable_cpp =
+"%{traditional|ftraditional|traditional-cpp:trad}cpp0";
+
+static const char *cpp_options =
+"%{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{std*} %{nostdinc*}\
+ %{C} %{v} %{I*} %{P} %{$} %I\
+ %{MD:-M -MF %W{!o: %b.d}%W{o*:%.d%*}}\
+ %{MMD:-MM -MF %W{!o: %b.d}%W{o*:%.d%*}}\
+ %{M} %{MM} %W{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{M|MD|MM|MMD:%{o*:-MQ %*}}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
+ %{fshort-wchar:-U__WCHAR_TYPE__ -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
+ %{ffreestanding:-D__STDC_HOSTED__=0} %{fno-hosted:-D__STDC_HOSTED__=0}\
+ %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}}\
+ %{fshow-column} %{fno-show-column}\
+ %{fleading-underscore} %{fno-leading-underscore}\
+ %{fno-operator-names} %{ftabstop=*} %{remap}\
+ %{g3:-dD} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{E:%{!M*:%W{o*}}}";
+
+/* NB: This is shared amongst all front-ends.  */
+static const char *cc1_options =
+"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*} %{ansi}\
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
+ %{aux-info*} %{Qn:-fno-ident} %{--help:--help}\
+ %{--target-help:--target-help}\
+ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
+ %{fsyntax-only:-o %j}";
+
+static const char *asm_options =
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
+
+static const char *invoke_as =
+"%{!S:-o %{|!pipe:%g.s} |\n as %(asm_options) %{!pipe:%g.s} %A }";
 
 /* 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
@@ -527,7 +643,7 @@ static const char *multilib_exclusions;
 #define MULTILIB_DEFAULTS { "" }
 #endif
 
-static const  char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
+static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 
 struct user_specs
 {
@@ -558,13 +674,13 @@ static struct user_specs *user_specs_head, *user_specs_tail;
   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
   || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
   || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
-  || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
+  || !strcmp (STR, "isystem") || !strcmp (STR, "specs") \
+  || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
 
 #ifndef WORD_SWITCH_TAKES_ARG
 #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) \
@@ -583,8 +699,11 @@ struct compiler
   const char *suffix;          /* Use this compiler for input files
                                   whose names end in this suffix.  */
 
-  const char *spec[4];         /* To use this compiler, concatenate these
-                                  specs and pass to do_spec.  */
+  const char *spec;            /* To use this compiler, run this spec.  */
+
+  const char *cpp_spec;         /* If non-NULL, substitute this spec
+                                  for `%C', rather than the usual
+                                  cpp_spec.  */
 };
 
 /* Pointer to a vector of `struct compiler' that gives the spec for
@@ -610,156 +729,54 @@ 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".  */
-  {".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"}},
+  {".m",  "#Objective-C"}, {".mi",  "#Objective-C"},
+  {".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"}, {".cp", "#C++"},
+  {".c++", "#C++"}, {".C", "#C++"}, {".ii", "#C++"},
+  {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
+  {".f", "#Fortran"}, {".for", "#Fortran"}, {".fpp", "#Fortran"},
+  {".F", "#Fortran"}, {".FOR", "#Fortran"}, {".FPP", "#Fortran"},
+  {".r", "#Ratfor"},
+  {".p", "#Pascal"}, {".pas", "#Pascal"},
+  {".ch", "#Chill"}, {".chi", "#Chill"},
+  {".java", "#Java"}, {".class", "#Java"},
+  {".zip", "#Java"}, {".jar", "#Java"},
   /* Next come the entries for C.  */
-  {".c", {"@c"}},
+  {".c", "@c"},
   {"@c",
-   {
-#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}\
-        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
-       %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
-        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-       %{ffast-math:-D__FAST_MATH__}\
-       %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-        %{traditional} %{ftraditional:-traditional}\
-        %{traditional-cpp:-traditional}\
-       %{fleading-underscore} %{fno-leading-underscore}\
-       %{fshow-column} %{fno-show-column}\
-       %{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}\
-                  %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
-                 %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
-                  %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-                 %{ffast-math:-D__FAST_MATH__}\
-                 %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-                 %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-                  %{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}\
-        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
-       %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
-        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-       %{ffast-math:-D__FAST_MATH__}\
-       %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-        %{traditional} %{ftraditional:-traditional}\
-        %{traditional-cpp:-traditional}\
-       %{fshow-column} %{fno-show-column}\
-       %{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 \
-                  %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
-                  %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
-                  %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
-                  %{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 }}}}"
-#endif /* ! USE_CPPLIB */
-  }},
+   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
+      external preprocessor if -save-temps or -traditional is given.  */
+     "%{E|M|MM:%(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)}\
+      %{!E:%{!M:%{!MM:\
+         %{save-temps:%(trad_capable_cpp) -lang-c %{ansi:-std=c89}\
+               %(cpp_options) %b.i \n\
+                   cc1 -fpreprocessed %b.i %(cc1_options)}\
+         %{!save-temps:\
+           %{traditional|ftraditional|traditional-cpp:\
+               tradcpp0 -lang-c %{ansi:-std=c89} %(cpp_options) %{!pipe:%g.i} |\n\
+                   cc1 -fpreprocessed %{!pipe:%g.i} %(cc1_options)}\
+           %{!traditional:%{!ftraditional:%{!traditional-cpp:\
+               cc1 -lang-c %{ansi:-std=c89} %(cpp_options) %(cc1_options)}}}}\
+        %{!fsyntax-only:%(invoke_as)}}}}"},
   {"-",
-   {"%{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}\
-        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
-       %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
-        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-       %{ffast-math:-D__FAST_MATH__}\
-       %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-        %{traditional} %{ftraditional:-traditional}\
-        %{traditional-cpp:-traditional}\
-       %{fshow-column} %{fno-show-column}\
-       %{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}"}},
-  {".h", {"@c-header"}},
+   "%{!E:%e-E required when input is from standard input}\
+    %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
+  {".h", "@c-header"},
   {"@c-header",
-   {"%{!E:%eCompilation of header file requested} \
-    cpp %{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}\
-        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
-       %{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
-        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-       %{ffast-math:-D__FAST_MATH__}\
-       %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-       %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-        %{traditional} %{ftraditional:-traditional}\
-        %{traditional-cpp:-traditional}\
-       %{fshow-column} %{fno-show-column}\
-       %{fleading-underscore} %{fno-leading-underscore}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
-        %i %W{o*}"}},
-  {".i", {"@cpp-output"}},
+   "%{!E:%eCompilation of header file requested} \
+    %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
+  {".i", "@cpp-output"},
   {"@cpp-output",
-   {"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
-                       %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
-                       %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
-                       %{aux-info*} %{Qn:-fno-ident} -fpreprocessed\
-                       %{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 }}}}"}},
-  {".s", {"@assembler"}},
+   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}"},
+  {".s", "@assembler"},
   {"@assembler",
-   {"%{!M:%{!MM:%{!E:%{!S:as %a %Y\
-                           %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
-                           %i %A\n }}}}"}},
-  {".S", {"@assembler-with-cpp"}},
+   "%{!M:%{!MM:%{!E:%{!S:as %(asm_options) %i %A }}}}"},
+  {".S", "@assembler-with-cpp"},
   {"@assembler-with-cpp",
-   {"cpp -lang-asm %{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} %{trigraphs}\
-        -$ %{!undef:%p %P} -D__ASSEMBLER__ \
-        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
-       %{ffast-math:-D__FAST_MATH__}\
-       %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
-        %{traditional} %{ftraditional:-traditional}\
-        %{traditional-cpp:-traditional}\
-       %{fshow-column} %{fno-show-column}\
-       %{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\
-                    %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
-                   %{!pipe:%g.s} %A\n }}}}"}},
+   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+       %{!M:%{!MM:%{!E:%(invoke_as)}}}"},
 #include "specs.h"
   /* Mark end of table */
-  {0, {0}}
+  {0, 0}
 };
 
 /* Number of elements in default_compilers, not counting the terminator.  */
@@ -767,47 +784,6 @@ static struct compiler default_compilers[] =
 static int n_default_compilers
   = (sizeof default_compilers / sizeof (struct compiler)) - 1;
 
-/* Here is the spec for running the linker, after compiling all files.  */
-
-/* -u* was put back because both BSD and SysV seem to support it.  */
-/* %{static:} simply prevents an error message if the target machine
-   doesn't handle -static.  */
-/* 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 const char *link_command_spec = 
-       LINK_COMMAND_SPEC;
-#else
-#ifdef LINK_LIBGCC_SPECIAL
-/* Don't generate -L options.  */
-static const char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!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\
-                       %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
-                       %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
-                       %{T*}\
-                       \n }}}}}}";
-#else
-/* Use -L.  */
-static const char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!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\
-                       %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
-                       %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
-                       %{T*}\
-                       \n }}}}}}";
-#endif
-#endif
-
 /* A vector of options to give to the linker.
    These options are accumulated by %x,
    and substituted into the linker command with %X.  */
@@ -933,11 +909,11 @@ struct option_map option_map[] =
 static void
 translate_options (argcp, argvp)
      int *argcp;
-     const char ***argvp;
+     const char *const **argvp;
 {
   int i;
   int argc = *argcp;
-  const char **argv = *argvp;
+  const char *const *argv = *argvp;
   const char **newv =
     (const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
   int newindex = 0;
@@ -952,7 +928,7 @@ translate_options (argcp, argvp)
        {
          size_t j;
          /* Find a mapping that applies to this option.  */
-         for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
+         for (j = 0; j < ARRAY_SIZE (option_map); j++)
            {
              size_t optlen = strlen (option_map[j].name);
              size_t arglen = strlen (argv[i]);
@@ -969,9 +945,7 @@ translate_options (argcp, argvp)
                  if (arglen < optlen)
                    {
                      size_t k;
-                     for (k = j + 1;
-                          k < sizeof (option_map) / sizeof (option_map[0]);
-                          k++)
+                     for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
                        if (strlen (option_map[k].name) >= arglen
                            && !strncmp (argv[i], option_map[k].name, arglen))
                          {
@@ -979,7 +953,7 @@ translate_options (argcp, argvp)
                            break;
                          }
 
-                     if (k != sizeof (option_map) / sizeof (option_map[0]))
+                     if (k != ARRAY_SIZE (option_map))
                        break;
                    }
 
@@ -991,7 +965,7 @@ translate_options (argcp, argvp)
 
                      /* If this mapping requires extra text at end of name,
                         accept that as "argument".  */
-                     else if (index (arginfo, '*') != 0)
+                     else if (strchr (arginfo, '*') != 0)
                        arg = argv[i] + optlen;
 
                      /* Otherwise, extra text at end means mismatch.
@@ -1000,14 +974,14 @@ translate_options (argcp, argvp)
                        continue;
                    }
 
-                 else if (index (arginfo, '*') != 0)
+                 else if (strchr (arginfo, '*') != 0)
                    {
                      error ("Incomplete `%s' option", option_map[j].name);
                      break;
                    }
 
                  /* Handle arguments.  */
-                 if (index (arginfo, 'a') != 0)
+                 if (strchr (arginfo, 'a') != 0)
                    {
                      if (arg == 0)
                        {
@@ -1021,9 +995,9 @@ translate_options (argcp, argvp)
                          arg = argv[++i];
                        }
                    }
-                 else if (index (arginfo, '*') != 0)
+                 else if (strchr (arginfo, '*') != 0)
                    ;
-                 else if (index (arginfo, 'o') == 0)
+                 else if (strchr (arginfo, 'o') == 0)
                    {
                      if (arg != 0)
                        error ("Extraneous argument to `%s' option",
@@ -1032,7 +1006,7 @@ translate_options (argcp, argvp)
                    }
 
                  /* Store the translation as one argv elt or as two.  */
-                 if (arg != 0 && index (arginfo, 'j') != 0)
+                 if (arg != 0 && strchr (arginfo, 'j') != 0)
                    newv[newindex++] = concat (option_map[j].equivalent, arg,
                                               NULL_PTR);
                  else if (arg != 0)
@@ -1104,7 +1078,8 @@ skip_whitespace (p)
        p++;
       else if (*p == '#')
        {
-         while (*p != '\n') p++;
+         while (*p != '\n')
+           p++;
          p++;
        }
       else
@@ -1113,6 +1088,104 @@ skip_whitespace (p)
 
   return p;
 }
+/* Structures to keep track of prefixes to try when looking for files.  */
+
+struct prefix_list
+{
+  char *prefix;               /* String to prepend to the path.  */
+  struct prefix_list *next;   /* Next in linked list.  */
+  int require_machine_suffix; /* Don't use without machine_suffix.  */
+  /* 2 means try both machine_suffix and just_machine_suffix.  */
+  int *used_flag_ptr;        /* 1 if a file was found with this prefix.  */
+  int priority;                      /* Sort key - priority within list */
+};
+
+struct path_prefix
+{
+  struct prefix_list *plist;  /* List of prefixes to try */
+  int max_len;                /* Max length of a prefix in PLIST */
+  const char *name;           /* Name of this list (used in config stuff) */
+};
+
+/* List of prefixes to try when looking for executables.  */
+
+static struct path_prefix exec_prefixes = { 0, 0, "exec" };
+
+/* List of prefixes to try when looking for startup (crt0) files.  */
+
+static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
+
+/* List of prefixes to try when looking for include files.  */
+
+static struct path_prefix include_prefixes = { 0, 0, "include" };
+
+/* Suffix to attach to directories searched for commands.
+   This looks like `MACHINE/VERSION/'.  */
+
+static const char *machine_suffix = 0;
+
+/* Suffix to attach to directories searched for commands.
+   This is just `MACHINE/'.  */
+
+static const char *just_machine_suffix = 0;
+
+/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
+
+static const char *gcc_exec_prefix;
+
+/* Default prefixes to attach to command names.  */
+
+#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+#undef MD_STARTFILE_PREFIX_1
+#endif
+
+/* If no prefixes defined, use the null string, which will disable them.  */
+#ifndef MD_EXEC_PREFIX
+#define MD_EXEC_PREFIX ""
+#endif
+#ifndef MD_STARTFILE_PREFIX
+#define MD_STARTFILE_PREFIX ""
+#endif
+#ifndef MD_STARTFILE_PREFIX_1
+#define MD_STARTFILE_PREFIX_1 ""
+#endif
+
+/* Supply defaults for the standard prefixes.  */
+
+#ifndef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
+#endif
+#ifndef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
+#endif
+#ifndef TOOLDIR_BASE_PREFIX
+#define TOOLDIR_BASE_PREFIX "/usr/local/"
+#endif
+#ifndef STANDARD_BINDIR_PREFIX
+#define STANDARD_BINDIR_PREFIX "/usr/local/bin"
+#endif
+
+static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
+static const char *standard_exec_prefix_1 = "/usr/lib/gcc/";
+static const char *md_exec_prefix = MD_EXEC_PREFIX;
+
+static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
+static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
+static const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
+static const char *standard_startfile_prefix_1 = "/lib/";
+static const char *standard_startfile_prefix_2 = "/usr/lib/";
+
+static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+static const char *tooldir_prefix;
+
+static const char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+
+/* Subdirectory to use for locating libraries.  Set by
+   set_multilib_dir based on the compilation options.  */
+
+static const char *multilib_dir;
 \f
 /* Structure to keep track of the specs that have been defined so far.
    These are accessed using %(specname) or %[specname] in a compiler
@@ -1134,15 +1207,20 @@ struct spec_list
 };
 
 #define INIT_STATIC_SPEC(NAME,PTR) \
-{ NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 }
+{ NAME, NULL_PTR, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
 
 /* List of statically defined specs.  */
 static struct spec_list static_specs[] =
 {
   INIT_STATIC_SPEC ("asm",                     &asm_spec),
   INIT_STATIC_SPEC ("asm_final",               &asm_final_spec),
+  INIT_STATIC_SPEC ("asm_options",             &asm_options),
+  INIT_STATIC_SPEC ("invoke_as",               &invoke_as),
   INIT_STATIC_SPEC ("cpp",                     &cpp_spec),
+  INIT_STATIC_SPEC ("cpp_options",             &cpp_options),
+  INIT_STATIC_SPEC ("trad_capable_cpp",                &trad_capable_cpp),
   INIT_STATIC_SPEC ("cc1",                     &cc1_spec),
+  INIT_STATIC_SPEC ("cc1_options",             &cc1_options),
   INIT_STATIC_SPEC ("cc1plus",                 &cc1plus_spec),
   INIT_STATIC_SPEC ("endfile",                 &endfile_spec),
   INIT_STATIC_SPEC ("link",                    &link_spec),
@@ -1160,6 +1238,10 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("multilib_matches",                &multilib_matches),
   INIT_STATIC_SPEC ("multilib_exclusions",     &multilib_exclusions),
   INIT_STATIC_SPEC ("linker",                  &linker_name_spec),
+  INIT_STATIC_SPEC ("link_libgcc",             &link_libgcc_spec),
+  INIT_STATIC_SPEC ("md_exec_prefix",          &md_exec_prefix),
+  INIT_STATIC_SPEC ("md_startfile_prefix",     &md_startfile_prefix),
+  INIT_STATIC_SPEC ("md_startfile_prefix_1",   &md_startfile_prefix_1),
 };
 
 #ifdef EXTRA_SPECS             /* additional specs needed */
@@ -1172,21 +1254,49 @@ struct spec_list_1
 };
 
 static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
-static struct spec_list * extra_specs = (struct spec_list *)0;
+static struct spec_list *extra_specs = (struct spec_list *) 0;
 #endif
 
 /* List of dynamically allocates specs that have been defined so far.  */
 
-static struct spec_list *specs = (struct spec_list *)0;
-
+static struct spec_list *specs = (struct spec_list *) 0;
 \f
+/* Add appropriate libgcc specs to OBSTACK, taking into account
+   various permutations of -shared-libgcc, -shared, and such.  */
+
+static void
+init_gcc_specs (obstack, shared_name, static_name)
+     struct obstack *obstack;
+     const char *shared_name;
+     const char *static_name;
+{
+  char buffer[128];
+
+  /* If we see -shared-libgcc, then use the shared version.  */
+  sprintf (buffer, "%%{shared-libgcc:%s}", shared_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* If we see -static-libgcc, then use the shared version.  */
+  sprintf (buffer, "%%{static-libgcc:%s}", static_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* Otherwise, if we see -shared, then use the shared version.  */
+  sprintf (buffer,
+          "%%{!shared-libgcc:%%{!static-libgcc:%%{shared:%s}}}", 
+          shared_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* Otherwise, use the static version.  */
+  sprintf (buffer, 
+          "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s}}}", 
+          static_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+}
+
 /* Initialize the specs lookup routines.  */
 
 static void
 init_spec ()
 {
-  struct spec_list *next = (struct spec_list *)0;
-  struct spec_list *sl   = (struct spec_list *)0;
+  struct spec_list *next = (struct spec_list *) 0;
+  struct spec_list *sl   = (struct spec_list *) 0;
   int i;
 
   if (specs)
@@ -1197,10 +1307,9 @@ init_spec ()
 
 #ifdef EXTRA_SPECS
   extra_specs = (struct spec_list *)
-    xcalloc (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--)
+    xcalloc (sizeof (struct spec_list), ARRAY_SIZE (extra_specs_1));
+
+  for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
     {
       sl = &extra_specs[i];
       sl->name = extra_specs_1[i].name;
@@ -1212,16 +1321,92 @@ init_spec ()
     }
 #endif
 
-  for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--)
+  for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
     {
       sl = &static_specs[i];
       sl->next = next;
       next = sl;
     }
 
+#ifdef ENABLE_SHARED_LIBGCC
+  /* ??? If neither -shared-libgcc nor --static-libgcc was
+     seen, then we should be making an educated guess.  Some proposed
+     heuristics for ELF include:
+
+       (1) If "-Wl,--export-dynamic", then it's a fair bet that the
+           program will be doing dynamic loading, which will likely
+           need the shared libgcc.
+
+       (2) If "-ldl", then it's also a fair bet that we're doing
+           dynamic loading.
+
+       (3) For each ET_DYN we're linking against (either through -lfoo
+           or /some/path/foo.so), check to see whether it or one of
+           its dependancies depends on a shared libgcc.
+
+       (4) If "-shared"
+
+           If the runtime is fixed to look for program headers instead
+           of calling __register_frame_info at all, for each object,
+           use the shared libgcc if any EH symbol referenced.
+
+           If crtstuff is fixed to not invoke __register_frame_info
+           automatically, for each object, use the shared libgcc if
+           any non-empty unwind section found.
+
+     Doing any of this probably requires invoking an external program to
+     do the actual object file scanning.  */
+  {
+    const char *p = libgcc_spec;
+    int in_sep = 1;
+    /* Transform the extant libgcc_spec into one that uses the shared libgcc
+       when given the proper command line arguments.  */
+    while (*p)
+      {
+        if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
+         {
+           init_gcc_specs (&obstack,
+#ifdef NO_SHARED_LIBGCC_MULTILIB
+                           "-lgcc_s"
+#else
+                           "-lgcc_s%M"
+#endif
+                           ,
+                           "-lgcc");
+           p += 5;
+           in_sep = 0;
+         }
+       else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
+         {
+           /* Ug.  We don't know shared library extensions.  Hope that
+              systems that use this form don't do shared libraries.  */
+           init_gcc_specs (&obstack,
+#ifdef NO_SHARED_LIBGCC_MULTILIB
+                           "-lgcc_s"
+#else
+                           "-lgcc_s%M"
+#endif
+                           ,
+                           "libgcc.a%s");
+           p += 10;
+           in_sep = 0;
+         }
+       else
+         {
+           obstack_1grow (&obstack, *p);
+           in_sep = (*p == ' ');
+           p += 1;
+         }
+      }
+
+    obstack_1grow (&obstack, '\0');
+    libgcc_spec = obstack_finish (&obstack);
+  }
+#endif
+
   specs = sl;
 }
-
 \f
 /* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
    removed; If the spec starts with a + then SPEC is added to the end of the
@@ -1240,9 +1425,8 @@ set_spec (name, spec)
   /* If this is the first call, initialize the statically allocated specs.  */
   if (!specs)
     {
-      struct spec_list *next = (struct spec_list *)0;
-      for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1;
-          i >= 0; i--)
+      struct spec_list *next = (struct spec_list *) 0;
+      for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
        {
          sl = &static_specs[i];
          sl->next = next;
@@ -1300,13 +1484,9 @@ 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
-
-/* 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/%j) and the associated
+   temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
+   it here.  */
 
 static struct temp_name {
   const char *suffix;  /* suffix associated with the code.  */
@@ -1316,8 +1496,6 @@ static struct temp_name {
   int filename_length; /* strlen (filename).  */
   struct temp_name *next;
 } *temp_names;
-#endif
-
 
 /* Number of commands executed so far.  */
 
@@ -1331,98 +1509,6 @@ static int signal_count;
 
 static const char *programname;
 \f
-/* Structures to keep track of prefixes to try when looking for files.  */
-
-struct prefix_list
-{
-  char *prefix;               /* String to prepend to the path.  */
-  struct prefix_list *next;   /* Next in linked list.  */
-  int require_machine_suffix; /* Don't use without machine_suffix.  */
-  /* 2 means try both machine_suffix and just_machine_suffix.  */
-  int *used_flag_ptr;        /* 1 if a file was found with this prefix.  */
-};
-
-struct path_prefix
-{
-  struct prefix_list *plist;  /* List of prefixes to try */
-  int max_len;                /* Max length of a prefix in PLIST */
-  const char *name;           /* Name of this list (used in config stuff) */
-};
-
-/* List of prefixes to try when looking for executables.  */
-
-static struct path_prefix exec_prefixes = { 0, 0, "exec" };
-
-/* List of prefixes to try when looking for startup (crt0) files.  */
-
-static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
-
-/* List of prefixes to try when looking for include files.  */
-
-static struct path_prefix include_prefixes = { 0, 0, "include" };
-
-/* Suffix to attach to directories searched for commands.
-   This looks like `MACHINE/VERSION/'.  */
-
-static const char *machine_suffix = 0;
-
-/* Suffix to attach to directories searched for commands.
-   This is just `MACHINE/'.  */
-
-static const char *just_machine_suffix = 0;
-
-/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
-
-static const char *gcc_exec_prefix;
-
-/* Default prefixes to attach to command names.  */
-
-#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
-#undef MD_EXEC_PREFIX
-#undef MD_STARTFILE_PREFIX
-#undef MD_STARTFILE_PREFIX_1
-#endif
-
-#ifndef STANDARD_EXEC_PREFIX
-#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
-#endif /* !defined STANDARD_EXEC_PREFIX */
-
-static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
-static const char *standard_exec_prefix_1 = "/usr/lib/gcc/";
-#ifdef MD_EXEC_PREFIX
-static const char *md_exec_prefix = MD_EXEC_PREFIX;
-#endif
-
-#ifndef STANDARD_STARTFILE_PREFIX
-#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
-#endif /* !defined STANDARD_STARTFILE_PREFIX */
-
-#ifdef MD_STARTFILE_PREFIX
-static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
-#endif
-#ifdef MD_STARTFILE_PREFIX_1
-static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
-#endif
-static const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
-static const char *standard_startfile_prefix_1 = "/lib/";
-static const char *standard_startfile_prefix_2 = "/usr/lib/";
-
-#ifndef TOOLDIR_BASE_PREFIX
-#define TOOLDIR_BASE_PREFIX "/usr/local/"
-#endif
-static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
-static const char *tooldir_prefix;
-
-#ifndef STANDARD_BINDIR_PREFIX
-#define STANDARD_BINDIR_PREFIX "/usr/local/bin"
-#endif
-static const char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
-
-/* Subdirectory to use for locating libraries.  Set by
-   set_multilib_dir based on the compilation options.  */
-
-static const char *multilib_dir;
-
 /* Clear out the vector of arguments (after a command is executed).  */
 
 static void
@@ -1456,10 +1542,10 @@ store_arg (arg, delete_always, delete_failure)
 }
 \f
 /* Load specs from a file name named FILENAME, replacing occurances of
-   various different types of line-endings, \r\n, \n\r and just \r, with 
+   various different types of line-endings, \r\n, \n\r and just \r, with
    a single \n.  */
 
-static char*
+static char *
 load_specs (filename)
      const char *filename;
 {
@@ -1496,10 +1582,10 @@ load_specs (filename)
       int skip = 0;
       char c = *buffer_p;
       if (c == '\r')
-        {
-         if (buffer_p > buffer && *(buffer_p-1) == '\n')       /* \n\r */
+       {
+         if (buffer_p > buffer && *(buffer_p - 1) == '\n')     /* \n\r */
            skip = 1;
-         else if (*(buffer_p+1) == '\n')                       /* \r\n */
+         else if (*(buffer_p + 1) == '\n')                     /* \r\n */
            skip = 1;
          else                                                  /* \r */
            c = '\n';
@@ -1556,9 +1642,10 @@ read_specs (filename, main_p)
          while (*p && *p != '\n')
            p++;
 
-         p++;                  /* Skip '\n' */
+         /* Skip '\n'.  */
+         p++;
 
-         if (!strncmp (p1, "%include", sizeof ("%include")-1)
+         if (!strncmp (p1, "%include", sizeof ("%include") - 1)
              && (p1[sizeof "%include" - 1] == ' '
                  || p1[sizeof "%include" - 1] == '\t'))
            {
@@ -1584,7 +1671,8 @@ read_specs (filename, main_p)
              char *new_filename;
 
              p1 += sizeof "%include_noerr";
-             while (*p1 == ' ' || *p1 == '\t') p1++;
+             while (*p1 == ' ' || *p1 == '\t')
+               p1++;
 
              if (*p1++ != '<' || p[-2] != '>')
                fatal ("specs %%include syntax malformed after %ld characters",
@@ -1610,12 +1698,12 @@ read_specs (filename, main_p)
              while (*p1 == ' ' || *p1 == '\t')
                p1++;
 
-             if (! ISALPHA ((unsigned char)*p1))
+             if (! ISALPHA ((unsigned char) *p1))
                fatal ("specs %%rename syntax malformed after %ld characters",
                       (long) (p1 - buffer));
 
              p2 = p1;
-             while (*p2 && !ISSPACE ((unsigned char)*p2))
+             while (*p2 && !ISSPACE ((unsigned char) *p2))
                p2++;
 
              if (*p2 != ' ' && *p2 != '\t')
@@ -1627,16 +1715,16 @@ read_specs (filename, main_p)
              while (*p2 == ' ' || *p2 == '\t')
                p2++;
 
-             if (! ISALPHA ((unsigned char)*p2))
+             if (! ISALPHA ((unsigned char) *p2))
                fatal ("specs %%rename syntax malformed after %ld characters",
                       (long) (p2 - buffer));
 
-             /* Get new spec name */
+             /* Get new spec name */
              p3 = p2;
-             while (*p3 && !ISSPACE ((unsigned char)*p3))
+             while (*p3 && !ISSPACE ((unsigned char) *p3))
                p3++;
 
-             if (p3 != p-1)
+             if (p3 != p - 1)
                fatal ("specs %%rename syntax malformed after %ld characters",
                       (long) (p3 - buffer));
              *p3 = '\0';
@@ -1736,9 +1824,7 @@ read_specs (filename, main_p)
                         (n_compilers + 2) * sizeof (struct compiler)));
 
          compilers[n_compilers].suffix = suffix;
-         memset (compilers[n_compilers].spec, 0,
-                 sizeof compilers[n_compilers].spec);
-         compilers[n_compilers].spec[0] = spec;
+         compilers[n_compilers].spec = spec;
          n_compilers++;
          memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
        }
@@ -1756,7 +1842,7 @@ read_specs (filename, main_p)
 
 /* This is the common prefix we use to make temp file names.
    It is chosen once for each run of this program.
-   It is substituted into a spec by %g.
+   It is substituted into a spec by %g or %j.
    Thus, all temp file names contain this prefix.
    In practice, all temp file names start with this prefix.
 
@@ -1796,7 +1882,7 @@ record_temp_file (filename, always_delete, fail_delete)
      int always_delete;
      int fail_delete;
 {
-  register char * const name = xstrdup (filename);
+  register char *const name = xstrdup (filename);
 
   if (always_delete)
     {
@@ -1925,16 +2011,15 @@ putenv (str)
     }
 
   /* Add a new environment variable */
-  environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
+  environ = (char **) xmalloc (sizeof (char *) * (num_envs + 2));
   *environ = str;
   memcpy ((char *) (environ + 1), (char *) old_environ,
-        sizeof (char *) * (num_envs+1));
+         sizeof (char *) * (num_envs + 1));
 
 #endif /* VMS */
 }
 
-#endif /* HAVE_PUTENV */
-
+#endif /* HAVE_PUTENV */
 \f
 /* Build a list of search directories from PATHS.
    PREFIX is a string to prepend to the list.
@@ -1967,7 +2052,7 @@ build_search_list (paths, prefix, check_dir_p)
        {
          if (!first_time)
            obstack_1grow (&collect_obstack, PATH_SEPARATOR);
-           
+
          first_time = FALSE;
          obstack_grow (&collect_obstack, pprefix->prefix, len);
          obstack_grow (&collect_obstack, machine_suffix, suffix_len);
@@ -1980,7 +2065,7 @@ build_search_list (paths, prefix, check_dir_p)
        {
          if (! first_time)
            obstack_1grow (&collect_obstack, PATH_SEPARATOR);
-           
+
          first_time = FALSE;
          obstack_grow (&collect_obstack, pprefix->prefix, len);
          obstack_grow (&collect_obstack, just_machine_suffix,
@@ -2097,7 +2182,7 @@ free_split_directories (dirs)
   while (dirs[i] != NULL_PTR)
     free (dirs[i++]);
 
-  free ((char *)dirs);
+  free ((char *) dirs);
 }
 
 /* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets
@@ -2148,14 +2233,14 @@ make_relative_prefix (progname, bin_prefix, prefix)
                    }
                  else
                    {
-                     strncpy (nstore, startp, endp-startp);
+                     strncpy (nstore, startp, endp - startp);
                      if (! IS_DIR_SEPARATOR (endp[-1]))
                        {
-                         nstore[endp-startp] = DIR_SEPARATOR;
-                         nstore[endp-startp+1] = 0;
+                         nstore[endp - startp] = DIR_SEPARATOR;
+                         nstore[endp - startp + 1] = 0;
                        }
                      else
-                       nstore[endp-startp] = 0;
+                       nstore[endp - startp] = 0;
                    }
                  strcat (nstore, progname);
                  if (! access (nstore, X_OK)
@@ -2200,7 +2285,7 @@ make_relative_prefix (progname, bin_prefix, prefix)
          std_loc_p = 1;
          free_split_directories (prog_dirs);
          free_split_directories (bin_dirs);
-         prog_dirs = bin_dirs = (char **)0;
+         prog_dirs = bin_dirs = (char **) 0;
          return NULL_PTR;
        }
     }
@@ -2231,7 +2316,7 @@ make_relative_prefix (progname, bin_prefix, prefix)
   /* Now build up the ..'s.  */
   for (i = common; i < n; i++)
     {
-      obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP)-1);
+      obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP) - 1);
       obstack_1grow (&obstack, DIR_SEPARATOR);
     }
 
@@ -2284,7 +2369,7 @@ find_a_file (pprefix, name, mode)
   int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
 
 #ifdef DEFAULT_ASSEMBLER
-  if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
+  if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
     return xstrdup (DEFAULT_ASSEMBLER);
 #endif
 
@@ -2300,12 +2385,7 @@ find_a_file (pprefix, name, mode)
 
   /* Determine the filename to execute (special case for absolute paths).  */
 
-  if (IS_DIR_SEPARATOR (*name)
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-      /* Check for disk name on MS-DOS-based systems.  */
-      || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
-#endif
-      )
+  if (IS_ABSOLUTE_PATHNAME (name))
     {
       if (access (name, mode) == 0)
        {
@@ -2411,8 +2491,18 @@ find_a_file (pprefix, name, mode)
   return 0;
 }
 
-/* Add an entry for PREFIX in PLIST.  If FIRST is set, it goes
-   at the start of the list, otherwise it goes at the end.
+/* Ranking of prefixes in the sort list. -B prefixes are put before
+   all others.  */
+
+enum path_prefix_priority
+{
+  PREFIX_PRIORITY_B_OPT,
+  PREFIX_PRIORITY_LAST
+};
+
+/* Add an entry for PREFIX in PLIST.  The PLIST is kept in assending
+   order according to PRIORITY.  Within each PRIORITY, new entries are
+   appended.
 
    If WARN is nonzero, we will warn if no file is found
    through this prefix.  WARN should point to an int
@@ -2425,25 +2515,21 @@ find_a_file (pprefix, name, mode)
    2 means try both machine_suffix and just_machine_suffix.  */
 
 static void
-add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
+add_prefix (pprefix, prefix, component, priority, require_machine_suffix, warn)
      struct path_prefix *pprefix;
      const char *prefix;
      const char *component;
-     int first;
+     /* enum prefix_priority */ int priority;
      int require_machine_suffix;
      int *warn;
 {
   struct prefix_list *pl, **prev;
   int len;
 
-  if (! first && pprefix->plist)
-    {
-      for (pl = pprefix->plist; pl->next; pl = pl->next)
-       ;
-      prev = &pl->next;
-    }
-  else
-    prev = &pprefix->plist;
+  for (prev = &pprefix->plist;
+       (*prev) != NULL && (*prev)->priority <= priority;
+       prev = &(*prev)->next)
+    ;
 
   /* Keep track of the longest prefix */
 
@@ -2456,42 +2542,14 @@ add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
   pl->prefix = save_string (prefix, len);
   pl->require_machine_suffix = require_machine_suffix;
   pl->used_flag_ptr = warn;
+  pl->priority = priority;
   if (warn)
     *warn = 0;
 
-  if (*prev)
-    pl->next = *prev;
-  else
-    pl->next = (struct prefix_list *) 0;
-  *prev = pl;
-}
-
-/* Print warnings for any prefixes in the list PPREFIX that were not used.  */
-
-static void
-unused_prefix_warnings (pprefix)
-     struct path_prefix *pprefix;
-{
-  struct prefix_list *pl = pprefix->plist;
-
-  while (pl)
-    {
-      if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr)
-       {
-         if (pl->require_machine_suffix && machine_suffix)
-           error ("file path prefix `%s%s' never used", pl->prefix,
-                  machine_suffix);
-         else
-           error ("file path prefix `%s' never used", pl->prefix);
-
-         /* Prevent duplicate warnings.  */
-         *pl->used_flag_ptr = 1;
-       }
-
-      pl = pl->next;
-    }
+  /* Insert after PREV */
+  pl->next = (*prev);
+  (*prev) = pl;
 }
-
 \f
 /* Execute the command specified by the arguments on the current line of spec.
    When using pipes, this includes several piped-together commands
@@ -2506,11 +2564,11 @@ execute ()
   int n_commands;              /* # of command.  */
   char *string;
   struct command
-    {
-      const char *prog;                /* program name.  */
-      const char **argv;       /* vector of args.  */
-      int pid;                 /* pid of process for this command.  */
-    };
+  {
+    const char *prog;          /* program name.  */
+    const char **argv;         /* vector of args.  */
+    int pid;                   /* pid of process for this command.  */
+  };
 
   struct command *commands;    /* each command buffer with above info.  */
 
@@ -2520,8 +2578,7 @@ execute ()
       n_commands++;
 
   /* Get storage for each command.  */
-  commands
-    = (struct command *) alloca (n_commands * sizeof (struct command));
+  commands = (struct command *) alloca (n_commands * sizeof (struct command));
 
   /* Split argbuf into its separate piped processes,
      and record info about each one.
@@ -2538,7 +2595,7 @@ execute ()
     if (strcmp (argbuf[i], "|") == 0)
       {                                /* each command.  */
 #if defined (__MSDOS__) || defined (OS2) || defined (VMS)
-        fatal ("-pipe not supported");
+       fatal ("-pipe not supported");
 #endif
        argbuf[i] = 0;  /* termination of command args.  */
        commands[n_commands].prog = argbuf[i + 1];
@@ -2558,11 +2615,11 @@ execute ()
       /* 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++)
+      for (i = 0; i < n_commands; i++)
        {
-         const char **j;
+         const char *const *j;
 
          for (j = commands[i].argv; *j; j++)
            fprintf (stderr, " %s", *j);
@@ -2593,7 +2650,9 @@ execute ()
       char *errmsg_fmt, *errmsg_arg;
       const char *string = commands[i].argv[0];
 
-      commands[i].pid = pexecute (string, commands[i].argv,
+      /* For some bizarre reason, the second argument of execvp() is
+        char *const *, not const char *const *.  */
+      commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
                                  programname, temp_filename,
                                  &errmsg_fmt, &errmsg_arg,
                                  ((i == 0 ? PEXECUTE_FIRST : 0)
@@ -2624,7 +2683,7 @@ execute ()
     double ut = 0.0, st = 0.0;
 #endif
 
-    for (i = 0; i < n_commands; )
+    for (i = 0; i < n_commands;)
       {
        int j;
        int status;
@@ -2645,11 +2704,11 @@ execute ()
            getrusage (RUSAGE_CHILDREN, &rus);
            d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
            d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
-           ut = (double)d.tv_sec + (double)d.tv_usec / 1.0e6;
-           
+           ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
+
            d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
            d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
-           st = (double)d.tv_sec + (double)d.tv_usec / 1.0e6;
+           st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
          }
 #endif
 
@@ -2657,22 +2716,35 @@ execute ()
          if (commands[j].pid == pid)
            {
              i++;
-             if (status != 0)
+             if (WIFSIGNALED (status))
                {
-                 if (WIFSIGNALED (status))
-                   {
-                     fatal ("Internal compiler error: program %s got fatal signal %d",
-                            commands[j].prog, WTERMSIG (status));
-                     signal_count++;
-                     ret_code = -1;
-                   }
-                 else if (WIFEXITED (status)
-                          && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
-                   {
-                     if (WEXITSTATUS (status) > greatest_status)
-                       greatest_status = WEXITSTATUS (status);
-                     ret_code = -1;
-                   }
+#ifdef SIGPIPE
+                 /* SIGPIPE is a special case.  It happens in -pipe mode
+                    when the compiler dies before the preprocessor is
+                    done, or the assembler dies before the compiler is
+                    done.  There's generally been an error already, and
+                    this is just fallout.  So don't generate another error
+                    unless we would otherwise have succeeded.  */
+                 if (WTERMSIG (status) == SIGPIPE
+                     && (signal_count || greatest_status >= MIN_FATAL_STATUS))
+                   ;
+                 else
+#endif
+                   fatal ("\
+Internal error: %s (program %s)\n\
+Please submit a full bug report.\n\
+See %s for instructions.",
+                          strsignal (WTERMSIG (status)), commands[j].prog,
+                          GCCBUGURL);
+                 signal_count++;
+                 ret_code = -1;
+               }
+             else if (WIFEXITED (status)
+                      && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
+               {
+                 if (WEXITSTATUS (status) > greatest_status)
+                   greatest_status = WEXITSTATUS (status);
+                 ret_code = -1;
                }
 #ifdef HAVE_GETRUSAGE
              if (report_times && ut + st != 0)
@@ -2709,7 +2781,8 @@ struct switchstr
   const char *part1;
   const char **args;
   int live_cond;
-  int validated;
+  unsigned char validated;
+  unsigned char ordering;
 };
 
 static struct switchstr *switches;
@@ -2745,7 +2818,6 @@ static int warn_std;
 
 /* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
 static int *warn_std_ptr = 0;
-
 \f
 #if defined(HAVE_OBJECT_SUFFIX) || defined(HAVE_EXECUTABLE_SUFFIX)
 
@@ -2762,7 +2834,7 @@ convert_filename (name, do_exe)
 
   if (name == NULL)
     return NULL;
-  
+
   len = strlen (name);
 
 #ifdef HAVE_OBJECT_SUFFIX
@@ -2777,7 +2849,7 @@ convert_filename (name, do_exe)
     }
 #endif
 
-#ifdef HAVE_EXECUTABLE_SUFFIX
+#if defined(HAVE_EXECUTABLE_SUFFIX) && !defined(NO_AUTO_EXE_SUFFIX)
   /* If there is no filetype, make it the executable suffix (which includes
      the ".").  But don't get confused if we have just "-o".  */
   if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
@@ -2809,6 +2881,7 @@ display_help ()
 
   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
   fputs (_("  --help                   Display this information\n"), stdout);
+  fputs (_("  --target-help            Display target specific command line options\n"), stdout);
   if (! verbose_flag)
     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
   fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
@@ -2846,22 +2919,23 @@ display_help ()
                            guessing the language based on the file's extension\n\
 "), stdout);
 
-  printf (_("\n\
-Options starting with -g, -f, -m, -O or -W are automatically passed on to\n\
+  printf (_("\
+\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n\
 the various sub-processes invoked by %s.  In order to pass other options\n\
-on to these processes the -W<letter> options must be used.\n\"), programname);
+on to these processes the -W<letter> options must be used.\n\
+"), programname);
 
   /* The rest of the options are displayed by invocations of the various
      sub-processes.  */
 }
 
-static void                                                            
-add_preprocessor_option (option, len)                                  
-     const char * option;
+static void
+add_preprocessor_option (option, len)
+     const char *option;
      int len;
-{                                                                      
+{
   n_preprocessor_options++;
-                                                                       
+
   if (! preprocessor_options)
     preprocessor_options
       = (char **) xmalloc (n_preprocessor_options * sizeof (char *));
@@ -2869,14 +2943,14 @@ add_preprocessor_option (option, len)
     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)                                     
-     const char * option;
+
+static void
+add_assembler_option (option, len)
+     const char *option;
      int len;
 {
   n_assembler_options++;
@@ -2891,11 +2965,11 @@ add_assembler_option (option, len)
 
   assembler_options [n_assembler_options - 1] = save_string (option, len);
 }
-     
-static void                                                            
-add_linker_option (option, len)                                        
-     const char * option;
-     int    len;
+
+static void
+add_linker_option (option, len)
+     const char *option;
+     int len;
 {
   n_linker_options++;
 
@@ -2916,7 +2990,7 @@ add_linker_option (option, len)
 static void
 process_command (argc, argv)
      int argc;
-     const char **argv;
+     const char *const *argv;
 {
   register int i;
   const char *temp;
@@ -2926,6 +3000,10 @@ process_command (argc, argv)
   int have_c = 0;
   int have_o = 0;
   int lang_n_infiles = 0;
+#ifdef MODIFY_TARGET_NAME
+  int is_modify_target_name;
+  int j;
+#endif
 
   GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
 
@@ -2935,7 +3013,7 @@ process_command (argc, argv)
 
   /* Figure compiler version from version string.  */
 
-  compiler_version = temp1 = xstrdup (version_string); 
+  compiler_version = temp1 = xstrdup (version_string);
 
   for (; *temp1; ++temp1)
     {
@@ -2963,20 +3041,23 @@ process_command (argc, argv)
   if (gcc_exec_prefix)
     {
       int len = strlen (gcc_exec_prefix);
-      if (len > (int) sizeof ("/lib/gcc-lib/")-1
+
+      if (len > (int) sizeof ("/lib/gcc-lib/") - 1
          && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
        {
          temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1;
          if (IS_DIR_SEPARATOR (*temp)
-             && strncmp (temp+1, "lib", 3) == 0
+             && strncmp (temp + 1, "lib", 3) == 0
              && IS_DIR_SEPARATOR (temp[4])
-             && strncmp (temp+5, "gcc-lib", 7) == 0)
+             && strncmp (temp + 5, "gcc-lib", 7) == 0)
            len -= sizeof ("/lib/gcc-lib/") - 1;
        }
 
       set_std_prefix (gcc_exec_prefix, len);
-      add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
-      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
+      add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC",
+                 PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
+                 PREFIX_PRIORITY_LAST, 0, NULL_PTR);
     }
 
   /* COMPILER_PATH and LIBRARY_PATH have values
@@ -2993,20 +3074,21 @@ process_command (argc, argv)
        {
          if (*endp == PATH_SEPARATOR || *endp == 0)
            {
-             strncpy (nstore, startp, endp-startp);
+             strncpy (nstore, startp, endp - startp);
              if (endp == startp)
                strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
              else if (!IS_DIR_SEPARATOR (endp[-1]))
                {
-                 nstore[endp-startp] = DIR_SEPARATOR;
-                 nstore[endp-startp+1] = 0;
+                 nstore[endp - startp] = DIR_SEPARATOR;
+                 nstore[endp - startp + 1] = 0;
                }
              else
-               nstore[endp-startp] = 0;
-             add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR);
+               nstore[endp - startp] = 0;
+             add_prefix (&exec_prefixes, nstore, 0,
+                         PREFIX_PRIORITY_LAST, 0, NULL_PTR);
              add_prefix (&include_prefixes,
                          concat (nstore, "include", NULL_PTR),
-                         0, 0, 0, NULL_PTR);
+                         0, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -3027,18 +3109,18 @@ process_command (argc, argv)
        {
          if (*endp == PATH_SEPARATOR || *endp == 0)
            {
-             strncpy (nstore, startp, endp-startp);
+             strncpy (nstore, startp, endp - startp);
              if (endp == startp)
                strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
              else if (!IS_DIR_SEPARATOR (endp[-1]))
                {
-                 nstore[endp-startp] = DIR_SEPARATOR;
-                 nstore[endp-startp+1] = 0;
+                 nstore[endp - startp] = DIR_SEPARATOR;
+                 nstore[endp - startp + 1] = 0;
                }
              else
-               nstore[endp-startp] = 0;
+               nstore[endp - startp] = 0;
              add_prefix (&startfile_prefixes, nstore, NULL_PTR,
-                         0, 0, NULL_PTR);
+                         PREFIX_PRIORITY_LAST, 0, NULL_PTR);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -3060,18 +3142,18 @@ process_command (argc, argv)
        {
          if (*endp == PATH_SEPARATOR || *endp == 0)
            {
-             strncpy (nstore, startp, endp-startp);
+             strncpy (nstore, startp, endp - startp);
              if (endp == startp)
                strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
              else if (!IS_DIR_SEPARATOR (endp[-1]))
                {
-                 nstore[endp-startp] = DIR_SEPARATOR;
-                 nstore[endp-startp+1] = 0;
+                 nstore[endp - startp] = DIR_SEPARATOR;
+                 nstore[endp - startp + 1] = 0;
                }
              else
-               nstore[endp-startp] = 0;
+               nstore[endp - startp] = 0;
              add_prefix (&startfile_prefixes, nstore, NULL_PTR,
-                         0, 0, NULL_PTR);
+                         PREFIX_PRIORITY_LAST, 0, NULL_PTR);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -3089,6 +3171,7 @@ process_command (argc, argv)
 
   /* Scan argv twice.  Here, the first time, just count how many switches
      there will be in their vector, and how many input files in theirs.
+     Also parse any switches that determine the configuration name, such as -b.
      Here we also parse the switches that cc itself uses (e.g. -v).  */
 
   for (i = 1; i < argc; i++)
@@ -3099,8 +3182,8 @@ process_command (argc, argv)
          init_spec ();
          for (sl = specs; sl; sl = sl->next)
            printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
-          if (link_command_spec)
-            printf ("*link_command:\n%s\n\n", link_command_spec);
+         if (link_command_spec)
+           printf ("*link_command:\n%s\n\n", link_command_spec);
          exit (0);
        }
       else if (! strcmp (argv[i], "-dumpversion"))
@@ -3111,7 +3194,7 @@ process_command (argc, argv)
       else if (! strcmp (argv[i], "-dumpmachine"))
        {
          printf ("%s\n", spec_machine);
-         exit  (0);
+         exit (0);
        }
       else if (strcmp (argv[i], "-fhelp") == 0)
        {
@@ -3121,11 +3204,24 @@ process_command (argc, argv)
          /* 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], "-ftarget-help") == 0)
+        {
+          /* translate_options() has turned --target-help into -ftarget-help. */
+          target_help_flag = 1;
+
+          /* We will be passing a dummy file on to the sub-processes.  */
+          n_infiles++;
+          n_switches++;
+
+          add_preprocessor_option ("--target-help", 13);
+          add_assembler_option ("--target-help", 13);
+          add_linker_option ("--target-help", 13);
+        }
       else if (! strcmp (argv[i], "-pass-exit-codes"))
        {
          pass_exit_codes = 1;
@@ -3156,7 +3252,7 @@ process_command (argc, argv)
                add_assembler_option (argv[i] + prev, j - prev);
                prev = j + 1;
              }
-         
+
          /* Record the part after the last comma.  */
          add_assembler_option (argv[i] + prev, j - prev);
        }
@@ -3173,7 +3269,7 @@ process_command (argc, argv)
                add_preprocessor_option (argv[i] + prev, j - prev);
                prev = j + 1;
              }
-         
+
          /* Record the part after the last comma.  */
          add_preprocessor_option (argv[i] + prev, j - prev);
        }
@@ -3209,7 +3305,7 @@ process_command (argc, argv)
          if (++i >= argc)
            fatal ("argument to `-specs' is missing");
 
-         user->next = (struct user_specs *)0;
+         user->next = (struct user_specs *) 0;
          user->filename = argv[i];
          if (user_specs_tail)
            user_specs_tail->next = user;
@@ -3224,8 +3320,8 @@ process_command (argc, argv)
          if (strlen (argv[i]) == 7)
            fatal ("argument to `-specs=' is missing");
 
-         user->next = (struct user_specs *)0;
-         user->filename = argv[i]+7;
+         user->next = (struct user_specs *) 0;
+         user->filename = argv[i] + 7;
          if (user_specs_tail)
            user_specs_tail->next = user;
          else
@@ -3242,7 +3338,7 @@ process_command (argc, argv)
          switch (c)
            {
            case 'b':
-              n_switches++;
+             n_switches++;
              if (p[1] == 0 && i + 1 == argc)
                fatal ("argument to `-b' is missing");
              if (p[1] == 0)
@@ -3262,16 +3358,9 @@ process_command (argc, argv)
                  value = argv[++i];
                else
                  value = p + 1;
-               add_prefix (&exec_prefixes, value, NULL_PTR, 1, 0, &warn_B);
-               add_prefix (&startfile_prefixes, value, NULL_PTR,
-                           1, 0, &warn_B);
-               add_prefix (&include_prefixes, concat (value, "include",
-                                                      NULL_PTR),
-                           NULL_PTR, 1, 0, NULL_PTR);
-
-               /* As a kludge, if the arg is "[foo/]stageN/", just add
-                  "[foo/]include" to the include prefix.  */
                {
+                 /* As a kludge, if the arg is "[foo/]stageN/", just
+                    add "[foo/]include" to the include prefix.  */
                  int len = strlen (value);
                  if ((len == 7
                       || (len > 7
@@ -3282,18 +3371,26 @@ process_command (argc, argv)
                    {
                      if (len == 7)
                        add_prefix (&include_prefixes, "include", NULL_PTR,
-                                   1, 0, NULL_PTR);
+                                   PREFIX_PRIORITY_B_OPT, 0, NULL_PTR);
                      else
                        {
                          char *string = xmalloc (len + 1);
                          strncpy (string, value, len-7);
                          strcpy (string+len-7, "include");
                          add_prefix (&include_prefixes, string, NULL_PTR,
-                                     1, 0, NULL_PTR);
+                                     PREFIX_PRIORITY_B_OPT, 0, NULL_PTR);
                        }
                    }
                }
-                n_switches++;
+               add_prefix (&exec_prefixes, value, NULL_PTR,
+                           PREFIX_PRIORITY_B_OPT, 0, &warn_B);
+               add_prefix (&startfile_prefixes, value, NULL_PTR,
+                           PREFIX_PRIORITY_B_OPT, 0, &warn_B);
+               add_prefix (&include_prefixes, concat (value, "include",
+                                                      NULL_PTR),
+                           NULL_PTR,
+                           PREFIX_PRIORITY_B_OPT, 0, NULL_PTR);
+               n_switches++;
              }
              break;
 
@@ -3364,7 +3461,7 @@ process_command (argc, argv)
              if (! have_c)
                {
                  int skip;
-                 
+
                  /* Forward scan, just in case -S or -c is specified
                     after -o.  */
                  int j = i + 1;
@@ -3391,7 +3488,7 @@ process_command (argc, argv)
 #endif
 #if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
              if (p[1] == 0)
-               argv[i+1] = convert_filename (argv[i+1], ! have_c);
+               argv[i + 1] = convert_filename (argv[i + 1], ! have_c);
              else
                argv[i] = convert_filename (argv[i], ! have_c);
 #endif
@@ -3399,6 +3496,46 @@ process_command (argc, argv)
 
            default:
            normal_switch:
+
+#ifdef MODIFY_TARGET_NAME
+             is_modify_target_name = 0;
+
+             for (j = 0;
+                  j < sizeof modify_target / sizeof modify_target[0]; j++)
+               if (! strcmp (argv[i], modify_target[j].sw))
+                 {
+                   char *new_name
+                     = (char *) xmalloc (strlen (modify_target[j].str)
+                                         + strlen (spec_machine));
+                   const char *p, *r;
+                   char *q;
+                   int made_addition = 0;
+
+                   is_modify_target_name = 1;
+                   for (p = spec_machine, q = new_name; *p != 0; )
+                     {
+                       if (modify_target[j].add_del == DELETE
+                           && (! strncmp (q, modify_target[j].str,
+                                          strlen (modify_target[j].str))))
+                         p += strlen (modify_target[j].str);
+                       else if (modify_target[j].add_del == ADD
+                                && ! made_addition && *p == '-')
+                         {
+                           for (r = modify_target[j].str; *r != 0; )
+                             *q++ = *r++;
+                           made_addition = 1;
+                         }
+
+                       *q++ = *p++;
+                     }
+
+                   spec_machine = new_name;
+                 }
+
+             if (is_modify_target_name)
+               break;
+#endif               
+
              n_switches++;
 
              if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
@@ -3425,19 +3562,19 @@ process_command (argc, argv)
      as well as trying the machine and the version.  */
 #ifndef OS2
   add_prefix (&exec_prefixes, standard_exec_prefix, "GCC",
-             0, 1, warn_std_ptr);
+             PREFIX_PRIORITY_LAST, 1, warn_std_ptr);
   add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
-             0, 2, warn_std_ptr);
+             PREFIX_PRIORITY_LAST, 2, warn_std_ptr);
   add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
-             0, 2, warn_std_ptr);
+             PREFIX_PRIORITY_LAST, 2, warn_std_ptr);
 #endif
 
   add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
-             0, 1, warn_std_ptr);
+             PREFIX_PRIORITY_LAST, 1, warn_std_ptr);
   add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS",
-             0, 1, warn_std_ptr);
+             PREFIX_PRIORITY_LAST, 1, warn_std_ptr);
 
-  tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 
+  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
                           dir_separator_str, NULL_PTR);
 
   /* If tooldir is relative, base it on exec_prefixes.  A relative
@@ -3447,7 +3584,7 @@ process_command (argc, argv)
      directories, so that we can search both the user specified directory
      and the standard place.  */
 
-  if (!IS_DIR_SEPARATOR (*tooldir_prefix))
+  if (!IS_ABSOLUTE_PATHNAME (tooldir_prefix))
     {
       if (gcc_exec_prefix)
        {
@@ -3456,31 +3593,30 @@ process_command (argc, argv)
                      spec_version, dir_separator_str, tooldir_prefix, NULL_PTR);
 
          add_prefix (&exec_prefixes,
-                     concat (gcc_exec_tooldir_prefix, "bin", 
+                     concat (gcc_exec_tooldir_prefix, "bin",
                              dir_separator_str, NULL_PTR),
-                     NULL_PTR, 0, 0, NULL_PTR);
+                     NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
          add_prefix (&startfile_prefixes,
-                     concat (gcc_exec_tooldir_prefix, "lib", 
+                     concat (gcc_exec_tooldir_prefix, "lib",
                              dir_separator_str, NULL_PTR),
-                     NULL_PTR, 0, 0, NULL_PTR);
+                     NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
        }
 
       tooldir_prefix = concat (standard_exec_prefix, spec_machine,
-                              dir_separator_str, spec_version, 
+                              dir_separator_str, spec_version,
                               dir_separator_str, tooldir_prefix, NULL_PTR);
     }
 
-  add_prefix (&exec_prefixes, 
-              concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR),
-             "BINUTILS", 0, 0, NULL_PTR);
+  add_prefix (&exec_prefixes,
+             concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR),
+             "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
   add_prefix (&startfile_prefixes,
              concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR),
-             "BINUTILS", 0, 0, NULL_PTR);
+             "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
 
   /* More prefixes are enabled in main, after we read the specs file
      and determine whether this is cross-compilation or not.  */
 
-
   /* Then create the space for the vectors and scan again.  */
 
   switches = ((struct switchstr *)
@@ -3497,6 +3633,17 @@ process_command (argc, argv)
   for (i = 1; i < argc; i++)
     {
       /* Just skip the switches that were handled by the preceding loop.  */
+#ifdef MODIFY_TARGET_NAME
+      is_modify_target_name = 0;
+
+      for (j = 0; j < sizeof modify_target / sizeof modify_target[0]; j++)
+       if (! strcmp (argv[i], modify_target[j].sw))
+         is_modify_target_name = 1;
+
+      if (is_modify_target_name)
+       ;
+      else
+#endif
       if (! strncmp (argv[i], "-Wa,", 4))
        ;
       else if (! strncmp (argv[i], "-Wp,", 4))
@@ -3515,6 +3662,22 @@ process_command (argc, argv)
        ;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        ;
+      else if (strcmp (argv[i], "-ftarget-help") == 0)
+        {
+           /* Create a dummy input file, so that we can pass --target-help on to
+              the various sub-processes.  */
+           infiles[n_infiles].language = "c";
+           infiles[n_infiles++].name   = "target-dummy";
+
+           /* Preserve the --target-help switch so that it can be caught by
+              the cc1 spec string.  */
+           switches[n_switches].part1     = "--target-help";
+           switches[n_switches].args      = 0;
+           switches[n_switches].live_cond = SWITCH_OK;
+           switches[n_switches].validated = 0;
+
+           n_switches++;
+        }
       else if (strcmp (argv[i], "-fhelp") == 0)
        {
          if (verbose_flag)
@@ -3523,14 +3686,14 @@ process_command (argc, argv)
                 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 = SWITCH_OK;
-             switches[n_switches].validated     = 0;
-             
+             switches[n_switches].validated = 0;
+
              n_switches++;
            }
        }
@@ -3585,11 +3748,11 @@ process_command (argc, argv)
        {
          /* -save-temps overrides -pipe, so that temp files are produced */
          if (save_temps_flag)
-           error ("Warning: -pipe ignored since -save-temps specified");
+           error ("Warning: -pipe ignored because -save-temps specified");
           /* -time overrides -pipe because we can't get correct stats when
             multiple children are running at once.  */
          else if (report_times)
-           error ("Warning: -pipe ignored since -time specified");
+           error ("Warning: -pipe ignored because -time specified");
        }
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
@@ -3635,7 +3798,7 @@ process_command (argc, argv)
              /* Null-terminate the vector.  */
              switches[n_switches].args[j] = 0;
            }
-         else if (index (switches_need_spaces, c))
+         else if (strchr (switches_need_spaces, c))
            {
              /* On some systems, ld cannot handle some options without
                 a space.  So split the option from its argument.  */
@@ -3643,7 +3806,7 @@ process_command (argc, argv)
              char *tmp;
              part1[0] = c;
              part1[1] = '\0';
-             
+
              switches[n_switches].part1 = part1;
              switches[n_switches].args
                = (const char **) xmalloc (2 * sizeof (const char *));
@@ -3656,15 +3819,18 @@ process_command (argc, argv)
 
          switches[n_switches].live_cond = SWITCH_OK;
          switches[n_switches].validated = 0;
-         /* This is always valid, since gcc.c itself understands it.  */
-         if (!strcmp (p, "save-temps"))
+         switches[n_switches].ordering = 0;
+         /* These are always valid, since gcc.c itself understands it.  */
+         if (!strcmp (p, "save-temps")
+             || !strcmp (p, "static-libgcc")
+             || !strcmp (p, "shared-libgcc"))
            switches[n_switches].validated = 1;
-          else
-            {
-              char ch = switches[n_switches].part1[0];
-              if (ch == 'V' || ch == 'b' || ch == 'B')
-                switches[n_switches].validated = 1;
-            }
+         else
+           {
+             char ch = switches[n_switches].part1[0];
+             if (ch == 'V' || ch == 'b' || ch == 'B')
+               switches[n_switches].validated = 1;
+           }
          n_switches++;
        }
       else
@@ -3673,7 +3839,7 @@ process_command (argc, argv)
          argv[i] = convert_filename (argv[i], 0);
 #endif
 
-         if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0)
+         if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
            {
              perror_with_name (argv[i]);
              error_count++;
@@ -3706,9 +3872,13 @@ const char *input_filename;
 static int input_file_number;
 size_t input_filename_length;
 static int basename_length;
+static int suffixed_basename_length;
 static const char *input_basename;
 static const char *input_suffix;
 
+/* The compiler used to process the current input file.  */
+static struct compiler *input_file_compiler;
+
 /* These are variables used within do_spec and do_spec_1.  */
 
 /* Nonzero if an arg has been started and not yet terminated
@@ -3731,6 +3901,10 @@ static int this_is_library_file;
 /* Nonzero means that the input of this command is coming from a pipe.  */
 static int input_from_pipe;
 
+/* Nonnull means substitute this for any suffix when outputting a switches
+   arguments. */
+static const char *suffix_subst;
+
 /* Process the spec SPEC and run the commands specified therein.
    Returns 0 if the spec is successfully processed; -1 if failed.  */
 
@@ -3746,6 +3920,7 @@ do_spec (spec)
   this_is_output_file = 0;
   this_is_library_file = 0;
   input_from_pipe = 0;
+  suffix_subst = NULL;
 
   value = do_spec_1 (spec, 0, NULL_PTR);
 
@@ -3890,6 +4065,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            arg_going = 1;
            break;
 
+         case 'B':
+           obstack_grow (&obstack, input_basename, suffixed_basename_length);
+           arg_going = 1;
+           break;
+
          case 'd':
            delete_this_arg = 2;
            break;
@@ -3912,7 +4092,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                  /* Relative directories always come from -B,
                     and it is better not to use them for searching
                     at run time.  In particular, stage1 loses.  */
-                 if (!IS_DIR_SEPARATOR (pl->prefix[0]))
+                 if (!IS_ABSOLUTE_PATHNAME (pl->prefix))
                    continue;
 #endif
                  /* Try subdirectory if there is one.  */
@@ -4008,7 +4188,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            {
              const char *q = p;
              char *buf;
-             while (*p != 0 && *p != '\n') p++;
+             while (*p != 0 && *p != '\n')
+               p++;
              buf = (char *) alloca (p - q + 1);
              strncpy (buf, q, p - q);
              buf[p - q] = 0;
@@ -4016,7 +4197,42 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              return -1;
            }
            break;
+         case 'n':
+           /* %nfoo means report an notice with `foo' on stderr.  */
+           {
+             const char *q = p;
+             char *buf;
+             while (*p != 0 && *p != '\n')
+               p++;
+             buf = (char *) alloca (p - q + 1);
+             strncpy (buf, q, p - q);
+             buf[p - q] = 0;
+             notice ("%s\n", buf);
+             if (*p)
+               p++;
+           }
+           break;
+
+         case 'j':
+           {
+             struct stat st;
+
+             /* If save_temps_flag is off, and the HOST_BIT_BUCKET is defined,
+                and it is not a directory, and it is writable, use it.
+                Otherwise, fall through and treat this like any other
+                temporary file.  */
 
+             if ((!save_temps_flag)
+                 && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
+                 && (access (HOST_BIT_BUCKET, W_OK) == 0))
+               {
+                 obstack_grow (&obstack, HOST_BIT_BUCKET,
+                               strlen (HOST_BIT_BUCKET));
+                 delete_this_arg = 0;
+                 arg_going = 1;
+                 break;
+               }
+           }
          case 'g':
          case 'u':
          case 'U':
@@ -4027,24 +4243,19 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              }
            else
              {
-#ifdef MKTEMP_EACH_FILE
-               /* ??? This has a problem: the total number of
-                  values mktemp can return is limited.
-                  That matters for the names of object files.
-                  In 2.4, do something about that.  */
                struct temp_name *t;
                int suffix_length;
                const char *suffix = p;
                char *saved_suffix = NULL;
 
-               while (*p == '.' || ISALPHA ((unsigned char)*p))
+               while (*p == '.' || ISALPHA ((unsigned char) *p))
                  p++;
                suffix_length = p - suffix;
                if (p[0] == '%' && p[1] == 'O')
                  {
                    p += 2;
                    /* We don't support extra suffix characters after %O.  */
-                   if (*p == '.' || ISALPHA ((unsigned char)*p))
+                   if (*p == '.' || ISALPHA ((unsigned char) *p))
                      abort ();
                    if (suffix_length == 0)
                      suffix = OBJECT_SUFFIX;
@@ -4068,8 +4279,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      && t->unique == (c != 'g'))
                    break;
 
-               /* Make a new association if needed.  %u requires one.  */
-               if (t == 0 || c == 'u')
+               /* Make a new association if needed.  %u and %j require one.  */
+               if (t == 0 || c == 'u' || c == 'j')
                  {
                    if (t == 0)
                      {
@@ -4091,19 +4302,6 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
                obstack_grow (&obstack, t->filename, t->filename_length);
                delete_this_arg = 1;
-#else
-               obstack_grow (&obstack, temp_filename, temp_filename_length);
-               if (c == 'u' || c == 'U')
-                 {
-                   static int unique;
-                   char buff[9];
-                   if (c == 'u')
-                     unique++;
-                   sprintf (buff, "%d", unique);
-                   obstack_grow (&obstack, buff, strlen (buff));
-                 }
-#endif
-               delete_this_arg = 1;
              }
            arg_going = 1;
            break;
@@ -4267,9 +4465,15 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case 'C':
-           value = do_spec_1 (cpp_spec, 0, NULL_PTR);
-           if (value != 0)
-             return value;
+           {
+             const char* spec 
+               = (input_file_compiler->cpp_spec 
+                  ? input_file_compiler->cpp_spec 
+                  : cpp_spec);
+             value = do_spec_1 (spec, 0, NULL_PTR);
+             if (value != 0)
+               return value;
+           }
            break;
 
          case 'E':
@@ -4296,6 +4500,23 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              return value;
            break;
 
+         case 'M':
+           if (multilib_dir && strcmp (multilib_dir, ".") != 0)
+             {
+               char *p;
+               const char *q;
+               size_t len;
+
+               len = strlen (multilib_dir);
+               obstack_blank (&obstack, len + 1);
+               p = obstack_next_free (&obstack) - (len + 1);
+
+               *p++ = '_';
+               for (q = multilib_dir; *q ; ++q, ++p)
+                 *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
+             }
+           break;
+
          case 'p':
            {
              char *x = (char *) alloca (strlen (cpp_predefines) + 1);
@@ -4351,9 +4572,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      *x++ = *y++;
 
                      if (*y != '_'
-                         || (*(y+1) != '_'
-                             && ! ISUPPER ((unsigned char)*(y+1))))
-                       {
+                         || (*(y + 1) != '_'
+                             && ! ISUPPER ((unsigned char) *(y + 1))))
+                       {
                          /* Stick __ at front of macro name.  */
                          if (*y != '_')
                            *x++ = '_';
@@ -4367,7 +4588,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        *x++ = *y++;
 
                      if (flag)
-                       {
+                       {
                          if (x[-1] != '_')
                            {
                              if (x[-2] != '_')
@@ -4399,9 +4620,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      y += 2;
 
                      if (*y != '_'
-                         || (*(y+1) != '_'
-                             && ! ISUPPER ((unsigned char)*(y+1))))
-                       {
+                         || (*(y + 1) != '_'
+                             && ! ISUPPER ((unsigned char) *(y + 1))))
+                       {
                          /* Stick -D__ at front of macro name.  */
                          *x++ = '-';
                          *x++ = 'D';
@@ -4475,6 +4696,17 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            obstack_1grow (&obstack, '%');
            break;
 
+         case '.':
+          {
+            unsigned len = 0;
+
+            while (p[len] && p[len] != ' ' && p[len] != '%')
+              len++;
+             suffix_subst = save_string (p - 1, len + 1);
+             p += len;
+           }
+          break;
+          
          case '*':
            if (soft_matched_part)
              {
@@ -4547,14 +4779,15 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                              flag = 1;
                              continue;
                            }
-                          else if (flag && (*y == ' ' || *y == '\t' || *y == '='
-                                            || *y == '}' || *y == 0))
+                         else if (flag
+                                  && (*y == ' ' || *y == '\t' || *y == '='
+                                      || *y == '}' || *y == 0))
                            {
                              *x++ = '_';
                              *x++ = '_';
                              flag = 0;
                            }
-                          if (*y == 0)
+                         if (*y == 0)
                            break;
                          else
                            *x++ = *y++;
@@ -4609,8 +4842,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                    v++;
                  if ((*v != 0) && (*v != ' ') && (*v != '.') && (*v != '-'))
                    abort ();
-                  if (*v != 0)
-                      v++;
+                 if (*v != 0)
+                   v++;
                }
 
              /* Set Q at the next period or at the end.  */
@@ -4620,12 +4853,12 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-')
                abort ();
 
-              if (q > v)
-               /* Put that part into the command.  */
-               obstack_grow (&obstack, v, q - v);
-              else
-                /* Default to "0" */
-                obstack_grow (&obstack, &zeroc, 1);
+             if (q > v)
+               /* Put that part into the command.  */
+               obstack_grow (&obstack, v, q - v);
+             else
+               /* Default to "0" */
+               obstack_grow (&obstack, &zeroc, 1);
              arg_going = 1;
            }
            break;
@@ -4652,7 +4885,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
        arg_going = 1;
       }
 
-  return 0;            /* End of string */
+  /* End of string.  */
+  return 0;
 }
 
 /* Return 0 if we call do_spec_1 and that returns -1.  */
@@ -4663,10 +4897,12 @@ handle_braces (p)
 {
   const char *filter, *body = NULL, *endbody = NULL;
   int pipe_p = 0;
+  int true_once = 0;   /* If, in %{a|b:d}, at least one of a,b was seen.  */
   int negate;
   int suffix;
   int include_blanks = 1;
   int elide_switch = 0;
+  int ordered = 0;
 
   if (*p == '^')
     {
@@ -4717,42 +4953,45 @@ next_member:
       abort ();
     }
 
+ next_ampersand:
   filter = p;
-  while (*p != ':' && *p != '}' && *p != '|') p++;
+  while (*p != ':' && *p != '}' && *p != '|' && *p != '&')
+    p++;
 
-  if (*p == '|' && pipe_p)
+  if (*p == '|' && (pipe_p || ordered))
     abort ();
 
   if (!body)
     {
-      if (*p != '}')
-        {
+      if (*p != '}' && *p != '&')
+       {
          register int count = 1;
          register const char *q = p;
 
-         while (*q++ != ':') continue;
+         while (*q++ != ':')
+           continue;
          body = q;
-         
+
          while (count > 0)
            {
              if (*q == '{')
-               count++;
+               count++;
              else if (*q == '}')
-               count--;
+               count--;
              else if (*q == 0)
-               abort ();
+               abort ();
              q++;
            }
          endbody = q;
        }
       else
-       body = p, endbody = p+1;
+       body = p, endbody = p + 1;
     }
 
   if (suffix)
     {
       int found = (input_suffix != 0
-                  && (long) strlen (input_suffix) == (long)(p - filter)
+                  && (long) strlen (input_suffix) == (long) (p - filter)
                   && strncmp (input_suffix, filter, p - filter) == 0);
 
       if (body[0] == '}')
@@ -4762,15 +5001,23 @@ next_member:
          && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
        return 0;
     }
-  else if (p[-1] == '*' && p[0] == '}')
+  else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&'))
     {
       /* Substitute all matching switches as separate args.  */
       register int i;
-      --p;
+
       for (i = 0; i < n_switches; i++)
-       if (!strncmp (switches[i].part1, filter, p - filter)
-           && check_live_switch (i, p - filter))
-         give_switch (i, 0, include_blanks);
+       if (!strncmp (switches[i].part1, filter, p - 1 - filter)
+           && check_live_switch (i, p - 1 - filter))
+         {
+           if (elide_switch)
+             {
+               switches[i].live_cond = SWITCH_IGNORE;
+               switches[i].validated = 1;
+             }
+           else
+             ordered = 1, switches[i].ordering = 1;
+         }
     }
   else
     {
@@ -4810,6 +5057,7 @@ next_member:
                    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
                    /* Pass any arguments this switch has.  */
                    give_switch (i, 1, 1);
+                   suffix_subst = NULL;
                  }
 
              /* We didn't match.  Try again.  */
@@ -4860,16 +5108,13 @@ next_member:
              switches[i].live_cond = SWITCH_IGNORE;
              switches[i].validated = 1;
            }
+         else if (ordered || *p == '&')
+           ordered = 1, switches[i].ordering = 1;
          else if (*p == '}')
-           {
-             give_switch (i, 0, include_blanks);
-           }
+           give_switch (i, 0, include_blanks);
          else
-           {
-             if (do_spec_1 (save_string (body, endbody - body - 1),
-                            0, NULL_PTR) < 0)
-               return 0;
-           }
+           /* Even if many alternatives are matched, only output once.  */
+           true_once = 1;
        }
       else if (pipe_p)
        {
@@ -4884,6 +5129,32 @@ next_member:
   if (*p++ == '|')
     goto next_member;
 
+  if (p[-1] == '&')
+    {
+      body = 0;
+      goto next_ampersand;
+    }
+
+  if (ordered)
+    {
+      int i;
+      /* Doing this set of switches later preserves their command-line
+        ordering.  This is needed for e.g. -U, -D and -A.  */
+      for (i = 0; i < n_switches; i++)
+       if (switches[i].ordering == 1)
+         {
+           switches[i].ordering = 0;
+           give_switch (i, 0, include_blanks);
+         }
+    }
+  /* Process the spec just once, regardless of match count.  */
+  else if (true_once)
+    {
+      if (do_spec_1 (save_string (body, endbody - body - 1),
+                    0, NULL_PTR) < 0)
+       return 0;
+    }
+
   return endbody;
 }
 \f
@@ -4918,13 +5189,13 @@ check_live_switch (switchnum, prefix_length)
   switch (*name)
     {
     case 'O':
-       for (i = switchnum + 1; i < n_switches; i++)
-         if (switches[i].part1[0] == 'O')
-           {
-             switches[switchnum].validated = 1;
-             switches[switchnum].live_cond = SWITCH_FALSE;
-             return 0;
-           }
+      for (i = switchnum + 1; i < n_switches; i++)
+       if (switches[i].part1[0] == 'O')
+         {
+           switches[switchnum].validated = 1;
+           switches[switchnum].live_cond = SWITCH_FALSE;
+           return 0;
+         }
       break;
 
     case 'W':  case 'f':  case 'm':
@@ -4934,11 +5205,11 @@ check_live_switch (switchnum, prefix_length)
          for (i = switchnum + 1; i < n_switches; i++)
            if (switches[i].part1[0] == name[0]
                && ! strcmp (&switches[i].part1[1], &name[4]))
-           {
-             switches[switchnum].validated = 1;
-             switches[switchnum].live_cond = SWITCH_FALSE;
-             return 0;
-           }
+             {
+               switches[switchnum].validated = 1;
+               switches[switchnum].live_cond = SWITCH_FALSE;
+               return 0;
+             }
        }
       else
        {
@@ -4949,11 +5220,11 @@ check_live_switch (switchnum, prefix_length)
                && switches[i].part1[2] == 'o'
                && switches[i].part1[3] == '-'
                && !strcmp (&switches[i].part1[4], &name[1]))
-           {
-             switches[switchnum].validated = 1;
-             switches[switchnum].live_cond = SWITCH_FALSE;
-             return 0;
-           }
+             {
+               switches[switchnum].validated = 1;
+               switches[switchnum].live_cond = SWITCH_FALSE;
+               return 0;
+             }
        }
       break;
     }
@@ -4994,9 +5265,29 @@ give_switch (switchnum, omit_first_word, include_blanks)
       const char **p;
       for (p = switches[switchnum].args; *p; p++)
        {
+         const char *arg = *p;
+
          if (include_blanks)
            do_spec_1 (" ", 0, NULL_PTR);
-         do_spec_1 (*p, 1, NULL_PTR);
+         if (suffix_subst)
+           {
+             unsigned length = strlen (arg);
+
+             while (length-- && !IS_DIR_SEPARATOR (arg[length]))
+               if (arg[length] == '.')
+                 {
+                   ((char *)arg)[length] = 0;
+                   break;
+                 }
+             do_spec_1 (arg, 1, NULL_PTR);
+             if (!arg[length])
+               {
+                 ((char *)arg)[length] = '.';
+                 do_spec_1 (suffix_subst, 1, NULL_PTR);
+               }
+           }
+         else
+           do_spec_1 (arg, 1, NULL_PTR);
        }
     }
 
@@ -5072,11 +5363,11 @@ is_directory (path1, path2, linker)
   /* Exclude directories that the linker is known to search.  */
   if (linker
       && ((cp - path == 6
-          && strcmp (path, concat (dir_separator_str, "lib", 
+          && strcmp (path, concat (dir_separator_str, "lib",
                                    dir_separator_str, ".", NULL_PTR)) == 0)
          || (cp - path == 10
-             && strcmp (path, concat (dir_separator_str, "usr", 
-                                      dir_separator_str, "lib", 
+             && strcmp (path, concat (dir_separator_str, "usr",
+                                      dir_separator_str, "lib",
                                       dir_separator_str, ".", NULL_PTR)) == 0)))
     return 0;
 
@@ -5094,7 +5385,7 @@ set_input (filename)
 
   input_filename = filename;
   input_filename_length = strlen (input_filename);
-  
+
   input_basename = input_filename;
 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
   /* Skip drive name so 'x:foo' is handled properly.  */
@@ -5108,8 +5399,10 @@ set_input (filename)
   /* Find a suffix starting with the last period,
      and set basename_length to exclude that suffix.  */
   basename_length = strlen (input_basename);
+  suffixed_basename_length = basename_length;
   p = input_basename + basename_length;
-  while (p != input_basename && *p != '.') --p;
+  while (p != input_basename && *p != '.')
+    --p;
   if (*p == '.' && p != input_basename)
     {
       basename_length = p - input_basename;
@@ -5133,15 +5426,14 @@ fatal_error (signum)
   kill (getpid (), signum);
 }
 
-extern int main PARAMS ((int, char **));
+extern int main PARAMS ((int, const char *const *));
 
 int
 main (argc, argv)
      int argc;
-     char **argv;
+     const char *const *argv;
 {
-  register size_t i;
-  size_t j;
+  size_t i;
   int value;
   int linker_was_run = 0;
   char *explicit_link_files;
@@ -5154,9 +5446,23 @@ main (argc, argv)
     --p;
   programname = p;
 
+  xmalloc_set_program_name (programname);
+
+#ifdef GCC_DRIVER_HOST_INITIALIZATION
+  /* Perform host dependant initialization when needed.  */
+  GCC_DRIVER_HOST_INITIALIZATION;
+#endif
+
+/* LC_CTYPE determines the character set used by the terminal so it has be set
+   to output messages correctly.  */
+
 #ifdef HAVE_LC_MESSAGES
+  setlocale (LC_CTYPE, "");
   setlocale (LC_MESSAGES, "");
+#else
+  setlocale (LC_ALL, "");
 #endif
+
   (void) bindtextdomain (PACKAGE, localedir);
   (void) textdomain (PACKAGE);
 
@@ -5172,6 +5478,9 @@ main (argc, argv)
   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
     signal (SIGPIPE, fatal_error);
 #endif
+  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+     receive the signal.  A different setting is inheritable */
+  signal (SIGCHLD, SIG_DFL);
 
   argbuf_length = 10;
   argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
@@ -5200,15 +5509,13 @@ main (argc, argv)
 
     q = multilib_exclusions_raw;
     while ((p = *q++) != (char *) 0)
-       obstack_grow (&multilib_obstack, p, strlen (p));
+      obstack_grow (&multilib_obstack, p, strlen (p));
 
     obstack_1grow (&multilib_obstack, 0);
     multilib_exclusions = obstack_finish (&multilib_obstack);
-    
+
     need_space = FALSE;
-    for (i = 0;
-        i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]);
-        i++)
+    for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
       {
        if (need_space)
          obstack_1grow (&multilib_obstack, ' ');
@@ -5226,8 +5533,8 @@ main (argc, argv)
      needed for collect.  We use argv[0] instead of programname because
      we need the complete pathname.  */
   obstack_init (&collect_obstack);
-  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1);
-  obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1);
+  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
+  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
   putenv (obstack_finish (&collect_obstack));
 
 #ifdef INIT_ENVIRONMENT
@@ -5235,13 +5542,6 @@ main (argc, argv)
   putenv (INIT_ENVIRONMENT);
 #endif
 
-  /* 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).
      Decode switches that are handled locally.  */
@@ -5254,35 +5554,35 @@ main (argc, argv)
     /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
        the compiler.  */
     obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
-                 sizeof ("COLLECT_GCC_OPTIONS=")-1);
+                 sizeof ("COLLECT_GCC_OPTIONS=") - 1);
 
     first_time = TRUE;
-    for (i = 0; (int)i < n_switches; i++)
+    for (i = 0; (int) i < n_switches; i++)
       {
-       const char **args;
+       const char *const *args;
        const char *p, *q;
        if (!first_time)
          obstack_grow (&collect_obstack, " ", 1);
 
        first_time = FALSE;
        obstack_grow (&collect_obstack, "'-", 2);
-        q = switches[i].part1;
-       while ((p = index (q,'\'')))
-          {
-            obstack_grow (&collect_obstack, q, p-q);
-            obstack_grow (&collect_obstack, "'\\''", 4);
-            q = ++p;
-          }
-        obstack_grow (&collect_obstack, q, strlen (q));
+       q = switches[i].part1;
+       while ((p = strchr (q, '\'')))
+         {
+           obstack_grow (&collect_obstack, q, p - q);
+           obstack_grow (&collect_obstack, "'\\''", 4);
+           q = ++p;
+         }
+       obstack_grow (&collect_obstack, q, strlen (q));
        obstack_grow (&collect_obstack, "'", 1);
 
        for (args = switches[i].args; args && *args; args++)
          {
            obstack_grow (&collect_obstack, " '", 2);
            q = *args;
-           while ((p = index (q,'\'')))
+           while ((p = strchr (q, '\'')))
              {
-               obstack_grow (&collect_obstack, q, p-q);
+               obstack_grow (&collect_obstack, q, p - q);
                obstack_grow (&collect_obstack, "'\\''", 4);
                q = ++p;
              }
@@ -5298,8 +5598,8 @@ main (argc, argv)
      This means one element containing 0s, as a terminator.  */
 
   compilers = (struct compiler *) xmalloc (sizeof default_compilers);
-  bcopy ((char *) default_compilers, (char *) compilers,
-        sizeof default_compilers);
+  memcpy ((char *) compilers, (char *) default_compilers,
+         sizeof default_compilers);
   n_compilers = n_default_compilers;
 
   /* Read specs from a file if there is one.  */
@@ -5326,68 +5626,64 @@ main (argc, argv)
   strcat (specs_file, "specs");
   if (access (specs_file, R_OK) == 0)
     read_specs (specs_file, TRUE);
+
   /* If not cross-compiling, look for startfiles in the standard places.  */
   if (*cross_compile == '0')
     {
-#ifdef MD_EXEC_PREFIX
-      add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
-      add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
-#endif
+      if (*md_exec_prefix)
+       {
+         add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
+                     PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+         add_prefix (&startfile_prefixes, md_exec_prefix, "GCC",
+                     PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+       }
 
-#ifdef MD_STARTFILE_PREFIX
-      add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
-                 0, 0, NULL_PTR);
-#endif
+      if (*md_startfile_prefix)
+       add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
+                   PREFIX_PRIORITY_LAST, 0, NULL_PTR);
 
-#ifdef MD_STARTFILE_PREFIX_1
-      add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
-                 0, 0, NULL_PTR);
-#endif
+      if (*md_startfile_prefix_1)
+       add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
+                   PREFIX_PRIORITY_LAST, 0, NULL_PTR);
 
       /* If standard_startfile_prefix is relative, base it on
         standard_exec_prefix.  This lets us move the installed tree
         as a unit.  If GCC_EXEC_PREFIX is defined, base
         standard_startfile_prefix on that as well.  */
-      if (IS_DIR_SEPARATOR (*standard_startfile_prefix)
-           || *standard_startfile_prefix == '$'
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-           /* Check for disk name on MS-DOS-based systems.  */
-          || (standard_startfile_prefix[1] == ':'
-             && (IS_DIR_SEPARATOR (standard_startfile_prefix[2])))
-#endif
-         )
+      if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix))
        add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
-                   0, 0, NULL_PTR);
+                   PREFIX_PRIORITY_LAST, 0, NULL_PTR);
       else
        {
          if (gcc_exec_prefix)
            add_prefix (&startfile_prefixes,
                        concat (gcc_exec_prefix, machine_suffix,
                                standard_startfile_prefix, NULL_PTR),
-                       NULL_PTR, 0, 0, NULL_PTR);
+                       NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
          add_prefix (&startfile_prefixes,
                      concat (standard_exec_prefix,
                              machine_suffix,
                              standard_startfile_prefix, NULL_PTR),
-                     NULL_PTR, 0, 0, NULL_PTR);
-       }                      
+                     NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+       }
 
       add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
-                 "BINUTILS", 0, 0, NULL_PTR);
+                 "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
       add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
-                 "BINUTILS", 0, 0, NULL_PTR);
+                 "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
 #if 0 /* Can cause surprises, and one can use -B./ instead.  */
-      add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR);
+      add_prefix (&startfile_prefixes, "./", NULL_PTR,
+                 PREFIX_PRIORITY_LAST, 1, NULL_PTR);
 #endif
     }
   else
     {
-      if (!IS_DIR_SEPARATOR (*standard_startfile_prefix) && gcc_exec_prefix)
+      if (!IS_ABSOLUTE_PATHNAME (standard_startfile_prefix)
+         && gcc_exec_prefix)
        add_prefix (&startfile_prefixes,
                    concat (gcc_exec_prefix, machine_suffix,
                            standard_startfile_prefix, NULL_PTR),
-                   "BINUTILS", 0, 0, NULL_PTR);
+                   "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
     }
 
   /* Process any user specified specs in the order given on the command
@@ -5401,9 +5697,9 @@ main (argc, argv)
   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
   if (gcc_exec_prefix)
     {
-      char * temp = (char *) xmalloc (strlen (gcc_exec_prefix)
-                                     + strlen (spec_version)
-                                     + strlen (spec_machine) + 3);
+      char *temp = (char *) xmalloc (strlen (gcc_exec_prefix)
+                                    + strlen (spec_version)
+                                    + strlen (spec_machine) + 3);
       strcpy (temp, gcc_exec_prefix);
       strcat (temp, spec_machine);
       strcat (temp, dir_separator_str);
@@ -5423,7 +5719,7 @@ main (argc, argv)
 
   /* Warn about any switches that no pass was interested in.  */
 
-  for (i = 0; (int)i < n_switches; i++)
+  for (i = 0; (int) i < n_switches; i++)
     if (! switches[i].validated)
       error ("unrecognized option `-%s'", switches[i].part1);
 
@@ -5465,6 +5761,16 @@ main (argc, argv)
       return (0);
     }
 
+  if (target_help_flag)
+   {
+      /* Print if any target specific options.*/
+
+      /* We do not exit here. Instead we have created a fake input file
+         called 'target-dummy' which needs to be compiled, and we pass this
+         on to the various sub-processes, along with the --target-help
+         switch. */
+    }
+
   if (print_help_list)
     {
       display_help ();
@@ -5473,7 +5779,7 @@ main (argc, argv)
        {
          printf (_("\nFor bug reporting instructions, please see:\n"));
          printf ("%s.\n", GCCBUGURL);
-         
+
          return (0);
        }
 
@@ -5481,11 +5787,13 @@ main (argc, argv)
         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;
 
+      notice ("Configured with: %s\n", configuration_arguments);
+
       /* compiler_version is truncated at the first space when initialized
         from version string, so truncate version_string at the first space
         before comparing.  */
@@ -5518,9 +5826,8 @@ main (argc, argv)
 
   explicit_link_files = xcalloc (1, n_infiles);
 
-  for (i = 0; (int)i < n_infiles; i++)
+  for (i = 0; (int) i < n_infiles; i++)
     {
-      register struct compiler *cp = 0;
       int this_file_error = 0;
 
       /* Tell do_spec what to substitute for %i.  */
@@ -5534,38 +5841,18 @@ main (argc, argv)
 
       /* Figure out which compiler from the file's suffix.  */
 
-      cp = lookup_compiler (infiles[i].name, input_filename_length,
-                           infiles[i].language);
-
-      if (cp)
+      input_file_compiler
+       = lookup_compiler (infiles[i].name, input_filename_length,
+                          infiles[i].language);
+      
+      if (input_file_compiler)
        {
          /* Ok, we found an applicable compiler.  Run its spec.  */
-         /* First say how much of input_filename to substitute for %b  */
-         int len;
 
-         if (cp->spec[0][0] == '#')
+         if (input_file_compiler->spec[0] == '#')
            error ("%s: %s compiler not installed on this system",
-                  input_filename, &cp->spec[0][1]);
-
-         len = 0;
-         for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
-           if (cp->spec[j])
-             len += strlen (cp->spec[j]);
-
-         {
-           char *p1 = (char *) xmalloc (len + 1);
-           
-           len = 0;
-           for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
-             if (cp->spec[j])
-               {
-                 strcpy (p1 + len, cp->spec[j]);
-                 len += strlen (cp->spec[j]);
-               }
-           
-           value = do_spec (p1);
-           free (p1);
-         }
+                  input_filename, &input_file_compiler->spec[1]);
+         value = do_spec (input_file_compiler->spec);
          if (value < 0)
            this_file_error = 1;
        }
@@ -5609,7 +5896,7 @@ main (argc, argv)
     {
       int tmp = execution_count;
 
-      /* We'll use ld if we can't find collect2. */
+      /* 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);
@@ -5627,17 +5914,13 @@ main (argc, argv)
       linker_was_run = (tmp != execution_count);
     }
 
-  /* Warn if a -B option was specified but the prefix was never used.  */
-  unused_prefix_warnings (&exec_prefixes);
-  unused_prefix_warnings (&startfile_prefixes);
-
   /* If options said don't run linker,
      complain about input files to be given to the linker.  */
 
   if (! linker_was_run && error_count == 0)
-    for (i = 0; (int)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",
+       error ("%s: linker input file unused because linking not done",
               outfiles[i]);
 
   /* Delete some or all of the temporary files we made.  */
@@ -5651,7 +5934,7 @@ main (argc, argv)
       printf (("\nFor bug reporting instructions, please see:\n"));
       printf ("%s\n", GCCBUGURL);
     }
-  
+
   return (signal_count != 0 ? 2
          : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
          : 0);
@@ -5716,41 +5999,28 @@ lookup_compiler (name, length, language)
       }
 #endif
 
-
   if (cp >= compilers)
     {
-      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.
-            Construct the new compiler spec.  */
-         language = cp->spec[0] + 1;
-         new = (struct compiler *) xmalloc (sizeof (struct compiler));
-         new->suffix = cp->suffix;
-         memcpy (new->spec,
-                 lookup_compiler (NULL_PTR, 0, language)->spec,
-                 sizeof new->spec);
-         return new;
-       }
-
-      /* A non-alias entry: return it.  */
-      return cp;
+      if (cp->spec[0] != '@')
+       /* A non-alias entry: return it.  */
+       return cp;
+
+      /* 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.  */
+      return lookup_compiler (NULL_PTR, 0, cp->spec + 1);
     }
-
   return 0;
 }
 \f
 static char *
 save_string (s, len)
-  const char *s;
-  int len;
+     const char *s;
+     int len;
 {
   register char *result = xmalloc (len + 1);
 
-  bcopy (s, result, len);
+  memcpy (result, s, len);
   result[len] = 0;
   return result;
 }
@@ -5861,7 +6131,6 @@ notice VPARAMS ((const char *msgid, ...))
   vfprintf (stderr, _(msgid), ap);
   va_end (ap);
 }
-
 \f
 static void
 validate_all_switches ()
@@ -5871,21 +6140,17 @@ validate_all_switches ()
   register char c;
   struct spec_list *spec;
 
-  for (comp = compilers; comp->spec[0]; comp++)
+  for (comp = compilers; comp->spec; comp++)
     {
-      size_t i;
-      for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
-       {
-         p = comp->spec[i];
-         while ((c = *p++))
-           if (c == '%' && *p == '{')
-             /* We have a switch spec.  */
-             validate_switches (p + 1);
-       }
+      p = comp->spec;
+      while ((c = *p++))
+       if (c == '%' && *p == '{')
+         /* We have a switch spec.  */
+         validate_switches (p + 1);
     }
 
   /* Look through the linked list of specs read from the specs file.  */
-  for (spec = specs; spec ; spec = spec->next)
+  for (spec = specs; spec; spec = spec->next)
     {
       p = *(spec->ptr_spec);
       while ((c = *p++))
@@ -5911,28 +6176,30 @@ validate_switches (start)
   register const char *p = start;
   const char *filter;
   register int i;
-  int suffix = 0;
+  int suffix;
 
   if (*p == '|')
     ++p;
 
+next_member:
   if (*p == '!')
     ++p;
 
+  suffix = 0;
   if (*p == '.')
     suffix = 1, ++p;
 
   filter = p;
-  while (*p != ':' && *p != '}') p++;
+  while (*p != ':' && *p != '}' && *p != '|' && *p != '&')
+    p++;
 
   if (suffix)
     ;
   else if (p[-1] == '*')
     {
       /* Mark all matching switches as valid.  */
-      --p;
       for (i = 0; i < n_switches; i++)
-       if (!strncmp (switches[i].part1, filter, p - filter))
+       if (!strncmp (switches[i].part1, filter, p - filter - 1))
          switches[i].validated = 1;
     }
   else
@@ -5945,6 +6212,9 @@ validate_switches (start)
            switches[i].validated = 1;
        }
     }
+
+  if (*p++ == '|' || p[-1] == '&')
+    goto next_member;
 }
 \f
 /* Check whether a particular argument was used.  The first time we
@@ -5973,13 +6243,14 @@ used_arg (p, len)
       const char *q;
       int cnt = 0;
 
-      /* Break multilib_matches into the component strings of string and replacement
-         string.  */
+      /* Break multilib_matches into the component strings of string
+         and replacement string.  */
       for (q = multilib_matches; *q != '\0'; q++)
        if (*q == ';')
          cnt++;
 
-      matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
+      matches =
+       (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
       i = 0;
       q = multilib_matches;
       while (*q != '\0')
@@ -6022,7 +6293,7 @@ used_arg (p, len)
              {
                mswitches[n_mswitches].str = matches[j].replace;
                mswitches[n_mswitches].len = matches[j].rep_len;
-               mswitches[n_mswitches].replace = (char *)0;
+               mswitches[n_mswitches].replace = (char *) 0;
                mswitches[n_mswitches].rep_len = 0;
                n_mswitches++;
                break;
@@ -6044,7 +6315,7 @@ default_arg (p, len)
 {
   const char *start, *end;
 
-  for (start = multilib_defaults; *start != '\0'; start = end+1)
+  for (start = multilib_defaults; *start != '\0'; start = end + 1)
     {
       while (*start == ' ' || *start == '\t')
        start++;
@@ -6052,7 +6323,7 @@ default_arg (p, len)
       if (*start == '\0')
        break;
 
-      for (end = start+1; *end != ' ' && *end != '\t' && *end != '\0'; end++)
+      for (end = start + 1; *end != ' ' && *end != '\t' && *end != '\0'; end++)
        ;
 
       if ((end - start) == len && strncmp (p, start, len) == 0)
@@ -6090,47 +6361,47 @@ set_multilib_dir ()
     {
       /* Ignore newlines.  */
       if (*p == '\n')
-        {
-          ++p;
-          continue;
-        }
+       {
+         ++p;
+         continue;
+       }
 
       /* Check the arguments.  */
       ok = 1;
       while (*p != ';')
-        {
-          if (*p == '\0')
-            abort ();
-
-          if (! ok)
-            {
-              ++p;
-              continue;
-            }
-
-          this_arg = p;
-          while (*p != ' ' && *p != ';')
-            {
-              if (*p == '\0')
-                abort ();
-              ++p;
-            }
-
-          if (*this_arg != '!')
-            not_arg = 0;
-          else
-            {
-              not_arg = 1;
-              ++this_arg;
-            }
-  
+       {
+         if (*p == '\0')
+           abort ();
+
+         if (! ok)
+           {
+             ++p;
+             continue;
+           }
+
+         this_arg = p;
+         while (*p != ' ' && *p != ';')
+           {
+             if (*p == '\0')
+               abort ();
+             ++p;
+           }
+
+         if (*this_arg != '!')
+           not_arg = 0;
+         else
+           {
+             not_arg = 1;
+             ++this_arg;
+           }
+
          ok = used_arg (this_arg, p - this_arg);
          if (not_arg)
            ok = ! ok;
 
-          if (*p == ' ')
-            ++p;
-        }
+         if (*p == ' ')
+           ++p;
+       }
 
       if (ok)
        return;
@@ -6211,7 +6482,7 @@ set_multilib_dir ()
          if (this_path_len != 1
              || this_path[0] != '.')
            {
-             char * new_multilib_dir = xmalloc (this_path_len + 1);
+             char *new_multilib_dir = xmalloc (this_path_len + 1);
              strncpy (new_multilib_dir, this_path, this_path_len);
              new_multilib_dir[this_path_len] = '\0';
              multilib_dir = new_multilib_dir;
@@ -6220,7 +6491,7 @@ set_multilib_dir ()
        }
 
       ++p;
-    }      
+    }
 }
 
 /* Print out the multiple library subdirectory selection
@@ -6263,99 +6534,99 @@ print_multilib_info ()
       /* Check for matches with the multilib_exclusions. We don't bother
          with the '!' in either list. If any of the exclusion rules match
          all of its options with the select rule, we skip it.  */
-        {
-          const char *e = multilib_exclusions;
-         const char *this_arg;
+      {
+       const char *e = multilib_exclusions;
+       const char *this_arg;
 
-         while (*e != '\0')
-           {
-             int m = 1;        
-             /* Ignore newlines.  */
-             if (*e == '\n')
-               {
-                 ++e;
-                 continue;
-               }
-             
-             /* Check the arguments.  */
-             while (*e != ';')
-               {
-                 const char *q;
-                 int mp = 0;
-
-                 if (*e == '\0')
-                   abort ();
-
-                 if (! m)
-                   {
-                     ++e;
-                     continue;
-                   }
+       while (*e != '\0')
+         {
+           int m = 1;
+           /* Ignore newlines.  */
+           if (*e == '\n')
+             {
+               ++e;
+               continue;
+             }
 
-                 this_arg = e;
-
-                 while (*e != ' ' && *e != ';')
-                   {
-                     if (*e == '\0')
-                       abort ();
-                     ++e;
-                   }
-                 
-                 q = p + 1;
-                 while (*q != ';')
-                   {
-                     const char *arg;
-                     int len = e - this_arg;
+           /* Check the arguments.  */
+           while (*e != ';')
+             {
+               const char *q;
+               int mp = 0;
 
-                     if (*q == '\0')
-                       abort ();
-       
-                     arg = q;
+               if (*e == '\0')
+                 abort ();
 
-                     while (*q != ' ' && *q != ';')
-                       {
-                         if (*q == '\0')
-                           abort ();
-                           ++q;
-                       }
+               if (! m)
+                 {
+                   ++e;
+                   continue;
+                 }
 
-                     if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
-                         default_arg (this_arg, e - this_arg))
-                       {
-                         mp = 1;
-                         break;
-                       }
+               this_arg = e;
+
+               while (*e != ' ' && *e != ';')
+                 {
+                   if (*e == '\0')
+                     abort ();
+                   ++e;
+                 }
+
+               q = p + 1;
+               while (*q != ';')
+                 {
+                   const char *arg;
+                   int len = e - this_arg;
+
+                   if (*q == '\0')
+                     abort ();
+
+                   arg = q;
 
-                     if (*q == ' ')
+                   while (*q != ' ' && *q != ';')
+                     {
+                       if (*q == '\0')
+                         abort ();
                        ++q;
-                   }
+                     }
 
-                 if (! mp)
-                   m = 0;
+                   if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
+                       default_arg (this_arg, e - this_arg))
+                     {
+                       mp = 1;
+                       break;
+                     }
 
-                 if (*e == ' ')
-                   ++e;
-               }
-             
-             if (m)
-               {
-                 skip = 1;
-                 break;
-               }
+                   if (*q == ' ')
+                     ++q;
+                 }
 
-             if (*e != '\0')
-               ++e;
-           }
-       }
+               if (! mp)
+                 m = 0;
+
+               if (*e == ' ')
+                 ++e;
+             }
+
+           if (m)
+             {
+               skip = 1;
+               break;
+             }
+
+           if (*e != '\0')
+             ++e;
+         }
+      }
 
       if (! skip)
-        {
-          /* If this is a duplicate, skip it.  */
-          skip = (last_path != 0 && (unsigned int)(p - this_path) == last_path_len
-                  && ! strncmp (last_path, this_path, last_path_len));
+       {
+         /* If this is a duplicate, skip it.  */
+         skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len
+                 && ! strncmp (last_path, this_path, last_path_len));
 
-          last_path = this_path;
-          last_path_len = p - this_path;
+         last_path = this_path;
+         last_path_len = p - this_path;
        }
 
       /* If this directory requires any default arguments, we can skip
@@ -6459,7 +6730,7 @@ print_multilib_info ()
                    }
                }
            }
-         
+
          putchar ('\n');
        }