OSDN Git Service

* c-decl.c (finish_function): Warn about a non-void function with
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 7a3c364..41c62a9 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,23 +1,23 @@
 /* Compiler driver program that can handle many languages.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
 
 This paragraph is here to try to keep Sun CC from dying.
 The number of chars here seems crucial!!!!  */
@@ -32,17 +32,55 @@ 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".  */
 
+/* A Short Introduction to Adding a Command-Line Option.
+
+   Before adding a command-line option, consider if it is really
+   necessary.  Each additional command-line option adds complexity and
+   is difficult to remove in subsequent versions.
+
+   In the following, consider adding the command-line argument
+   `--bar'.
+
+   1. Each command-line option is specified in the specs file.  The
+   notation is described below in the comment entitled "The Specs
+   Language".  Read it.
+
+   2. In this file, add an entry to "option_map" equating the long
+   `--' argument version and any shorter, single letter version.  Read
+   the comments in the declaration of "struct option_map" for an
+   explanation.  Do not omit the first `-'.
+
+   3. Look in the "specs" file to determine which program or option
+   list should be given the argument, e.g., "cc1_options".  Add the
+   appropriate syntax for the shorter option version to the
+   corresponding "const char *" entry in this file.  Omit the first
+   `-' from the option.  For example, use `-bar', rather than `--bar'.
+
+   4. If the argument takes an argument, e.g., `--baz argument1',
+   modify either DEFAULT_SWITCH_TAKES_ARG or
+   DEFAULT_WORD_SWITCH_TAKES_ARG in this file.  Omit the first `-'
+   from `--baz'.
+
+   5. Document the option in this file's display_help().  If the
+   option is passed to a subprogram, modify its corresponding
+   function, e.g., cppinit.c:print_help() or toplev.c:display_help(),
+   instead.
+
+   6. Compile and test.  Make sure that your new specs file is being
+   read.  For example, use a debugger to investigate the value of
+   "specs_file" in main().  */
+
 #include "config.h"
 #include "system.h"
 #include <signal.h>
+#if ! defined( SIGCHLD ) && defined( SIGCLD )
+#  define SIGCHLD SIGCLD
+#endif
 #include "obstack.h"
 #include "intl.h"
 #include "prefix.h"
 #include "gcc.h"
-
-#ifdef VMS
-#define exit __posix_exit
-#endif
+#include "flags.h"
 
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
@@ -51,18 +89,27 @@ compilation is specified by a string called a "spec".  */
 extern int getrusage PARAMS ((int, struct rusage *));
 #endif
 
-/* By default there is no special suffix for executables.  */
-#ifdef EXECUTABLE_SUFFIX
-#define HAVE_EXECUTABLE_SUFFIX
+/* By default there is no special suffix for target executables.  */
+/* FIXME: when autoconf is fixed, remove the host check - dj */
+#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
+#define HAVE_TARGET_EXECUTABLE_SUFFIX
+#else
+#undef TARGET_EXECUTABLE_SUFFIX
+#define TARGET_EXECUTABLE_SUFFIX ""
+#endif
+
+/* By default there is no special suffix for host executables.  */
+#ifdef HOST_EXECUTABLE_SUFFIX
+#define HAVE_HOST_EXECUTABLE_SUFFIX
 #else
-#define EXECUTABLE_SUFFIX ""
+#define HOST_EXECUTABLE_SUFFIX ""
 #endif
 
-/* By default, the suffix for object files is ".o".  */
-#ifdef OBJECT_SUFFIX
-#define HAVE_OBJECT_SUFFIX
+/* By default, the suffix for target object files is ".o".  */
+#ifdef TARGET_OBJECT_SUFFIX
+#define HAVE_TARGET_OBJECT_SUFFIX
 #else
-#define OBJECT_SUFFIX ".o"
+#define TARGET_OBJECT_SUFFIX ".o"
 #endif
 
 #ifndef VMS
@@ -73,7 +120,7 @@ extern int getrusage PARAMS ((int, struct rusage *));
 #endif /* DIR_UP */
 #endif /* VMS */
 
-static char dir_separator_str[] = { DIR_SEPARATOR, 0 };
+static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
@@ -96,6 +143,9 @@ static char dir_separator_str[] = { DIR_SEPARATOR, 0 };
 
 #define MIN_FATAL_STATUS 1
 
+/* Flag set by cppspec.c to 1.  */
+int is_cpp_driver;
+
 /* Flag saying to pass the greatest exit code returned by a sub-process
    to the calling program.  */
 static int pass_exit_codes;
@@ -136,7 +186,14 @@ static int print_help_list;
 
 static int verbose_flag;
 
-/* Flag indicating to print target specific command line options. */
+/* Flag indicating whether we should ONLY print the command and
+   arguments (like verbose_flag) without executing the command.
+   Displayed arguments are quoted so that the generated command
+   line is suitable for execution.  This is intended for use in
+   shell scripts to capture the driver-generated command line.  */
+static int verbose_only_flag;
+
+/* Flag indicating to print target specific command line options.  */
 
 static int target_help_flag;
 
@@ -177,11 +234,11 @@ static const char *cross_compile = "0";
    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
+static const struct modify_target
 {
-  const char *sw;
-  enum add_del {ADD, DELETE} add_del;
-  const char *str;
+  const char *const sw;
+  const enum add_del {ADD, DELETE} add_del;
+  const char *const str;
 }
 modify_target[] = MODIFY_TARGET_NAME;
 #endif
@@ -233,7 +290,6 @@ static void add_prefix              PARAMS ((struct path_prefix *, const char *,
                                         const char *, int, int, int *));
 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 *));
 static void delete_temp_files  PARAMS ((void));
 static void delete_failure_queue PARAMS ((void));
@@ -241,6 +297,7 @@ static void clear_failure_queue PARAMS ((void));
 static int check_live_switch   PARAMS ((int, int));
 static const char *handle_braces PARAMS ((const char *));
 static char *save_string       PARAMS ((const char *, int));
+static void set_collect_gcc_options PARAMS ((void));
 static int do_spec_1           PARAMS ((const char *, int, const char *));
 static const char *find_file   PARAMS ((const char *));
 static int is_directory                PARAMS ((const char *, const char *, int));
@@ -251,12 +308,9 @@ static int used_arg                PARAMS ((const char *, int));
 static int default_arg         PARAMS ((const char *, int));
 static void set_multilib_dir   PARAMS ((void));
 static void print_multilib_info        PARAMS ((void));
-static void pfatal_with_name   PARAMS ((const char *)) ATTRIBUTE_NORETURN;
 static void perror_with_name   PARAMS ((const char *));
 static void pfatal_pexecute    PARAMS ((const char *, const char *))
   ATTRIBUTE_NORETURN;
-static void error              PARAMS ((const char *, ...))
-  ATTRIBUTE_PRINTF_1;
 static void notice             PARAMS ((const char *, ...))
   ATTRIBUTE_PRINTF_1;
 static void display_help       PARAMS ((void));
@@ -267,9 +321,18 @@ static void process_command                PARAMS ((int, const char *const *));
 static int execute                     PARAMS ((void));
 static void clear_args                 PARAMS ((void));
 static void fatal_error                        PARAMS ((int));
-static void set_input                  PARAMS ((const char *));
+#ifdef ENABLE_SHARED_LIBGCC
+static void init_gcc_specs              PARAMS ((struct obstack *,
+                                                const char *, const char *,
+                                                const char *));
+#endif
+#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+static const char *convert_filename    PARAMS ((const char *, int, int));
+#endif
 \f
-/* Specs are strings containing lines, each of which (if not blank)
+/* The Specs Language
+
+Specs are strings containing lines, each of which (if not blank)
 is made up of a program name, and arguments separated by spaces.
 The program name must be exact and start from root, since no path
 is searched and it is unreliable to depend on the current working directory.
@@ -318,6 +381,10 @@ or with constant text in a single argument.
         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.
@@ -353,6 +420,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.
@@ -377,7 +445,6 @@ or with constant text in a single argument.
        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.
  %1    process CC1_SPEC as a spec.
  %2    process CC1PLUS_SPEC as a spec.
@@ -402,7 +469,7 @@ 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.
+ %{<S}  remove all occurrences 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.
@@ -443,7 +510,7 @@ CC also knows implicitly that arguments starting in `-l' are to be
 treated as compiler output files, and passed to the linker in their
 proper position among the other output files.  */
 \f
-/* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1.  */
+/* Define the macros used for specs %a, %l, %L, %S, %C, %1.  */
 
 /* config.h can define ASM_SPEC to provide extra args to the assembler
    or extra switch-translations.  */
@@ -514,21 +581,32 @@ proper position among the other output files.  */
 #define ENDFILE_SPEC ""
 #endif
 
-/* This spec is used for telling cpp whether char is signed or not.  */
-#ifndef SIGNED_CHAR_SPEC
-/* Use #if rather than ?:
-   because MIPS C compiler rejects like ?: in initializers.  */
-#if DEFAULT_SIGNED_CHAR
-#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
-#else
-#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
-#endif
-#endif
-
 #ifndef LINKER_NAME
 #define LINKER_NAME "collect2"
 #endif
 
+/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
+   to the assembler.  */
+#ifndef ASM_DEBUG_SPEC
+# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
+     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
+#  define ASM_DEBUG_SPEC                                       \
+      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG                   \
+       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"  \
+       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
+# else
+#  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
+#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
+#  endif
+#  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
+#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
+#  endif
+# endif
+#endif
+#ifndef ASM_DEBUG_SPEC
+# define ASM_DEBUG_SPEC ""
+#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.  */
@@ -556,11 +634,11 @@ proper position among the other output files.  */
 # endif
 #endif
 
+static const char *asm_debug = ASM_DEBUG_SPEC;
 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;
@@ -582,23 +660,30 @@ static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
 static const char *trad_capable_cpp =
 "%{traditional|ftraditional|traditional-cpp:trad}cpp0";
 
-static const char *cpp_options =
+static const char *cpp_unique_options =
 "%{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{std*} %{nostdinc*}\
- %{C} %{v} %{I*} %{P} %{$} %I\
- %{M} %{MM} %{MD:-M -MF %b.d} %{MMD:-MM -MF %b.d} %{MF} %{MG} %{MP} %{MQ} %{MT}\
+ %{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__}\
+ %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{fno-inline|O0|!O*:-D__NO_INLINE__} %{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}}\
+ %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}} %{remap}\
+ %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{E:%{!M*:%W{o*}}}";
+
+/* This contains cpp options which are common with cc1_options and are passed
+   only when preprocessing only to avoid duplication.  */
+static const char *cpp_options =
+"%(cpp_unique_options) %{std*} %{d*} %{W*} %{w} %{pedantic*}\
  %{fshow-column} %{fno-show-column}\
+ %{fsigned-char&funsigned-char}\
  %{fleading-underscore} %{fno-leading-underscore}\
- %{fno-operator-names} %{ftabstop=*} %{remap}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*&U*&A*} %{i*} %Z %i\
- %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}";
+ %{fno-operator-names} %{ftabstop=*}";
 
 /* NB: This is shared amongst all front-ends.  */
 static const char *cc1_options =
@@ -606,10 +691,10 @@ static const char *cc1_options =
  %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}\
+ %{Qn:-fno-ident} %{--help:--help}\
  %{--target-help:--target-help}\
  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
- %{fsyntax-only:-o %j}";
+ %{fsyntax-only:-o %j} %{-param*}";
 
 static const char *asm_options =
 "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
@@ -664,14 +749,15 @@ 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, "-param") \
+  || !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
+#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
 /* This defines which switches stop a full compilation.  */
 #define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
   ((CHAR) == 'c' || (CHAR) == 'S')
@@ -690,6 +776,10 @@ struct compiler
                                   whose names end in this suffix.  */
 
   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
@@ -709,25 +799,26 @@ static int n_compilers;
 
 /* The default list of file name suffixes and their compilation specs.  */
 
-static struct compiler default_compilers[] =
+static const struct compiler default_compilers[] =
 {
   /* Add lists of suffixes of known languages here.  If those languages
      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"}, {".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"},
+  {".m",  "#Objective-C", 0}, {".mi",  "#Objective-C", 0},
+  {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0},
+  {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0},
+  {".ii", "#C++", 0},
+  {".ads", "#Ada", 0}, {".adb", "#Ada", 0},
+  {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0},
+  {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0},
+  {".r", "#Ratfor", 0},
+  {".p", "#Pascal", 0}, {".pas", "#Pascal", 0},
+  {".ch", "#Chill", 0}, {".chi", "#Chill", 0},
+  {".java", "#Java", 0}, {".class", "#Java", 0},
+  {".zip", "#Java", 0}, {".jar", "#Java", 0},
   /* Next come the entries for C.  */
-  {".c", "@c"},
+  {".c", "@c", 0},
   {"@c",
    /* cc1 has an integrated ISO C preprocessor.  We should invoke the
       external preprocessor if -save-temps or -traditional is given.  */
@@ -741,28 +832,29 @@ static struct compiler default_compilers[] =
                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)}}}}"},
+               cc1 -lang-c %{ansi:-std=c89} %(cpp_unique_options) %(cc1_options)}}}}\
+        %{!fsyntax-only:%(invoke_as)}}}}", 0},
   {"-",
    "%{!E:%e-E required when input is from standard input}\
-    %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
-  {".h", "@c-header"},
+    %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)", 0},
+  {".h", "@c-header", 0},
   {"@c-header",
-   "%{!E:%eCompilation of header file requested} \
-    %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
-  {".i", "@cpp-output"},
+   "%{!E:%ecompilation of header file requested} \
+    %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)", 0},
+  {".i", "@cpp-output", 0},
   {"@cpp-output",
-   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}"},
-  {".s", "@assembler"},
+   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
+  {".s", "@assembler", 0},
   {"@assembler",
-   "%{!M:%{!MM:%{!E:%{!S:as %(asm_options) %i %A }}}}"},
-  {".S", "@assembler-with-cpp"},
+   "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0},
+  {".S", "@assembler-with-cpp", 0},
   {"@assembler-with-cpp",
    "%(trad_capable_cpp) -lang-asm %(cpp_options)\
-       %{!M:%{!MM:%{!E:%(invoke_as)}}}"},
+      %{!M:%{!MM:%{!E:%{!S:-o %{|!pipe:%g.s} |\n\
+       as %(asm_debug) %(asm_options) %{!pipe:%g.s} %A }}}}", 0},
 #include "specs.h"
   /* Mark end of table */
-  {0, 0}
+  {0, 0, 0}
 };
 
 /* Number of elements in default_compilers, not counting the terminator.  */
@@ -794,21 +886,21 @@ static char **preprocessor_options;
 struct option_map
 {
   /* The long option's name.  */
-  const char *name;
+  const char *const name;
   /* The equivalent short option.  */
-  const char *equivalent;
+  const char *const equivalent;
   /* Argument info.  A string of flag chars; NULL equals no options.
      a => argument required.
      o => argument optional.
      j => join argument to equivalent, making one word.
      * => require other text after NAME as an argument.  */
-  const char *arg_info;
+  const char *const arg_info;
 };
 
 /* This is the table of mappings.  Mappings are tried sequentially
    for each option encountered; the first one that matches, wins.  */
 
-struct option_map option_map[] =
+static const struct option_map option_map[] =
  {
    {"--all-warnings", "-Wall", 0},
    {"--ansi", "-ansi", 0},
@@ -849,6 +941,7 @@ struct option_map option_map[] =
    {"--optimize", "-O", "oj"},
    {"--output", "-o", "a"},
    {"--output-class-directory", "-foutput-class-dir=", "ja"},
+   {"--param", "--param", "a"},
    {"--pedantic", "-pedantic", 0},
    {"--pedantic-errors", "-pedantic-errors", 0},
    {"--pipe", "-pipe", 0},
@@ -881,13 +974,24 @@ struct option_map option_map[] =
    {"--use-version", "-V", "a"},
    {"--user-dependencies", "-MM", 0},
    {"--verbose", "-v", 0},
-   {"--version", "-dumpversion", 0},
    {"--warn-", "-W", "*j"},
    {"--write-dependencies", "-MD", 0},
    {"--write-user-dependencies", "-MMD", 0},
    {"--", "-f", "*j"}
  };
 \f
+
+#ifdef TARGET_OPTION_TRANSLATE_TABLE
+static const struct {
+  const char *const option_found;
+  const char *const replacements;
+} target_option_translations[] =
+{
+  TARGET_OPTION_TRANSLATE_TABLE,
+  { 0, 0 }
+};
+#endif
+
 /* Translate the options described by *ARGCP and *ARGVP.
    Make a new vector and store it back in *ARGVP,
    and store its length in *ARGVC.  */
@@ -900,8 +1004,9 @@ translate_options (argcp, argvp)
   int i;
   int argc = *argcp;
   const char *const *argv = *argvp;
+  int newvsize = (argc + 2) * 2 * sizeof (const char *);
   const char **newv =
-    (const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
+    (const char **) xmalloc (newvsize);
   int newindex = 0;
 
   i = 0;
@@ -909,6 +1014,55 @@ translate_options (argcp, argvp)
 
   while (i < argc)
     {
+#ifdef TARGET_OPTION_TRANSLATE_TABLE
+      int tott_idx;
+
+      for (tott_idx = 0;
+          target_option_translations[tott_idx].option_found;
+          tott_idx++)
+       {
+         if (strcmp (target_option_translations[tott_idx].option_found,
+                     argv[i]) == 0)
+           {
+             int spaces = 1;
+             const char *sp;
+             char *np;
+
+             for (sp = target_option_translations[tott_idx].replacements;
+                  *sp; sp++)
+               {
+                 if (*sp == ' ')
+                   spaces ++;
+               }
+
+             newvsize += spaces * sizeof (const char *);
+             newv = (const char **) xrealloc (newv, newvsize);
+
+             sp = target_option_translations[tott_idx].replacements;
+             np = xstrdup (sp);
+
+             while (1)
+               {
+                 while (*np == ' ')
+                   np++;
+                 if (*np == 0)
+                   break;
+                 newv[newindex++] = np;
+                 while (*np != ' ' && *np)
+                   np++;
+                 if (*np == 0)
+                   break;
+                 *np++ = 0;
+               }
+
+             i ++;
+             break;
+           }
+       }
+      if (target_option_translations[tott_idx].option_found)
+       continue;
+#endif
+
       /* Translate -- options.  */
       if (argv[i][0] == '-' && argv[i][1] == '-')
        {
@@ -935,7 +1089,7 @@ translate_options (argcp, argvp)
                        if (strlen (option_map[k].name) >= arglen
                            && !strncmp (argv[i], option_map[k].name, arglen))
                          {
-                           error ("Ambiguous abbreviation %s", argv[i]);
+                           error ("ambiguous abbreviation %s", argv[i]);
                            break;
                          }
 
@@ -962,7 +1116,7 @@ translate_options (argcp, argvp)
 
                  else if (strchr (arginfo, '*') != 0)
                    {
-                     error ("Incomplete `%s' option", option_map[j].name);
+                     error ("incomplete `%s' option", option_map[j].name);
                      break;
                    }
 
@@ -973,7 +1127,7 @@ translate_options (argcp, argvp)
                        {
                          if (i + 1 == argc)
                            {
-                             error ("Missing argument to `%s' option",
+                             error ("missing argument to `%s' option",
                                     option_map[j].name);
                              break;
                            }
@@ -986,7 +1140,7 @@ translate_options (argcp, argvp)
                  else if (strchr (arginfo, 'o') == 0)
                    {
                      if (arg != 0)
-                       error ("Extraneous argument to `%s' option",
+                       error ("extraneous argument to `%s' option",
                               option_map[j].name);
                      arg = 0;
                    }
@@ -994,7 +1148,7 @@ translate_options (argcp, argvp)
                  /* Store the translation as one argv elt or as two.  */
                  if (arg != 0 && strchr (arginfo, 'j') != 0)
                    newv[newindex++] = concat (option_map[j].equivalent, arg,
-                                              NULL_PTR);
+                                              NULL);
                  else if (arg != 0)
                    {
                      newv[newindex++] = option_map[j].equivalent;
@@ -1078,7 +1232,7 @@ skip_whitespace (p)
 
 struct prefix_list
 {
-  char *prefix;               /* String to prepend to the path.  */
+  const 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.  */
@@ -1153,20 +1307,20 @@ static const char *gcc_exec_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 *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
+static const char *const 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 *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
+static const char *const standard_startfile_prefix_1 = "/lib/";
+static const char *const standard_startfile_prefix_2 = "/usr/lib/";
 
-static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
 static const char *tooldir_prefix;
 
-static const char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
 
 /* Subdirectory to use for locating libraries.  Set by
    set_multilib_dir based on the compilation options.  */
@@ -1193,17 +1347,19 @@ struct spec_list
 };
 
 #define INIT_STATIC_SPEC(NAME,PTR) \
-{ NAME, NULL_PTR, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
+{ NAME, NULL, 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_debug",               &asm_debug),
   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 ("cpp_unique_options",      &cpp_unique_options),
   INIT_STATIC_SPEC ("trad_capable_cpp",                &trad_capable_cpp),
   INIT_STATIC_SPEC ("cc1",                     &cc1_spec),
   INIT_STATIC_SPEC ("cc1_options",             &cc1_options),
@@ -1214,7 +1370,6 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("libgcc",                  &libgcc_spec),
   INIT_STATIC_SPEC ("startfile",               &startfile_spec),
   INIT_STATIC_SPEC ("switches_need_spaces",    &switches_need_spaces),
-  INIT_STATIC_SPEC ("signed_char",             &signed_char_spec),
   INIT_STATIC_SPEC ("predefines",              &cpp_predefines),
   INIT_STATIC_SPEC ("cross_compile",           &cross_compile),
   INIT_STATIC_SPEC ("version",                 &compiler_version),
@@ -1235,11 +1390,11 @@ static struct spec_list static_specs[] =
    That is all that the EXTRA_SPECS macro gives us.  */
 struct spec_list_1
 {
-  const char *name;
-  const char *ptr;
+  const char *const name;
+  const char *const ptr;
 };
 
-static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
 static struct spec_list *extra_specs = (struct spec_list *) 0;
 #endif
 
@@ -1247,6 +1402,45 @@ static struct spec_list *extra_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.  */
+
+#ifdef ENABLE_SHARED_LIBGCC
+static void
+init_gcc_specs (obstack, shared_name, static_name, eh_name)
+     struct obstack *obstack;
+     const char *shared_name;
+     const char *static_name;
+     const char *eh_name;
+{
+  char buffer[128];
+  const char *p;
+
+  /* If we see -shared-libgcc, then use the shared version.  */
+  sprintf (buffer, "%%{shared-libgcc:%s %s}", shared_name, static_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* If we see -static-libgcc, then use the static version.  */
+  sprintf (buffer, "%%{static-libgcc:%s %s}", static_name, eh_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* Otherwise, if we see -shared, then use the shared version
+     if using EH registration routines or static version without
+     exception handling routines otherwise.  */
+  p = "%{!shared-libgcc:%{!static-libgcc:%{shared:";
+  obstack_grow (obstack, p, strlen (p));
+#ifdef LINK_EH_SPEC
+  sprintf (buffer, "%s}}}", static_name);
+#else
+  sprintf (buffer, "%s}}}", shared_name);
+#endif
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* Otherwise, use the static version.  */
+  sprintf (buffer, 
+          "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s %s}}}", 
+          static_name, eh_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+}
+#endif /* ENABLE_SHARED_LIBGCC */
+
 /* Initialize the specs lookup routines.  */
 
 static void
@@ -1260,7 +1454,7 @@ init_spec ()
     return;                    /* Already initialized.  */
 
   if (verbose_flag)
-    notice ("Using builtin specs.\n");
+    notice ("Using built-in specs.\n");
 
 #ifdef EXTRA_SPECS
   extra_specs = (struct spec_list *)
@@ -1299,7 +1493,7 @@ init_spec ()
 
        (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.
+           its dependencies depends on a shared libgcc.
 
        (4) If "-shared"
 
@@ -1321,15 +1515,17 @@ init_spec ()
        when given the proper command line arguments.  */
     while (*p)
       {
-       const char *r;
         if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
          {
+           init_gcc_specs (&obstack,
 #ifdef NO_SHARED_LIBGCC_MULTILIB
-           r = "%{shared-libgcc:-lgcc_s}%{!shared-libgcc:-lgcc}";
+                           "-lgcc_s"
 #else
-           r = "%{shared-libgcc:-lgcc_s%M}%{!shared-libgcc:-lgcc}";
+                           "-lgcc_s%M"
 #endif
-           obstack_grow (&obstack, r, strlen(r));
+                           ,
+                           "-lgcc",
+                           "-lgcc_eh");
            p += 5;
            in_sep = 0;
          }
@@ -1337,12 +1533,15 @@ init_spec ()
          {
            /* 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
-           r = "%{shared-libgcc:-lgcc_s}%{!shared-libgcc:libgcc.a%s}";
+                           "-lgcc_s"
 #else
-           r = "%{shared-libgcc:-lgcc_s%M}%{!shared-libgcc:libgcc.a%s}";
+                           "-lgcc_s%M"
 #endif
-           obstack_grow (&obstack, r, strlen(r));
+                           ,
+                           "libgcc.a%s",
+                           "libgcc_eh.a%s");
            p += 10;
            in_sep = 0;
          }
@@ -1358,6 +1557,21 @@ init_spec ()
     libgcc_spec = obstack_finish (&obstack);
   }
 #endif
+#ifdef USE_AS_TRADITIONAL_FORMAT
+  /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
+  {
+    static const char tf[] = "--traditional-format ";
+    obstack_grow (&obstack, tf, sizeof(tf) - 1);
+    obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
+    asm_spec = obstack_finish (&obstack);
+  }
+#endif
+#ifdef LINK_EH_SPEC
+  /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
+  obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
+  obstack_grow0 (&obstack, link_spec, strlen (link_spec));
+  link_spec = obstack_finish (&obstack);
+#endif
 
   specs = sl;
 }
@@ -1409,7 +1623,7 @@ set_spec (name, spec)
 
   old_spec = *(sl->ptr_spec);
   *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
-                    ? concat (old_spec, spec + 1, NULL_PTR)
+                    ? concat (old_spec, spec + 1, NULL)
                     : xstrdup (spec));
 
 #ifdef DEBUG_SPECS
@@ -1495,7 +1709,7 @@ store_arg (arg, delete_always, delete_failure)
     record_temp_file (arg, delete_always, delete_failure);
 }
 \f
-/* Load specs from a file name named FILENAME, replacing occurances of
+/* Load specs from a file name named FILENAME, replacing occurrences of
    various different types of line-endings, \r\n, \n\r and just \r, with
    a single \n.  */
 
@@ -1558,7 +1772,7 @@ load_specs (filename)
 
    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.
+   *asm, *cc1, *cpp, *link, *startfile, etc.
    The corresponding spec is stored in asm_spec, etc.,
    rather than in the `compilers' vector.
 
@@ -1570,7 +1784,7 @@ read_specs (filename, main_p)
      int main_p;
 {
   char *buffer;
-  register char *p;
+  char *p;
 
   buffer = load_specs (filename);
 
@@ -1637,7 +1851,7 @@ read_specs (filename, main_p)
              if (new_filename)
                read_specs (new_filename, FALSE);
              else if (verbose_flag)
-               notice ("Could not find specs file %s\n", p1);
+               notice ("could not find specs file %s\n", p1);
              continue;
            }
          else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
@@ -1830,17 +2044,17 @@ static struct temp_file *failure_delete_queue;
    FAIL_DELETE nonzero means delete it if a compilation step fails;
    otherwise delete it in any case.  */
 
-static void
+void
 record_temp_file (filename, always_delete, fail_delete)
      const char *filename;
      int always_delete;
      int fail_delete;
 {
-  register char *const name = xstrdup (filename);
+  char *const name = xstrdup (filename);
 
   if (always_delete)
     {
-      register struct temp_file *temp;
+      struct temp_file *temp;
       for (temp = always_delete_queue; temp; temp = temp->next)
        if (! strcmp (name, temp->name))
          goto already1;
@@ -1855,7 +2069,7 @@ record_temp_file (filename, always_delete, fail_delete)
 
   if (fail_delete)
     {
-      register struct temp_file *temp;
+      struct temp_file *temp;
       for (temp = failure_delete_queue; temp; temp = temp->next)
        if (! strcmp (name, temp->name))
          goto already2;
@@ -1897,7 +2111,7 @@ delete_if_ordinary (name)
 static void
 delete_temp_files ()
 {
-  register struct temp_file *temp;
+  struct temp_file *temp;
 
   for (temp = always_delete_queue; temp; temp = temp->next)
     delete_if_ordinary (temp->name);
@@ -1909,7 +2123,7 @@ delete_temp_files ()
 static void
 delete_failure_queue ()
 {
-  register struct temp_file *temp;
+  struct temp_file *temp;
 
   for (temp = failure_delete_queue; temp; temp = temp->next)
     delete_if_ordinary (temp->name);
@@ -1921,60 +2135,6 @@ clear_failure_queue ()
   failure_delete_queue = 0;
 }
 \f
-/* Routine to add variables to the environment.  We do this to pass
-   the pathname of the gcc driver, and the directories search to the
-   collect2 program, which is being run as ld.  This way, we can be
-   sure of executing the right compiler when collect2 wants to build
-   constructors and destructors.  Since the environment variables we
-   use come from an obstack, we don't have to worry about allocating
-   space for them.  */
-
-#ifndef HAVE_PUTENV
-
-void
-putenv (str)
-     char *str;
-{
-#ifndef VMS                    /* nor about VMS */
-
-  extern char **environ;
-  char **old_environ = environ;
-  char **envp;
-  int num_envs = 0;
-  int name_len = 1;
-  int str_len = strlen (str);
-  char *p = str;
-  int ch;
-
-  while ((ch = *p++) != '\0' && ch != '=')
-    name_len++;
-
-  if (!ch)
-    abort ();
-
-  /* Search for replacing an existing environment variable, and
-     count the number of total environment variables.  */
-  for (envp = old_environ; *envp; envp++)
-    {
-      num_envs++;
-      if (!strncmp (str, *envp, name_len))
-       {
-         *envp = str;
-         return;
-       }
-    }
-
-  /* Add a new environment variable */
-  environ = (char **) xmalloc (sizeof (char *) * (num_envs + 2));
-  *environ = str;
-  memcpy ((char *) (environ + 1), (char *) old_environ,
-         sizeof (char *) * (num_envs + 1));
-
-#endif /* VMS */
-}
-
-#endif /* HAVE_PUTENV */
-\f
 /* Build a list of search directories from PATHS.
    PREFIX is a string to prepend to the list.
    If CHECK_DIR_P is non-zero we ensure the directory exists.
@@ -2118,7 +2278,7 @@ split_directories (name, ptr_num_dirs)
   if (p - 1 - q > 0)
     dirs[num_dirs++] = save_string (q, p - 1 - q);
 
-  dirs[num_dirs] = NULL_PTR;
+  dirs[num_dirs] = NULL;
   if (ptr_num_dirs)
     *ptr_num_dirs = num_dirs;
 
@@ -2133,7 +2293,7 @@ free_split_directories (dirs)
 {
   int i = 0;
 
-  while (dirs[i] != NULL_PTR)
+  while (dirs[i] != NULL)
     free (dirs[i++]);
 
   free ((char *) dirs);
@@ -2171,8 +2331,12 @@ make_relative_prefix (progname, bin_prefix, prefix)
       GET_ENV_PATH_LIST (temp, "PATH");
       if (temp)
        {
-         char *startp, *endp;
-         char *nstore = (char *) alloca (strlen (temp) + strlen (progname) + 1);
+         char *startp, *endp, *nstore;
+         size_t prefixlen = strlen (temp) + 1;
+         if (prefixlen < 2)
+           prefixlen = 2;
+
+         nstore = (char *) alloca (prefixlen + strlen (progname) + 1);
 
          startp = endp = temp;
          while (1)
@@ -2198,8 +2362,8 @@ make_relative_prefix (progname, bin_prefix, prefix)
                    }
                  strcat (nstore, progname);
                  if (! access (nstore, X_OK)
-#ifdef HAVE_EXECUTABLE_SUFFIX
-                      || ! access (strcat (nstore, EXECUTABLE_SUFFIX), X_OK)
+#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+                      || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
 #endif
                      )
                    {
@@ -2240,7 +2404,7 @@ make_relative_prefix (progname, bin_prefix, prefix)
          free_split_directories (prog_dirs);
          free_split_directories (bin_dirs);
          prog_dirs = bin_dirs = (char **) 0;
-         return NULL_PTR;
+         return NULL;
        }
     }
 
@@ -2260,7 +2424,7 @@ make_relative_prefix (progname, bin_prefix, prefix)
       free_split_directories (prog_dirs);
       free_split_directories (bin_dirs);
       free_split_directories (prefix_dirs);
-      return NULL_PTR;
+      return NULL;
     }
 
   /* Build up the pathnames in argv[0].  */
@@ -2318,7 +2482,8 @@ find_a_file (pprefix, name, mode)
      int mode;
 {
   char *temp;
-  const char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
+  const char *const file_suffix =
+    ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "");
   struct prefix_list *pl;
   int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
 
@@ -2493,7 +2658,7 @@ add_prefix (pprefix, prefix, component, priority, require_machine_suffix, warn)
     pprefix->max_len = len;
 
   pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
-  pl->prefix = save_string (prefix, len);
+  pl->prefix = prefix;
   pl->require_machine_suffix = require_machine_suffix;
   pl->used_flag_ptr = warn;
   pl->priority = priority;
@@ -2575,8 +2740,24 @@ execute ()
        {
          const char *const *j;
 
-         for (j = commands[i].argv; *j; j++)
-           fprintf (stderr, " %s", *j);
+         if (verbose_only_flag)
+           {
+             for (j = commands[i].argv; *j; j++)
+               {
+                 const char *p;
+                 fprintf (stderr, " \"");
+                 for (p = *j; *p; ++p)
+                   {
+                     if (*p == '"' || *p == '\\' || *p == '$')
+                       fputc ('\\', stderr);
+                     fputc (*p, stderr);
+                   }
+                 fputc ('"', stderr);
+               }
+           }
+         else
+           for (j = commands[i].argv; *j; j++)
+             fprintf (stderr, " %s", *j);
 
          /* Print a pipe symbol after all but the last command.  */
          if (i + 1 != n_commands)
@@ -2584,6 +2765,8 @@ execute ()
          fprintf (stderr, "\n");
        }
       fflush (stderr);
+      if (verbose_only_flag != 0)
+        return 0;
 #ifdef DEBUG
       notice ("\nGo ahead? (y or n) ");
       fflush (stderr);
@@ -2753,7 +2936,7 @@ struct infile
 
 static struct infile *infiles;
 
-static int n_infiles;
+int n_infiles;
 
 /* This counts the number of libraries added by lang_specific_driver, so that
    we can tell if there were any user supplied any files or libraries.  */
@@ -2762,7 +2945,7 @@ static int added_libraries;
 
 /* And a vector of corresponding output files is made up later.  */
 
-static const char **outfiles;
+const char **outfiles;
 
 /* Used to track if none of the -B paths are used.  */
 static int warn_B;
@@ -2773,17 +2956,21 @@ 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)
+#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
 
 /* Convert NAME to a new name if it is the standard suffix.  DO_EXE
-   is true if we should look for an executable suffix as well.  */
+   is true if we should look for an executable suffix.  DO_OBJ
+   is true if we should look for an object suffix.  */
 
-static char *
-convert_filename (name, do_exe)
-     char *name;
-     int do_exe;
+static const char *
+convert_filename (name, do_exe, do_obj)
+     const char *name;
+     int do_exe ATTRIBUTE_UNUSED;
+     int do_obj ATTRIBUTE_UNUSED;
 {
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
   int i;
+#endif
   int len;
 
   if (name == NULL)
@@ -2791,22 +2978,22 @@ convert_filename (name, do_exe)
 
   len = strlen (name);
 
-#ifdef HAVE_OBJECT_SUFFIX
-  /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj".  */
-  if (len > 2
+#ifdef HAVE_TARGET_OBJECT_SUFFIX
+  /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj".  */
+  if (do_obj && len > 2
       && name[len - 2] == '.'
       && name[len - 1] == 'o')
     {
       obstack_grow (&obstack, name, len - 2);
-      obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
+      obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
       name = obstack_finish (&obstack);
     }
 #endif
 
-#ifdef HAVE_EXECUTABLE_SUFFIX
+#if defined(HAVE_TARGET_EXECUTABLE_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] == '-'))
+  if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
     return name;
 
   for (i = len - 1; i >= 0; i--)
@@ -2818,7 +3005,8 @@ convert_filename (name, do_exe)
       return name;
 
   obstack_grow (&obstack, name, len);
-  obstack_grow0 (&obstack, EXECUTABLE_SUFFIX, strlen (EXECUTABLE_SUFFIX));
+  obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
+                strlen (TARGET_EXECUTABLE_SUFFIX));
   name = obstack_finish (&obstack);
 #endif
 
@@ -2856,12 +3044,13 @@ display_help ()
   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 (_("  -specs=<file>            Override built-in 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 (_("  -###                     Like -v but options quoted and commands not executed\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);
@@ -2869,14 +3058,14 @@ display_help ()
   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\
+                           'none' means revert to the default behavior 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\
+\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
+ passed on to the various sub-processes invoked by %s.  In order to pass\n\
+ other options 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
@@ -2946,7 +3135,7 @@ process_command (argc, argv)
      int argc;
      const char *const *argv;
 {
-  register int i;
+  int i;
   const char *temp;
   char *temp1;
   const char *spec_lang = 0;
@@ -2988,7 +3177,7 @@ process_command (argc, argv)
       gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
                                              standard_exec_prefix);
       if (gcc_exec_prefix)
-       putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL_PTR));
+       putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
     }
 #endif
 
@@ -3009,9 +3198,9 @@ process_command (argc, argv)
 
       set_std_prefix (gcc_exec_prefix, len);
       add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC",
-                 PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                 PREFIX_PRIORITY_LAST, 0, NULL);
       add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
-                 PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                 PREFIX_PRIORITY_LAST, 0, NULL);
     }
 
   /* COMPILER_PATH and LIBRARY_PATH have values
@@ -3030,7 +3219,7 @@ process_command (argc, argv)
            {
              strncpy (nstore, startp, endp - startp);
              if (endp == startp)
-               strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
+               strcpy (nstore, concat (".", dir_separator_str, NULL));
              else if (!IS_DIR_SEPARATOR (endp[-1]))
                {
                  nstore[endp - startp] = DIR_SEPARATOR;
@@ -3039,10 +3228,10 @@ process_command (argc, argv)
              else
                nstore[endp - startp] = 0;
              add_prefix (&exec_prefixes, nstore, 0,
-                         PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                         PREFIX_PRIORITY_LAST, 0, NULL);
              add_prefix (&include_prefixes,
-                         concat (nstore, "include", NULL_PTR),
-                         0, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                         concat (nstore, "include", NULL),
+                         0, PREFIX_PRIORITY_LAST, 0, NULL);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -3065,7 +3254,7 @@ process_command (argc, argv)
            {
              strncpy (nstore, startp, endp - startp);
              if (endp == startp)
-               strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
+               strcpy (nstore, concat (".", dir_separator_str, NULL));
              else if (!IS_DIR_SEPARATOR (endp[-1]))
                {
                  nstore[endp - startp] = DIR_SEPARATOR;
@@ -3073,8 +3262,8 @@ process_command (argc, argv)
                }
              else
                nstore[endp - startp] = 0;
-             add_prefix (&startfile_prefixes, nstore, NULL_PTR,
-                         PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+             add_prefix (&startfile_prefixes, nstore, NULL,
+                         PREFIX_PRIORITY_LAST, 0, NULL);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -3098,7 +3287,7 @@ process_command (argc, argv)
            {
              strncpy (nstore, startp, endp - startp);
              if (endp == startp)
-               strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
+               strcpy (nstore, concat (".", dir_separator_str, NULL));
              else if (!IS_DIR_SEPARATOR (endp[-1]))
                {
                  nstore[endp - startp] = DIR_SEPARATOR;
@@ -3106,8 +3295,8 @@ process_command (argc, argv)
                }
              else
                nstore[endp - startp] = 0;
-             add_prefix (&startfile_prefixes, nstore, NULL_PTR,
-                         PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+             add_prefix (&startfile_prefixes, nstore, NULL,
+                         PREFIX_PRIORITY_LAST, 0, NULL);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -3150,6 +3339,17 @@ process_command (argc, argv)
          printf ("%s\n", spec_machine);
          exit (0);
        }
+      else if (strcmp (argv[i], "-fversion") == 0)
+       {
+         /* translate_options () has turned --version into -fversion.  */
+         printf (_("%s (GCC) %s\n"), programname, version_string);
+         fputs (_("Copyright (C) 2002 Free Software Foundation, Inc.\n"),
+                stdout);
+         fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
+                stdout);
+         exit (0);
+       }
       else if (strcmp (argv[i], "-fhelp") == 0)
        {
          /* translate_options () has turned --help into -fhelp.  */
@@ -3159,20 +3359,24 @@ process_command (argc, argv)
          n_infiles++;
          n_switches++;
 
-         add_preprocessor_option ("--help", 6);
+         /* CPP driver cannot obtain switch from cc1_options.  */
+         if (is_cpp_driver)
+           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. */
+          /* 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);
+         /* CPP driver cannot obtain switch from cc1_options.  */
+         if (is_cpp_driver)
+           add_preprocessor_option ("--target-help", 13);
           add_assembler_option ("--target-help", 13);
           add_linker_option ("--target-help", 13);
         }
@@ -3245,6 +3449,14 @@ process_command (argc, argv)
          n_infiles++;
          i++;
        }
+      else if (strcmp (argv[i], "-l") == 0)
+       {
+         if (i + 1 == argc)
+           fatal ("argument to `-l' is missing");
+
+         n_infiles++;
+         i++;
+       }
       else if (strncmp (argv[i], "-l", 2) == 0)
        n_infiles++;
       else if (strcmp (argv[i], "-save-temps") == 0)
@@ -3284,10 +3496,19 @@ process_command (argc, argv)
        }
       else if (strcmp (argv[i], "-time") == 0)
        report_times = 1;
+      else if (strcmp (argv[i], "-###") == 0)
+       {
+         /* This is similar to -v except that there is no execution
+            of the commands and the echoed arguments are quoted.  It
+            is intended for use in shell scripts to capture the
+            driver-generated command line.  */
+         verbose_only_flag++;
+         verbose_flag++;
+       }
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
-         register const char *p = &argv[i][1];
-         register int c = *p;
+         const char *p = &argv[i][1];
+         int c = *p;
 
          switch (c)
            {
@@ -3306,44 +3527,63 @@ process_command (argc, argv)
            case 'B':
              {
                const char *value;
+               int len;
+
                if (p[1] == 0 && i + 1 == argc)
                  fatal ("argument to `-B' is missing");
                if (p[1] == 0)
                  value = argv[++i];
                else
                  value = p + 1;
-               {
-                 /* 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
-                          && (IS_DIR_SEPARATOR (value[len - 8]))))
-                     && strncmp (value + len - 7, "stage", 5) == 0
-                     && ISDIGIT (value[len - 2])
-                     && (IS_DIR_SEPARATOR (value[len - 1])))
-                   {
-                     if (len == 7)
-                       add_prefix (&include_prefixes, "include", 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,
-                                     PREFIX_PRIORITY_B_OPT, 0, NULL_PTR);
-                       }
-                   }
-               }
-               add_prefix (&exec_prefixes, value, NULL_PTR,
+
+               len = strlen (value);
+
+               /* Catch the case where the user has forgotten to append a
+                  directory separator to the path.  Note, they may be using
+                  -B to add an executable name prefix, eg "i386-elf-", in
+                  order to distinguish between multiple installations of
+                  GCC in the same directory.  Hence we must check to see
+                  if appending a directory separator actually makes a
+                  valid directory name.  */
+               if (! IS_DIR_SEPARATOR (value [len - 1])
+                   && is_directory (value, "", 0))
+                 {
+                   char *tmp = xmalloc (len + 2);
+                   strcpy (tmp, value);
+                   tmp[len] = DIR_SEPARATOR;
+                   tmp[++ len] = 0;
+                   value = tmp;
+                 }
+               
+               /* As a kludge, if the arg is "[foo/]stageN/", just
+                  add "[foo/]include" to the include prefix.  */
+               if ((len == 7
+                    || (len > 7
+                        && (IS_DIR_SEPARATOR (value[len - 8]))))
+                   && strncmp (value + len - 7, "stage", 5) == 0
+                   && ISDIGIT (value[len - 2])
+                   && (IS_DIR_SEPARATOR (value[len - 1])))
+                 {
+                   if (len == 7)
+                     add_prefix (&include_prefixes, "include", NULL,
+                                 PREFIX_PRIORITY_B_OPT, 0, NULL);
+                   else
+                     {
+                       char * string = xmalloc (len + 1);
+
+                       strncpy (string, value, len - 7);
+                       strcpy (string + len - 7, "include");
+                       add_prefix (&include_prefixes, string, NULL,
+                                   PREFIX_PRIORITY_B_OPT, 0, NULL);
+                     }
+                 }
+
+               add_prefix (&exec_prefixes, value, NULL,
                            PREFIX_PRIORITY_B_OPT, 0, &warn_B);
-               add_prefix (&startfile_prefixes, value, NULL_PTR,
+               add_prefix (&startfile_prefixes, value, NULL,
                            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);
+               add_prefix (&include_prefixes, concat (value, "include", NULL),
+                           NULL, PREFIX_PRIORITY_B_OPT, 0, NULL);
                n_switches++;
              }
              break;
@@ -3411,7 +3651,7 @@ process_command (argc, argv)
 
            case 'o':
              have_o = 1;
-#if defined(HAVE_EXECUTABLE_SUFFIX)
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
              if (! have_c)
                {
                  int skip;
@@ -3431,20 +3671,20 @@ process_command (argc, argv)
                              have_c = 1;
                              break;
                            }
-                         else if (skip = SWITCH_TAKES_ARG (argv[j][1]))
+                         else if ((skip = SWITCH_TAKES_ARG (argv[j][1])))
                            j += skip - (argv[j][2] != 0);
-                         else if (skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))
+                         else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)))
                            j += skip;
                        }
                      j++;
                    }
                }
 #endif
-#if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_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, 0);
              else
-               argv[i] = convert_filename (argv[i], ! have_c);
+               argv[i] = convert_filename (argv[i], ! have_c, 0);
 #endif
              goto normal_switch;
 
@@ -3529,7 +3769,7 @@ process_command (argc, argv)
              PREFIX_PRIORITY_LAST, 1, warn_std_ptr);
 
   tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
-                          dir_separator_str, NULL_PTR);
+                          dir_separator_str, NULL);
 
   /* If tooldir is relative, base it on exec_prefixes.  A relative
      tooldir lets us move the installed tree as a unit.
@@ -3544,29 +3784,29 @@ process_command (argc, argv)
        {
          char *gcc_exec_tooldir_prefix
            = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
-                     spec_version, dir_separator_str, tooldir_prefix, NULL_PTR);
+                     spec_version, dir_separator_str, tooldir_prefix, NULL);
 
          add_prefix (&exec_prefixes,
                      concat (gcc_exec_tooldir_prefix, "bin",
-                             dir_separator_str, NULL_PTR),
-                     NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                             dir_separator_str, NULL),
+                     NULL, PREFIX_PRIORITY_LAST, 0, NULL);
          add_prefix (&startfile_prefixes,
                      concat (gcc_exec_tooldir_prefix, "lib",
-                             dir_separator_str, NULL_PTR),
-                     NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                             dir_separator_str, NULL),
+                     NULL, PREFIX_PRIORITY_LAST, 0, NULL);
        }
 
       tooldir_prefix = concat (standard_exec_prefix, spec_machine,
                               dir_separator_str, spec_version,
-                              dir_separator_str, tooldir_prefix, NULL_PTR);
+                              dir_separator_str, tooldir_prefix, NULL);
     }
 
   add_prefix (&exec_prefixes,
-             concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR),
-             "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+             concat (tooldir_prefix, "bin", dir_separator_str, NULL),
+             "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL);
   add_prefix (&startfile_prefixes,
-             concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR),
-             "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+             concat (tooldir_prefix, "lib", dir_separator_str, NULL),
+             "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL);
 
   /* More prefixes are enabled in main, after we read the specs file
      and determine whether this is cross-compilation or not.  */
@@ -3616,41 +3856,10 @@ 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)
-           {
-             /* Create a dummy input file, so that we can pass --help on to
-                the various sub-processes.  */
-             infiles[n_infiles].language = "c";
-             infiles[n_infiles++].name   = "help-dummy";
-
-             /* Preserve the --help switch so that it can be caught by the
-                cc1 spec string.  */
-             switches[n_switches].part1     = "--help";
-             switches[n_switches].args      = 0;
-             switches[n_switches].live_cond = SWITCH_OK;
-             switches[n_switches].validated = 0;
-
-             n_switches++;
-           }
-       }
+      else if (! strcmp (argv[i], "-ftarget-help"))
+       ;
+      else if (! strcmp (argv[i], "-fhelp"))
+       ;
       else if (argv[i][0] == '+' && argv[i][1] == 'e')
        {
          /* Compensate for the +e options to the C++ front-end;
@@ -3686,6 +3895,12 @@ process_command (argc, argv)
          infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[++i];
        }
+      else if (strcmp (argv[i], "-l") == 0)
+       { /* POSIX allows separation of -l and the lib arg;
+            canonicalize by concatenating -l with its arg */
+         infiles[n_infiles].language = "*";
+         infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
+       }
       else if (strncmp (argv[i], "-l", 2) == 0)
        {
          infiles[n_infiles].language = "*";
@@ -3702,12 +3917,14 @@ process_command (argc, argv)
        {
          /* -save-temps overrides -pipe, so that temp files are produced */
          if (save_temps_flag)
-           error ("Warning: -pipe ignored because -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 because -time specified");
+           error ("warning: -pipe ignored because -time specified");
        }
+      else if (strcmp (argv[i], "-###") == 0)
+       ;
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
          const char *p = &argv[i][1];
@@ -3757,15 +3974,13 @@ 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
                = (const char **) xmalloc (2 * sizeof (const char *));
-             switches[n_switches].args[0] = tmp = xmalloc (strlen (p));
-             strcpy (tmp, &p[1]);
+             switches[n_switches].args[0] = xstrdup (p+1);
              switches[n_switches].args[1] = 0;
            }
          else
@@ -3773,6 +3988,7 @@ process_command (argc, argv)
 
          switches[n_switches].live_cond = SWITCH_OK;
          switches[n_switches].validated = 0;
+         switches[n_switches].ordering = 0;
          /* These are always valid, since gcc.c itself understands it.  */
          if (!strcmp (p, "save-temps")
              || !strcmp (p, "static-libgcc")
@@ -3788,8 +4004,8 @@ process_command (argc, argv)
        }
       else
        {
-#ifdef HAVE_OBJECT_SUFFIX
-         argv[i] = convert_filename (argv[i], 0);
+#ifdef HAVE_TARGET_OBJECT_SUFFIX
+         argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
 #endif
 
          if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
@@ -3806,11 +4022,99 @@ process_command (argc, argv)
     }
 
   if (n_infiles == last_language_n_infiles && spec_lang != 0)
-    error ("Warning: `-x %s' after last input file has no effect", spec_lang);
+    error ("warning: `-x %s' after last input file has no effect", spec_lang);
+
+  /* Ensure we only invoke each subprocess once.  */
+  if (target_help_flag || print_help_list)
+    {
+      n_infiles = 1;
+
+      /* Create a dummy input file, so that we can pass --target-help on to
+        the various sub-processes.  */
+      infiles[0].language = "c";
+      infiles[0].name   = "help-dummy";
+
+      if (target_help_flag)
+       {
+         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++;
+       }
+
+      if (print_help_list)
+       {
+         switches[n_switches].part1     = "--help";
+         switches[n_switches].args      = 0;
+         switches[n_switches].live_cond = SWITCH_OK;
+         switches[n_switches].validated = 0;
+
+         n_switches++;
+       }
+    }
 
   switches[n_switches].part1 = 0;
   infiles[n_infiles].name = 0;
 }
+
+/* Store switches not filtered out by %{<S} in spec in COLLECT_GCC_OPTIONS
+   and place that in the environment.  */
+
+static void
+set_collect_gcc_options ()
+{
+  int i;
+  int first_time;
+
+  /* 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);
+
+  first_time = TRUE;
+  for (i = 0; (int) i < n_switches; i++)
+    {
+      const char *const *args;
+      const char *p, *q;
+      if (!first_time)
+       obstack_grow (&collect_obstack, " ", 1);
+
+      first_time = FALSE;
+
+      /* Ignore elided switches.  */
+      if (switches[i].live_cond == SWITCH_IGNORE)
+       continue;
+
+      obstack_grow (&collect_obstack, "'-", 2);
+      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 = 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);
+       }
+    }
+  obstack_grow (&collect_obstack, "\0", 1);
+  putenv (obstack_finish (&collect_obstack));
+}
 \f
 /* Process a spec string, accumulating and running commands.  */
 
@@ -3828,6 +4132,11 @@ static int basename_length;
 static int suffixed_basename_length;
 static const char *input_basename;
 static const char *input_suffix;
+static struct stat input_stat;
+static int input_stat_set;
+
+/* 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.  */
 
@@ -3851,6 +4160,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.  */
 
@@ -3866,8 +4179,9 @@ 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);
+  value = do_spec_1 (spec, 0, NULL);
 
   /* Force out any unfinished command.
      If -pipe, this forces out the last command if it ended in `|'.  */
@@ -3876,6 +4190,8 @@ do_spec (spec)
       if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
        argbuf_index--;
 
+      set_collect_gcc_options ();
+
       if (argbuf_index > 0)
        value = execute ();
     }
@@ -3901,8 +4217,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
      int inswitch;
      const char *soft_matched_part;
 {
-  register const char *p = spec;
-  register int c;
+  const char *p = spec;
+  int c;
   int i;
   const char *string;
   int value;
@@ -3946,6 +4262,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              argbuf_index--;
          }
 
+       set_collect_gcc_options ();
+
        if (argbuf_index > 0)
          {
            value = execute ();
@@ -4003,7 +4321,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
        switch (c = *p++)
          {
          case 0:
-           fatal ("Invalid specification!  Bug in cc.");
+           fatal ("invalid specification!  Bug in cc");
 
          case 'b':
            obstack_grow (&obstack, input_basename, basename_length);
@@ -4054,28 +4372,28 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                          strcat (buffer, machine_suffix);
                          if (is_directory (buffer, multilib_dir, 1))
                            {
-                             do_spec_1 ("-L", 0, NULL_PTR);
+                             do_spec_1 ("-L", 0, NULL);
 #ifdef SPACE_AFTER_L_OPTION
-                             do_spec_1 (" ", 0, NULL_PTR);
+                             do_spec_1 (" ", 0, NULL);
 #endif
-                             do_spec_1 (buffer, 1, NULL_PTR);
-                             do_spec_1 (multilib_dir, 1, NULL_PTR);
+                             do_spec_1 (buffer, 1, NULL);
+                             do_spec_1 (multilib_dir, 1, NULL);
                              /* Make this a separate argument.  */
-                             do_spec_1 (" ", 0, NULL_PTR);
+                             do_spec_1 (" ", 0, NULL);
                            }
                        }
                      if (!pl->require_machine_suffix)
                        {
                          if (is_directory (pl->prefix, multilib_dir, 1))
                            {
-                             do_spec_1 ("-L", 0, NULL_PTR);
+                             do_spec_1 ("-L", 0, NULL);
 #ifdef SPACE_AFTER_L_OPTION
-                             do_spec_1 (" ", 0, NULL_PTR);
+                             do_spec_1 (" ", 0, NULL);
 #endif
-                             do_spec_1 (pl->prefix, 1, NULL_PTR);
-                             do_spec_1 (multilib_dir, 1, NULL_PTR);
+                             do_spec_1 (pl->prefix, 1, NULL);
+                             do_spec_1 (multilib_dir, 1, NULL);
                              /* Make this a separate argument.  */
-                             do_spec_1 (" ", 0, NULL_PTR);
+                             do_spec_1 (" ", 0, NULL);
                            }
                        }
                    }
@@ -4083,11 +4401,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                    {
                      if (is_directory (pl->prefix, machine_suffix, 1))
                        {
-                         do_spec_1 ("-L", 0, NULL_PTR);
+                         do_spec_1 ("-L", 0, NULL);
 #ifdef SPACE_AFTER_L_OPTION
-                         do_spec_1 (" ", 0, NULL_PTR);
+                         do_spec_1 (" ", 0, NULL);
 #endif
-                         do_spec_1 (pl->prefix, 1, NULL_PTR);
+                         do_spec_1 (pl->prefix, 1, NULL);
                          /* Remove slash from machine_suffix.  */
                          if (strlen (machine_suffix) >= bufsize)
                            bufsize = strlen (machine_suffix) * 2 + 1;
@@ -4096,18 +4414,18 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                          idx = strlen (buffer);
                          if (IS_DIR_SEPARATOR (buffer[idx - 1]))
                            buffer[idx - 1] = 0;
-                         do_spec_1 (buffer, 1, NULL_PTR);
+                         do_spec_1 (buffer, 1, NULL);
                          /* Make this a separate argument.  */
-                         do_spec_1 (" ", 0, NULL_PTR);
+                         do_spec_1 (" ", 0, NULL);
                        }
                    }
                  if (!pl->require_machine_suffix)
                    {
                      if (is_directory (pl->prefix, "", 1))
                        {
-                         do_spec_1 ("-L", 0, NULL_PTR);
+                         do_spec_1 ("-L", 0, NULL);
 #ifdef SPACE_AFTER_L_OPTION
-                         do_spec_1 (" ", 0, NULL_PTR);
+                         do_spec_1 (" ", 0, NULL);
 #endif
                          /* Remove slash from pl->prefix.  */
                          if (strlen (pl->prefix) >= bufsize)
@@ -4117,9 +4435,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                          idx = strlen (buffer);
                          if (IS_DIR_SEPARATOR (buffer[idx - 1]))
                            buffer[idx - 1] = 0;
-                         do_spec_1 (buffer, 1, NULL_PTR);
+                         do_spec_1 (buffer, 1, NULL);
                          /* Make this a separate argument.  */
-                         do_spec_1 (" ", 0, NULL_PTR);
+                         do_spec_1 (" ", 0, NULL);
                        }
                    }
                }
@@ -4142,6 +4460,21 @@ 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':
            {
@@ -4166,12 +4499,6 @@ do_spec_1 (spec, inswitch, soft_matched_part)
          case 'g':
          case 'u':
          case 'U':
-           if (save_temps_flag)
-             {
-               obstack_grow (&obstack, input_basename, basename_length);
-               delete_this_arg = 0;
-             }
-           else
              {
                struct temp_name *t;
                int suffix_length;
@@ -4188,17 +4515,65 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                    if (*p == '.' || ISALPHA ((unsigned char) *p))
                      abort ();
                    if (suffix_length == 0)
-                     suffix = OBJECT_SUFFIX;
+                     suffix = TARGET_OBJECT_SUFFIX;
                    else
                      {
                        saved_suffix
                          = (char *) xmalloc (suffix_length
-                                             + strlen (OBJECT_SUFFIX));
+                                             + strlen (TARGET_OBJECT_SUFFIX));
                        strncpy (saved_suffix, suffix, suffix_length);
                        strcpy (saved_suffix + suffix_length,
-                               OBJECT_SUFFIX);
+                               TARGET_OBJECT_SUFFIX);
+                     }
+                   suffix_length += strlen (TARGET_OBJECT_SUFFIX);
+                 }
+               
+               /* If the input_filename has the same suffix specified
+                  for the %g, %u, or %U, and -save-temps is specified,
+                  we could end up using that file as an intermediate
+                  thus clobbering the user's source file (.e.g.,
+                  gcc -save-temps foo.s would clobber foo.s with the
+                  output of cpp0).  So check for this condition and
+                  generate a temp file as the intermediate.  */
+                  
+               if (save_temps_flag)
+                 {
+                   temp_filename_length = basename_length + suffix_length;
+                   temp_filename = alloca (temp_filename_length + 1);
+                   strncpy ((char *) temp_filename, input_basename, basename_length);
+                   strncpy ((char *) temp_filename + basename_length, suffix,
+                            suffix_length);
+                   *((char *) temp_filename + temp_filename_length) = '\0';
+                   if (strcmp (temp_filename, input_filename) != 0)
+                     {
+                       struct stat st_temp;
+                       
+                       /* Note, set_input() resets input_stat_set to 0.  */
+                       if (input_stat_set == 0)
+                         {
+                           input_stat_set = stat (input_filename, &input_stat);
+                           if (input_stat_set >= 0)
+                             input_stat_set = 1;
+                         }
+                         
+                       /* If we have the stat for the input_filename
+                          and we can do the stat for the temp_filename
+                          then the they could still refer to the same
+                          file if st_dev/st_ino's are the same.  */
+                       
+                       if (input_stat_set != 1
+                           || stat (temp_filename, &st_temp) < 0
+                           || input_stat.st_dev != st_temp.st_dev
+                           || input_stat.st_ino != st_temp.st_ino)
+                         {
+                           temp_filename = save_string (temp_filename,
+                                                        temp_filename_length + 1);
+                           obstack_grow (&obstack, temp_filename,
+                                                   temp_filename_length);
+                           arg_going = 1;
+                           break;
+                         }
                      }
-                   suffix_length += strlen (OBJECT_SUFFIX);
                  }
 
                /* See if we already have an association of %g/%u/%U and
@@ -4209,7 +4584,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      && t->unique == (c != 'g'))
                    break;
 
-               /* Make a new association if needed.  %u and %j require one.  */
+               /* Make a new association if needed.  %u and %j
+                  require one.  */
                if (t == 0 || c == 'u' || c == 'j')
                  {
                    if (t == 0)
@@ -4219,7 +4595,13 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        temp_names = t;
                      }
                    t->length = suffix_length;
-                   t->suffix = save_string (suffix, suffix_length);
+                   if (saved_suffix)
+                     {
+                       t->suffix = saved_suffix;
+                       saved_suffix = NULL;
+                     }
+                   else
+                     t->suffix = save_string (suffix, suffix_length);
                    t->unique = (c != 'g');
                    temp_filename = make_temp_file (t->suffix);
                    temp_filename_length = strlen (temp_filename);
@@ -4247,20 +4629,20 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              if (gcc_exec_prefix)
                {
-                 do_spec_1 ("-iprefix", 1, NULL_PTR);
+                 do_spec_1 ("-iprefix", 1, NULL);
                  /* Make this a separate argument.  */
-                 do_spec_1 (" ", 0, NULL_PTR);
-                 do_spec_1 (gcc_exec_prefix, 1, NULL_PTR);
-                 do_spec_1 (" ", 0, NULL_PTR);
+                 do_spec_1 (" ", 0, NULL);
+                 do_spec_1 (gcc_exec_prefix, 1, NULL);
+                 do_spec_1 (" ", 0, NULL);
                }
 
              for (; pl; pl = pl->next)
                {
-                 do_spec_1 ("-isystem", 1, NULL_PTR);
+                 do_spec_1 ("-isystem", 1, NULL);
                  /* Make this a separate argument.  */
-                 do_spec_1 (" ", 0, NULL_PTR);
-                 do_spec_1 (pl->prefix, 1, NULL_PTR);
-                 do_spec_1 (" ", 0, NULL_PTR);
+                 do_spec_1 (" ", 0, NULL);
+                 do_spec_1 (pl->prefix, 1, NULL);
+                 do_spec_1 (" ", 0, NULL);
                }
            }
            break;
@@ -4277,7 +4659,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            }
 
          case 'O':
-           obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
+           obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
            arg_going = 1;
            break;
 
@@ -4335,9 +4717,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
          case 'X':
            for (i = 0; i < n_linker_options; i++)
              {
-               do_spec_1 (linker_options[i], 1, NULL_PTR);
+               do_spec_1 (linker_options[i], 1, NULL);
                /* Make each accumulated option a separate argument.  */
-               do_spec_1 (" ", 0, NULL_PTR);
+               do_spec_1 (" ", 0, NULL);
              }
            break;
 
@@ -4345,9 +4727,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
          case 'Y':
            for (i = 0; i < n_assembler_options; i++)
              {
-               do_spec_1 (assembler_options[i], 1, NULL_PTR);
+               do_spec_1 (assembler_options[i], 1, NULL);
                /* Make each accumulated option a separate argument.  */
-               do_spec_1 (" ", 0, NULL_PTR);
+               do_spec_1 (" ", 0, NULL);
              }
            break;
 
@@ -4355,9 +4737,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
          case 'Z':
            for (i = 0; i < n_preprocessor_options; i++)
              {
-               do_spec_1 (preprocessor_options[i], 1, NULL_PTR);
+               do_spec_1 (preprocessor_options[i], 1, NULL);
                /* Make each accumulated option a separate argument.  */
-               do_spec_1 (" ", 0, NULL_PTR);
+               do_spec_1 (" ", 0, NULL);
              }
            break;
 
@@ -4365,61 +4747,61 @@ do_spec_1 (spec, inswitch, soft_matched_part)
               a certain constant string as a spec.  */
 
          case '1':
-           value = do_spec_1 (cc1_spec, 0, NULL_PTR);
+           value = do_spec_1 (cc1_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case '2':
-           value = do_spec_1 (cc1plus_spec, 0, NULL_PTR);
+           value = do_spec_1 (cc1plus_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case 'a':
-           value = do_spec_1 (asm_spec, 0, NULL_PTR);
+           value = do_spec_1 (asm_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case 'A':
-           value = do_spec_1 (asm_final_spec, 0, NULL_PTR);
-           if (value != 0)
-             return value;
-           break;
-
-         case 'c':
-           value = do_spec_1 (signed_char_spec, 0, NULL_PTR);
+           value = do_spec_1 (asm_final_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case 'C':
-           value = do_spec_1 (cpp_spec, 0, NULL_PTR);
-           if (value != 0)
-             return value;
+           {
+             const char *const spec
+               = (input_file_compiler->cpp_spec 
+                  ? input_file_compiler->cpp_spec 
+                  : cpp_spec);
+             value = do_spec_1 (spec, 0, NULL);
+             if (value != 0)
+               return value;
+           }
            break;
 
          case 'E':
-           value = do_spec_1 (endfile_spec, 0, NULL_PTR);
+           value = do_spec_1 (endfile_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case 'l':
-           value = do_spec_1 (link_spec, 0, NULL_PTR);
+           value = do_spec_1 (link_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case 'L':
-           value = do_spec_1 (lib_spec, 0, NULL_PTR);
+           value = do_spec_1 (lib_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
 
          case 'G':
-           value = do_spec_1 (libgcc_spec, 0, NULL_PTR);
+           value = do_spec_1 (libgcc_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
@@ -4433,7 +4815,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
                len = strlen (multilib_dir);
                obstack_blank (&obstack, len + 1);
-               p = obstack_next_free (&obstack) - len;
+               p = obstack_next_free (&obstack) - (len + 1);
 
                *p++ = '_';
                for (q = multilib_dir; *q ; ++q, ++p)
@@ -4465,7 +4847,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              *x = 0;
 
-             value = do_spec_1 (buf, 0, NULL_PTR);
+             value = do_spec_1 (buf, 0, NULL);
              if (value != 0)
                return value;
            }
@@ -4596,14 +4978,14 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              *x = 0;
 
-             value = do_spec_1 (buf, 0, NULL_PTR);
+             value = do_spec_1 (buf, 0, NULL);
              if (value != 0)
                return value;
            }
            break;
 
          case 'S':
-           value = do_spec_1 (startfile_spec, 0, NULL_PTR);
+           value = do_spec_1 (startfile_spec, 0, NULL);
            if (value != 0)
              return value;
            break;
@@ -4620,17 +5002,28 @@ 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)
              {
-               do_spec_1 (soft_matched_part, 1, NULL_PTR);
-               do_spec_1 (" ", 0, NULL_PTR);
+               do_spec_1 (soft_matched_part, 1, NULL);
+               do_spec_1 (" ", 0, NULL);
              }
            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");
+             error ("spec failure: '%%*' has not been initialized by pattern match");
            break;
 
            /* Process a string found as the value of a spec given by name.
@@ -4639,7 +5032,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
               %[...] modifies -D options the way %P does;
               %(...) uses the spec unmodified.  */
          case '[':
-           error ("Warning: use of obsolete %%[ operator in specs");
+           error ("warning: use of obsolete %%[ operator in specs");
          case '(':
            {
              const char *name = p;
@@ -4667,7 +5060,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                {
                  if (c == '(')
                    {
-                     value = do_spec_1 (name, 0, NULL_PTR);
+                     value = do_spec_1 (name, 0, NULL);
                      if (value != 0)
                        return value;
                    }
@@ -4707,7 +5100,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        }
                      *x = 0;
 
-                     value = do_spec_1 (buf, 0, NULL_PTR);
+                     value = do_spec_1 (buf, 0, NULL);
                      if (value != 0)
                        return value;
                    }
@@ -4778,11 +5171,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
          case '|':
            if (input_from_pipe)
-             do_spec_1 ("-", 0, NULL_PTR);
+             do_spec_1 ("-", 0, NULL);
            break;
 
          default:
-           error ("Spec failure: Unrecognised spec option '%c'", c);
+           error ("spec failure: unrecognized spec option '%c'", c);
            break;
          }
        break;
@@ -4806,7 +5199,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
 static const char *
 handle_braces (p)
-     register const char *p;
+     const char *p;
 {
   const char *filter, *body = NULL, *endbody = NULL;
   int pipe_p = 0;
@@ -4878,8 +5271,8 @@ next_member:
     {
       if (*p != '}' && *p != '&')
        {
-         register int count = 1;
-         register const char *q = p;
+         int count = 1;
+         const char *q = p;
 
          while (*q++ != ':')
            continue;
@@ -4892,7 +5285,7 @@ next_member:
              else if (*q == '}')
                count--;
              else if (*q == 0)
-               abort ();
+               fatal ("mismatched braces in specs");
              q++;
            }
          endbody = q;
@@ -4911,13 +5304,13 @@ next_member:
        abort ();
 
       if (negate != found
-         && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
+         && do_spec_1 (save_string (body, endbody-body-1), 0, NULL) < 0)
        return 0;
     }
   else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&'))
     {
       /* Substitute all matching switches as separate args.  */
-      register int i;
+      int i;
 
       for (i = 0; i < n_switches; i++)
        if (!strncmp (switches[i].part1, filter, p - 1 - filter)
@@ -4935,7 +5328,7 @@ next_member:
   else
     {
       /* Test for presence of the specified switch.  */
-      register int i;
+      int i;
       int present = 0;
 
       /* If name specified ends in *, as in {x*:...},
@@ -4970,6 +5363,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.  */
@@ -5032,7 +5426,7 @@ next_member:
        {
          /* Here if a %{|...} conditional fails: output a minus sign,
             which means "standard output" or "standard input".  */
-         do_spec_1 ("-", 0, NULL_PTR);
+         do_spec_1 ("-", 0, NULL);
          return endbody;
        }
     }
@@ -5063,7 +5457,7 @@ next_member:
   else if (true_once)
     {
       if (do_spec_1 (save_string (body, endbody - body - 1),
-                    0, NULL_PTR) < 0)
+                    0, NULL) < 0)
        return 0;
     }
 
@@ -5168,8 +5562,8 @@ give_switch (switchnum, omit_first_word, include_blanks)
 
   if (!omit_first_word)
     {
-      do_spec_1 ("-", 0, NULL_PTR);
-      do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
+      do_spec_1 ("-", 0, NULL);
+      do_spec_1 (switches[switchnum].part1, 1, NULL);
     }
 
   if (switches[switchnum].args != 0)
@@ -5177,13 +5571,33 @@ 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);
+           do_spec_1 (" ", 0, NULL);
+         if (suffix_subst)
+           {
+             unsigned length = strlen (arg);
+             int dot = 0;
+
+             while (length-- && !IS_DIR_SEPARATOR (arg[length]))
+               if (arg[length] == '.')
+                 {
+                   ((char *)arg)[length] = 0;
+                   dot = 1;
+                   break;
+                 }
+             do_spec_1 (arg, 1, NULL);
+             if (dot)
+               ((char *)arg)[length] = '.';
+             do_spec_1 (suffix_subst, 1, NULL);
+           }
+         else
+           do_spec_1 (arg, 1, NULL);
        }
     }
 
-  do_spec_1 (" ", 0, NULL_PTR);
+  do_spec_1 (" ", 0, NULL);
   switches[switchnum].validated = 1;
 }
 \f
@@ -5200,12 +5614,7 @@ find_file (name)
   /* Try multilib_dir if it is defined.  */
   if (multilib_dir != NULL)
     {
-      char *try;
-
-      try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2);
-      strcpy (try, multilib_dir);
-      strcat (try, dir_separator_str);
-      strcat (try, name);
+      const char *const try = ACONCAT ((multilib_dir, dir_separator_str, name, NULL));
 
       newname = find_a_file (&startfile_prefixes, try, R_OK);
 
@@ -5256,11 +5665,11 @@ is_directory (path1, path2, linker)
   if (linker
       && ((cp - path == 6
           && strcmp (path, concat (dir_separator_str, "lib",
-                                   dir_separator_str, ".", NULL_PTR)) == 0)
+                                   dir_separator_str, ".", NULL)) == 0)
          || (cp - path == 10
              && strcmp (path, concat (dir_separator_str, "usr",
                                       dir_separator_str, "lib",
-                                      dir_separator_str, ".", NULL_PTR)) == 0)))
+                                      dir_separator_str, ".", NULL)) == 0)))
     return 0;
 
   return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
@@ -5269,11 +5678,11 @@ is_directory (path1, path2, linker)
 /* Set up the various global variables to indicate that we're processing
    the input file named FILENAME.  */
 
-static void
+void
 set_input (filename)
      const char *filename;
 {
-  register const char *p;
+  const char *p;
 
   input_filename = filename;
   input_filename_length = strlen (input_filename);
@@ -5302,6 +5711,11 @@ set_input (filename)
     }
   else
     input_suffix = "";
+  
+  /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
+     we will need to do a stat on the input_filename.  The
+     INPUT_STAT_SET signals that the stat is needed.  */
+  input_stat_set = 0;
 }
 \f
 /* On fatal signals, delete all the temporary files.  */
@@ -5341,22 +5755,11 @@ main (argc, argv)
   xmalloc_set_program_name (programname);
 
 #ifdef GCC_DRIVER_HOST_INITIALIZATION
-  /* Perform host dependant initialization when needed.  */
+  /* Perform host dependent 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);
+  gcc_init_libintl ();
 
   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
     signal (SIGINT, fatal_error);
@@ -5370,6 +5773,11 @@ main (argc, argv)
   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
     signal (SIGPIPE, fatal_error);
 #endif
+#ifdef SIGCHLD
+  /* 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);
+#endif
 
   argbuf_length = 10;
   argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
@@ -5437,52 +5845,6 @@ main (argc, argv)
 
   process_command (argc, argv);
 
-  {
-    int first_time;
-
-    /* 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);
-
-    first_time = TRUE;
-    for (i = 0; (int) i < n_switches; i++)
-      {
-       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 = 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 = 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);
-         }
-      }
-    obstack_grow (&collect_obstack, "\0", 1);
-    putenv (obstack_finish (&collect_obstack));
-  }
-
   /* Initialize the vector of specs to just the default.
      This means one element containing 0s, as a terminator.  */
 
@@ -5494,8 +5856,8 @@ main (argc, argv)
   /* Read specs from a file if there is one.  */
 
   machine_suffix = concat (spec_machine, dir_separator_str,
-                          spec_version, dir_separator_str, NULL_PTR);
-  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL_PTR);
+                          spec_version, dir_separator_str, NULL);
+  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
 
   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
   /* Read the specs file unless it is a default one.  */
@@ -5522,18 +5884,18 @@ main (argc, argv)
       if (*md_exec_prefix)
        {
          add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
-                     PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                     PREFIX_PRIORITY_LAST, 0, NULL);
          add_prefix (&startfile_prefixes, md_exec_prefix, "GCC",
-                     PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                     PREFIX_PRIORITY_LAST, 0, NULL);
        }
 
       if (*md_startfile_prefix)
        add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
-                   PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                   PREFIX_PRIORITY_LAST, 0, NULL);
 
       if (*md_startfile_prefix_1)
        add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
-                   PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                   PREFIX_PRIORITY_LAST, 0, NULL);
 
       /* If standard_startfile_prefix is relative, base it on
         standard_exec_prefix.  This lets us move the installed tree
@@ -5541,28 +5903,28 @@ main (argc, argv)
         standard_startfile_prefix on that as well.  */
       if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix))
        add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
-                   PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                   PREFIX_PRIORITY_LAST, 0, NULL);
       else
        {
          if (gcc_exec_prefix)
            add_prefix (&startfile_prefixes,
                        concat (gcc_exec_prefix, machine_suffix,
-                               standard_startfile_prefix, NULL_PTR),
-                       NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                               standard_startfile_prefix, NULL),
+                       NULL, PREFIX_PRIORITY_LAST, 0, NULL);
          add_prefix (&startfile_prefixes,
                      concat (standard_exec_prefix,
                              machine_suffix,
-                             standard_startfile_prefix, NULL_PTR),
-                     NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                             standard_startfile_prefix, NULL),
+                     NULL, PREFIX_PRIORITY_LAST, 0, NULL);
        }
 
       add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
-                 "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                 "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL);
       add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
-                 "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                 "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL);
 #if 0 /* Can cause surprises, and one can use -B./ instead.  */
-      add_prefix (&startfile_prefixes, "./", NULL_PTR,
-                 PREFIX_PRIORITY_LAST, 1, NULL_PTR);
+      add_prefix (&startfile_prefixes, "./", NULL,
+                 PREFIX_PRIORITY_LAST, 1, NULL);
 #endif
     }
   else
@@ -5571,8 +5933,8 @@ main (argc, argv)
          && gcc_exec_prefix)
        add_prefix (&startfile_prefixes,
                    concat (gcc_exec_prefix, machine_suffix,
-                           standard_startfile_prefix, NULL_PTR),
-                   "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR);
+                           standard_startfile_prefix, NULL),
+                   "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL);
     }
 
   /* Process any user specified specs in the order given on the command
@@ -5585,17 +5947,8 @@ 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);
-      strcpy (temp, gcc_exec_prefix);
-      strcat (temp, spec_machine);
-      strcat (temp, dir_separator_str);
-      strcat (temp, spec_version);
-      strcat (temp, dir_separator_str);
-      gcc_exec_prefix = temp;
-    }
+    gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
+                             spec_version, dir_separator_str, NULL);
 
   /* Now we have the specs.
      Set the `valid' bits for switches that match anything in any spec.  */
@@ -5652,12 +6005,12 @@ main (argc, argv)
 
   if (target_help_flag)
    {
-      /* Print if any target specific options.*/
+      /* 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. */
+         switch.  */
     }
 
   if (print_help_list)
@@ -5674,15 +6027,30 @@ main (argc, argv)
 
       /* We do not exit here.  Instead we have created a fake input file
         called 'help-dummy' which needs to be compiled, and we pass this
-        on the the various sub-processes, along with the --help switch.  */
+        on the various sub-processes, along with the --help switch.  */
     }
 
   if (verbose_flag)
     {
       int n;
+      const char *thrmod;
 
       notice ("Configured with: %s\n", configuration_arguments);
 
+#ifdef THREAD_MODEL_SPEC
+      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+        but there's no point in doing all this processing just to get
+        thread_model back.  */
+      obstack_init (&obstack);
+      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+      obstack_1grow (&obstack, '\0');
+      thrmod = obstack_finish (&obstack);
+#else
+      thrmod = thread_model;
+#endif
+
+      notice ("Thread model: %s\n", thrmod);
+
       /* compiler_version is truncated at the first space when initialized
         from version string, so truncate version_string at the first space
         before comparing.  */
@@ -5702,7 +6070,7 @@ main (argc, argv)
     }
 
   if (n_infiles == added_libraries)
-    fatal ("No input files");
+    fatal ("no input files");
 
   /* Make a place to record the compiler output file names
      that correspond to the input files.  */
@@ -5717,7 +6085,6 @@ main (argc, argv)
 
   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.  */
@@ -5731,19 +6098,26 @@ 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.  */
 
-         if (cp->spec[0] == '#')
-           error ("%s: %s compiler not installed on this system",
-                  input_filename, &cp->spec[1]);
-         value = do_spec (cp->spec);
-         if (value < 0)
-           this_file_error = 1;
+         if (input_file_compiler->spec[0] == '#')
+           {
+             error ("%s: %s compiler not installed on this system",
+                    input_filename, &input_file_compiler->spec[1]);
+             this_file_error = 1;
+           }
+         else
+           {
+             value = do_spec (input_file_compiler->spec);
+             if (value < 0)
+               this_file_error = 1;
+           }
        }
 
       /* If this file's name does not contain a recognized suffix,
@@ -5897,7 +6271,7 @@ lookup_compiler (name, length, language)
       /* 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 lookup_compiler (NULL, 0, cp->spec + 1);
     }
   return 0;
 }
@@ -5907,14 +6281,14 @@ save_string (s, len)
      const char *s;
      int len;
 {
-  register char *result = xmalloc (len + 1);
+  char *result = xmalloc (len + 1);
 
   memcpy (result, s, len);
   result[len] = 0;
   return result;
 }
 
-static void
+void
 pfatal_with_name (name)
      const char *name;
 {
@@ -5955,7 +6329,7 @@ pfatal_pexecute (errmsg_fmt, errmsg_arg)
 void
 fancy_abort ()
 {
-  fatal ("Internal gcc abort.");
+  fatal ("internal gcc abort");
 }
 \f
 /* Output an error message and exit */
@@ -5963,42 +6337,26 @@ fancy_abort ()
 void
 fatal VPARAMS ((const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   fprintf (stderr, "%s: ", programname);
   vfprintf (stderr, _(msgid), ap);
-  va_end (ap);
+  VA_CLOSE (ap);
   fprintf (stderr, "\n");
   delete_temp_files ();
   exit (1);
 }
 
-static void
+void
 error VPARAMS ((const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   fprintf (stderr, "%s: ", programname);
   vfprintf (stderr, _(msgid), ap);
-  va_end (ap);
+  VA_CLOSE (ap);
 
   fprintf (stderr, "\n");
 }
@@ -6006,27 +6364,19 @@ error VPARAMS ((const char *msgid, ...))
 static void
 notice VPARAMS ((const char *msgid, ...))
 {
-#ifndef ANSI_PROTOTYPES
-  const char *msgid;
-#endif
-  va_list ap;
-
-  VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
-  msgid = va_arg (ap, const char *);
-#endif
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, const char *, msgid);
 
   vfprintf (stderr, _(msgid), ap);
-  va_end (ap);
+  VA_CLOSE (ap);
 }
 \f
 static void
 validate_all_switches ()
 {
   struct compiler *comp;
-  register const char *p;
-  register char c;
+  const char *p;
+  char c;
   struct spec_list *spec;
 
   for (comp = compilers; comp->spec; comp++)
@@ -6062,9 +6412,9 @@ static void
 validate_switches (start)
      const char *start;
 {
-  register const char *p = start;
+  const char *p = start;
   const char *filter;
-  register int i;
+  int i;
   int suffix;
 
   if (*p == '|')