OSDN Git Service

2009-04-13 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index f2a7d1b..de429f8 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,13 +1,13 @@
 /* Compiler driver program that can handle many languages.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,12 +16,8 @@ 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 GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
-
-This paragraph is here to try to keep Sun CC from dying.
-The number of chars here seems crucial!!!!  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This program is the user interface to the C compiler and possibly to
 other compilers.  It is used because compilation is a complicated procedure
@@ -127,6 +123,9 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
 /* Flag set by cppspec.c to 1.  */
 int is_cpp_driver;
 
+/* Flag set to nonzero if an @file argument has been supplied to gcc.  */
+static bool at_file_supplied;
+
 /* Flag saying to pass the greatest exit code returned by a sub-process
    to the calling program.  */
 static int pass_exit_codes;
@@ -153,6 +152,8 @@ static const char *print_prog_name = NULL;
 
 static int print_multi_directory;
 
+static int print_sysroot;
+
 /* Flag saying to print the relative path we'd use to
    find OS libraries given the current compiler flags.  */
 
@@ -217,7 +218,15 @@ static const char *target_sysroot_hdrs_suffix = 0;
 /* Nonzero means write "temp" files in source directory
    and use the source file's name in them, and don't delete them.  */
 
-static int save_temps_flag;
+static enum save_temps {
+  SAVE_TEMPS_NONE,             /* no -save-temps */
+  SAVE_TEMPS_CWD,              /* -save-temps in current directory */
+  SAVE_TEMPS_OBJ               /* -save-temps in object directory */
+} save_temps_flag;
+
+/* Output file to use to get the object directory for -save-temps=obj  */
+static char *save_temps_prefix = 0;
+static size_t save_temps_length = 0;
 
 /* Nonzero means pass multiple source files to the compiler at one time.  */
 
@@ -283,18 +292,28 @@ static struct obstack obstack;
 
 static struct obstack collect_obstack;
 
+/* This is a list of a wrapper program and its arguments.
+   e.g. wrapper_string of "strace,-c"
+   will cause all programs to run as
+       strace -c program arguments
+   instead of just
+       program arguments */
+static const char  *wrapper_string;
+
 /* Forward declaration for prototypes.  */
 struct path_prefix;
 struct prefix_list;
 
 static void init_spec (void);
 static void store_arg (const char *, int, int);
+static void insert_wrapper (const char *);
 static char *load_specs (const char *);
 static void read_specs (const char *, int);
 static void set_spec (const char *, const char *);
 static struct compiler *lookup_compiler (const char *, size_t, const char *);
 static char *build_search_list (const struct path_prefix *, const char *,
                                bool, bool);
+static void xputenv (const char *);
 static void putenv_from_prefixes (const struct path_prefix *, const char *,
                                  bool);
 static int access_check (const char *, int);
@@ -361,6 +380,7 @@ static const char *if_exists_else_spec_function (int, const char **);
 static const char *replace_outfile_spec_function (int, const char **);
 static const char *version_compare_spec_function (int, const char **);
 static const char *include_spec_function (int, const char **);
+static const char *print_asm_header_spec_function (int, const char **);
 \f
 /* The Specs Language
 
@@ -381,7 +401,8 @@ or with constant text in a single argument.
  %i     substitute the name of the input file being processed.
  %b     substitute the basename of the input file being processed.
        This is the substring up to (and not including) the last period
-       and not including the directory.
+       and not including the directory unless -save-temps was specified
+       to put temporaries in a different location.     
  %B    same as %b, but include the file suffix (text after the last period).
  %gSUFFIX
        substitute a file name that has suffix SUFFIX and is chosen
@@ -424,7 +445,7 @@ or with constant text in a single argument.
         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
+       temporary file name, so that that file will be deleted if GCC exits
        successfully.  Unlike %g, this contributes no text to the argument.
  %w    marks the argument containing or following the %w as the
        "output file" of this compilation.  This puts the argument
@@ -493,12 +514,12 @@ or with constant text in a single argument.
        argument vector in the usual fashion.  The function returns
        a string which is processed as if it had appeared literally
        as part of the current spec.
- %{S}   substitutes the -S switch, if that switch was given to CC.
+ %{S}   substitutes the -S switch, if that switch was given to GCC.
        If that switch was not specified, this substitutes nothing.
        Here S is a metasyntactic variable.
- %{S*}  substitutes all the switches specified to CC whose names start
+ %{S*}  substitutes all the switches specified to GCC whose names start
        with -S.  This is used for -o, -I, etc; switches that take
-       arguments.  CC considers `-o foo' as being one switch whose
+       arguments.  GCC considers `-o foo' as being one switch whose
        name starts with `o'.  %{o*} would substitute this text,
        including the space; thus, two arguments would be generated.
  %{S*&T*} likewise, but preserve order of S and T options (the order
@@ -506,10 +527,10 @@ or with constant text in a single argument.
        of ampersand-separated variables; for each the wild card is
        optional.  Useful for CPP as %{D*&U*&A*}.
 
- %{S:X}   substitutes X, if the -S switch was given to CC.
- %{!S:X}  substitutes X, if the -S switch was NOT given to CC.
+ %{S:X}   substitutes X, if the -S switch was given to GCC.
+ %{!S:X}  substitutes X, if the -S switch was NOT given to GCC.
  %{S*:X}  substitutes X if one or more switches whose names start
-          with -S was given to CC.  Normally X is substituted only
+          with -S was given to GCC.  Normally X is substituted only
           once, no matter how many such switches appeared.  However,
           if %* appears somewhere in X, then X will be substituted
           once for each matching switch, with the %* replaced by the
@@ -519,13 +540,13 @@ or with constant text in a single argument.
  %{,S:X}  substitutes X, if processing a file which will use spec S.
  %{!,S:X} substitutes X, if NOT processing a file which will use spec S.
          
- %{S|T:X} substitutes X if either -S or -T was given to CC.  This may be
+ %{S|T:X} substitutes X if either -S or -T was given to GCC.  This may be
          combined with '!', '.', ',', and '*' as above binding stronger
          than the OR.
          If %* appears in X, all of the alternatives must be starred, and
          only the first matching alternative is substituted.
- %{S:X;   if S was given to CC, substitutes X;
-   T:Y;   else if T was given to CC, substitutes Y;
+ %{S:X;   if S was given to GCC, substitutes X;
+   T:Y;   else if T was given to GCC, substitutes Y;
     :D}   else substitutes D.  There can be as many clauses as you need.
           This may be combined with '.', '!', ',', '|', and '*' as above.
 
@@ -549,15 +570,15 @@ The character | at the beginning of the predicate text is used to indicate
 that a command should be piped to the following command, but only if -pipe
 is specified.
 
-Note that it is built into CC which switches take arguments and which
+Note that it is built into GCC which switches take arguments and which
 do not.  You might think it would be useful to generalize this to
 allow each compiler's spec to say which switches take arguments.  But
-this cannot be done in a consistent fashion.  CC cannot even decide
+this cannot be done in a consistent fashion.  GCC cannot even decide
 which input files have been specified without knowing which switches
 take arguments, and it must know which input files to compile in order
 to tell which compilers to run.
 
-CC also knows implicitly that arguments starting in `-l' are to be
+GCC 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
@@ -652,21 +673,27 @@ proper position among the other output files.  */
 #define LINKER_NAME "collect2"
 #endif
 
+#ifdef HAVE_AS_DEBUG_PREFIX_MAP
+#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
+#else
+#define ASM_MAP ""
+#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}}")
+#  define ASM_DEBUG_SPEC                                               \
+      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG                           \
+       ? "%{!g0:%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}}" ASM_MAP   \
+       : "%{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
 # else
 #  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
+#   define ASM_DEBUG_SPEC "%{g*:%{!g0:--gstabs}}" ASM_MAP
 #  endif
 #  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
-#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
+#   define ASM_DEBUG_SPEC "%{g*:%{!g0:--gdwarf2}}" ASM_MAP
 #  endif
 # endif
 #endif
@@ -711,7 +738,7 @@ proper position among the other output files.  */
     %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
     %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
     %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
-    %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
+    %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
     %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
     %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
@@ -784,7 +811,7 @@ static const char *cpp_unique_options =
  %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
  %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
  %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
- %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
+ %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
  %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\
  %{H} %C %{D*&U*&A*} %{i*} %Z %i\
  %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
@@ -798,14 +825,14 @@ static const char *cpp_unique_options =
    in turn cause preprocessor symbols to be defined specially.  */
 static const char *cpp_options =
 "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
- %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
- %{undef} %{save-temps:-fpch-preprocess}";
+ %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\
+ %{undef} %{save-temps*:-fpch-preprocess}";
 
 /* This contains cpp options which are not passed when the preprocessor
    output will be used by another program.  */
 static const char *cpp_debug_options = "%{d*}";
 
-/* NB: This is shared amongst all front-ends.  */
+/* NB: This is shared amongst all front-ends, except for Ada.  */
 static const char *cc1_options =
 "%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
  %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
@@ -821,6 +848,12 @@ static const char *cc1_options =
  %{coverage:-fprofile-arcs -ftest-coverage}";
 
 static const char *asm_options =
+"%{--target-help:%:print-asm-header()} "
+#if HAVE_GNU_AS
+/* If GNU AS is used, then convert -w (no warnings), -I, and -v
+   to the assembler equivalents.  */
+"%{v} %{w:-W} %{I*} "
+#endif
 "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
 
 static const char *invoke_as =
@@ -854,7 +887,7 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 /* Adding -fopenmp should imply pthreads.  This is particularly important
    for targets that use different start files and suchlike.  */
 #ifndef GOMP_SELF_SPECS
-#define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
+#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
 #endif
 
 static const char *const driver_self_specs[] = {
@@ -950,11 +983,14 @@ static const struct compiler default_compilers[] =
   {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
   {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
   {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
-  {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0},
-  {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
-  {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
-  {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0},
-  {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+  {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
+  {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
+  {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
+  {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
+  {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
+  {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+  {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
+  {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
   {".r", "#Ratfor", 0, 0, 0},
   {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
   {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
@@ -969,17 +1005,17 @@ static const struct compiler default_compilers[] =
           %{traditional|ftraditional:\
 %eGNU C no longer supports -traditional without -E}\
        %{!combine:\
-         %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
-               %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
-                   cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
+         %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+               %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+                   cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
                        %(cc1_options)}\
-         %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+         %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
                cc1 %(cpp_unique_options) %(cc1_options)}}}\
           %{!fsyntax-only:%(invoke_as)}} \
       %{combine:\
-         %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
-               %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\
-         %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+         %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+               %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i}}\
+         %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
                cc1 %(cpp_unique_options) %(cc1_options)}}\
                 %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
   {"-",
@@ -991,13 +1027,13 @@ static const struct compiler default_compilers[] =
       external preprocessor if -save-temps is given.  */
      "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
       %{!E:%{!M:%{!MM:\
-         %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
-               %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
-                   cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
+         %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+               %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+                   cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
                        %(cc1_options)\
                         -o %g.s %{!o*:--output-pch=%i.gch}\
                         %W{o*:--output-pch=%*}%V}\
-         %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+         %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
                cc1 %(cpp_unique_options) %(cc1_options)\
                     -o %g.s %{!o*:--output-pch=%i.gch}\
                     %W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0},
@@ -1007,15 +1043,16 @@ static const struct compiler default_compilers[] =
   {".s", "@assembler", 0, 1, 0},
   {"@assembler",
    "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
+  {".sx", "@assembler-with-cpp", 0, 1, 0},
   {".S", "@assembler-with-cpp", 0, 1, 0},
   {"@assembler-with-cpp",
 #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
-   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+   "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
       %{E|M|MM:%(cpp_debug_options)}\
       %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
        as %(asm_debug) %(asm_options) %|.s %A }}}}"
 #else
-   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+   "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
       %{E|M|MM:%(cpp_debug_options)}\
       %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
        as %(asm_debug) %(asm_options) %m.s %A }}}}"
@@ -1133,6 +1170,7 @@ static const struct option_map option_map[] =
    {"--print-multi-directory", "-print-multi-directory", 0},
    {"--print-multi-os-directory", "-print-multi-os-directory", 0},
    {"--print-prog-name", "-print-prog-name=", "aj"},
+   {"--print-sysroot", "-print-sysroot", 0},
    {"--print-sysroot-headers-suffix", "-print-sysroot-headers-suffix", 0},
    {"--profile", "-p", 0},
    {"--profile-blocks", "-a", 0},
@@ -1174,7 +1212,7 @@ static const struct {
 
 /* Translate the options described by *ARGCP and *ARGVP.
    Make a new vector and store it back in *ARGVP,
-   and store its length in *ARGVC.  */
+   and store its length in *ARGCP.  */
 
 static void
 translate_options (int *argcp, const char *const **argvp)
@@ -1183,7 +1221,7 @@ translate_options (int *argcp, const char *const **argvp)
   int argc = *argcp;
   const char *const *argv = *argvp;
   int newvsize = (argc + 2) * 2 * sizeof (const char *);
-  const char **newv = xmalloc (newvsize);
+  const char **newv = XNEWVAR (const char *, newvsize);
   int newindex = 0;
 
   i = 0;
@@ -1213,7 +1251,7 @@ translate_options (int *argcp, const char *const **argvp)
                }
 
              newvsize += spaces * sizeof (const char *);
-             newv =  xrealloc (newv, newvsize);
+             newv =  XRESIZEVAR (const char *, newv, newvsize);
 
              sp = target_option_translations[tott_idx].replacements;
              np = xstrdup (sp);
@@ -1617,6 +1655,7 @@ static const struct spec_function static_spec_functions[] =
   { "replace-outfile",         replace_outfile_spec_function },
   { "version-compare",         version_compare_spec_function },
   { "include",                 include_spec_function },
+  { "print-asm-header",                print_asm_header_spec_function },
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -1686,8 +1725,7 @@ init_spec (void)
     notice ("Using built-in specs.\n");
 
 #ifdef EXTRA_SPECS
-  extra_specs = xcalloc (sizeof (struct spec_list),
-                        ARRAY_SIZE (extra_specs_1));
+  extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
 
   for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
     {
@@ -1701,10 +1739,6 @@ init_spec (void)
     }
 #endif
 
-  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
-     on ?: in file-scope variable initializations.  */
-  asm_debug = ASM_DEBUG_SPEC;
-
   for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
     {
       sl = &static_specs[i];
@@ -1871,7 +1905,7 @@ set_spec (const char *name, const char *spec)
 
   /* Free the old spec.  */
   if (old_spec && sl->alloc_p)
-    free ((void *) old_spec);
+    free (CONST_CAST(char *, old_spec));
 
   sl->alloc_p = 1;
 }
@@ -1954,7 +1988,7 @@ static void
 store_arg (const char *arg, int delete_always, int delete_failure)
 {
   if (argbuf_index + 1 == argbuf_length)
-    argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
+    argbuf = XRESIZEVEC (const char *, argbuf, (argbuf_length *= 2));
 
   argbuf[argbuf_index++] = arg;
   argbuf[argbuf_index] = 0;
@@ -2176,7 +2210,7 @@ read_specs (const char *filename, int main_p)
 
              set_spec (p2, *(sl->ptr_spec));
              if (sl->alloc_p)
-               free ((void *) *(sl->ptr_spec));
+               free (CONST_CAST (char *, *(sl->ptr_spec)));
 
              *(sl->ptr_spec) = "";
              sl->alloc_p = 0;
@@ -2246,8 +2280,7 @@ read_specs (const char *filename, int main_p)
        {
          /* Add this pair to the vector.  */
          compilers
-           = xrealloc (compilers,
-                       (n_compilers + 2) * sizeof (struct compiler));
+           = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
 
          compilers[n_compilers].suffix = suffix;
          compilers[n_compilers].spec = spec;
@@ -2526,18 +2559,18 @@ for_each_path (const struct path_prefix *paths,
         Don't repeat any we have already seen.  */
       if (multi_dir)
        {
-         free ((char *) multi_dir);
+         free (CONST_CAST (char *, multi_dir));
          multi_dir = NULL;
-         free ((char *) multi_suffix);
+         free (CONST_CAST (char *, multi_suffix));
          multi_suffix = machine_suffix;
-         free ((char *) just_multi_suffix);
+         free (CONST_CAST (char *, just_multi_suffix));
          just_multi_suffix = just_machine_suffix;
        }
       else
        skip_multi_dir = true;
       if (multi_os_dir)
        {
-         free ((char *) multi_os_dir);
+         free (CONST_CAST (char *, multi_os_dir));
          multi_os_dir = NULL;
        }
       else
@@ -2546,12 +2579,12 @@ for_each_path (const struct path_prefix *paths,
 
   if (multi_dir)
     {
-      free ((char *) multi_dir);
-      free ((char *) multi_suffix);
-      free ((char *) just_multi_suffix);
+      free (CONST_CAST (char *, multi_dir));
+      free (CONST_CAST (char *, multi_suffix));
+      free (CONST_CAST (char *, just_multi_suffix));
     }
   if (multi_os_dir)
-    free ((char *) multi_os_dir);
+    free (CONST_CAST (char *, multi_os_dir));
   if (ret != path)
     free (path);
   return ret;
@@ -2568,7 +2601,7 @@ struct add_to_obstack_info {
 static void *
 add_to_obstack (char *path, void *data)
 {
-  struct add_to_obstack_info *info = data;
+  struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
 
   if (info->check_dir && !is_directory (path, false))
     return NULL;
@@ -2582,6 +2615,16 @@ add_to_obstack (char *path, void *data)
   return NULL;
 }
 
+/* Add or change the value of an environment variable, outputting the
+   change to standard error if in verbose mode.  */
+static void
+xputenv (const char *string)
+{
+  if (verbose_flag)
+    notice ("%s\n", string);
+  putenv (CONST_CAST (char *, string));
+}
+
 /* Build a list of search directories from PATHS.
    PREFIX is a string to prepend to the list.
    If CHECK_DIR_P is true we ensure the directory exists.
@@ -2616,7 +2659,7 @@ static void
 putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
                      bool do_multi)
 {
-  putenv (build_search_list (paths, env_var, true, do_multi));
+  xputenv (build_search_list (paths, env_var, true, do_multi));
 }
 \f
 /* Check whether NAME can be accessed in MODE.  This is like access,
@@ -2652,7 +2695,7 @@ struct file_at_path_info {
 static void *
 file_at_path (char *path, void *data)
 {
-  struct file_at_path_info *info = data;
+  struct file_at_path_info *info = (struct file_at_path_info *) data;
   size_t len = strlen (path);
 
   memcpy (path + len, info->name, info->name_len);
@@ -2711,8 +2754,9 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
   info.suffix_len = strlen (info.suffix);
   info.mode = mode;
 
-  return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len,
-                       file_at_path, &info);
+  return (char*) for_each_path (pprefix, do_multi,
+                               info.name_len + info.suffix_len,
+                               file_at_path, &info);
 }
 
 /* Ranking of prefixes in the sort list. -B prefixes are put before
@@ -2818,13 +2862,20 @@ execute (void)
 
   gcc_assert (!processing_spec_function);
 
+  if (wrapper_string)
+    {
+      string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false);
+      argbuf[0] = (string) ? string : argbuf[0];
+      insert_wrapper (wrapper_string);
+    }
+
   /* Count # of piped commands.  */
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
       n_commands++;
 
   /* Get storage for each command.  */
-  commands = alloca (n_commands * sizeof (struct command));
+  commands = (struct command *) alloca (n_commands * sizeof (struct command));
 
   /* Split argbuf into its separate piped processes,
      and record info about each one.
@@ -2832,10 +2883,12 @@ execute (void)
 
   commands[0].prog = argbuf[0]; /* first command.  */
   commands[0].argv = &argbuf[0];
-  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
-
-  if (string)
-    commands[0].argv[0] = string;
+  if (!wrapper_string)
+    {
+      string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
+      commands[0].argv[0] = (string) ? string : commands[0].argv[0];
+    }
 
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
@@ -2929,7 +2982,7 @@ execute (void)
       for (argc = 0; commands[i].argv[argc] != NULL; argc++)
        ;
 
-      argv = alloca ((argc + 3) * sizeof (char *));
+      argv = XALLOCAVEC (const char *, argc + 3);
 
       argv[0] = VALGRIND_PATH;
       argv[1] = "-q";
@@ -2958,7 +3011,7 @@ execute (void)
       errmsg = pex_run (pex,
                        ((i + 1 == n_commands ? PEX_LAST : 0)
                         | (string == commands[i].prog ? PEX_SEARCH : 0)),
-                       string, (char * const *) commands[i].argv,
+                       string, CONST_CAST (char **, commands[i].argv),
                        NULL, NULL, &err);
       if (errmsg != NULL)
        {
@@ -2972,7 +3025,7 @@ execute (void)
        }
 
       if (string != commands[i].prog)
-       free ((void *) string);
+       free (CONST_CAST (char *, string));
     }
 
   execution_count++;
@@ -2984,13 +3037,13 @@ execute (void)
     struct pex_time *times = NULL;
     int ret_code = 0;
 
-    statuses = alloca (n_commands * sizeof (int));
+    statuses = (int *) alloca (n_commands * sizeof (int));
     if (!pex_get_status (pex, n_commands, statuses))
       pfatal_with_name (_("failed to get exit status"));
 
     if (report_times)
       {
-       times = alloca (n_commands * sizeof (struct pex_time));
+       times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
        if (!pex_get_times (pex, n_commands, times))
          pfatal_with_name (_("failed to get process times"));
       }
@@ -3058,24 +3111,22 @@ See %s for instructions.",
    If a switch uses following arguments, then the `part1' field
    is the switch itself and the `args' field
    is a null-terminated vector containing the following arguments.
-   The `live_cond' field is:
-   0 when initialized
-   1 if the switch is true in a conditional spec,
-   -1 if false (overridden by a later switch)
-   -2 if this switch should be ignored (used in %<S)
+   Bits in the `live_cond' field are:
+   SWITCH_LIVE to indicate this switch is true in a conditional spec.
+   SWITCH_FALSE to indicate this switch is overridden by a later switch.
+   SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
    The `validated' field is nonzero if any spec has looked at this switch;
    if it remains zero at the end of the run, it must be meaningless.  */
 
-#define SWITCH_OK       0
-#define SWITCH_FALSE   -1
-#define SWITCH_IGNORE  -2
-#define SWITCH_LIVE     1
+#define SWITCH_LIVE    0x1
+#define SWITCH_FALSE   0x2
+#define SWITCH_IGNORE  0x4
 
 struct switchstr
 {
   const char *part1;
   const char **args;
-  int live_cond;
+  unsigned int live_cond;
   unsigned char validated;
   unsigned char ordering;
 };
@@ -3186,10 +3237,11 @@ display_help (void)
   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
   fputs (_("  --help                   Display this information\n"), stdout);
   fputs (_("  --target-help            Display target specific command line options\n"), stdout);
-  fputs (_("  --help={target|optimizers|warnings|undocumented|params}[,{[^]joined|[^]separate}]\n"), stdout);
+  fputs (_("  --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
   fputs (_("                           Display specific types of command line options\n"), stdout);
   if (! verbose_flag)
     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
+  fputs (_("  --version                Display compiler version information\n"), stdout);
   fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
   fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
   fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
@@ -3202,6 +3254,7 @@ display_help (void)
   -print-multi-lib         Display the mapping between command line options and\n\
                            multiple library search directories\n"), stdout);
   fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
+  fputs (_("  -print-sysroot           Display the target libraries directory\n"), stdout);
   fputs (_("  -print-sysroot-headers-suffix Display the sysroot suffix used to find headers\n"), stdout);
   fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
   fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
@@ -3211,6 +3264,7 @@ display_help (void)
   fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
   fputs (_("  -combine                 Pass multiple source files to compiler at once\n"), stdout);
   fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
+  fputs (_("  -save-temps=<arg>        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 built-in specs with the contents of <file>\n"), stdout);
@@ -3252,8 +3306,8 @@ add_preprocessor_option (const char *option, int len)
   if (! preprocessor_options)
     preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
   else
-    preprocessor_options = xrealloc (preprocessor_options,
-                                    n_preprocessor_options * sizeof (char *));
+    preprocessor_options = XRESIZEVEC (char *, preprocessor_options,
+                                      n_preprocessor_options);
 
   preprocessor_options [n_preprocessor_options - 1] =
     save_string (option, len);
@@ -3267,8 +3321,8 @@ add_assembler_option (const char *option, int len)
   if (! assembler_options)
     assembler_options = XNEWVEC (char *, n_assembler_options);
   else
-    assembler_options = xrealloc (assembler_options,
-                                 n_assembler_options * sizeof (char *));
+    assembler_options = XRESIZEVEC (char *, assembler_options,
+                                   n_assembler_options);
 
   assembler_options [n_assembler_options - 1] = save_string (option, len);
 }
@@ -3281,8 +3335,7 @@ add_linker_option (const char *option, int len)
   if (! linker_options)
     linker_options = XNEWVEC (char *, n_linker_options);
   else
-    linker_options = xrealloc (linker_options,
-                              n_linker_options * sizeof (char *));
+    linker_options = XRESIZEVEC (char *, linker_options, n_linker_options);  
 
   linker_options [n_linker_options - 1] = save_string (option, len);
 }
@@ -3329,8 +3382,10 @@ process_command (int argc, const char **argv)
      Use heuristic that all configuration names must have at least
      one dash '-'. This allows us to pass options starting with -b.  */
   if (argc > 1 && argv[1][0] == '-'
-      && (argv[1][1] == 'V' ||
-        ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
+      && (argv[1][1] == 'V'
+         || (argv[1][1] == 'b'
+             && (argv[1][2] == '\0'
+                 || NULL != strchr (argv[1] + 2, '-')))))
     {
       const char *new_version = DEFAULT_TARGET_VERSION;
       const char *new_machine = DEFAULT_TARGET_MACHINE;
@@ -3338,10 +3393,15 @@ process_command (int argc, const char **argv)
       char **new_argv;
       char *new_argv0;
       int baselen;
+      int status = 0;
+      int err = 0;
+      const char *errmsg;
 
       while (argc > 1 && argv[1][0] == '-'
-            && (argv[1][1] == 'V' ||
-               ((argv[1][1] == 'b') && ( NULL != strchr(argv[1] + 2,'-')))))
+            && (argv[1][1] == 'V'
+                || (argv[1][1] == 'b'
+                    && (argv[1][2] == '\0'
+                        || NULL != strchr (argv[1] + 2, '-')))))
        {
          char opt = argv[1][1];
          const char *arg;
@@ -3368,19 +3428,28 @@ process_command (int argc, const char **argv)
       for (baselen = strlen (progname); baselen > 0; baselen--)
        if (IS_DIR_SEPARATOR (progname[baselen-1]))
          break;
-      new_argv0 = xmemdup (progname, baselen,
+      new_argv0 = XDUPVAR (char, progname, baselen,
                           baselen + concat_length (new_version, new_machine,
                                                    "-gcc-", NULL) + 1);
       strcpy (new_argv0 + baselen, new_machine);
       strcat (new_argv0, "-gcc-");
       strcat (new_argv0, new_version);
 
-      new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
-                         (argc + 1) * sizeof (argv[0]));
+      new_argv = XDUPVEC (char *, argv, argc + 1);
       new_argv[0] = new_argv0;
 
-      execvp (new_argv0, new_argv);
-      fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno));
+      errmsg = pex_one (PEX_SEARCH, new_argv0, new_argv, progname, NULL,
+                       NULL, &status, &err);
+
+      if (errmsg)
+       {
+         if (err == 0)
+           fatal ("couldn't run '%s': %s", new_argv0, errmsg);
+         else
+           fatal ("couldn't run '%s': %s: %s", new_argv0, errmsg,
+                   xstrerror (err));
+        }
+      exit (status);
     }
 
   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
@@ -3397,7 +3466,7 @@ process_command (int argc, const char **argv)
                                                 standard_bindir_prefix,
                                                 standard_libexec_prefix);
       if (gcc_exec_prefix)
-       putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
+       xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
     }
   else
     {
@@ -3451,7 +3520,7 @@ process_command (int argc, const char **argv)
   if (temp)
     {
       const char *startp, *endp;
-      char *nstore = alloca (strlen (temp) + 3);
+      char *nstore = (char *) alloca (strlen (temp) + 3);
 
       startp = endp = temp;
       while (1)
@@ -3485,7 +3554,7 @@ process_command (int argc, const char **argv)
   if (temp && *cross_compile == '0')
     {
       const char *startp, *endp;
-      char *nstore = alloca (strlen (temp) + 3);
+      char *nstore = (char *) alloca (strlen (temp) + 3);
 
       startp = endp = temp;
       while (1)
@@ -3518,7 +3587,7 @@ process_command (int argc, const char **argv)
   if (temp && *cross_compile == '0')
     {
       const char *startp, *endp;
-      char *nstore = alloca (strlen (temp) + 3);
+      char *nstore = (char *) alloca (strlen (temp) + 3);
 
       startp = endp = temp;
       while (1)
@@ -3581,8 +3650,9 @@ process_command (int argc, const char **argv)
       else if (strcmp (argv[i], "-fversion") == 0)
        {
          /* translate_options () has turned --version into -fversion.  */
-         printf (_("%s (GCC) %s\n"), programname, version_string);
-         printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
+         printf (_("%s %s%s\n"), programname, pkgversion_string,
+                 version_string);
+         printf ("Copyright %s 2009 Free Software Foundation, Inc.\n",
                  _("(C)"));
          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"),
@@ -3645,6 +3715,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        print_multi_lib = 1;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        print_multi_directory = 1;
+      else if (! strcmp (argv[i], "-print-sysroot"))
+       print_sysroot = 1;
       else if (! strcmp (argv[i], "-print-multi-os-directory"))
        print_multi_os_directory = 1;
       else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
@@ -3727,8 +3799,19 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        n_infiles++;
       else if (strcmp (argv[i], "-save-temps") == 0)
        {
-         save_temps_flag = 1;
+         save_temps_flag = SAVE_TEMPS_CWD;
+         n_switches++;
+       }
+      else if (strncmp (argv[i], "-save-temps=", 12) == 0)
+       {
          n_switches++;
+         if (strcmp (argv[i]+12, "cwd") == 0)
+           save_temps_flag = SAVE_TEMPS_CWD;
+         else if (strcmp (argv[i]+12, "obj") == 0
+                  || strcmp (argv[i]+12, "object") == 0)
+           save_temps_flag = SAVE_TEMPS_OBJ;
+         else
+           fatal ("'%s' is an unknown -save-temps option", argv[i]);
        }
       else if (strcmp (argv[i], "-combine") == 0)
        {
@@ -3772,6 +3855,15 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          use_pipes = 1;
          n_switches++;
        }
+      else if (strcmp (argv[i], "-wrapper") == 0)
+        {
+         if (++i >= argc)
+           fatal ("argument to '-wrapper' is missing");
+
+          wrapper_string = argv[i];
+         n_switches++;
+         n_switches++;
+        }
       else if (strcmp (argv[i], "-###") == 0)
        {
          /* This is similar to -v except that there is no execution
@@ -3789,7 +3881,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          switch (c)
            {
            case 'b':
-             if (NULL == strchr(argv[i] + 2, '-'))
+             if (p[1] && NULL == strchr (argv[i] + 2, '-'))
                goto normal_switch;
 
              /* Fall through.  */
@@ -3894,6 +3986,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
              else
                argv[i] = convert_filename (argv[i], ! have_c, 0);
 #endif
+             /* Save the output name in case -save-temps=obj was used.  */
+             save_temps_prefix = xstrdup ((p[1] == 0) ? argv[i + 1] : argv[i] + 1);
              goto normal_switch;
 
            default:
@@ -3905,7 +3999,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
              for (j = 0; j < ARRAY_SIZE (modify_target); j++)
                if (! strcmp (argv[i], modify_target[j].sw))
                  {
-                   char *new_name = xmalloc (strlen (modify_target[j].str)
+                   char *new_name = XNEWVEC (char, strlen (modify_target[j].str)
                                              + strlen (spec_machine));
                    const char *p, *r;
                    char *q;
@@ -3951,6 +4045,25 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
     }
 
+  /* If -save-temps=obj and -o name, create the prefix to use for %b.
+     Otherwise just make -save-temps=obj the same as -save-temps=cwd.  */
+  if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
+    {
+      save_temps_length = strlen (save_temps_prefix);
+      temp = strrchr (lbasename (save_temps_prefix), '.');
+      if (temp)
+       {
+         save_temps_length -= strlen (temp);
+         save_temps_prefix[save_temps_length] = '\0';
+       }
+
+    }
+  else if (save_temps_prefix != NULL)
+    {
+      free (save_temps_prefix);
+      save_temps_prefix = NULL;
+    }
+
   if (save_temps_flag && use_pipes)
     {
       /* -save-temps overrides -pipe, so that temp files are produced */
@@ -4076,6 +4189,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        ;
       else if (! strcmp (argv[i], "-print-multi-directory"))
        ;
+      else if (! strcmp (argv[i], "-print-sysroot"))
+       ;
       else if (! strcmp (argv[i], "-print-multi-os-directory"))
        ;
       else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
@@ -4094,7 +4209,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
             -e0 or -e1 down into the linker.  */
          switches[n_switches].part1 = &argv[i][0];
          switches[n_switches].args = 0;
-         switches[n_switches].live_cond = SWITCH_OK;
+         switches[n_switches].live_cond = 0;
          switches[n_switches].validated = 0;
          n_switches++;
        }
@@ -4137,6 +4252,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[i];
        }
+      else if (strcmp (argv[i], "-wrapper") == 0)
+        i++;
       else if (strcmp (argv[i], "-specs") == 0)
        i++;
       else if (strncmp (argv[i], "-specs=", 7) == 0)
@@ -4205,14 +4322,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          else
            switches[n_switches].args = 0;
 
-         switches[n_switches].live_cond = SWITCH_OK;
+         switches[n_switches].live_cond = 0;
          switches[n_switches].validated = 0;
          switches[n_switches].ordering = 0;
-         /* These are always valid, since gcc.c itself understands them.  */
+         /* These are always valid, since gcc.c itself understands the
+            first four and gfortranspec.c understands -static-libgfortran.  */
          if (!strcmp (p, "save-temps")
              || !strcmp (p, "static-libgcc")
              || !strcmp (p, "shared-libgcc")
-             || !strcmp (p, "pipe"))
+             || !strcmp (p, "pipe")
+             || !strcmp (p, "static-libgfortran"))
            switches[n_switches].validated = 1;
          else
            {
@@ -4284,7 +4403,7 @@ set_collect_gcc_options (void)
       first_time = FALSE;
 
       /* Ignore elided switches.  */
-      if (switches[i].live_cond == SWITCH_IGNORE)
+      if ((switches[i].live_cond & SWITCH_IGNORE) != 0)
        continue;
 
       obstack_grow (&collect_obstack, "'-", 2);
@@ -4313,7 +4432,7 @@ set_collect_gcc_options (void)
        }
     }
   obstack_grow (&collect_obstack, "\0", 1);
-  putenv (XOBFINISH (&collect_obstack, char *));
+  xputenv (XOBFINISH (&collect_obstack, char *));
 }
 \f
 /* Process a spec string, accumulating and running commands.  */
@@ -4366,6 +4485,72 @@ static int input_from_pipe;
    arguments.  */
 static const char *suffix_subst;
 
+/* If there is an argument being accumulated, terminate it and store it.  */
+
+static void
+end_going_arg (void)
+{
+  if (arg_going)
+    {
+      const char *string;
+
+      obstack_1grow (&obstack, 0);
+      string = XOBFINISH (&obstack, const char *);
+      if (this_is_library_file)
+       string = find_file (string);
+      store_arg (string, delete_this_arg, this_is_output_file);
+      if (this_is_output_file)
+       outfiles[input_file_number] = string;
+      arg_going = 0;
+    }
+}
+
+
+/* Parse the WRAPPER string which is a comma separated list of the command line
+   and insert them into the beginning of argbuf.  */
+
+static void
+insert_wrapper (const char *wrapper)
+{
+  int n = 0;
+  int i;
+  char *buf = xstrdup (wrapper);
+  char *p = buf;
+
+  do
+    {
+      n++;
+      while (*p == ',')
+        p++;
+    }
+  while ((p = strchr (p, ',')) != NULL);
+
+  if (argbuf_index + n >= argbuf_length)
+    {
+      argbuf_length = argbuf_length * 2;
+      while (argbuf_length < argbuf_index + n)
+       argbuf_length *= 2;
+      argbuf = XRESIZEVEC (const char *, argbuf, argbuf_length);
+    }
+  for (i = argbuf_index - 1; i >= 0; i--)
+    argbuf[i + n] = argbuf[i];
+
+  i = 0;
+  p = buf;
+  do
+    {
+      while (*p == ',')
+        {
+          *p = 0;
+          p++;
+        }
+      argbuf[i++] = p;
+    }
+  while ((p = strchr (p, ',')) != NULL);
+  gcc_assert (i == n);
+  argbuf_index += n;
+}
+
 /* Process the spec SPEC and run the commands specified therein.
    Returns 0 if the spec is successfully processed; -1 if failed.  */
 
@@ -4395,7 +4580,6 @@ do_spec (const char *spec)
 static int
 do_spec_2 (const char *spec)
 {
-  const char *string;
   int result;
 
   clear_args ();
@@ -4408,18 +4592,7 @@ do_spec_2 (const char *spec)
 
   result = do_spec_1 (spec, 0, NULL);
 
-  /* End any pending argument.  */
-  if (arg_going)
-    {
-      obstack_1grow (&obstack, 0);
-      string = XOBFINISH (&obstack, const char *);
-      if (this_is_library_file)
-       string = find_file (string);
-      store_arg (string, delete_this_arg, this_is_output_file);
-      if (this_is_output_file)
-       outfiles[input_file_number] = string;
-      arg_going = 0;
-    }
+  end_going_arg ();
 
   return result;
 }
@@ -4457,7 +4630,7 @@ do_option_spec (const char *name, const char *spec)
     }
 
   /* Replace each %(VALUE) by the specified value.  */
-  tmp_spec = alloca (strlen (spec) + 1
+  tmp_spec = (char *) alloca (strlen (spec) + 1
                     + value_count * (value_len - strlen ("%(VALUE)")));
   tmp_spec_p = tmp_spec;
   q = spec;
@@ -4489,8 +4662,7 @@ do_self_spec (const char *spec)
 
       first = n_switches;
       n_switches += argbuf_index;
-      switches = xrealloc (switches,
-                          sizeof (struct switchstr) * (n_switches + 1));
+      switches = XRESIZEVEC (struct switchstr, switches, n_switches + 1);
 
       switches[n_switches] = switches[first];
       for (i = 0; i < argbuf_index; i++)
@@ -4504,7 +4676,7 @@ do_self_spec (const char *spec)
          sw = &switches[i + first];
          sw->part1 = &argbuf[i][1];
          sw->args = 0;
-         sw->live_cond = SWITCH_OK;
+         sw->live_cond = 0;
          sw->validated = 0;
          sw->ordering = 0;
        }
@@ -4524,7 +4696,7 @@ struct spec_path_info {
 static void *
 spec_path (char *path, void *data)
 {
-  struct spec_path_info *info = data;
+  struct spec_path_info *info = (struct spec_path_info *) data;
   size_t len = 0;
   char save = 0;
 
@@ -4580,7 +4752,6 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
   const char *p = spec;
   int c;
   int i;
-  const char *string;
   int value;
 
   while ((c = *p++))
@@ -4589,19 +4760,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
     switch (inswitch ? 'a' : c)
       {
       case '\n':
-       /* End of line: finish any pending argument,
-          then run the pending command if one has been started.  */
-       if (arg_going)
-         {
-           obstack_1grow (&obstack, 0);
-           string = XOBFINISH (&obstack, const char *);
-           if (this_is_library_file)
-             string = find_file (string);
-           store_arg (string, delete_this_arg, this_is_output_file);
-           if (this_is_output_file)
-             outfiles[input_file_number] = string;
-         }
-       arg_going = 0;
+       end_going_arg ();
 
        if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
          {
@@ -4635,17 +4794,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
        break;
 
       case '|':
-       /* End any pending argument.  */
-       if (arg_going)
-         {
-           obstack_1grow (&obstack, 0);
-           string = XOBFINISH (&obstack, const char *);
-           if (this_is_library_file)
-             string = find_file (string);
-           store_arg (string, delete_this_arg, this_is_output_file);
-           if (this_is_output_file)
-             outfiles[input_file_number] = string;
-         }
+       end_going_arg ();
 
        /* Use pipe */
        obstack_1grow (&obstack, c);
@@ -4654,19 +4803,9 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
       case '\t':
       case ' ':
-       /* Space or tab ends an argument if one is pending.  */
-       if (arg_going)
-         {
-           obstack_1grow (&obstack, 0);
-           string = XOBFINISH (&obstack, const char *);
-           if (this_is_library_file)
-             string = find_file (string);
-           store_arg (string, delete_this_arg, this_is_output_file);
-           if (this_is_output_file)
-             outfiles[input_file_number] = string;
-         }
+       end_going_arg ();
+
        /* Reinitialize for a new argument.  */
-       arg_going = 0;
        delete_this_arg = 0;
        this_is_output_file = 0;
        this_is_library_file = 0;
@@ -4679,12 +4818,18 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
            fatal ("spec '%s' invalid", spec);
 
          case 'b':
-           obstack_grow (&obstack, input_basename, basename_length);
+           if (save_temps_length)
+             obstack_grow (&obstack, save_temps_prefix, save_temps_length);
+           else
+             obstack_grow (&obstack, input_basename, basename_length);
            arg_going = 1;
            break;
 
          case 'B':
-           obstack_grow (&obstack, input_basename, suffixed_basename_length);
+           if (save_temps_length)
+             obstack_grow (&obstack, save_temps_prefix, save_temps_length);
+           else
+             obstack_grow (&obstack, input_basename, suffixed_basename_length);
            arg_going = 1;
            break;
 
@@ -4725,7 +4870,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              char *buf;
              while (*p != 0 && *p != '\n')
                p++;
-             buf = alloca (p - q + 1);
+             buf = (char *) alloca (p - q + 1);
              strncpy (buf, q, p - q);
              buf[p - q] = 0;
              error ("%s", buf);
@@ -4739,7 +4884,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              char *buf;
              while (*p != 0 && *p != '\n')
                p++;
-             buf = alloca (p - q + 1);
+             buf = (char *) alloca (p - q + 1);
              strncpy (buf, q, p - q);
              buf[p - q] = 0;
              notice ("%s\n", buf);
@@ -4830,6 +4975,26 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    suffix_length += strlen (TARGET_OBJECT_SUFFIX);
                  }
 
+               /* If -save-temps=obj and -o were specified, use that for the
+                  temp file.  */
+               if (save_temps_length)
+                 {
+                   char *tmp;
+                   temp_filename_length
+                     = save_temps_length + suffix_length + 1;
+                   tmp = (char *) alloca (temp_filename_length);
+                   memcpy (tmp, save_temps_prefix, save_temps_length);
+                   memcpy (tmp + save_temps_length, suffix, suffix_length);
+                   tmp[save_temps_length + suffix_length] = '\0';
+                   temp_filename = save_string (tmp,
+                                                temp_filename_length + 1);
+                   obstack_grow (&obstack, temp_filename,
+                                 temp_filename_length);
+                   arg_going = 1;
+                   delete_this_arg = 0;
+                   break;
+                 }
+
                /* 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
@@ -4840,12 +5005,14 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
                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';
+                   char *tmp;
+                   temp_filename_length = basename_length + suffix_length + 1;
+                   tmp = (char *) alloca (temp_filename_length);
+                   memcpy (tmp, input_basename, basename_length);
+                   memcpy (tmp + basename_length, suffix, suffix_length);
+                   tmp[basename_length + suffix_length] = '\0';
+                   temp_filename = tmp;
+
                    if (strcmp (temp_filename, input_filename) != 0)
                      {
 #ifndef HOST_LACKS_INODE_NUMBERS
@@ -4902,7 +5069,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                  {
                    if (t == 0)
                      {
-                       t = xmalloc (sizeof (struct temp_name));
+                       t = XNEW (struct temp_name);
                        t->next = temp_names;
                        temp_names = t;
                      }
@@ -5006,9 +5173,63 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              int max = n_infiles;
              max += lang_specific_extra_outfiles;
 
-             for (i = 0; i < max; i++)
-               if (outfiles[i])
-                 store_arg (outfiles[i], 0, 0);
+              if (HAVE_GNU_LD && at_file_supplied)
+                {
+                  /* We are going to expand `%o' to `@FILE', where FILE
+                     is a newly-created temporary filename.  The filenames
+                     that would usually be expanded in place of %o will be
+                     written to the temporary file.  */
+
+                  char *temp_file = make_temp_file ("");
+                  char *at_argument;
+                  char **argv;
+                  int n_files, j, status;
+                  FILE *f;
+
+                  at_argument = concat ("@", temp_file, NULL);
+                  store_arg (at_argument, 0, 0);
+
+                  /* Convert OUTFILES into a form suitable for writeargv.  */
+
+                  /* Determine how many are non-NULL.  */
+                  for (n_files = 0, i = 0; i < max; i++)
+                    n_files += outfiles[i] != NULL;
+
+                  argv = (char **) alloca (sizeof (char *) * (n_files + 1));
+
+                  /* Copy the strings over.  */
+                  for (i = 0, j = 0; i < max; i++)
+                    if (outfiles[i])
+                      {
+                        argv[j] = CONST_CAST (char *, outfiles[i]);
+                        j++;
+                      }
+                  argv[j] = NULL;
+
+                  f = fopen (temp_file, "w");
+
+                  if (f == NULL)
+                    fatal ("could not open temporary response file %s",
+                           temp_file);
+
+                  status = writeargv (argv, f);
+
+                  if (status)
+                    fatal ("could not write to temporary response file %s",
+                           temp_file);
+
+                  status = fclose (f);
+
+                  if (EOF == status)
+                    fatal ("could not close temporary response file %s",
+                           temp_file);
+
+                  record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+                }
+              else
+                for (i = 0; i < max; i++)
+                 if (outfiles[i])
+                   store_arg (outfiles[i], 0, 0);
              break;
            }
 
@@ -5038,18 +5259,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              p = handle_braces (p + 1);
              if (p == 0)
                return -1;
-             /* End any pending argument.  */
-             if (arg_going)
-               {
-                 obstack_1grow (&obstack, 0);
-                 string = XOBFINISH (&obstack, const char *);
-                 if (this_is_library_file)
-                   string = find_file (string);
-                 store_arg (string, delete_this_arg, this_is_output_file);
-                 if (this_is_output_file)
-                   outfiles[input_file_number] = string;
-                 arg_going = 0;
-               }
+             end_going_arg ();
              /* If any args were output, mark the last one for deletion
                 on failure.  */
              if (argbuf_index != cur_index)
@@ -5242,7 +5452,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                if (!strncmp (switches[i].part1, p, len - have_wildcard)
                    && (have_wildcard || switches[i].part1[len] == '\0'))
                  {
-                   switches[i].live_cond = SWITCH_IGNORE;
+                   switches[i].live_cond |= SWITCH_IGNORE;
                    switches[i].validated = 1;
                  }
 
@@ -5303,7 +5513,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    }
                  else
                    {
-                     char *x = alloca (strlen (name) * 2 + 1);
+                     char *x = (char *) alloca (strlen (name) * 2 + 1);
                      char *buf = x;
                      const char *y = name;
                      int flag = 0;
@@ -5368,17 +5578,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
   /* End of string.  If we are processing a spec function, we need to
      end any pending argument.  */
-  if (processing_spec_function && arg_going)
-    {
-      obstack_1grow (&obstack, 0);
-      string = XOBFINISH (&obstack, const char *);
-      if (this_is_library_file)
-        string = find_file (string);
-      store_arg (string, delete_this_arg, this_is_output_file);
-      if (this_is_output_file)
-        outfiles[input_file_number] = string;
-      arg_going = 0;
-    }
+  if (processing_spec_function)
+    end_going_arg ();
 
   return 0;
 }
@@ -5869,7 +6070,8 @@ check_live_switch (int switchnum, int prefix_length)
   /* If we already processed this switch and determined if it was
      live or not, return our past determination.  */
   if (switches[switchnum].live_cond != 0)
-    return switches[switchnum].live_cond > 0;
+    return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
+           && (switches[switchnum].live_cond & SWITCH_FALSE) == 0);
 
   /* Now search for duplicate in a manner that depends on the name.  */
   switch (*name)
@@ -5916,7 +6118,7 @@ check_live_switch (int switchnum, int prefix_length)
     }
 
   /* Otherwise the switch is live.  */
-  switches[switchnum].live_cond = SWITCH_LIVE;
+  switches[switchnum].live_cond |= SWITCH_LIVE;
   return 1;
 }
 \f
@@ -5931,7 +6133,7 @@ check_live_switch (int switchnum, int prefix_length)
 static void
 give_switch (int switchnum, int omit_first_word)
 {
-  if (switches[switchnum].live_cond == SWITCH_IGNORE)
+  if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
     return;
 
   if (!omit_first_word)
@@ -5956,13 +6158,13 @@ give_switch (int switchnum, int omit_first_word)
              while (length-- && !IS_DIR_SEPARATOR (arg[length]))
                if (arg[length] == '.')
                  {
-                   ((char *)arg)[length] = 0;
+                   (CONST_CAST(char *, arg))[length] = 0;
                    dot = 1;
                    break;
                  }
              do_spec_1 (arg, 1, NULL);
              if (dot)
-               ((char *)arg)[length] = '.';
+               (CONST_CAST(char *, arg))[length] = '.';
              do_spec_1 (suffix_subst, 1, NULL);
            }
          else
@@ -5999,7 +6201,7 @@ is_directory (const char *path1, bool linker)
   /* Ensure the string ends with "/.".  The resulting path will be a
      directory even if the given path is a symbolic link.  */
   len1 = strlen (path1);
-  path = alloca (3 + len1);
+  path = (char *) alloca (3 + len1);
   memcpy (path, path1, len1);
   cp = path + len1;
   if (!IS_DIR_SEPARATOR (cp[-1]))
@@ -6031,16 +6233,7 @@ set_input (const char *filename)
 
   input_filename = filename;
   input_filename_length = strlen (input_filename);
-
-  input_basename = input_filename;
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-  /* Skip drive name so 'x:foo' is handled properly.  */
-  if (input_basename[1] == ':')
-    input_basename += 2;
-#endif
-  for (p = input_basename; *p; p++)
-    if (IS_DIR_SEPARATOR (*p))
-      input_basename = p + 1;
+  input_basename = lbasename (input_filename);
 
   /* Find a suffix starting with the last period,
      and set basename_length to exclude that suffix.  */
@@ -6090,6 +6283,11 @@ main (int argc, char **argv)
   char *specs_file;
   const char *p;
   struct user_specs *uptr;
+  char **old_argv = argv;
+
+  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
+     on ?: in file-scope variable initializations.  */
+  asm_debug = ASM_DEBUG_SPEC;
 
   p = argv[0] + strlen (argv[0]);
   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
@@ -6100,6 +6298,10 @@ main (int argc, char **argv)
 
   expandargv (&argc, &argv);
 
+  /* Determine if any expansions were made.  */
+  if (argv != old_argv)
+    at_file_supplied = true;
+
   prune_options (&argc, &argv);
 
 #ifdef GCC_DRIVER_HOST_INITIALIZATION
@@ -6183,11 +6385,11 @@ main (int argc, char **argv)
   obstack_init (&collect_obstack);
   obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
   obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
-  putenv (XOBFINISH (&collect_obstack, char *));
+  xputenv (XOBFINISH (&collect_obstack, char *));
 
 #ifdef INIT_ENVIRONMENT
   /* Set up any other necessary machine specific environment variables.  */
-  putenv (INIT_ENVIRONMENT);
+  xputenv (INIT_ENVIRONMENT);
 #endif
 
   /* Make a table of what switches there are (switches, n_switches).
@@ -6199,7 +6401,7 @@ main (int argc, char **argv)
   /* Initialize the vector of specs to just the default.
      This means one element containing 0s, as a terminator.  */
 
-  compilers = xmalloc (sizeof default_compilers);
+  compilers = XNEWVAR (struct compiler, sizeof default_compilers);
   memcpy (compilers, default_compilers, sizeof default_compilers);
   n_compilers = n_default_compilers;
 
@@ -6218,7 +6420,7 @@ main (int argc, char **argv)
 
   /* We need to check standard_exec_prefix/just_machine_suffix/specs
      for any override of as, ld and libraries.  */
-  specs_file = alloca (strlen (standard_exec_prefix)
+  specs_file = (char *) alloca (strlen (standard_exec_prefix)
                       + strlen (just_machine_suffix) + sizeof ("specs"));
 
   strcpy (specs_file, standard_exec_prefix);
@@ -6409,6 +6611,18 @@ main (int argc, char **argv)
       return (0);
     }
 
+  if (print_sysroot)
+    {
+      if (target_system_root)
+       {
+          if (target_sysroot_suffix)
+           printf ("%s%s\n", target_system_root, target_sysroot_suffix);
+          else
+           printf ("%s\n", target_system_root);
+       }
+      return (0);
+    }
+
   if (print_multi_os_directory)
     {
       if (multilib_os_dir == NULL)
@@ -6447,7 +6661,10 @@ main (int argc, char **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 various sub-processes, along with the --help switch.  */
+        on the various sub-processes, along with the --help switch.
+        Ensure their output appears after ours.  */
+      fputc ('\n', stdout);
+      fflush (stdout);
     }
 
   if (verbose_flag)
@@ -6481,10 +6698,10 @@ main (int argc, char **argv)
 
       if (! strncmp (version_string, compiler_version, n)
          && compiler_version[n] == 0)
-       notice ("gcc version %s\n", version_string);
+       notice ("gcc version %s %s\n", version_string, pkgversion_string);
       else
-       notice ("gcc driver version %s executing gcc version %s\n",
-               version_string, compiler_version);
+       notice ("gcc driver version %s %sexecuting gcc version %s\n",
+               version_string, pkgversion_string, compiler_version);
 
       if (n_infiles == 0)
        return (0);
@@ -6692,7 +6909,7 @@ main (int argc, char **argv)
 
   /* Run ld to link all the compiler output files.  */
 
-  if (num_linker_inputs > 0 && error_count == 0)
+  if (num_linker_inputs > 0 && error_count == 0 && print_subprocess_help < 2)
     {
       int tmp = execution_count;
 
@@ -6708,6 +6925,13 @@ main (int argc, char **argv)
       putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
       putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
 
+      if (print_subprocess_help == 1)
+       {
+         printf (_("\nLinker options\n==============\n\n"));
+         printf (_("Use \"-Wl,OPTION\" to pass \"OPTION\""
+                   " to the linker.\n\n"));
+         fflush (stdout);
+       }
       value = do_spec (link_command_spec);
       if (value < 0)
        error_count = 1;
@@ -6719,7 +6943,8 @@ main (int argc, char **argv)
 
   if (! linker_was_run && error_count == 0)
     for (i = 0; (int) i < n_infiles; i++)
-      if (explicit_link_files[i])
+      if (explicit_link_files[i]
+         && !(infiles[i].language && infiles[i].language[0] == '*'))
        error ("%s: linker input file unused because linking not done",
               outfiles[i]);
 
@@ -7043,7 +7268,8 @@ used_arg (const char *p, int len)
        if (*q == ';')
          cnt++;
 
-      matches = alloca ((sizeof (struct mswitchstr)) * cnt);
+      matches
+       = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
       i = 0;
       q = multilib_matches;
       while (*q != '\0')
@@ -7080,7 +7306,7 @@ used_arg (const char *p, int len)
       mswitches
        = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
       for (i = 0; i < n_switches; i++)
-       if (switches[i].live_cond != SWITCH_IGNORE)
+       if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
          {
            int xlen = strlen (switches[i].part1);
            for (j = 0; j < cnt; j++)
@@ -7402,7 +7628,7 @@ set_multilib_dir (void)
   if (multilib_dir == NULL && multilib_os_dir != NULL
       && strcmp (multilib_os_dir, ".") == 0)
     {
-      free ((char *) multilib_os_dir);
+      free (CONST_CAST (char *, multilib_os_dir));
       multilib_os_dir = NULL;
     }
   else if (multilib_dir != NULL && multilib_os_dir == NULL)
@@ -7679,6 +7905,9 @@ static const char *
 getenv_spec_function (int argc, const char **argv)
 {
   char *value;
+  char *result;
+  char *ptr;
+  size_t len;
 
   if (argc != 2)
     return NULL;
@@ -7687,7 +7916,21 @@ getenv_spec_function (int argc, const char **argv)
   if (!value)
     fatal ("environment variable \"%s\" not defined", argv[0]);
 
-  return concat (value, argv[1], NULL);
+  /* We have to escape every character of the environment variable so
+     they are not interpreted as active spec characters.  A
+     particularly painful case is when we are reading a variable
+     holding a windows path complete with \ separators.  */
+  len = strlen (value) * 2 + strlen (argv[1]) + 1;
+  result = XNEWVAR (char, len);
+  for (ptr = result; *value; ptr += 2)
+    {
+      ptr[0] = '\\';
+      ptr[1] = *value++;
+    }
+  
+  strcpy (ptr, argv[1]);
+  
+  return result;
 }
 
 /* if-exists built-in spec function.
@@ -7878,8 +8121,21 @@ include_spec_function (int argc, const char **argv)
   if (argc != 1)
     abort ();
 
-  file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
+  file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
   read_specs (file ? file : argv[0], FALSE);
 
   return NULL;
 }
+
+/* %:print-asm-header spec function.  Print a banner to say that the
+   following output is from the assembler.  */
+
+static const char *
+print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
+                               const char **argv ATTRIBUTE_UNUSED)
+{
+  printf (_("Assembler options\n=================\n\n"));
+  printf (_("Use \"-Wa,OPTION\" to pass \"OPTION\" to the assembler.\n\n"));
+  fflush (stdout);
+  return NULL;
+}