OSDN Git Service

(fixup_var_refs_1, case ZERO_EXTRACT): Don't call fixup_memory_subreg
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index eba5f07..488a291 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -37,7 +37,7 @@ compilation is specified by a string called a "spec".  */
 #include <sys/stat.h>
 #include <errno.h>
 
-#ifndef _WIN32
+#ifndef NO_SYS_FILE_H
 #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
 #endif
 
@@ -63,9 +63,10 @@ extern int pexecute PROTO ((const char *, char * const *, const char *,
                            const char *, char **, char **, int));
 extern int pwait PROTO ((int, int *, int));
 /* Flag arguments to pexecute.  */
-#define PEXECUTE_FIRST  1
-#define PEXECUTE_LAST   2
-#define PEXECUTE_SEARCH 4
+#define PEXECUTE_FIRST   1
+#define PEXECUTE_LAST    2
+#define PEXECUTE_SEARCH  4
+#define PEXECUTE_VERBOSE 8
 
 #ifndef WIFSIGNALED
 #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
@@ -80,7 +81,11 @@ extern int pwait PROTO ((int, int *, int));
 #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
 #endif
 
-/* Define O_RDONLY if the system hasn't defined it for us. */
+#ifdef VMS
+#define exit __posix_exit
+#endif
+
+/* Define O_RDONLY if the system hasn't defined it for us.  */
 #ifndef O_RDONLY
 #define O_RDONLY 0
 #endif
@@ -100,11 +105,13 @@ extern int pwait PROTO ((int, int *, int));
 #endif
 
 /* By default there is no special suffix for executables.  */
-#ifndef EXECUTABLE_SUFFIX
+#ifdef EXECUTABLE_SUFFIX
+#define HAVE_EXECUTABLE_SUFFIX
+#else
 #define EXECUTABLE_SUFFIX ""
 #endif
 
-/* By default, the suffix for object files is ".o". */
+/* By default, the suffix for object files is ".o".  */
 #ifdef OBJECT_SUFFIX
 #define HAVE_OBJECT_SUFFIX
 #else
@@ -160,7 +167,7 @@ static int print_search_dirs;
 
 static char *print_file_name = NULL;
 
-/* As print_file_name, but search for executable file. */
+/* As print_file_name, but search for executable file.  */
 
 static char *print_prog_name = NULL;
 
@@ -246,7 +253,7 @@ static char *find_file              PROTO((char *));
 static int is_directory                PROTO((char *, char *, int));
 static void validate_switches  PROTO((char *));
 static void validate_all_switches PROTO((void));
-static void give_switch                PROTO((int, int));
+static void give_switch                PROTO((int, int, int));
 static int used_arg            PROTO((char *, int));
 static int default_arg         PROTO((char *, int));
 static void set_multilib_dir   PROTO((void));
@@ -355,6 +362,7 @@ or with constant text in a single argument.
        arguments.  CC considers `-o foo' as being one switch whose
        name starts with `o'.  %{o*} would substitute this text,
        including the space; thus, two arguments would be generated.
+ %{^S*} likewise, but don't put a blank between a switch and any args.
  %{S*:X} substitutes X if one or more switches whose names start with -S are
        specified to CC.  Note that the tail part of the -S option
        (i.e. the part matched by the `*') will be substituted for each
@@ -490,17 +498,33 @@ static char *startfile_spec = STARTFILE_SPEC;
 static char *switches_need_spaces = SWITCHES_NEED_SPACES;
 
 /* Some compilers have limits on line lengths, and the multilib_select
-   string can be very long, so we build it at run time.  */
+   and/or multilib_matches strings can be very long, so we build them at
+   run time.  */
 static struct obstack multilib_obstack;
-static char *multilib_raw[] = {
-#include "multilib.h"
-};
 static char *multilib_select;
+static char *multilib_matches;
+static char *multilib_defaults;
+#include "multilib.h"
+
+/* Check whether a particular argument is a default argument.  */
+
+#ifndef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "" }
+#endif
+
+static char *multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 
 #ifdef EXTRA_SPECS
 static struct { char *name, *spec; } extra_specs[] = { EXTRA_SPECS };
 #endif
 
+struct user_specs {
+  struct user_specs *next;
+  char *filename;
+};
+
+static struct user_specs *user_specs_head, *user_specs_tail;
+
 /* This defines which switch letters take arguments.  */
 
 #define DEFAULT_SWITCH_TAKES_ARG(CHAR)      \
@@ -521,7 +545,7 @@ static struct { char *name, *spec; } extra_specs[] = { EXTRA_SPECS };
   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
   || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
   || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
-  || !strcmp (STR, "isystem"))
+  || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
 
 #ifndef WORD_SWITCH_TAKES_ARG
 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
@@ -557,13 +581,22 @@ static int n_compilers;
 
 static struct compiler default_compilers[] =
 {
+  /* Add lists of suffixes of known languages here.  If those languages
+     were no present when we built the driver, we will hit these copies
+     and given a more meaningful error than "file not used since
+     linking is not done".  */
+  {".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"}, {".c++", "#C++"},
+  {".C", "#C++"}, {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
+  {".f", "#Fortran"}, {".for", "#Fortran"}, {".F", "#Fortran"},
+  {".fpp", "#Fortran"},
+  /* Next come the entries for C.  */
   {".c", "@c"},
   {"@c",
    "cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
        %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-       %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
+       %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs} \
         %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
@@ -584,7 +617,7 @@ static struct compiler default_compilers[] =
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
        %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-       %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
+       %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
         %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
@@ -597,7 +630,7 @@ static struct compiler default_compilers[] =
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
        %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-        %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
+        %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
         %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
@@ -621,7 +654,7 @@ static struct compiler default_compilers[] =
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
         %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
-        %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
+        %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
         %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
@@ -681,9 +714,11 @@ static char *link_command_spec = "\
  %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
-                       %{static:} %{L*} %{T*} %o\
+                       %{static:} %{L*} %o\
                        %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
-                       %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}}";
+                       %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
+                       %{T*}\
+                       \n }}}}}}";
 #else
 /* Use -L.  */
 static char *link_command_spec = "\
@@ -691,9 +726,11 @@ static char *link_command_spec = "\
  %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
                        %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
-                       %{static:} %{L*} %D %{T*} %o\
+                       %{static:} %{L*} %D %o\
                        %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
-                       %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}}";
+                       %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
+                       %{T*}\
+                       \n }}}}}}";
 #endif
 
 /* A vector of options to give to the linker.
@@ -743,7 +780,7 @@ struct option_map option_map[] =
    {"--comments", "-C", 0},
    {"--compile", "-c", 0},
    {"--debug", "-g", "oj"},
-   {"--define-macro", "-D", "a"},
+   {"--define-macro", "-D", "aj"},
    {"--dependencies", "-M", 0},
    {"--dump", "-d", "a"},
    {"--dumpbase", "-dumpbase", "a"},
@@ -755,7 +792,7 @@ struct option_map option_map[] =
    {"--imacros", "-imacros", "a"},
    {"--include", "-include", "a"},
    {"--include-barrier", "-I-", 0},
-   {"--include-directory", "-I", "a"},
+   {"--include-directory", "-I", "aj"},
    {"--include-directory-after", "-idirafter", "a"},
    {"--include-prefix", "-iprefix", "a"},
    {"--include-with-prefix", "-iwithprefix", "a"},
@@ -790,6 +827,7 @@ struct option_map option_map[] =
    {"--save-temps", "-save-temps", 0},
    {"--shared", "-shared", 0},
    {"--silent", "-q", 0},
+   {"--specs", "-specs=", "aj"},
    {"--static", "-static", 0},
    {"--symbolic", "-symbolic", 0},
    {"--target", "-b", "a"},
@@ -797,7 +835,7 @@ struct option_map option_map[] =
    {"--traditional", "-traditional", 0},
    {"--traditional-cpp", "-traditional-cpp", 0},
    {"--trigraphs", "-trigraphs", 0},
-   {"--undefine-macro", "-U", "a"},
+   {"--undefine-macro", "-U", "aj"},
    {"--use-version", "-V", "a"},
    {"--user-dependencies", "-MM", 0},
    {"--verbose", "-v", 0},
@@ -973,8 +1011,8 @@ char *
 my_strerror(e)
      int e;
 {
-
 #ifdef HAVE_STRERROR
+
   return strerror(e);
 
 #else
@@ -1135,23 +1173,24 @@ skip_whitespace (p)
   return p;
 }
 \f
-/* Structure to keep track of the specs that have been defined so far.  These
-   are accessed using %(specname) or %[specname] in a compiler or link spec. */
+/* Structure to keep track of the specs that have been defined so far.
+   These are accessed using %(specname) or %[specname] in a compiler
+   or link spec.  */
 
 struct spec_list
 {
-  char *name;                 /* Name of the spec. */
-  char *spec;                 /* The spec itself. */
-  struct spec_list *next;     /* Next spec in linked list. */
+  char *name;                 /* Name of the spec.  */
+  char *spec;                 /* The spec itself.  */
+  struct spec_list *next;     /* Next spec in linked list.  */
 };
 
-/* List of specs that have been defined so far. */
+/* List of specs that have been defined so far.  */
 
 static struct spec_list *specs = (struct spec_list *) 0;
 \f
 /* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
    removed; If the spec starts with a + then SPEC is added to the end of the
-   current spec. */
+   current spec.  */
 
 static void
 set_spec (name, spec)
@@ -1212,6 +1251,14 @@ set_spec (name, spec)
     cross_compile = atoi (sl->spec);
   else if (! strcmp (name, "multilib"))
     multilib_select = sl->spec;
+  else if (! strcmp (name, "multilib_matches"))
+    multilib_matches = sl->spec;
+  else if (! strcmp (name, "multilib_extra"))
+    multilib_extra = sl->spec;
+  else if (! strcmp (name, "multilib_defaults"))
+    multilib_defaults = sl->spec;
+  else if (! strcmp (name, "version"))
+    compiler_version = sl->spec;
 #ifdef EXTRA_SPECS
   else
     {
@@ -1270,12 +1317,12 @@ static int signal_count;
 
 static char *programname;
 \f
-/* Structures to keep track of prefixes to try when looking for files. */
+/* Structures to keep track of prefixes to try when looking for files.  */
 
 struct prefix_list
 {
-  char *prefix;               /* String to prepend to the path. */
-  struct prefix_list *next;   /* Next in linked list. */
+  char *prefix;               /* String to prepend to the path.  */
+  struct prefix_list *next;   /* Next in linked list.  */
   int require_machine_suffix; /* Don't use without machine_suffix.  */
   /* 2 means try both machine_suffix and just_machine_suffix.  */
   int *used_flag_ptr;        /* 1 if a file was found with this prefix.  */
@@ -1288,11 +1335,11 @@ struct path_prefix
   char *name;                 /* Name of this list (used in config stuff) */
 };
 
-/* List of prefixes to try when looking for executables. */
+/* List of prefixes to try when looking for executables.  */
 
 static struct path_prefix exec_prefixes = { 0, 0, "exec" };
 
-/* List of prefixes to try when looking for startup (crt0) files. */
+/* List of prefixes to try when looking for startup (crt0) files.  */
 
 static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
 
@@ -1633,7 +1680,8 @@ build_search_list (paths, prefix, check_dir_p)
   return obstack_finish (&collect_obstack);
 }
 
-/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect.  */
+/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
+   for collect.  */
 
 static void
 putenv_from_prefixes (paths, env_var)
@@ -1645,7 +1693,7 @@ putenv_from_prefixes (paths, env_var)
 \f
 /* Search for NAME using the prefix list PREFIXES.  MODE is passed to
    access to check permissions.
-   Return 0 if not found, otherwise return its name, allocated with malloc. */
+   Return 0 if not found, otherwise return its name, allocated with malloc.  */
 
 static char *
 find_a_file (pprefix, name, mode)
@@ -1847,7 +1895,7 @@ unused_prefix_warnings (pprefix)
     }
 }
 
-/* Get rid of all prefixes built up so far in *PLISTP. */
+/* Get rid of all prefixes built up so far in *PLISTP.  */
 
 static void
 free_path_prefix (pprefix)
@@ -1909,7 +1957,7 @@ execute ()
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
       {                                /* each command.  */
-#if defined (__MSDOS__) || defined (_WIN32) || defined (OS2)
+#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN32__)) || defined (OS2)
         fatal ("-pipe not supported");
 #endif
        argbuf[i] = 0;  /* termination of command args.  */
@@ -1965,7 +2013,8 @@ execute ()
                                  ((i == 0 ? PEXECUTE_FIRST : 0)
                                   | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
                                   | (string == commands[i].prog
-                                     ? PEXECUTE_SEARCH : 0)));
+                                     ? PEXECUTE_SEARCH : 0)
+                                  | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
 
       if (commands[i].pid == -1)
        pfatal_pexecute (errmsg_fmt, errmsg_arg);
@@ -2067,6 +2116,55 @@ static int warn_std;
 /* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
 static int *warn_std_ptr = 0;
 
+\f
+#if defined(HAVE_OBJECT_SUFFIX) || defined(HAVE_EXECUTABLE_SUFFIX)
+
+/* Convert NAME to a new name if it is the standard suffix.  DO_EXE
+   is true if we should look for an executable suffix as well.  */
+
+static char *
+convert_filename (name, do_exe)
+     char *name;
+     int do_exe;
+{
+  int i;
+  int len = strlen (name);
+
+#ifdef HAVE_OBJECT_SUFFIX
+  /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj".  */
+  if (len > 2
+      && name[len - 2] == '.'
+      && name[len - 1] == 'o')
+    {
+      obstack_grow (&obstack, name[i], len - 2);
+      obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
+      name = obstack_finish (&obstack);
+    }
+#endif
+
+#ifdef HAVE_EXECUTABLE_SUFFIX
+  /* If there is no filetype, make it the executable suffix (which includes
+     the ".").  But don't get confused if we have just "-o".  */
+  if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
+    return name;
+
+  for (i = len - 1; i >= 0; i--)
+    if (name[i] == '/' || name[i] == DIR_SEPARATOR)
+      break;
+
+  for (i++; i < len; i++)
+    if (name[i] == '.')
+      return name;
+
+  obstack_grow (&obstack, name, len);
+  obstack_grow0 (&obstack, EXECUTABLE_SUFFIX, strlen (EXECUTABLE_SUFFIX));
+  name = obstack_finish (&obstack);
+#endif
+
+  return name;
+}
+#endif
+\f
 /* Create the vector `switches' and its contents.
    Store its length in `n_switches'.  */
 
@@ -2208,6 +2306,11 @@ process_command (argc, argv)
   /* Convert new-style -- options to old-style.  */
   translate_options (&argc, &argv);
 
+#ifdef LANG_SPECIFIC_DRIVER
+  /* Do language-specific adjustment/addition of flags.  */
+  lang_specific_driver (&fatal, &argc, &argv);
+#endif
+
   /* Scan argv twice.  Here, the first time, just count how many switches
      there will be in their vector, and how many input files in theirs.
      Here we also parse the switches that cc itself uses (e.g. -v).  */
@@ -2230,7 +2333,11 @@ process_command (argc, argv)
          printf ("*signed_char:\n%s\n\n", signed_char_spec);
          printf ("*predefines:\n%s\n\n", cpp_predefines);
          printf ("*cross_compile:\n%d\n\n", cross_compile);
+         printf ("*version:\n%s\n\n", compiler_version);
          printf ("*multilib:\n%s\n\n", multilib_select);
+         printf ("*multilib_defaults:\n%s\n\n", multilib_defaults);
+         printf ("*multilib_extra:\n%s\n\n", multilib_extra);
+         printf ("*multilib_matches:\n%s\n\n", multilib_matches);
 
 #ifdef EXTRA_SPECS
          {
@@ -2349,6 +2456,36 @@ process_command (argc, argv)
          save_temps_flag = 1;
          n_switches++;
        }
+      else if (strcmp (argv[i], "-specs") == 0)
+       {
+         struct user_specs *user = (struct user_specs *)
+           xmalloc (sizeof (struct user_specs));
+         if (++i >= argc)
+           fatal ("argument to `-specs' is missing");
+
+         user->next = (struct user_specs *)0;
+         user->filename = argv[i];
+         if (user_specs_tail)
+           user_specs_tail->next = user;
+         else
+           user_specs_head = user;
+         user_specs_tail = user;
+       }
+      else if (strncmp (argv[i], "-specs=", 7) == 0)
+       {
+         struct user_specs *user = (struct user_specs *)
+           xmalloc (sizeof (struct user_specs));
+         if (strlen (argv[i]) == 7)
+           fatal ("argument to `-specs=' is missing");
+
+         user->next = (struct user_specs *)0;
+         user->filename = argv[i]+7;
+         if (user_specs_tail)
+           user_specs_tail->next = user;
+         else
+           user_specs_head = user;
+         user_specs_tail = user;
+       }
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
          register char *p = &argv[i][1];
@@ -2442,6 +2579,11 @@ process_command (argc, argv)
 
            case 'o':
              have_o = 1;
+#if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
+             argv[i] = convert_filename (argv[i], 1);
+             if (p[1] == 0)
+               argv[i+1] = convert_filename (argv[i+1], 1);
+#endif
              goto normal_switch;
 
            default:
@@ -2594,6 +2736,10 @@ process_command (argc, argv)
          infiles[n_infiles].language = 0;
          infiles[n_infiles++].name = argv[i];
        }
+      else if (strcmp (argv[i], "-specs") == 0)
+       i++;
+      else if (strncmp (argv[i], "-specs=", 7) == 0)
+       ;
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
          register char *p = &argv[i][1];
@@ -2672,20 +2818,7 @@ process_command (argc, argv)
       else
        {
 #ifdef HAVE_OBJECT_SUFFIX
-         /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj".  */
-         if (strlen (argv[i]) > 2
-             && argv[i][strlen (argv[i]) - 2] == '.'
-             && argv[i][strlen (argv[i]) - 1] == 'o')
-           {
-             int j;
-
-             for (j = 0; j < strlen (argv[i]) - 2; j++)
-               obstack_1grow (&obstack, argv[i][j]);
-
-             obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
-             obstack_1grow (&obstack, 0);
-             argv[i] = obstack_finish (&obstack);
-           }
+         argv[i] = convert_filename (argv[i], 0);
 #endif
 
          if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0)
@@ -3474,7 +3607,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              int len;
 
              /* The string after the S/P is the name of a spec that is to be
-                processed. */
+                processed.  */
              while (*p && *p != ')' && *p != ']')
                p++;
 
@@ -3504,6 +3637,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                         every -D and at the end of each arg,  */
                      while (1)
                        {
+                         int flag;
+
                          if (! strncmp (y, "-D", 2))
                            {
                              *x++ = '-';
@@ -3511,16 +3646,18 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                              *x++ = '_';
                              *x++ = '_';
                              y += 2;
+                             flag = 1;
+                             continue;
                            }
-                         else if (*y == ' ' || *y == 0)
+                          else if (flag && (*y == ' ' || *y == '\t' || *y == '='
+                                            || *y == '}' || *y == 0))
                            {
                              *x++ = '_';
                              *x++ = '_';
-                             if (*y == 0)
-                               break;
-                             else
-                               *x++ = *y++;
+                             flag = 0;
                            }
+                          if (*y == 0)
+                           break;
                          else
                            *x++ = *y++;
                        }
@@ -3612,6 +3749,11 @@ handle_braces (p)
   int pipe_p = 0;
   int negate = 0;
   int suffix = 0;
+  int include_blanks = 1;
+
+  if (*p == '^')
+    /* A '^' after the open-brace means to not give blanks before args.  */
+    include_blanks = 0, ++p;
 
   if (*p == '|')
     /* A `|' after the open-brace means,
@@ -3677,7 +3819,7 @@ handle_braces (p)
       for (i = 0; i < n_switches; i++)
        if (!strncmp (switches[i].part1, filter, p - filter)
            && check_live_switch (i, p - filter))
-         give_switch (i, 0);
+         give_switch (i, 0, include_blanks);
     }
   else
     {
@@ -3716,7 +3858,7 @@ handle_braces (p)
                  {
                    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
                    /* Pass any arguments this switch has.  */
-                   give_switch (i, 1);
+                   give_switch (i, 1, 1);
                  }
 
              return q;
@@ -3760,7 +3902,7 @@ handle_braces (p)
        {
          if (*p == '}')
            {
-             give_switch (i, 0);
+             give_switch (i, 0, include_blanks);
            }
          else
            {
@@ -3822,7 +3964,7 @@ check_live_switch (switchnum, prefix_length)
     case 'W':  case 'f':  case 'm':
       if (! strncmp (name + 1, "no-", 3))
        {
-         /* We have Xno-YYY, search for XYYY. */
+         /* We have Xno-YYY, search for XYYY.  */
          for (i = switchnum + 1; i < n_switches; i++)
            if (switches[i].part1[0] == name[0]
                && ! strcmp (&switches[i].part1[1], &name[4]))
@@ -3861,28 +4003,35 @@ check_live_switch (switchnum, prefix_length)
    the vector of switches gcc received, which is `switches'.
    This cannot fail since it never finishes a command line.
 
-   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
+   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.
+
+   If INCLUDE_BLANKS is nonzero, then we include blanks before each argument
+   of the switch.  */
 
 static void
-give_switch (switchnum, omit_first_word)
+give_switch (switchnum, omit_first_word, include_blanks)
      int switchnum;
      int omit_first_word;
+     int include_blanks;
 {
   if (!omit_first_word)
     {
       do_spec_1 ("-", 0, NULL_PTR);
       do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
     }
-  do_spec_1 (" ", 0, NULL_PTR);
+
   if (switches[switchnum].args != 0)
     {
       char **p;
       for (p = switches[switchnum].args; *p; p++)
        {
+         if (include_blanks)
+           do_spec_1 (" ", 0, NULL_PTR);
          do_spec_1 (*p, 1, NULL_PTR);
-         do_spec_1 (" ", 0, NULL_PTR);
        }
     }
+
+  do_spec_1 (" ", 0, NULL_PTR);
   switches[switchnum].valid = 1;
 }
 \f
@@ -3991,6 +4140,7 @@ main (argc, argv)
   char *explicit_link_files;
   char *specs_file;
   char *p;
+  struct user_specs *uptr;
 
   p = argv[0] + strlen (argv[0]);
   while (p != argv[0] && p[-1] != '/' && p[-1] != DIR_SEPARATOR) --p;
@@ -4014,17 +4164,41 @@ main (argc, argv)
 
   obstack_init (&obstack);
 
-  /* Build multilib_select from the separate lines that make up each multilib
-     selection.  */
+  /* Build multilib_select, et. al from the separate lines that make up each
+     multilib selection.  */
   {
     char **q = multilib_raw;
+    int need_space;
 
     obstack_init (&multilib_obstack);
-    while ((p = *q++) != (char *)0)
+    while ((p = *q++) != (char *) 0)
       obstack_grow (&multilib_obstack, p, strlen (p));
 
     obstack_1grow (&multilib_obstack, 0);
     multilib_select = obstack_finish (&multilib_obstack);
+
+    q = multilib_matches_raw;
+    while ((p = *q++) != (char *) 0)
+      obstack_grow (&multilib_obstack, p, strlen (p));
+
+    obstack_1grow (&multilib_obstack, 0);
+    multilib_matches = obstack_finish (&multilib_obstack);
+
+    need_space = FALSE;
+    for (i = 0;
+        i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]);
+        i++)
+      {
+       if (need_space)
+         obstack_1grow (&multilib_obstack, ' ');
+       obstack_grow (&multilib_obstack,
+                     multilib_defaults_raw[i],
+                     strlen (multilib_defaults_raw[i]));
+       need_space = TRUE;
+      }
+
+    obstack_1grow (&multilib_obstack, 0);
+    multilib_defaults = obstack_finish (&multilib_obstack);
   }
 
   /* Set up to remember the pathname of gcc and any options
@@ -4079,6 +4253,14 @@ main (argc, argv)
     }
 #endif
 
+  /* Process any user specified specs in the order given on the command
+     line.  */
+  for (uptr = user_specs_head; uptr; uptr = uptr->next)
+    {
+      char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
+      read_specs (filename ? filename : uptr->filename);
+    }
+
   /* If not cross-compiling, look for startfiles in the standard places.  */
   /* The fact that these are done here, after reading the specs file,
      means that it cannot be found in these directories.
@@ -4257,6 +4439,10 @@ main (argc, argv)
          register char *p;
          int len;
 
+         if (cp->spec[0][0] == '#')
+           error ("%s: %s compiler not installed on this system",
+                  input_filename, &cp->spec[0][1]);
+
          input_basename = input_filename;
          for (p = input_filename; *p; p++)
            if (*p == '/' || *p == DIR_SEPARATOR)
@@ -4486,7 +4672,7 @@ concat VPROTO((char *first, ...))
   char *first;
 #endif
 
-  /* First compute the size of the result and get sufficient memory. */
+  /* First compute the size of the result and get sufficient memory.  */
 
   VA_START (args, first);
 #ifndef __STDC__
@@ -4505,7 +4691,7 @@ concat VPROTO((char *first, ...))
   newstr = (char *) xmalloc (length + 1);
   va_end (args);
 
-  /* Now copy the individual pieces to the result string. */
+  /* Now copy the individual pieces to the result string.  */
 
   VA_START (args, first);
 #ifndef __STDC__
@@ -4557,18 +4743,6 @@ pfatal_pexecute (errmsg_fmt, errmsg_arg)
      char *errmsg_fmt;
      char *errmsg_arg;
 {
-  char buf[30];
-  char *s;
-
-  /* ??? Why doesn't my_strerror handle this?  */
-  if (errno < sys_nerr)
-    s = my_strerror (errno);
-  else
-    {
-      sprintf (buf, "unknown error %d", errno);
-      s = buf;
-    }
-
   if (errmsg_arg)
     {
       /* Space for trailing '\0' is in %s.  */
@@ -4577,7 +4751,7 @@ pfatal_pexecute (errmsg_fmt, errmsg_arg)
       errmsg_fmt = msg;
     }
 
-  fatal ("%s: %s", errmsg_fmt, s);
+  fatal ("%s: %s", errmsg_fmt, my_strerror (errno));
 }
 
 /* More 'friendly' abort that prints the line and file.
@@ -4604,7 +4778,7 @@ fatal VPROTO((char *format, ...))
   VA_START (ap, format);
 
 #ifndef __STDC__
-  format = va_arg (ap, char*);
+  format = va_arg (ap, char *);
 #endif
 
   fprintf (stderr, "%s: ", programname);
@@ -4626,7 +4800,7 @@ error VPROTO((char *format, ...))
   VA_START (ap, format);
 
 #ifndef __STDC__
-  format = va_arg (ap, char*);
+  format = va_arg (ap, char *);
 #endif
 
   fprintf (stderr, "%s: ", programname);
@@ -4820,43 +4994,119 @@ validate_switches (start)
     }
 }
 \f
-/* Check whether a particular argument was used.  */
+/* Check whether a particular argument was used.  The first time we
+   canonialize the switches to keep only the ones we care about.  */
 
 static int
 used_arg (p, len)
      char *p;
      int len;
 {
-  int i;
+  struct mswitchstr {
+    char *str;
+    char *replace;
+    int len;
+    int rep_len;
+  };
+
+  static struct mswitchstr *mswitches;
+  static int n_mswitches;
+  int i, j;
+
+  if (!mswitches)
+    {
+      struct mswitchstr *matches;
+      char *q;
+      int cnt = 0;
+
+      /* Break multilib_matches into the component strings of string and replacement
+         string */
+      for (q = multilib_matches; *q != '\0'; q++)
+       if (*q == ';')
+         cnt++;
+
+      matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
+      i = 0;
+      q = multilib_matches;
+      while (*q != '\0')
+       {
+         matches[i].str = q;
+         while (*q != ' ')
+           {
+             if (*q == '\0')
+               abort ();
+             q++;
+           }
+         *q = '\0';
+         matches[i].len = q - matches[i].str;
 
-  for (i = 0; i < n_switches; i++)
-    if (! strncmp (switches[i].part1, p, len)
-       && strlen (switches[i].part1) == len)
-      return 1;
-  return 0;
-}
+         matches[i].replace = ++q;
+         while (*q != ';' && *q != '\0')
+           {
+             if (*q == ' ')
+               abort ();
+             q++;
+           }
+         matches[i].rep_len = q - matches[i].replace;
+         i++;
+         if (*q == ';')
+           *q++ = '\0';
+         else
+           break;
+       }
 
-/* Check whether a particular argument is a default argument.  */
+      /* Now build a list of the replacement string for switches that we care
+        about.  Make sure we allocate at least one entry.  This prevents
+        xmalloc from calling fatal, and prevents us from re-executing this
+        block of code.  */
+      mswitches
+       = (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr))
+                                        * (n_switches ? n_switches : 1));
+      for (i = 0; i < n_switches; i++)
+       {
+         int xlen = strlen (switches[i].part1);
+         for (j = 0; j < cnt; j++)
+           if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str))
+             {
+               mswitches[n_mswitches].str = matches[j].replace;
+               mswitches[n_mswitches].len = matches[j].rep_len;
+               mswitches[n_mswitches].replace = (char *)0;
+               mswitches[n_mswitches].rep_len = 0;
+               n_mswitches++;
+               break;
+             }
+       }
+    }
 
-#ifndef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { NULL }
-#endif
+  for (i = 0; i < n_mswitches; i++)
+    if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
+      return 1;
 
-static char *multilib_defaults[] = MULTILIB_DEFAULTS;
+  return 0;
+}
 
 static int
 default_arg (p, len)
      char *p;
      int len;
 {
-  int count = sizeof multilib_defaults / sizeof multilib_defaults[0];
+  char *start, *end;
   int i;
 
-  for (i = 0; i < count; i++)
-    if (multilib_defaults[i] != NULL
-       && strncmp (multilib_defaults[i], p, len) == 0
-       && multilib_defaults[i][len] == '\0')
-      return 1;
+  for (start = multilib_defaults; *start != '\0'; start = end+1)
+    {
+      while (*start == ' ' || *start == '\t')
+       start++;
+
+      if (*start == '\0')
+       break;
+
+      for (end = start+1; *end != ' ' && *end != '\t' && *end != '\0'; end++)
+       ;
+
+      if ((end - start) == len && strncmp (p, start, len) == 0)
+       return 1;
+    }
 
   return 0;
 }
@@ -5084,7 +5334,28 @@ print_multilib_info ()
        }
 
       if (! skip)
-       putchar ('\n');
+       {
+         /* If there are extra options, print them now */
+         if (multilib_extra && *multilib_extra)
+           {
+             int print_at = TRUE;
+             char *q;
+
+             for (q = multilib_extra; *q != '\0'; q++)
+               {
+                 if (*q == ' ')
+                   print_at = TRUE;
+                 else
+                   {
+                     if (print_at)
+                       putchar ('@');
+                     putchar (*q);
+                     print_at = FALSE;
+                   }
+               }
+           }
+         putchar ('\n');
+       }
 
       ++p;
     }