OSDN Git Service

Fix the Xassembler and Xpreprocessor options, which have never worked right.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 8076f51..e131eb6 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,6 +1,7 @@
 /* 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation,
+   Inc.
 
 This file is part of GCC.
 
@@ -58,7 +59,7 @@ compilation is specified by a string called a "spec".  */
 
    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 `-'
+   DEFAULT_WORD_SWITCH_TAKES_ARG in gcc.h.  Omit the first `-'
    from `--baz'.
 
    5. Document the option in this file's display_help().  If the
@@ -85,13 +86,6 @@ compilation is specified by a string called a "spec".  */
 #include "gcc.h"
 #include "flags.h"
 
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
-extern int getrusage (int, struct rusage *);
-#endif
-
 /* 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)
@@ -282,12 +276,6 @@ static struct obstack obstack;
 
 static struct obstack collect_obstack;
 
-/* These structs are used to collect resource usage information for
-   subprocesses.  */
-#ifdef HAVE_GETRUSAGE
-static struct rusage rus, prus;
-#endif
-
 /* Forward declaration for prototypes.  */
 struct path_prefix;
 struct prefix_list;
@@ -361,6 +349,7 @@ static const char *convert_filename (const char *, int, int);
 
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
+static const char *replace_outfile_spec_function (int, const char **);
 \f
 /* The Specs Language
 
@@ -471,8 +460,8 @@ or with constant text in a single argument.
  %l     process LINK_SPEC as a spec.
  %L     process LIB_SPEC as a spec.
  %G     process LIBGCC_SPEC as a spec.
- %M     output multilib_dir with directory separators replaced with "_";
-       if multilib_dir is not set or is ".", output "".
+ %R     Output the concatenation of target_system_root and
+        target_sysroot_suffix.
  %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 CPP_SPEC as a spec.
@@ -620,7 +609,7 @@ proper position among the other output files.  */
 #ifndef LIBGCC_SPEC
 #if defined(REAL_LIBGCC_SPEC)
 #define LIBGCC_SPEC REAL_LIBGCC_SPEC
-#elif defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
+#elif defined(LINK_LIBGCC_SPECIAL_1)
 /* Have gcc do the search for libgcc.a.  */
 #define LIBGCC_SPEC "libgcc.a%s"
 #else
@@ -700,25 +689,24 @@ 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 %(mflib)\
-    %{fprofile-arcs|fprofile-generate:-lgcov}\
+    %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
     %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
     %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
 #endif
 
 #ifndef LINK_LIBGCC_SPEC
-# ifdef LINK_LIBGCC_SPECIAL
-/* Don't generate -L options for startfile prefix list.  */
-#  define LINK_LIBGCC_SPEC ""
-# else
-/* Do generate them.  */
-#  define LINK_LIBGCC_SPEC "%D"
-# endif
+/* Generate -L options for startfile prefix list.  */
+# define LINK_LIBGCC_SPEC "%D"
 #endif
 
 #ifndef STARTFILE_PREFIX_SPEC
 # define STARTFILE_PREFIX_SPEC ""
 #endif
 
+#ifndef SYSROOT_SPEC
+# define SYSROOT_SPEC "--sysroot=%R"
+#endif
+
 #ifndef SYSROOT_SUFFIX_SPEC
 # define SYSROOT_SUFFIX_SPEC ""
 #endif
@@ -746,6 +734,7 @@ static const char *linker_name_spec = LINKER_NAME;
 static const char *link_command_spec = LINK_COMMAND_SPEC;
 static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
 static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
+static const char *sysroot_spec = SYSROOT_SPEC;
 static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
 static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
 
@@ -771,7 +760,7 @@ static const char *cpp_unique_options =
  %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
  %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
  %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
- %{trigraphs} %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
  %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
  %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
  %{E|M|MM:%W{o*}}";
@@ -782,9 +771,9 @@ static const char *cpp_unique_options =
    options used to set target flags.  Those special target flags settings may
    in turn cause preprocessor symbols to be defined specially.  */
 static const char *cpp_options =
-"%(cpp_unique_options) %1 %{m*} %{std*} %{ansi} %{W*&pedantic*} %{w} %{f*}\
- %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*} %{undef}\
- %{save-temps:-fpch-preprocess}";
+"%(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}";
 
 /* This contains cpp options which are not passed when the preprocessor
    output will be used by another program.  */
@@ -795,13 +784,14 @@ 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*}\
  %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
- %{g*} %{O*} %{W*&pedantic*} %{w} %{std*} %{ansi}\
+ %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
  %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
  %{Qn:-fno-ident} %{--help:--help}\
  %{--target-help:--target-help}\
  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
  %{fsyntax-only:-o %j} %{-param*}\
- %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}";
+ %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
+ %{coverage:-fprofile-arcs -ftest-coverage}";
 
 static const char *asm_options =
 "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
@@ -959,7 +949,7 @@ static const struct compiler default_compilers[] =
                cc1 %(cpp_unique_options) %(cc1_options)}}\
                 %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
   {"-",
-   "%{!E:%e-E required when input is from standard input}\
+   "%{!E:%e-E or -x required when input is from standard input}\
     %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0},
   {".h", "@c-header", 0, 0, 0},
   {"@c-header",
@@ -1063,11 +1053,14 @@ static const struct option_map option_map[] =
    {"--dependencies", "-M", 0},
    {"--dump", "-d", "a"},
    {"--dumpbase", "-dumpbase", "a"},
+   {"--encoding", "-fencoding=", "aj"},
    {"--entry", "-e", 0},
    {"--extra-warnings", "-W", 0},
+   {"--extdirs", "-fextdirs=", "aj"},
    {"--for-assembler", "-Wa", "a"},
    {"--for-linker", "-Xlinker", "a"},
    {"--force-link", "-u", "a"},
+   {"--coverage", "-coverage", 0},
    {"--imacros", "-imacros", "a"},
    {"--include", "-include", "a"},
    {"--include-barrier", "-I-", 0},
@@ -1091,6 +1084,7 @@ static const struct option_map option_map[] =
    {"--output", "-o", "a"},
    {"--output-class-directory", "-foutput-class-dir=", "ja"},
    {"--param", "--param", "a"},
+   {"--pass-exit-codes", "-pass-exit-codes", 0},
    {"--pedantic", "-pedantic", 0},
    {"--pedantic-errors", "-pedantic-errors", 0},
    {"--pie", "-pie", 0},
@@ -1263,7 +1257,7 @@ translate_options (int *argcp, const char *const **argvp)
 
                  else if (strchr (arginfo, '*') != 0)
                    {
-                     error ("incomplete `%s' option", option_map[j].name);
+                     error ("incomplete '%s' option", option_map[j].name);
                      break;
                    }
 
@@ -1274,7 +1268,7 @@ translate_options (int *argcp, const char *const **argvp)
                        {
                          if (i + 1 == argc)
                            {
-                             error ("missing argument to `%s' option",
+                             error ("missing argument to '%s' option",
                                     option_map[j].name);
                              break;
                            }
@@ -1287,7 +1281,7 @@ translate_options (int *argcp, const char *const **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;
                    }
@@ -1545,6 +1539,7 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("md_startfile_prefix",     &md_startfile_prefix),
   INIT_STATIC_SPEC ("md_startfile_prefix_1",   &md_startfile_prefix_1),
   INIT_STATIC_SPEC ("startfile_prefix_spec",   &startfile_prefix_spec),
+  INIT_STATIC_SPEC ("sysroot_spec",             &sysroot_spec),
   INIT_STATIC_SPEC ("sysroot_suffix_spec",     &sysroot_suffix_spec),
   INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",        &sysroot_hdrs_suffix_spec),
 };
@@ -1572,6 +1567,7 @@ static const struct spec_function static_spec_functions[] =
 {
   { "if-exists",               if_exists_spec_function },
   { "if-exists-else",          if_exists_else_spec_function },
+  { "replace-outfile",         replace_outfile_spec_function },
   { 0, 0 }
 };
 
@@ -1698,11 +1694,7 @@ init_spec (void)
        if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
          {
            init_gcc_specs (&obstack,
-#ifdef NO_SHARED_LIBGCC_MULTILIB
                            "-lgcc_s"
-#else
-                           "-lgcc_s%M"
-#endif
 #ifdef USE_LIBUNWIND_EXCEPTIONS
                            " -lunwind"
 #endif
@@ -1710,7 +1702,11 @@ init_spec (void)
                            "-lgcc",
                            "-lgcc_eh"
 #ifdef USE_LIBUNWIND_EXCEPTIONS
+# ifdef HAVE_LD_STATIC_DYNAMIC
+                           " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
+# else
                            " -lunwind"
+# endif
 #endif
                            );
 
@@ -1722,12 +1718,7 @@ init_spec (void)
            /* Ug.  We don't know shared library extensions.  Hope that
               systems that use this form don't do shared libraries.  */
            init_gcc_specs (&obstack,
-#ifdef NO_SHARED_LIBGCC_MULTILIB
-                           "-lgcc_s"
-#else
-                           "-lgcc_s%M"
-#endif
-                           ,
+                           "-lgcc_s",
                            "libgcc.a%s",
                            "libgcc_eh.a%s"
 #ifdef USE_LIBUNWIND_EXCEPTIONS
@@ -2628,7 +2619,7 @@ add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
                      int require_machine_suffix, int os_multilib)
 {
   if (!IS_ABSOLUTE_PATH (prefix))
-    abort ();
+    fatal ("system path '%s' is not absolute", prefix);
 
   if (target_system_root)
     {
@@ -2657,17 +2648,16 @@ execute (void)
   int i;
   int n_commands;              /* # of command.  */
   char *string;
+  struct pex_obj *pex;
   struct command
   {
     const char *prog;          /* program name.  */
     const char **argv;         /* vector of args.  */
-    int pid;                   /* pid of process for this command.  */
   };
 
   struct command *commands;    /* each command buffer with above info.  */
 
-  if (processing_spec_function)
-    abort ();
+  gcc_assert (!processing_spec_function);
 
   /* Count # of piped commands.  */
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
@@ -2795,24 +2785,32 @@ execute (void)
 
   /* Run each piped subprocess.  */
 
+  pex = pex_init (PEX_USE_PIPES | (report_times ? PEX_RECORD_TIMES : 0),
+                 programname, temp_filename);
+  if (pex == NULL)
+    pfatal_with_name (_("pex_init failed"));
+
   for (i = 0; i < n_commands; i++)
     {
-      char *errmsg_fmt, *errmsg_arg;
+      const char *errmsg;
+      int err;
       const char *string = commands[i].argv[0];
 
-      /* For some bizarre reason, the second argument of execvp() is
-        char *const *, not const char *const *.  */
-      commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
-                                 programname, temp_filename,
-                                 &errmsg_fmt, &errmsg_arg,
-                                 ((i == 0 ? PEXECUTE_FIRST : 0)
-                                  | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
-                                  | (string == commands[i].prog
-                                     ? PEXECUTE_SEARCH : 0)
-                                  | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
-
-      if (commands[i].pid == -1)
-       pfatal_pexecute (errmsg_fmt, errmsg_arg);
+      errmsg = pex_run (pex,
+                       ((i + 1 == n_commands ? PEX_LAST : 0)
+                        | (string == commands[i].prog ? PEX_SEARCH : 0)),
+                       string, (char * const *) commands[i].argv,
+                       NULL, NULL, &err);
+      if (errmsg != NULL)
+       {
+         if (err == 0)
+           fatal (errmsg);
+         else
+           {
+             errno = err;
+             pfatal_with_name (errmsg);
+           }
+       }
 
       if (string != commands[i].prog)
        free ((void *) string);
@@ -2820,89 +2818,76 @@ execute (void)
 
   execution_count++;
 
-  /* Wait for all the subprocesses to finish.
-     We don't care what order they finish in;
-     we know that N_COMMANDS waits will get them all.
-     Ignore subprocesses that we don't know about,
-     since they can be spawned by the process that exec'ed us.  */
+  /* Wait for all the subprocesses to finish.  */
 
   {
+    int *statuses;
+    struct pex_time *times = NULL;
     int ret_code = 0;
-#ifdef HAVE_GETRUSAGE
-    struct timeval d;
-    double ut = 0.0, st = 0.0;
-#endif
 
-    for (i = 0; i < n_commands;)
+    statuses = alloca (n_commands * sizeof (int));
+    if (!pex_get_status (pex, n_commands, statuses))
+      pfatal_with_name (_("failed to get exit status"));
+
+    if (report_times)
       {
-       int j;
-       int status;
-       int pid;
+       times = alloca (n_commands * sizeof (struct pex_time));
+       if (!pex_get_times (pex, n_commands, times))
+         pfatal_with_name (_("failed to get process times"));
+      }
 
-       pid = pwait (commands[i].pid, &status, 0);
-       if (pid < 0)
-         abort ();
+    pex_free (pex);
 
-#ifdef HAVE_GETRUSAGE
-       if (report_times)
-         {
-           /* getrusage returns the total resource usage of all children
-              up to now.  Copy the previous values into prus, get the
-              current statistics, then take the difference.  */
-
-           prus = rus;
-           getrusage (RUSAGE_CHILDREN, &rus);
-           d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
-           d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
-           ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
-
-           d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
-           d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
-           st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
-         }
-#endif
+    for (i = 0; i < n_commands; ++i)
+      {
+       int status = statuses[i];
 
-       for (j = 0; j < n_commands; j++)
-         if (commands[j].pid == pid)
-           {
-             i++;
-             if (WIFSIGNALED (status))
-               {
+       if (WIFSIGNALED (status))
+         {
 #ifdef SIGPIPE
-                 /* SIGPIPE is a special case.  It happens in -pipe mode
-                    when the compiler dies before the preprocessor is
-                    done, or the assembler dies before the compiler is
-                    done.  There's generally been an error already, and
-                    this is just fallout.  So don't generate another error
-                    unless we would otherwise have succeeded.  */
-                 if (WTERMSIG (status) == SIGPIPE
-                     && (signal_count || greatest_status >= MIN_FATAL_STATUS))
-                   ;
-                 else
+           /* SIGPIPE is a special case.  It happens in -pipe mode
+              when the compiler dies before the preprocessor is done,
+              or the assembler dies before the compiler is done.
+              There's generally been an error already, and this is
+              just fallout.  So don't generate another error unless
+              we would otherwise have succeeded.  */
+           if (WTERMSIG (status) == SIGPIPE
+               && (signal_count || greatest_status >= MIN_FATAL_STATUS))
+             ;
+           else
 #endif
-                   fatal ("\
+             fatal ("\
 Internal error: %s (program %s)\n\
 Please submit a full bug report.\n\
 See %s for instructions.",
-                          strsignal (WTERMSIG (status)), commands[j].prog,
-                          bug_report_url);
-                 signal_count++;
-                 ret_code = -1;
-               }
-             else if (WIFEXITED (status)
-                      && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
-               {
-                 if (WEXITSTATUS (status) > greatest_status)
-                   greatest_status = WEXITSTATUS (status);
-                 ret_code = -1;
-               }
-#ifdef HAVE_GETRUSAGE
-             if (report_times && ut + st != 0)
-               notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
-#endif
-             break;
-           }
+                    strsignal (WTERMSIG (status)), commands[i].prog,
+                    bug_report_url);
+           signal_count++;
+           ret_code = -1;
+         }
+       else if (WIFEXITED (status)
+                && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
+         {
+           if (WEXITSTATUS (status) > greatest_status)
+             greatest_status = WEXITSTATUS (status);
+           ret_code = -1;
+         }
+
+       if (report_times)
+         {
+           struct pex_time *pt = &times[i];
+           double ut, st;
+
+           ut = ((double) pt->user_seconds
+                 + (double) pt->user_microseconds / 1.0e6);
+           st = ((double) pt->system_seconds
+                 + (double) pt->system_microseconds / 1.0e6);
+
+           if (ut + st != 0)
+             notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st);
+         }
       }
+
     return ret_code;
   }
 }
@@ -3196,7 +3181,7 @@ process_command (int argc, const char **argv)
              argv += 2;
            }
          else
-           fatal ("`-%c' option must have argument", opt);
+           fatal ("'-%c' option must have argument", opt);
          if (opt == 'V')
            new_version = arg;
          else
@@ -3218,7 +3203,7 @@ process_command (int argc, const char **argv)
       new_argv[0] = new_argv0;
 
       execvp (new_argv0, new_argv);
-      fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
+      fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno));
     }
 
   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
@@ -3404,7 +3389,7 @@ process_command (int argc, const char **argv)
        {
          /* translate_options () has turned --version into -fversion.  */
          printf (_("%s (GCC) %s\n"), programname, version_string);
-         printf ("Copyright %s 2004 Free Software Foundation, Inc.\n",
+         printf ("Copyright %s 2005 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"),
@@ -3507,7 +3492,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
       else if (strcmp (argv[i], "-Xlinker") == 0)
        {
          if (i + 1 == argc)
-           fatal ("argument to `-Xlinker' is missing");
+           fatal ("argument to '-Xlinker' is missing");
 
          n_infiles++;
          i++;
@@ -3515,21 +3500,21 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
       else if (strcmp (argv[i], "-Xpreprocessor") == 0)
        {
          if (i + 1 == argc)
-           fatal ("argument to `-Xpreprocessor' is missing");
+           fatal ("argument to '-Xpreprocessor' is missing");
 
          add_preprocessor_option (argv[i+1], strlen (argv[i+1]));
        }
       else if (strcmp (argv[i], "-Xassembler") == 0)
        {
          if (i + 1 == argc)
-           fatal ("argument to `-Xassembler' is missing");
+           fatal ("argument to '-Xassembler' is missing");
 
          add_assembler_option (argv[i+1], strlen (argv[i+1]));
        }
       else if (strcmp (argv[i], "-l") == 0)
        {
          if (i + 1 == argc)
-           fatal ("argument to `-l' is missing");
+           fatal ("argument to '-l' is missing");
 
          n_infiles++;
          i++;
@@ -3550,7 +3535,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        {
          struct user_specs *user = xmalloc (sizeof (struct user_specs));
          if (++i >= argc)
-           fatal ("argument to `-specs' is missing");
+           fatal ("argument to '-specs' is missing");
 
          user->next = (struct user_specs *) 0;
          user->filename = argv[i];
@@ -3564,7 +3549,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        {
          struct user_specs *user = xmalloc (sizeof (struct user_specs));
          if (strlen (argv[i]) == 7)
-           fatal ("argument to `-specs=' is missing");
+           fatal ("argument to '-specs=' is missing");
 
          user->next = (struct user_specs *) 0;
          user->filename = argv[i] + 7;
@@ -3601,7 +3586,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
            {
            case 'b':
            case 'V':
-             fatal ("`-%c' must come at the start of the command line", c);
+             fatal ("'-%c' must come at the start of the command line", c);
              break;
 
            case 'B':
@@ -3610,7 +3595,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                int len;
 
                if (p[1] == 0 && i + 1 == argc)
-                 fatal ("argument to `-B' is missing");
+                 fatal ("argument to '-B' is missing");
                if (p[1] == 0)
                  value = argv[++i];
                else
@@ -3779,16 +3764,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        }
     }
 
-  if ((save_temps_flag || report_times) && use_pipes)
+  if (save_temps_flag && use_pipes)
     {
       /* -save-temps overrides -pipe, so that temp files are produced */
       if (save_temps_flag)
        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");
-
       use_pipes = 0;
     }
 
@@ -3962,16 +3942,12 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          infiles[n_infiles].language = "*";
          infiles[n_infiles++].name = argv[++i];
        }
+      /* Xassembler and Xpreprocessor were already handled in the first argv
+        scan, so all we need to do here is ignore them and their argument.  */
       else if (strcmp (argv[i], "-Xassembler") == 0)
-       {
-         infiles[n_infiles].language = "*";
-         infiles[n_infiles++].name = argv[++i];
-       }
+       i++;
       else if (strcmp (argv[i], "-Xpreprocessor") == 0)
-       {
-         infiles[n_infiles].language = "*";
-         infiles[n_infiles++].name = argv[++i];
-       }
+       i++;
       else if (strcmp (argv[i], "-l") == 0)
        { /* POSIX allows separation of -l and the lib arg;
             canonicalize by concatenating -l with its arg */
@@ -3999,7 +3975,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          if (c == 'x')
            {
              if (p[1] == 0 && i + 1 == argc)
-               fatal ("argument to `-x' is missing");
+               fatal ("argument to '-x' is missing");
              if (p[1] == 0)
                spec_lang = argv[++i];
              else
@@ -4027,7 +4003,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
                  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
                }
              if (i + n_args >= argc)
-               fatal ("argument to `-%s' is missing", p);
+               fatal ("argument to '-%s' is missing", p);
              switches[n_switches].args
                = xmalloc ((n_args + 1) * sizeof(const char *));
              while (j < n_args)
@@ -4088,7 +4064,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
     }
 
   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)
@@ -4365,7 +4341,7 @@ do_self_spec (const char *spec)
 
          /* Each switch should start with '-'.  */
          if (argbuf[i][0] != '-')
-           abort ();
+           fatal ("switch '%s' does not start with '-'", argbuf[i]);
 
          sw = &switches[i + first];
          sw->part1 = &argbuf[i][1];
@@ -4387,6 +4363,7 @@ do_spec_path (struct prefix_list *pl, const char *option,
   static size_t bufsize = 0;
   static char *buffer;
   int idx;
+  bool multilib_p = false;
 
   /* Used on systems which record the specified -L dirs
      and use them to search for dynamic linking.  */
@@ -4409,6 +4386,7 @@ do_spec_path (struct prefix_list *pl, const char *option,
       strcat (buffer, machine_suffix);
       if (is_directory (buffer, dir_for_machine_suffix, 1))
        {
+         multilib_p = true;
          do_spec_1 (option, separate_options, NULL);
          if (separate_options)
            do_spec_1 (" ", 0, NULL);
@@ -4422,6 +4400,7 @@ do_spec_path (struct prefix_list *pl, const char *option,
     {
       if (is_directory (pl->prefix, dir_for_no_suffix, 1))
        {
+         multilib_p = true;
          do_spec_1 (option, separate_options, NULL);
          if (separate_options)
            do_spec_1 (" ", 0, NULL);
@@ -4432,7 +4411,7 @@ do_spec_path (struct prefix_list *pl, const char *option,
        }
     }
 
-  if (only_subdir)
+  if (only_subdir || multilib_p)
     return;
 
   if (machine_suffix)
@@ -4592,7 +4571,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
        switch (c = *p++)
          {
          case 0:
-           fatal ("invalid specification!  Bug in cc");
+           fatal ("spec '%s' invalid", spec);
 
          case 'b':
            obstack_grow (&obstack, input_basename, basename_length);
@@ -4731,7 +4710,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    p += 2;
                    /* We don't support extra suffix characters after %O.  */
                    if (*p == '.' || ISALPHA ((unsigned char) *p))
-                     abort ();
+                     fatal ("spec '%s' has invalid '%%0%c'", spec, *p);
                    if (suffix_length == 0)
                      suffix = TARGET_OBJECT_SUFFIX;
                    else
@@ -4928,7 +4907,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              int cur_index = argbuf_index;
              /* Handle the {...} following the %W.  */
              if (*p != '{')
-               abort ();
+               fatal ("spec '%s' has invalid '%%W%c", spec, *p);
              p = handle_braces (p + 1);
              if (p == 0)
                return -1;
@@ -4959,7 +4938,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 
              /* Skip past the option value and make a copy.  */
              if (*p != '{')
-               abort ();
+               fatal ("spec '%s' has invalid '%%x%c'", spec, *p);
              while (*p++ != '}')
                ;
              string = save_string (p1 + 1, p - p1 - 2);
@@ -5070,23 +5049,6 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              return value;
            break;
 
-         case 'M':
-           if (multilib_dir && strcmp (multilib_dir, ".") != 0)
-             {
-               char *p;
-               const char *q;
-               size_t len;
-
-               len = strlen (multilib_dir);
-               obstack_blank (&obstack, len + 1);
-               p = obstack_next_free (&obstack) - (len + 1);
-
-               *p++ = '_';
-               for (q = multilib_dir; *q ; ++q, ++p)
-                 *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
-             }
-           break;
-
          case 'R':
            /* We assume there is a directory
               separator at the end of this string.  */
@@ -5169,7 +5131,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
              }
            else
              /* Catch the case where a spec string contains something like
-                '%{foo:%*}'.  ie there is no * in the pattern on the left
+                '%{foo:%*}'.  i.e. there is no * in the pattern on the left
                 hand side of the :.  */
              error ("spec failure: '%%*' has not been initialized by pattern match");
            break;
@@ -5340,7 +5302,7 @@ eval_spec_function (const char *func, const char *args)
 
   sf = lookup_spec_function (func);
   if (sf == NULL)
-    fatal ("unknown spec function `%s'", func);
+    fatal ("unknown spec function '%s'", func);
 
   /* Push the spec processing context.  */
   save_argbuf_index = argbuf_index;
@@ -5359,7 +5321,7 @@ eval_spec_function (const char *func, const char *args)
 
   alloc_args ();
   if (do_spec_2 (args) < 0)
-    fatal ("error in args to spec function `%s'", func);
+    fatal ("error in args to spec function '%s'", func);
 
   /* argbuf_index is an index for the next argument to be inserted, and
      so contains the count of the args already inserted.  */
@@ -5452,6 +5414,22 @@ handle_spec_function (const char *p)
 static inline bool
 input_suffix_matches (const char *atom, const char *end_atom)
 {
+  /* We special case the semantics of {.s:...} and {.S:...} and their
+     negative variants.  Instead of testing the input filename suffix,
+     we test whether the input source file is an assembler file or an
+     assembler-with-cpp file respectively.  This allows us to correctly
+     handle the -x command line option.  */
+
+  if (atom + 1 == end_atom
+      && input_file_compiler
+      && input_file_compiler->suffix)
+    {
+      if (*atom == 's')
+       return !strcmp (input_file_compiler->suffix, "@assembler");
+      if (*atom == 'S')
+       return !strcmp (input_file_compiler->suffix, "@assembler-with-cpp");
+    }
+
   return (input_suffix
          && !strncmp (input_suffix, atom, end_atom - atom)
          && input_suffix[end_atom - atom] == '\0');
@@ -5517,6 +5495,7 @@ handle_braces (const char *p)
 {
   const char *atom, *end_atom;
   const char *d_atom = NULL, *d_end_atom = NULL;
+  const char *orig = p;
 
   bool a_is_suffix;
   bool a_is_starred;
@@ -5536,7 +5515,7 @@ handle_braces (const char *p)
   do
     {
       if (a_must_be_last)
-       abort ();
+       goto invalid;
 
       /* Scan one "atom" (S in the description above of %{}, possibly
         with !, ., or * modifiers).  */
@@ -5560,32 +5539,33 @@ handle_braces (const char *p)
        p++, a_is_starred = 1;
 
       SKIP_WHITE();
-      if (*p == '&' || *p == '}')
+      switch (*p)
        {
+       case '&': case '}':
          /* Substitute the switch(es) indicated by the current atom.  */
          ordered_set = true;
          if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
              || atom == end_atom)
-           abort ();
+           goto invalid;
 
          mark_matching_switches (atom, end_atom, a_is_starred);
 
          if (*p == '}')
            process_marked_switches ();
-       }
-      else if (*p == '|' || *p == ':')
-       {
+         break;
+
+       case '|': case ':':
          /* Substitute some text if the current atom appears as a switch
             or suffix.  */
          disjunct_set = true;
          if (ordered_set)
-           abort ();
+           goto invalid;
 
          if (atom == end_atom)
            {
              if (!n_way_choice || disj_matched || *p == '|'
                  || a_is_negated || a_is_suffix || a_is_starred)
-               abort ();
+               goto invalid;
 
              /* An empty term may appear as the last choice of an
                 N-way choice set; it means "otherwise".  */
@@ -5596,7 +5576,7 @@ handle_braces (const char *p)
          else
            {
               if (a_is_suffix && a_is_starred)
-                abort ();
+                goto invalid;
 
               if (!a_is_starred)
                 disj_starred = false;
@@ -5639,14 +5619,19 @@ handle_braces (const char *p)
                  d_atom = d_end_atom = NULL;
                }
            }
+         break;
+
+       default:
+         goto invalid;
        }
-      else
-       abort ();
     }
   while (*p++ != '}');
 
   return p;
-
+  
+ invalid:
+  fatal ("braced spec '%s' is invalid at '%c'", orig, *p);
+  
 #undef SKIP_WHITE
 }
 
@@ -5686,7 +5671,7 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
       else if (*p == '%' && p[1] == '*' && nesting_level == 1)
        have_subst = true;
       else if (*p == '\0')
-       abort ();
+       goto invalid;
       p++;
     }
 
@@ -5695,7 +5680,7 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
     end_body--;
 
   if (have_subst && !starred)
-    abort ();
+    goto invalid;
 
   if (matched)
     {
@@ -5731,6 +5716,9 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
     }
 
   return p;
+
+ invalid:
+  fatal ("braced spec body '%s' is invalid", body);
 }
 \f
 /* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
@@ -6011,6 +5999,9 @@ main (int argc, const char **argv)
   GCC_DRIVER_HOST_INITIALIZATION;
 #endif
 
+  /* Unlock the stdio streams.  */
+  unlock_std_streams ();
+
   gcc_init_libintl ();
 
   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
@@ -6161,6 +6152,19 @@ main (int argc, const char **argv)
         target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]);
     }
 
+#ifdef HAVE_LD_SYSROOT
+  /* Pass the --sysroot option to the linker, if it supports that.  If
+     there is a sysroot_suffix_spec, it has already been processed by
+     this point, so target_system_root really is the system root we
+     should be using.  */
+  if (target_system_root)
+    {
+      obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
+      obstack_grow0 (&obstack, link_spec, strlen (link_spec));
+      set_spec ("link", obstack_finish (&obstack));
+    }
+#endif
+
   /* Process sysroot_hdrs_suffix_spec.  */
   if (*sysroot_hdrs_suffix_spec != 0
       && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
@@ -6185,10 +6189,6 @@ main (int argc, const char **argv)
      startfile_prefix_spec exclusively.  */
   else if (*cross_compile == '0' || target_system_root)
     {
-      if (*md_exec_prefix)
-       add_sysrooted_prefix (&startfile_prefixes, md_exec_prefix, "GCC",
-                             PREFIX_PRIORITY_LAST, 0, 1);
-
       if (*md_startfile_prefix)
        add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
                              "GCC", PREFIX_PRIORITY_LAST, 0, 1);
@@ -6259,7 +6259,7 @@ main (int argc, const char **argv)
 
   for (i = 0; (int) i < n_switches; i++)
     if (! switches[i].validated)
-      error ("unrecognized option `-%s'", switches[i].part1);
+      error ("unrecognized option '-%s'", switches[i].part1);
 
   /* Obey some of the options.  */
 
@@ -6340,6 +6340,7 @@ main (int argc, const char **argv)
       int n;
       const char *thrmod;
 
+      notice ("Target: %s\n", spec_machine);
       notice ("Configured with: %s\n", configuration_arguments);
 
 #ifdef THREAD_MODEL_SPEC
@@ -6454,13 +6455,13 @@ main (int argc, const char **argv)
                {
                  value = do_spec (input_file_compiler->spec);
                  infiles[i].preprocessed = true;
-                 if (have_o_argbuf_index)
-                   infiles[i].name = argbuf[have_o_argbuf_index];
-                 else
-                   abort ();
-                 infiles[i].incompiler = lookup_compiler (infiles[i].name,
-                                                      strlen (infiles[i].name),
-                                                      infiles[i].language);
+                 if (!have_o_argbuf_index)
+                   fatal ("spec '%s' is invalid", input_file_compiler->spec);
+                 infiles[i].name = argbuf[have_o_argbuf_index];
+                 infiles[i].incompiler
+                   = lookup_compiler (infiles[i].name,
+                                      strlen (infiles[i].name),
+                                      infiles[i].language);
 
                  if (value < 0)
                    this_file_error = 1;
@@ -6535,7 +6536,6 @@ main (int argc, const char **argv)
        {
          delete_failure_queue ();
          error_count++;
-         break;
        }
       /* If this compilation succeeded, don't delete those files later.  */
       clear_failure_queue ();
@@ -6921,7 +6921,10 @@ used_arg (const char *p, int len)
          while (*q != ' ')
            {
              if (*q == '\0')
-               abort ();
+               {
+               invalid_matches:
+                 fatal ("multilib spec '%s' is invalid", multilib_matches);
+               }
              q++;
            }
          matches[i].len = q - matches[i].str;
@@ -6930,7 +6933,7 @@ used_arg (const char *p, int len)
          while (*q != ';' && *q != '\0')
            {
              if (*q == ' ')
-               abort ();
+               goto invalid_matches;
              q++;
            }
          matches[i].rep_len = q - matches[i].replace;
@@ -7110,7 +7113,11 @@ set_multilib_dir (void)
       while (*p != ';')
        {
          if (*p == '\0')
-           abort ();
+           {
+           invalid_exclusions:
+             fatal ("multilib exclusions '%s' is invalid",
+                    multilib_exclusions);
+           }
 
          if (! ok)
            {
@@ -7122,7 +7129,7 @@ set_multilib_dir (void)
          while (*p != ' ' && *p != ';')
            {
              if (*p == '\0')
-               abort ();
+               goto invalid_exclusions;
              ++p;
            }
 
@@ -7164,7 +7171,11 @@ set_multilib_dir (void)
       while (*p != ' ')
        {
          if (*p == '\0')
-           abort ();
+           {
+           invalid_select:
+             fatal ("multilib select '%s' is invalid",
+                    multilib_select);
+           }
          ++p;
        }
       this_path_len = p - this_path;
@@ -7176,7 +7187,7 @@ set_multilib_dir (void)
       while (*p != ';')
        {
          if (*p == '\0')
-           abort ();
+           goto invalid_select;
 
          if (! ok)
            {
@@ -7188,7 +7199,7 @@ set_multilib_dir (void)
          while (*p != ' ' && *p != ';')
            {
              if (*p == '\0')
-               abort ();
+               goto invalid_select;
              ++p;
            }
 
@@ -7301,7 +7312,11 @@ print_multilib_info (void)
       while (*p != ' ')
        {
          if (*p == '\0')
-           abort ();
+           {
+           invalid_select:
+             fatal ("multilib select '%s' is invalid", multilib_select);
+           }
+         
          ++p;
        }
 
@@ -7335,7 +7350,11 @@ print_multilib_info (void)
                int mp = 0;
 
                if (*e == '\0')
-                 abort ();
+                 {
+                 invalid_exclusion:
+                   fatal ("multilib exclusion '%s' is invalid",
+                          multilib_exclusions);
+                 }
 
                if (! m)
                  {
@@ -7348,7 +7367,7 @@ print_multilib_info (void)
                while (*e != ' ' && *e != ';')
                  {
                    if (*e == '\0')
-                     abort ();
+                     goto invalid_exclusion;
                    ++e;
                  }
 
@@ -7359,19 +7378,20 @@ print_multilib_info (void)
                    int len = e - this_arg;
 
                    if (*q == '\0')
-                     abort ();
+                     goto invalid_select;
 
                    arg = q;
 
                    while (*q != ' ' && *q != ';')
                      {
                        if (*q == '\0')
-                         abort ();
+                         goto invalid_select;
                        ++q;
                      }
 
-                   if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
-                       default_arg (this_arg, e - this_arg))
+                   if (! strncmp (arg, this_arg,
+                                  (len < q - arg) ? q - arg : len)
+                       || default_arg (this_arg, e - this_arg))
                      {
                        mp = 1;
                        break;
@@ -7402,7 +7422,8 @@ print_multilib_info (void)
       if (! skip)
        {
          /* If this is a duplicate, skip it.  */
-         skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len
+         skip = (last_path != 0
+                 && (unsigned int) (p - this_path) == last_path_len
                  && ! strncmp (last_path, this_path, last_path_len));
 
          last_path = this_path;
@@ -7422,7 +7443,7 @@ print_multilib_info (void)
              const char *arg;
 
              if (*q == '\0')
-               abort ();
+               goto invalid_select;
 
              if (*q == '!')
                arg = NULL;
@@ -7432,7 +7453,7 @@ print_multilib_info (void)
              while (*q != ' ' && *q != ';')
                {
                  if (*q == '\0')
-                   abort ();
+                   goto invalid_select;
                  ++q;
                }
 
@@ -7463,7 +7484,7 @@ print_multilib_info (void)
          int use_arg;
 
          if (*p == '\0')
-           abort ();
+           goto invalid_select;
 
          if (skip)
            {
@@ -7479,7 +7500,7 @@ print_multilib_info (void)
          while (*p != ' ' && *p != ';')
            {
              if (*p == '\0')
-               abort ();
+               goto invalid_select;
              if (use_arg)
                putchar (*p);
              ++p;
@@ -7553,3 +7574,24 @@ if_exists_else_spec_function (int argc, const char **argv)
 
   return argv[1];
 }
+
+/* replace-outfile built-in spec function.
+   This looks for the first argument in the outfiles array's name and replaces it
+   with the second argument.  */
+
+static const char *
+replace_outfile_spec_function (int argc, const char **argv)
+{
+  int i;
+  /* Must have exactly two arguments.  */
+  if (argc != 2)
+    abort ();
+  
+  for (i = 0; i < n_infiles; i++)
+    {
+      if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
+       outfiles[i] = xstrdup (argv[1]);
+    }
+  return NULL;
+}
+