OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 6ac6b98..8316128 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,5 +1,6 @@
 /* Compiler driver program that can handle many languages.
-   Copyright (C) 1987, 89, 92-99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 
+   1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -47,7 +48,7 @@ compilation is specified by a string called a "spec".  */
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif
-#ifdef NEED_DECLARATION_GETRUSAGE
+#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
 extern int getrusage PARAMS ((int, struct rusage *));
 #endif
 
@@ -145,11 +146,11 @@ static int save_temps_flag;
 
 /* The compiler version.  */
 
-static char *compiler_version;
+static const char *compiler_version;
 
 /* The target version specified with -V */
 
-static char *spec_version = DEFAULT_TARGET_VERSION;
+static const char *spec_version = DEFAULT_TARGET_VERSION;
 
 /* The target machine specified with -b.  */
 
@@ -159,9 +160,9 @@ static const char *spec_machine = DEFAULT_TARGET_MACHINE;
    When -b is used, the value comes from the `specs' file.  */
 
 #ifdef CROSS_COMPILE
-static char *cross_compile = "1";
+static const char *cross_compile = "1";
 #else
-static char *cross_compile = "0";
+static const char *cross_compile = "0";
 #endif
 
 /* The number of errors that have occurred; the link phase will not be
@@ -198,6 +199,8 @@ static char **split_directories     PARAMS ((const char *, int *));
 static void free_split_directories PARAMS ((char **));
 static char *make_relative_prefix PARAMS ((const char *, const char *, const char *));
 #endif /* VMS */
+static void store_arg          PARAMS ((const char *, int, int));
+static char *load_specs                PARAMS ((const char *));
 static void read_specs         PARAMS ((const char *, int));
 static void set_spec           PARAMS ((const char *, const char *));
 static struct compiler *lookup_compiler PARAMS ((const char *, size_t, const char *));
@@ -207,6 +210,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 char *skip_whitespace   PARAMS ((char *));
 static void record_temp_file   PARAMS ((const char *, int, int));
 static void delete_if_ordinary PARAMS ((const char *));
@@ -238,7 +242,7 @@ 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, char **));
+static void process_command            PARAMS ((int, const char **));
 static int execute                     PARAMS ((void));
 static void unused_prefix_warnings     PARAMS ((struct path_prefix *));
 static void clear_args                 PARAMS ((void));
@@ -263,6 +267,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
@@ -365,6 +370,10 @@ or with constant text in a single argument.
        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.
+        Note - this option is position dependent.  % 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.
  %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
@@ -488,28 +497,93 @@ proper position among the other output files.  */
 #define LINKER_NAME "collect2"
 #endif
 
-static char *cpp_spec = CPP_SPEC;
-static char *cpp_predefines = CPP_PREDEFINES;
-static char *cc1_spec = CC1_SPEC;
-static char *cc1plus_spec = CC1PLUS_SPEC;
-static char *signed_char_spec = SIGNED_CHAR_SPEC;
-static char *asm_spec = ASM_SPEC;
-static char *asm_final_spec = ASM_FINAL_SPEC;
-static char *link_spec = LINK_SPEC;
-static char *lib_spec = LIB_SPEC;
-static char *libgcc_spec = LIBGCC_SPEC;
-static char *endfile_spec = ENDFILE_SPEC;
-static char *startfile_spec = STARTFILE_SPEC;
-static char *switches_need_spaces = SWITCHES_NEED_SPACES;
-static char *linker_name_spec = LINKER_NAME;
+/* 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;
+static const char *cc1plus_spec = CC1PLUS_SPEC;
+static const char *signed_char_spec = SIGNED_CHAR_SPEC;
+static const char *asm_spec = ASM_SPEC;
+static const char *asm_final_spec = ASM_FINAL_SPEC;
+static const char *link_spec = LINK_SPEC;
+static const char *lib_spec = LIB_SPEC;
+static const char *libgcc_spec = LIBGCC_SPEC;
+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}cpp";
+
+static const char *cpp_options =
+"%{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{std*} %{nostdinc*}\
+ %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
+ %{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}\
+ %{fshow-column} %{fno-show-column}\
+ %{fleading-underscore} %{fno-leading-underscore}\
+ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z %i\
+ %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}";
+
+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}\
+ %{S:%W{o*}%{!o*:-o %b.s}}";
+
+static const char *asm_options =
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
 
 /* 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
    run time.  */
 static struct obstack multilib_obstack;
-static char *multilib_select;
-static char *multilib_matches;
-static char *multilib_defaults;
+static const char *multilib_select;
+static const char *multilib_matches;
+static const char *multilib_defaults;
+static const char *multilib_exclusions;
 #include "multilib.h"
 
 /* Check whether a particular argument is a default argument.  */
@@ -520,7 +594,8 @@ static char *multilib_defaults;
 
 static const  char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 
-struct user_specs {
+struct user_specs
+{
   struct user_specs *next;
   const char *filename;
 };
@@ -573,8 +648,7 @@ 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.  */
 };
 
 /* Pointer to a vector of `struct compiler' that gives the spec for
@@ -600,151 +674,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"},
+  {".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"},
+  {".c++", "#C++"}, {".C", "#C++"},
+  {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
+  {".f", "#Fortran"}, {".for", "#Fortran"}, {".F", "#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}\
-       %{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 }}}}"
+     "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %(cpp_options)}\
+      %{!E:%{!M:%{!MM:cc1 -lang-c %{ansi:-std=c89} %(cpp_options)\
+                         %(cc1_options) %{!S:-o %{|!pipe:%g.s} |\n\
+      as %(asm_options) %{!pipe:%g.s} %A }}}}"
 #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}\
-       %{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 }}}}"
+     "%(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options) \
+                         %{!M:%{!MM:%{!E:%{!pipe:%g.i} |\n\
+      cc1 %{!pipe:%g.i} %(cc1_options)  %{!S:-o %{|!pipe:%g.s} |\n\
+      as %(asm_options) %{!pipe:%g.s} %A }}}}\n"
 #endif /* ! USE_CPPLIB */
-  }},
+  },
   {"-",
-   {"%{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}\
-       %{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}\
-       %{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 %i %(cc1_options) %{!S:|\n\
+    as %(asm_options) %{!pipe:%g.s} %A }}}}"},
+  {".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}\
-       %{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:%{!S: %{!pipe:%g.s} |\n\
+    as %(asm_options) %{!pipe:%g.s} %A }}}}"},
 #include "specs.h"
   /* Mark end of table */
-  {0, {0}}
+  {0, 0}
 };
 
 /* Number of elements in default_compilers, not counting the terminator.  */
@@ -752,47 +729,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.  */
@@ -1107,12 +1043,12 @@ struct spec_list
 {
                                /* The following 2 fields must be first */
                                /* to allow EXTRA_SPECS to be initialized */
-  char *name;                  /* name of the spec.  */
-  char *ptr;                   /* available ptr if no static pointer */
+  const char *name;            /* name of the spec.  */
+  const char *ptr;             /* available ptr if no static pointer */
 
                                /* The following fields are not initialized */
                                /* by EXTRA_SPECS */
-  char **ptr_spec;             /* pointer to the spec itself.  */
+  const char **ptr_spec;       /* pointer to the spec itself.  */
   struct spec_list *next;      /* Next spec in linked list.  */
   int name_len;                        /* length of the name */
   int alloc_p;                 /* whether string was allocated */
@@ -1121,12 +1057,17 @@ struct spec_list
 #define INIT_STATIC_SPEC(NAME,PTR) \
 { NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 }
 
-/* List of statically defined specs */
-static struct spec_list static_specs[] = {
+/* 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 ("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),
@@ -1142,16 +1083,18 @@ static struct spec_list static_specs[] = {
   INIT_STATIC_SPEC ("multilib_defaults",       &multilib_defaults),
   INIT_STATIC_SPEC ("multilib_extra",          &multilib_extra),
   INIT_STATIC_SPEC ("multilib_matches",                &multilib_matches),
+  INIT_STATIC_SPEC ("multilib_exclusions",     &multilib_exclusions),
   INIT_STATIC_SPEC ("linker",                  &linker_name_spec),
+  INIT_STATIC_SPEC ("link_libgcc",             &link_libgcc_spec),
 };
 
 #ifdef EXTRA_SPECS             /* additional specs needed */
 /* Structure to keep track of just the first two args of a spec_list.
-   That is all that the EXTRA_SPECS macro gives us. */
+   That is all that the EXTRA_SPECS macro gives us.  */
 struct spec_list_1
 {
-  char *name;
-  char *ptr;
+  const char *name;
+  const char *ptr;
 };
 
 static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
@@ -1173,7 +1116,7 @@ init_spec ()
   int i;
 
   if (specs)
-    return;                    /* already initialized */
+    return;                    /* Already initialized.  */
 
   if (verbose_flag)
     notice ("Using builtin specs.\n");
@@ -1216,11 +1159,11 @@ set_spec (name, spec)
      const char *spec;
 {
   struct spec_list *sl;
-  char *old_spec;
+  const char *old_spec;
   int name_len = strlen (name);
   int i;
 
-  /* If this is the first call, initialize the statically allocated specs */
+  /* If this is the first call, initialize the statically allocated specs */
   if (!specs)
     {
       struct spec_list *next = (struct spec_list *)0;
@@ -1234,14 +1177,14 @@ set_spec (name, spec)
       specs = sl;
     }
 
-  /* See if the spec already exists */
+  /* See if the spec already exists */
   for (sl = specs; sl; sl = sl->next)
     if (name_len == sl->name_len && !strcmp (sl->name, name))
       break;
 
   if (!sl)
     {
-      /* Not found - make it */
+      /* Not found - make it */
       sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
       sl->name = xstrdup (name);
       sl->name_len = name_len;
@@ -1262,9 +1205,9 @@ set_spec (name, spec)
     notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
 #endif
 
-  /* Free the old spec */
+  /* Free the old spec */
   if (old_spec && sl->alloc_p)
-    free (old_spec);
+    free ((PTR) old_spec);
 
   sl->alloc_p = 1;
 }
@@ -1273,7 +1216,7 @@ set_spec (name, spec)
 
 /* Vector of pointers to arguments in the current line of specifications.  */
 
-static char **argbuf;
+static const char **argbuf;
 
 /* Number of elements allocated in argbuf.  */
 
@@ -1399,7 +1342,7 @@ static const char *tooldir_prefix;
 #ifndef STANDARD_BINDIR_PREFIX
 #define STANDARD_BINDIR_PREFIX "/usr/local/bin"
 #endif
-static char *standard_bindir_prefix = STANDARD_BINDIR_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.  */
@@ -1423,12 +1366,13 @@ clear_args ()
 
 static void
 store_arg (arg, delete_always, delete_failure)
-     char *arg;
+     const char *arg;
      int delete_always, delete_failure;
 {
   if (argbuf_index + 1 == argbuf_length)
     argbuf
-      = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
+      = (const char **) xrealloc (argbuf,
+                                 (argbuf_length *= 2) * sizeof (const char *));
 
   argbuf[argbuf_index++] = arg;
   argbuf[argbuf_index] = 0;
@@ -1437,27 +1381,21 @@ store_arg (arg, delete_always, delete_failure)
     record_temp_file (arg, delete_always, delete_failure);
 }
 \f
-/* Read compilation specs from a file named FILENAME,
-   replacing the default ones.
-
-   A suffix which starts with `*' is a definition for
-   one of the machine-specific sub-specs.  The "suffix" should be
-   *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
-   The corresponding spec is stored in asm_spec, etc.,
-   rather than in the `compilers' vector.
-
-   Anything invalid in the file is a fatal error.  */
+/* 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 
+   a single \n.  */
 
-static void
-read_specs (filename, main_p)
+static char*
+load_specs (filename)
      const char *filename;
-     int main_p;
 {
   int desc;
   int readlen;
   struct stat statbuf;
   char *buffer;
-  register char *p;
+  char *buffer_p;
+  char *specs;
+  char *specs_p;
 
   if (verbose_flag)
     notice ("Reading specs from %s\n", filename);
@@ -1477,6 +1415,51 @@ read_specs (filename, main_p)
   buffer[readlen] = 0;
   close (desc);
 
+  specs = xmalloc (readlen + 1);
+  specs_p = specs;
+  for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
+    {
+      int skip = 0;
+      char c = *buffer_p;
+      if (c == '\r')
+        {
+         if (buffer_p > buffer && *(buffer_p-1) == '\n')       /* \n\r */
+           skip = 1;
+         else if (*(buffer_p+1) == '\n')                       /* \r\n */
+           skip = 1;
+         else                                                  /* \r */
+           c = '\n';
+       }
+      if (! skip)
+       *specs_p++ = c;
+    }
+  *specs_p = '\0';
+
+  free (buffer);
+  return (specs);
+}
+
+/* Read compilation specs from a file named FILENAME,
+   replacing the default ones.
+
+   A suffix which starts with `*' is a definition for
+   one of the machine-specific sub-specs.  The "suffix" should be
+   *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
+   The corresponding spec is stored in asm_spec, etc.,
+   rather than in the `compilers' vector.
+
+   Anything invalid in the file is a fatal error.  */
+
+static void
+read_specs (filename, main_p)
+     const char *filename;
+     int main_p;
+{
+  char *buffer;
+  register char *p;
+
+  buffer = load_specs (filename);
+
   /* Scan BUFFER for specs, putting them in the vector.  */
   p = buffer;
   while (1)
@@ -1604,7 +1587,7 @@ read_specs (filename, main_p)
 
              set_spec (p2, *(sl->ptr_spec));
              if (sl->alloc_p)
-               free (*(sl->ptr_spec));
+               free ((PTR) *(sl->ptr_spec));
 
              *(sl->ptr_spec) = "";
              sl->alloc_p = 0;
@@ -1679,9 +1662,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]);
        }
@@ -2049,7 +2030,7 @@ free_split_directories (dirs)
 
    For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is
    /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this
-   function will return /reg/green/blue/../omega.
+   function will return /red/green/blue/../omega.
 
    If no relative prefix can be found, return NULL.  */
 
@@ -2150,7 +2131,7 @@ make_relative_prefix (progname, bin_prefix, prefix)
 
   prefix_dirs = split_directories (prefix, &prefix_num);
 
-  /* Find how many directories are in common between bin_prefix & prefix */
+  /* Find how many directories are in common between bin_prefix & prefix */
   n = (prefix_num < bin_num) ? prefix_num : bin_num;
   for (common = 0; common < n; common++)
     {
@@ -2451,7 +2432,7 @@ execute ()
   struct command
     {
       const char *prog;                /* program name.  */
-      char **argv;     /* vector of args.  */
+      const char **argv;       /* vector of args.  */
       int pid;                 /* pid of process for this command.  */
     };
 
@@ -2505,7 +2486,7 @@ execute ()
       /* Print each piped command as a separate line.  */
       for (i = 0; i < n_commands ; i++)
        {
-         char **j;
+         const char **j;
 
          for (j = commands[i].argv; *j; j++)
            fprintf (stderr, " %s", *j);
@@ -2534,7 +2515,7 @@ execute ()
   for (i = 0; i < n_commands; i++)
     {
       char *errmsg_fmt, *errmsg_arg;
-      char *string = commands[i].argv[0];
+      const char *string = commands[i].argv[0];
 
       commands[i].pid = pexecute (string, commands[i].argv,
                                  programname, temp_filename,
@@ -2549,7 +2530,7 @@ execute ()
        pfatal_pexecute (errmsg_fmt, errmsg_arg);
 
       if (string != commands[i].prog)
-       free (string);
+       free ((PTR) string);
     }
 
   execution_count++;
@@ -2600,22 +2581,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)
@@ -2634,15 +2628,23 @@ execute ()
    If a switch uses following arguments, then the `part1' field
    is the switch itself and the `args' field
    is a null-terminated vector containing the following arguments.
-   The `live_cond' field is 1 if the switch is true in a conditional spec,
-   -1 if false (overridden by a later switch), and is initialized to zero.
+   The `live_cond' field is:
+   0 when initialized
+   1 if the switch is true in a conditional spec,
+   -1 if false (overridden by a later switch)
+   -2 if this switch should be ignored (used in %{<S})
    The `validated' field is nonzero if any spec has looked at this switch;
    if it remains zero at the end of the run, it must be meaningless.  */
 
+#define SWITCH_OK       0
+#define SWITCH_FALSE   -1
+#define SWITCH_IGNORE  -2
+#define SWITCH_LIVE     1
+
 struct switchstr
 {
   const char *part1;
-  char **args;
+  const char **args;
   int live_cond;
   int validated;
 };
@@ -2739,49 +2741,53 @@ convert_filename (name, do_exe)
 static void
 display_help ()
 {
-  printf ("Usage: %s [options] file...\n", programname);
-  printf ("Options:\n");
+  printf (_("Usage: %s [options] file...\n"), programname);
+  fputs (_("Options:\n"), stdout);
 
-  printf ("  -pass-exit-codes         Exit with highest error code from a phase\n");
-  printf ("  --help                   Display this information\n");
+  fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
+  fputs (_("  --help                   Display this information\n"), stdout);
   if (! verbose_flag)
-    printf ("  (Use '-v --help' to display command line options of sub-processes)\n");
-  printf ("  -dumpspecs               Display all of the built in spec strings\n");
-  printf ("  -dumpversion             Display the version of the compiler\n");
-  printf ("  -dumpmachine             Display the compiler's target processor\n");
-  printf ("  -print-search-dirs       Display the directories in the compiler's search path\n");
-  printf ("  -print-libgcc-file-name  Display the name of the compiler's companion library\n");
-  printf ("  -print-file-name=<lib>   Display the full path to library <lib>\n");
-  printf ("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n");
-  printf ("  -print-multi-directory   Display the root directory for versions of libgcc\n");
-  printf ("  -print-multi-lib         Display the mapping between command line options and\n");
-  printf ("                            multiple library search directories\n");
-  printf ("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n");
-  printf ("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n");
-  printf ("  -Wl,<options>            Pass comma-separated <options> on to the linker\n");
-  printf ("  -Xlinker <arg>           Pass <arg> on to the linker\n");
-  printf ("  -save-temps              Do not delete intermediate files\n");
-  printf ("  -pipe                    Use pipes rather than intermediate files\n");
-  printf ("  -time                    Time the execution of each subprocess\n");
-  printf ("  -specs=<file>            Override builtin specs with the contents of <file>\n");
-  printf ("  -std=<standard>          Assume that the input sources are for <standard>\n");
-  printf ("  -B <directory>           Add <directory> to the compiler's search paths\n");
-  printf ("  -b <machine>             Run gcc for target <machine>, if installed\n");
-  printf ("  -V <version>             Run gcc version number <version>, if installed\n");
-  printf ("  -v                       Display the programs invoked by the compiler\n");
-  printf ("  -E                       Preprocess only; do not compile, assemble or link\n");
-  printf ("  -S                       Compile only; do not assemble or link\n");
-  printf ("  -c                       Compile and assemble, but do not link\n");
-  printf ("  -o <file>                Place the output into <file>\n");
-  printf ("  -x <language>            Specify the language of the following input files\n");
-  printf ("                            Permissable languages include: c c++ assembler none\n");
-  printf ("                            'none' means revert to the default behaviour of\n");
-  printf ("                            guessing the language based on the file's extension\n");
-
-  printf ("\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n");
-  printf ("the various sub-processes invoked by %s.  In order to pass other options\n",
-         programname);
-  printf ("on to these processes the -W<letter> options must be used.\n");
+    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);
+  fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
+  fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
+  fputs (_("  -print-search-dirs       Display the directories in the compiler's search path\n"), stdout);
+  fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
+  fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
+  fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
+  fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
+  fputs (_("\
+  -print-multi-lib         Display the mapping between command line options and\n\
+                           multiple library search directories\n"), stdout);
+  fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
+  fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
+  fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
+  fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
+  fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
+  fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
+  fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
+  fputs (_("  -specs=<file>            Override builtin specs with the contents of <file>\n"), stdout);
+  fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
+  fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
+  fputs (_("  -b <machine>             Run gcc for target <machine>, if installed\n"), stdout);
+  fputs (_("  -V <version>             Run gcc version number <version>, if installed\n"), stdout);
+  fputs (_("  -v                       Display the programs invoked by the compiler\n"), stdout);
+  fputs (_("  -E                       Preprocess only; do not compile, assemble or link\n"), stdout);
+  fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
+  fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
+  fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
+  fputs (_("\
+  -x <language>            Specify the language of the following input files\n\
+                           Permissable languages include: c c++ assembler none\n\
+                           'none' means revert to the default behaviour of\n\
+                           guessing the language based on the file's extension\n\
+"), stdout);
+
+  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);
 
   /* The rest of the options are displayed by invocations of the various
      sub-processes.  */
@@ -2848,12 +2854,12 @@ add_linker_option (option, len)
 static void
 process_command (argc, argv)
      int argc;
-     char **argv;
+     const char **argv;
 {
   register int i;
   const char *temp;
   char *temp1;
-  char *spec_lang = 0;
+  const char *spec_lang = 0;
   int last_language_n_infiles;
   int have_c = 0;
   int have_o = 0;
@@ -3168,7 +3174,7 @@ process_command (argc, argv)
        report_times = 1;
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
-         register char *p = &argv[i][1];
+         register const char *p = &argv[i][1];
          register int c = *p;
 
          switch (c)
@@ -3187,7 +3193,7 @@ process_command (argc, argv)
 
            case 'B':
              {
-               char *value;
+               const char *value;
                if (p[1] == 0 && i + 1 == argc)
                  fatal ("argument to `-B' is missing");
                if (p[1] == 0)
@@ -3460,7 +3466,7 @@ process_command (argc, argv)
                 cc1 spec string.  */
              switches[n_switches].part1     = "--help";
              switches[n_switches].args      = 0;
-             switches[n_switches].live_cond = 0;
+             switches[n_switches].live_cond = SWITCH_OK;
              switches[n_switches].validated     = 0;
              
              n_switches++;
@@ -3475,7 +3481,7 @@ process_command (argc, argv)
             -e0 or -e1 down into the linker.  */
          switches[n_switches].part1 = &argv[i][0];
          switches[n_switches].args = 0;
-         switches[n_switches].live_cond = 0;
+         switches[n_switches].live_cond = SWITCH_OK;
          switches[n_switches].validated = 0;
          n_switches++;
        }
@@ -3525,8 +3531,8 @@ process_command (argc, argv)
        }
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
-         register char *p = &argv[i][1];
-         register int c = *p;
+         const char *p = &argv[i][1];
+         int c = *p;
 
          if (c == 'x')
            {
@@ -3561,7 +3567,7 @@ process_command (argc, argv)
              if (i + n_args >= argc)
                fatal ("argument to `-%s' is missing", p);
              switches[n_switches].args
-               = (char **) xmalloc ((n_args + 1) * sizeof (char *));
+               = (const char **) xmalloc ((n_args + 1) * sizeof(const char *));
              while (j < n_args)
                switches[n_switches].args[j++] = argv[++i];
              /* Null-terminate the vector.  */
@@ -3572,19 +3578,21 @@ process_command (argc, argv)
              /* On some systems, ld cannot handle some options without
                 a space.  So split the option from its argument.  */
              char *part1 = (char *) xmalloc (2);
+             char *tmp;
              part1[0] = c;
              part1[1] = '\0';
              
              switches[n_switches].part1 = part1;
-             switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *));
-             switches[n_switches].args[0] = xmalloc (strlen (p));
-             strcpy (switches[n_switches].args[0], &p[1]);
+             switches[n_switches].args
+               = (const char **) xmalloc (2 * sizeof (const char *));
+             switches[n_switches].args[0] = tmp = xmalloc (strlen (p));
+             strcpy (tmp, &p[1]);
              switches[n_switches].args[1] = 0;
            }
          else
            switches[n_switches].args = 0;
 
-         switches[n_switches].live_cond = 0;
+         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"))
@@ -3636,6 +3644,7 @@ 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;
 
@@ -3820,6 +3829,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;
@@ -3841,7 +3855,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                     and use them to search for dynamic linking.  */
                  /* Relative directories always come from -B,
                     and it is better not to use them for searching
-                    at run time.  In particular, stage1 loses  */
+                    at run time.  In particular, stage1 loses.  */
                  if (!IS_DIR_SEPARATOR (pl->prefix[0]))
                    continue;
 #endif
@@ -4230,7 +4244,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            {
              char *x = (char *) alloca (strlen (cpp_predefines) + 1);
              char *buf = x;
-             char *y;
+             const char *y;
 
              /* Copy all of the -D options in CPP_PREDEFINES into BUF.  */
              y = cpp_predefines;
@@ -4260,10 +4274,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            {
              char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
              char *buf = x;
-             char *y;
+             const char *y;
 
              /* Copy all of CPP_PREDEFINES into BUF,
-                but force them all into the reserved name space if they                         aren't already there.  The reserved name space is all
+                but force them all into the reserved name space if they
+                aren't already there.  The reserved name space is all
                 identifiers beginning with two underscores or with one
                 underscore and a capital letter.  We do the forcing by
                 adding up to two underscores to the beginning and end
@@ -4356,7 +4371,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                  else if (*y == ' ' || *y == '\t')
                    /* Copy whitespace to the result.  */
                    *x++ = *y++;
-                 /* Don't copy -A options  */
+                 /* Don't copy -A options.  */
                  else
                    y++;
                }
@@ -4405,8 +4420,16 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case '*':
-           do_spec_1 (soft_matched_part, 1, NULL_PTR);
-           do_spec_1 (" ", 0, NULL_PTR);
+           if (soft_matched_part)
+             {
+               do_spec_1 (soft_matched_part, 1, NULL_PTR);
+               do_spec_1 (" ", 0, NULL_PTR);
+             }
+           else
+             /* Catch the case where a spec string contains something like
+                '%{foo:%*}'.  ie there is no * in the pattern on the left
+                hand side of the :.  */
+             error ("Spec failure: '%%*' has not been initialised by pattern match");
            break;
 
            /* Process a string found as the value of a spec given by name.
@@ -4427,7 +4450,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              while (*p && *p != ')' && *p != ']')
                p++;
 
-             /* See if it's in the list */
+             /* See if it's in the list */
              for (len = p - name, sl = specs; sl; sl = sl->next)
                if (sl->name_len == len && !strncmp (sl->name, name, len))
                  {
@@ -4455,7 +4478,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      int flag = 0;
 
                      /* Copy all of NAME into BUF, but put __ after
-                        every -D and at the end of each arg,  */
+                        every -D and at the end of each arg.  */
                      while (1)
                        {
                          if (! strncmp (y, "-D", 2))
@@ -4497,8 +4520,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
          case 'v':
            {
              int c1 = *p++;  /* Select first or second version number.  */
-             char *v = compiler_version;
-             char *q;
+             const char *v = compiler_version;
+             const char *q;
              static const char zeroc = '0';
 
              /* The format of the version string is
@@ -4538,7 +4561,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              q = v;
              while (ISDIGIT (*q))
                q++;
-             if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
+             if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-')
                abort ();
 
               if (q > v)
@@ -4557,7 +4580,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          default:
-           abort ();
+           error ("Spec failure: Unrecognised spec option '%c'", c);
+           break;
          }
        break;
 
@@ -4586,16 +4610,31 @@ handle_braces (p)
   int negate;
   int suffix;
   int include_blanks = 1;
+  int elide_switch = 0;
 
   if (*p == '^')
-    /* A '^' after the open-brace means to not give blanks before args.  */
-    include_blanks = 0, ++p;
+    {
+      /* A '^' after the open-brace means to not give blanks before args.  */
+      include_blanks = 0;
+      ++p;
+    }
 
   if (*p == '|')
-    /* A `|' after the open-brace means,
-       if the test fails, output a single minus sign rather than nothing.
-       This is used in %{|!pipe:...}.  */
-    pipe_p = 1, ++p;
+    {
+      /* A `|' after the open-brace means,
+        if the test fails, output a single minus sign rather than nothing.
+        This is used in %{|!pipe:...}.  */
+      pipe_p = 1;
+      ++p;
+    }
+
+  if (*p == '<')
+    {
+      /* A `<' after the open-brace means that the switch should be
+        removed from the command-line.  */
+      elide_switch = 1;
+      ++p;
+    }
 
 next_member:
   negate = suffix = 0;
@@ -4615,6 +4654,13 @@ next_member:
       ++p;
     }
 
+  if (elide_switch && (negate || pipe_p || suffix))
+    {
+      /* It doesn't make sense to mix elision with other flags.  We
+        could fatal() here, but the standard seems to be to abort.  */
+      abort ();
+    }
+
   filter = p;
   while (*p != ':' && *p != '}' && *p != '|') p++;
 
@@ -4729,6 +4775,7 @@ next_member:
                  && check_live_switch (i, hard_match_len))
                {
                  present = 1;
+                 break;
                }
            }
        }
@@ -4752,7 +4799,12 @@ next_member:
         conditional text.  */
       if (present != negate)
        {
-         if (*p == '}')
+         if (elide_switch)
+           {
+             switches[i].live_cond = SWITCH_IGNORE;
+             switches[i].validated = 1;
+           }
+         else if (*p == '}')
            {
              give_switch (i, 0, include_blanks);
            }
@@ -4814,7 +4866,7 @@ check_live_switch (switchnum, prefix_length)
          if (switches[i].part1[0] == 'O')
            {
              switches[switchnum].validated = 1;
-             switches[switchnum].live_cond = -1;
+             switches[switchnum].live_cond = SWITCH_FALSE;
              return 0;
            }
       break;
@@ -4828,7 +4880,7 @@ check_live_switch (switchnum, prefix_length)
                && ! strcmp (&switches[i].part1[1], &name[4]))
            {
              switches[switchnum].validated = 1;
-             switches[switchnum].live_cond = -1;
+             switches[switchnum].live_cond = SWITCH_FALSE;
              return 0;
            }
        }
@@ -4843,7 +4895,7 @@ check_live_switch (switchnum, prefix_length)
                && !strcmp (&switches[i].part1[4], &name[1]))
            {
              switches[switchnum].validated = 1;
-             switches[switchnum].live_cond = -1;
+             switches[switchnum].live_cond = SWITCH_FALSE;
              return 0;
            }
        }
@@ -4851,7 +4903,7 @@ check_live_switch (switchnum, prefix_length)
     }
 
   /* Otherwise the switch is live.  */
-  switches[switchnum].live_cond = 1;
+  switches[switchnum].live_cond = SWITCH_LIVE;
   return 1;
 }
 \f
@@ -4872,6 +4924,9 @@ give_switch (switchnum, omit_first_word, include_blanks)
      int omit_first_word;
      int include_blanks;
 {
+  if (switches[switchnum].live_cond == SWITCH_IGNORE)
+    return;
+
   if (!omit_first_word)
     {
       do_spec_1 ("-", 0, NULL_PTR);
@@ -4880,7 +4935,7 @@ give_switch (switchnum, omit_first_word, include_blanks)
 
   if (switches[switchnum].args != 0)
     {
-      char **p;
+      const char **p;
       for (p = switches[switchnum].args; *p; p++)
        {
          if (include_blanks)
@@ -4985,13 +5040,19 @@ set_input (filename)
   input_filename_length = strlen (input_filename);
   
   input_basename = input_filename;
-  for (p = input_filename; *p; p++)
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  /* Skip drive name so 'x:foo' is handled properly.  */
+  if (input_basename[1] == ':')
+    input_basename += 2;
+#endif
+  for (p = input_basename; *p; p++)
     if (IS_DIR_SEPARATOR (*p))
       input_basename = p + 1;
 
   /* 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;
   if (*p == '.' && p != input_basename)
@@ -5024,8 +5085,7 @@ main (argc, argv)
      int argc;
      char **argv;
 {
-  register size_t i;
-  size_t j;
+  size_t i;
   int value;
   int linker_was_run = 0;
   char *explicit_link_files;
@@ -5058,14 +5118,14 @@ main (argc, argv)
 #endif
 
   argbuf_length = 10;
-  argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
+  argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
 
   obstack_init (&obstack);
 
   /* Build multilib_select, et. al from the separate lines that make up each
      multilib selection.  */
   {
-    char **q = multilib_raw;
+    const char *const *q = multilib_raw;
     int need_space;
 
     obstack_init (&multilib_obstack);
@@ -5082,6 +5142,13 @@ main (argc, argv)
     obstack_1grow (&multilib_obstack, 0);
     multilib_matches = obstack_finish (&multilib_obstack);
 
+    q = multilib_exclusions_raw;
+    while ((p = *q++) != (char *) 0)
+       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]);
@@ -5136,7 +5203,7 @@ main (argc, argv)
     first_time = TRUE;
     for (i = 0; (int)i < n_switches; i++)
       {
-       char **args;
+       const char **args;
        const char *p, *q;
        if (!first_time)
          obstack_grow (&collect_obstack, " ", 1);
@@ -5193,7 +5260,7 @@ main (argc, argv)
     init_spec ();
 
   /* We need to check standard_exec_prefix/just_machine_suffix/specs
-     for any override of as, ld and libraries. */
+     for any override of as, ld and libraries.  */
   specs_file = (char *) alloca (strlen (standard_exec_prefix)
                                + strlen (just_machine_suffix)
                                + sizeof ("specs"));
@@ -5308,9 +5375,9 @@ main (argc, argv)
 
   if (print_search_dirs)
     {
-      printf ("install: %s%s\n", standard_exec_prefix, machine_suffix);
-      printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0));
-      printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0));
+      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
+      printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
+      printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
       return (0);
     }
 
@@ -5348,7 +5415,7 @@ main (argc, argv)
 
       if (! verbose_flag)
        {
-         printf ("\nFor bug reporting instructions, please see:\n");
+         printf (_("\nFor bug reporting instructions, please see:\n"));
          printf ("%s.\n", GCCBUGURL);
          
          return (0);
@@ -5417,32 +5484,11 @@ main (argc, argv)
       if (cp)
        {
          /* 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 (cp->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, &cp->spec[1]);
+         value = do_spec (cp->spec);
          if (value < 0)
            this_file_error = 1;
        }
@@ -5525,7 +5571,7 @@ main (argc, argv)
 
   if (print_help_list)
     {
-      printf ("\nFor bug reporting instructions, please see:\n");
+      printf (("\nFor bug reporting instructions, please see:\n"));
       printf ("%s\n", GCCBUGURL);
     }
   
@@ -5546,7 +5592,7 @@ lookup_compiler (name, length, language)
 {
   struct compiler *cp;
 
-  /* If this was specified by the user to be a linker input, indicate that. */
+  /* If this was specified by the user to be a linker input, indicate that.  */
   if (language != 0 && language[0] == '*')
     return 0;
 
@@ -5568,40 +5614,42 @@ lookup_compiler (name, length, language)
          (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
          || (strlen (cp->suffix) < length
              /* See if the suffix matches the end of NAME.  */
-#ifdef OS2
-             && ((!strcmp (cp->suffix,
-                          name + length - strlen (cp->suffix))
-                  || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
-                 && !strcasecmp (cp->suffix,
-                                 name + length - strlen (cp->suffix)))
-#else
              && !strcmp (cp->suffix,
                          name + length - strlen (cp->suffix))
-#endif
         ))
-       {
-         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;
-       }
+        break;
     }
 
+#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* look again, but case-insensitively this time.  */
+  if (cp < compilers)
+    for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
+      {
+       if (/* The suffix `-' matches only the file name `-'.  */
+           (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
+           || (strlen (cp->suffix) < length
+               /* See if the suffix matches the end of NAME.  */
+               && ((!strcmp (cp->suffix,
+                            name + length - strlen (cp->suffix))
+                    || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+                   && !strcasecmp (cp->suffix,
+                                   name + length - strlen (cp->suffix)))
+          ))
+         break;
+      }
+#endif
+
+  if (cp >= compilers)
+    {
+      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
@@ -5733,20 +5781,16 @@ 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 */
+  /* Look through the linked list of specs read from the specs file.  */
   for (spec = specs; spec ; spec = spec->next)
     {
       p = *(spec->ptr_spec);
@@ -5817,9 +5861,10 @@ used_arg (p, len)
      const char *p;
      int len;
 {
-  struct mswitchstr {
-    char *str;
-    char *replace;
+  struct mswitchstr
+  {
+    const char *str;
+    const char *replace;
     int len;
     int rep_len;
   };
@@ -5831,11 +5876,11 @@ used_arg (p, len)
   if (!mswitches)
     {
       struct mswitchstr *matches;
-      char *q;
+      const char *q;
       int cnt = 0;
 
       /* Break multilib_matches into the component strings of string and replacement
-         string */
+         string */
       for (q = multilib_matches; *q != '\0'; q++)
        if (*q == ';')
          cnt++;
@@ -5852,7 +5897,6 @@ used_arg (p, len)
                abort ();
              q++;
            }
-         *q = '\0';
          matches[i].len = q - matches[i].str;
 
          matches[i].replace = ++q;
@@ -5865,9 +5909,7 @@ used_arg (p, len)
          matches[i].rep_len = q - matches[i].replace;
          i++;
          if (*q == ';')
-           *q++ = '\0';
-         else
-           break;
+           q++;
        }
 
       /* Now build a list of the replacement string for switches that we care
@@ -5881,7 +5923,8 @@ used_arg (p, len)
        {
          int xlen = strlen (switches[i].part1);
          for (j = 0; j < cnt; j++)
-           if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str))
+           if (xlen == matches[j].len
+               && ! strncmp (switches[i].part1, matches[j].str, xlen))
              {
                mswitches[n_mswitches].str = matches[j].replace;
                mswitches[n_mswitches].len = matches[j].rep_len;
@@ -5905,7 +5948,7 @@ default_arg (p, len)
      const char *p;
      int len;
 {
-  char *start, *end;
+  const char *start, *end;
 
   for (start = multilib_defaults; *start != '\0'; start = end+1)
     {
@@ -5928,23 +5971,80 @@ default_arg (p, len)
   return 0;
 }
 
-/* Work out the subdirectory to use based on the
-   options.  The format of multilib_select is a list of elements.
-   Each element is a subdirectory name followed by a list of options
-   followed by a semicolon.  gcc will consider each line in turn.  If
-   none of the options beginning with an exclamation point are
-   present, and all of the other options are present, that
-   subdirectory will be used.  */
+/* Work out the subdirectory to use based on the options. The format of
+   multilib_select is a list of elements. Each element is a subdirectory
+   name followed by a list of options followed by a semicolon. The format
+   of multilib_exclusions is the same, but without the preceding
+   directory. First gcc will check the exclusions, if none of the options
+   beginning with an exclamation point are present, and all of the other
+   options are present, then we will ignore this completely. Passing
+   that, gcc will consider each multilib_select in turn using the same
+   rules for matching the options. If a match is found, that subdirectory
+   will be used.  */
 
 static void
 set_multilib_dir ()
 {
-  char *p = multilib_select;
-  int this_path_len;
-  char *this_path, *this_arg;
+  const char *p;
+  unsigned int this_path_len;
+  const char *this_path, *this_arg;
   int not_arg;
   int ok;
 
+  p = multilib_exclusions;
+  while (*p != '\0')
+    {
+      /* Ignore newlines.  */
+      if (*p == '\n')
+        {
+          ++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;
+            }
+  
+         ok = used_arg (this_arg, p - this_arg);
+         if (not_arg)
+           ok = ! ok;
+
+          if (*p == ' ')
+            ++p;
+        }
+
+      if (ok)
+       return;
+
+      ++p;
+    }
+
+  p = multilib_select;
   while (*p != '\0')
     {
       /* Ignore newlines.  */
@@ -6036,18 +6136,20 @@ set_multilib_dir ()
    matches.  The options are print without a leading dash.  There are
    no spaces to make it easy to use the information in the shell.
    Each subdirectory is printed only once.  This assumes the ordering
-   generated by the genmultilib script.  */
+   generated by the genmultilib script. Also, we leave out ones that match
+   the exclusions.  */
 
 static void
 print_multilib_info ()
 {
-  char *p = multilib_select;
-  char *last_path = 0, *this_path;
+  const char *p = multilib_select;
+  const char *last_path = 0, *this_path;
   int skip;
-  int last_path_len = 0;
+  unsigned int last_path_len = 0;
 
   while (*p != '\0')
     {
+      skip = 0;
       /* Ignore newlines.  */
       if (*p == '\n')
        {
@@ -6064,24 +6166,115 @@ print_multilib_info ()
          ++p;
        }
 
-      /* If this is a duplicate, skip it.  */
-      skip = (last_path != 0 && p - this_path == last_path_len
-             && ! strncmp (last_path, this_path, last_path_len));
+      /* 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;
+
+         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;
+                   }
 
-      last_path = this_path;
-      last_path_len = p - this_path;
+                 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;
+
+                     while (*q != ' ' && *q != ';')
+                       {
+                         if (*q == '\0')
+                           abort ();
+                           ++q;
+                       }
+
+                     if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
+                         default_arg (this_arg, e - this_arg))
+                       {
+                         mp = 1;
+                         break;
+                       }
+
+                     if (*q == ' ')
+                       ++q;
+                   }
+
+                 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));
+
+          last_path = this_path;
+          last_path_len = p - this_path;
+       }
 
       /* If this directory requires any default arguments, we can skip
         it.  We will already have printed a directory identical to
         this one which does not require that default argument.  */
       if (! skip)
        {
-         char *q;
+         const char *q;
 
          q = p + 1;
          while (*q != ';')
            {
-             char *arg;
+             const char *arg;
 
              if (*q == '\0')
                abort ();
@@ -6112,7 +6305,7 @@ print_multilib_info ()
 
       if (! skip)
        {
-         char *p1;
+         const char *p1;
 
          for (p1 = last_path; p1 < p; p1++)
            putchar (*p1);
@@ -6153,11 +6346,11 @@ print_multilib_info ()
 
       if (! skip)
        {
-         /* If there are extra options, print them now */
+         /* If there are extra options, print them now */
          if (multilib_extra && *multilib_extra)
            {
              int print_at = TRUE;
-             char *q;
+             const char *q;
 
              for (q = multilib_extra; *q != '\0'; q++)
                {
@@ -6172,6 +6365,7 @@ print_multilib_info ()
                    }
                }
            }
+         
          putchar ('\n');
        }