OSDN Git Service

emit-rtl.c (init_emit): Clear sequence_stack.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index b161350..f50e2ec 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -30,7 +30,6 @@ CC recognizes how to compile each input file by suffixes in the file names.
 Once it knows which kind of compilation to perform, the procedure for
 compilation is specified by a string called a "spec".  */
 \f
-#include <stdio.h>
 #include <sys/types.h>
 #include <ctype.h>
 #include <signal.h>
@@ -40,6 +39,7 @@ compilation is specified by a string called a "spec".  */
 #include "config.h"
 #include "obstack.h"
 #include "gvarargs.h"
+#include <stdio.h>
 
 #ifndef R_OK
 #define R_OK 4
@@ -144,6 +144,10 @@ static int cross_compile = 1;
 static int cross_compile = 0;
 #endif
 
+/* The number of errors that have occurred; the link phase will not be
+   run if this is non-zero.  */
+static int error_count = 0;
+
 /* This is the obstack which we use to allocate many strings.  */
 
 static struct obstack obstack;
@@ -205,6 +209,7 @@ or with constant text in a single argument.
        concatenation of constant strings on the end, as in `%g.s'.
        %g also has the same effect of %d.
  %u    like %g, but make the temporary file name unique.
+ %U    returns the last file name generated with %u.
  %d    marks the argument containing or following the %d as a
        temporary file name, so that that file will be deleted if CC exits
        successfully.  Unlike %g, this contributes no text to the argument.
@@ -250,6 +255,7 @@ or with constant text in a single argument.
  %C     process CPP_SPEC as a spec.  A capital C is actually used here.
  %1    process CC1_SPEC as a spec.
  %2    process CC1PLUS_SPEC as a spec.
+ %|    output "-" if the input for the current command is coming from a pipe.
  %*    substitute the variable part of a matched option.  (See below.)
        Note that each comma in the substituted string is replaced by
        a single space.
@@ -261,7 +267,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*:X} substitutes X if one or more switches whose names with -S are
+ %{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
        occurrence of %* within X.
@@ -355,9 +361,13 @@ proper position among the other output files.  */
 
 /* This spec is used for telling cpp whether char is signed or not.  */
 #ifndef SIGNED_CHAR_SPEC
-#define SIGNED_CHAR_SPEC  \
-  (DEFAULT_SIGNED_CHAR ? "%{funsigned-char:-D__CHAR_UNSIGNED__}"       \
-   : "%{!fsigned-char:-D__CHAR_UNSIGNED__}")
+/* Use #if rather than ?:
+   because MIPS C compiler rejects like ?: in initializers.  */
+#if DEFAULT_SIGNED_CHAR
+#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
+#else
+#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
+#endif
 #endif
 
 static char *cpp_spec = CPP_SPEC;
@@ -387,7 +397,8 @@ static char *switches_need_spaces = SWITCHES_NEED_SPACES;
 
 #ifndef WORD_SWITCH_TAKES_ARG
 #define WORD_SWITCH_TAKES_ARG(STR)                     \
- (!strcmp (STR, "Tdata") || !strcmp (STR, "include")   \
+ (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")     \
+  || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info"))
 #endif
 \f
@@ -397,8 +408,9 @@ struct compiler
 {
   char *suffix;                        /* Use this compiler for input files
                                   whose names end in this suffix.  */
-  char *spec;                  /* To use this compiler, pass this spec
-                                  to do_spec.  */
+
+  char *spec[4];               /* To use this compiler, concatenate these
+                                  specs and pass to do_spec.  */
 };
 
 /* Pointer to a vector of `struct compiler' that gives the spec for
@@ -422,16 +434,16 @@ static struct compiler default_compilers[] =
 {
   {".c", "@c"},
   {"@c",
-   "cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{D*} %{U*} %{I*} %{i*} %{P} %I\
+   "cpp -lang-c %{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}\
         -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
-       %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+       %{!undef:%{!ansi:%p} %P} %{trigraphs} \
         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\
-        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\
-    %{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
+        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
+   "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
                   %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\
                   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
                   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
@@ -442,28 +454,28 @@ static struct compiler default_compilers[] =
                      %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
                       %{!pipe:%g.s} %A\n }}}}"},
   {"-",
-   "%{E:cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{D*} %{U*} %{I*} %{i*} %{P} %I\
+   "%{E:cpp -lang-c %{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}\
         -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
         %i %W{o*}}\
     %{!E:%e-E required when input is from standard input}"},
   {".m", "@objective-c"},
   {"@objective-c",
-   "cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{D*} %{U*} %{I*} %{i*} %{P} %I\
+   "cpp -lang-objc %{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}\
         -undef -D__OBJC__ -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\
-        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\
-    %{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
+        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
+   "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
                   %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\
                   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
                   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
@@ -477,32 +489,32 @@ static struct compiler default_compilers[] =
   {".h", "@c-header"},
   {"@c-header",
    "%{!E:%eCompilation of header file requested} \
-    cpp %{nostdinc*} %{C} %{v} %{A*} %{D*} %{U*} %{I*} %{i*} %{P} %I\
+    cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
         %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} \
         -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
         %i %W{o*}"},
   {".cc", "@c++"},
   {".cxx", "@c++"},
   {".C", "@c++"},
   {"@c++",
-   "cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{D*} %{U*} %{I*} %{i*} %{P} %I\
+   "cpp -lang-c++ %{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} \
        -undef -D__GNUC__=2 -D__GNUG__=2 -D__cplusplus \
        %{ansi:-trigraphs -$ -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional} %{trigraphs}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\
-        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\
-    %{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.i} %1 %2\
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
+        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
+   "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.i} %1 %2\
                   %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
                   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
-                  %{v:-version} %{pg:-p} %{p} %{f*}\
+                  %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\
                   %{aux-info*}\
                   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
                   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
@@ -523,7 +535,7 @@ static struct compiler default_compilers[] =
   {"@c++-cpp-output",
    "cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
            %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
-           %{v:-version} %{pg:-p} %{p} %{f*}\
+           %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\
            %{aux-info*}\
            %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
            %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
@@ -536,15 +548,15 @@ static struct compiler default_compilers[] =
             %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %i %A\n }"},
   {".S", "@assembler-with-cpp"},
   {"@assembler-with-cpp",
-   "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{D*} %{U*} %{I*} %{i*} %{P} %I\
+   "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
        %{C:%{!E:%eGNU C does not support -C without using -E}}\
        %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{trigraphs} \
         -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
-       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\
-        %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\
-    %{!M:%{!MM:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
+       %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
+        %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
+   "%{!M:%{!MM:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
                     %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
                    %{!pipe:%g.s} %A\n }}}}"},
   /* Mark end of table */
@@ -558,23 +570,35 @@ static int n_default_compilers
 
 /* Here is the spec for running the linker, after compiling all files.  */
 
-#ifdef LINK_LIBGCC_SPECIAL
-/* Have gcc do the search for libgcc.a.  */
 /* -u* was put back because both BSD and SysV seem to support it.  */
 /* %{static:} simply prevents an error message if the target machine
    doesn't handle -static.  */
+#ifdef LINK_LIBGCC_SPECIAL_1
+/* Have gcc do the search for libgcc.a, but generate -L options as usual.  */
 static char *link_command_spec = "\
-%{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+%{!fsyntax-only: \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
-                       %{!A:%{!nostdlib:%S}} %{static:}\
-                       %{L*} %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}";
+                       %{!A:%{!nostartfiles:%{!nostdlib:%S}}} %{static:}\
+                       %{L*} %D %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}}";
+#else
+#ifdef LINK_LIBGCC_SPECIAL
+/* Have gcc do the search for libgcc.a, and don't generate -L options.  */
+static char *link_command_spec = "\
+%{!fsyntax-only: \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+                       %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
+                       %{!A:%{!nostartfiles:%{!nostdlib:%S}}} %{static:}\
+                       %{L*} %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}}";
 #else
 /* Use -L and have the linker do the search for -lgcc.  */
 static char *link_command_spec = "\
-%{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+%{!fsyntax-only: \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
                        %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
-                       %{!A:%{!nostdlib:%S}} %{static:}\
-                       %{L*} %D %o %{!nostdlib:-lgcc %L -lgcc %{!A:%E}}\n }}}}}";
+                       %{!A:%{!nostartfiles:%{!nostdlib:%S}}} %{static:}\
+                       %{L*} %D %o %{!nostdlib:-lgcc %L -lgcc %{!A:%E}}\n }}}}}}";
+#endif
 #endif
 
 /* A vector of options to give to the linker.
@@ -589,6 +613,211 @@ static char **linker_options;
 static int n_assembler_options;
 static char **assembler_options;
 \f
+/* Define how to map long options into short ones.  */
+
+/* This structure describes one mapping.  */
+struct option_map
+{
+  /* The long option's name.  */
+  char *name;
+  /* The equivalent short option.  */
+  char *equivalent;
+  /* Argument info.  A string of flag chars; NULL equals no options.
+     a => argument required.
+     o => argument optional.
+     j => join argument to equivalent, making one word.
+     * => allow other text after NAME as an argument.  */
+  char *arg_info;
+};
+
+/* This is the table of mappings.  Mappings are tried sequentially
+   for each option encountered; the first one that matches, wins.  */
+
+struct option_map option_map[] =
+ {
+   {"--profile-blocks", "-a", 0},
+   {"--target", "-b", "a"},
+   {"--compile", "-c", 0},
+   {"--dump", "-d", "a"},
+   {"--entry", "-e", 0},
+   {"--debug", "-g", "oj"},
+   {"--include", "-include", "a"},
+   {"--imacros", "-imacros", "a"},
+   {"--include-prefix", "-iprefix", "a"},
+   {"--include-directory-after", "-idirafter", "a"},
+   {"--include-with-prefix", "-iwithprefix", "a"},
+   {"--machine-", "-m", "*j"},
+   {"--machine", "-m", "aj"},
+   {"--no-standard-includes", "-nostdinc", 0},
+   {"--no-standard-libraries", "-nostdlib", 0},
+   {"--no-precompiled-includes", "-noprecomp", 0},
+   {"--output", "-o", "a"},
+   {"--profile", "-p", 0},
+   {"--quiet", "-q", 0},
+   {"--silent", "-q", 0},
+   {"--force-link", "-u", "a"},
+   {"--verbose", "-v", 0},
+   {"--no-warnings", "-w", 0},
+   {"--language", "-x", "a"},
+
+   {"--assert", "-A", "a"},
+   {"--prefix", "-B", "a"},
+   {"--comments", "-C", 0},
+   {"--define-macro", "-D", "a"},
+   {"--preprocess", "-E", 0},
+   {"--trace-includes", "-H", 0},
+   {"--include-directory", "-I", "a"},
+   {"--include-barrier", "-I-", 0},
+   {"--library-directory", "-L", "a"},
+   {"--dependencies", "-M", 0},
+   {"--user-dependencies", "-MM", 0},
+   {"--write-dependencies", "-MD", 0},
+   {"--write-user-dependencies", "-MMD", 0},
+   {"--optimize", "-O", "oj"},
+   {"--no-line-commands", "-P", 0},
+   {"--assemble", "-S", 0},
+   {"--undefine-macro", "-U", "a"},
+   {"--version", "-V", "a"},
+   {"--for-assembler", "-Wa", "a"},
+   {"--extra-warnings", "-W", 0},
+   {"--all-warnings", "-Wall", 0},
+   {"--warn-", "-W", "*j"},
+   {"--for-linker", "-Xlinker", "a"},
+
+   {"--ansi", "-ansi", 0},
+   {"--traditional", "-traditional", 0},
+   {"--traditional-cpp", "-traditional-cpp", 0},
+   {"--trigraphs", "-trigraphs", 0},
+   {"--pipe", "-pipe", 0},
+   {"--dumpbase", "-dumpbase", "a"},
+   {"--pedantic", "-pedantic", 0},
+   {"--pedantic-errors", "-pedantic-errors", 0},
+   {"--save-temps", "-save-temps", 0},
+   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
+   {"--static", "-static", 0},
+   {"--shared", "-shared", 0},
+   {"--symbolic", "-symbolic", 0},
+   {"--", "-f", "*j"}
+ };
+\f
+/* Translate the options described by *ARGCP and *ARGVP.
+   Make a new vector and store it back in *ARGVP,
+   and store its length in *ARGVC.  */
+
+static void
+translate_options (argcp, argvp)
+     int *argcp;
+     char ***argvp;
+{
+  int i, j;
+  int argc = *argcp;
+  char **argv = *argvp;
+  char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
+  int newindex = 0;
+
+  i = 0;
+  newv[newindex++] = argv[i++];
+
+  while (i < argc)
+    {
+      /* Translate -- options.  */
+      if (argv[i][0] == '-' && argv[i][1] == '-')
+       {
+         /* Find a mapping that applies to this option.  */
+         for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
+           {
+             int optlen = strlen (option_map[j].name);
+             int complen = strlen (argv[i]);
+             if (complen > optlen)
+               complen = optlen;
+             if (!strncmp (argv[i], option_map[j].name, complen))
+               {
+                 int extra = strlen (argv[i]) > optlen;
+                 char *arg = 0;
+
+                 if (extra)
+                   {
+                     /* If the option has an argument, accept that.  */
+                     if (argv[i][optlen] == '=')
+                       arg = argv[i] + optlen + 1;
+                     /* If this mapping allows extra text at end of name,
+                        accept that as "argument".  */
+                     else if (index (option_map[j].arg_info, '*') != 0)
+                       arg = argv[i] + optlen;
+                     /* Otherwise, extra text at end means mismatch.
+                        Try other mappings.  */
+                     else
+                       continue;
+                   }
+                 else if (index (option_map[j].arg_info, '*') != 0)
+                   error ("Incomplete `%s' option", option_map[j].name);
+
+                 /* Handle arguments.  */
+                 if (index (option_map[j].arg_info, 'o') != 0)
+                   {
+                     if (arg == 0)
+                       {
+                         if (i + 1 == argc)
+                           error ("Missing argument to `%s' option",
+                                  option_map[j].name);
+                         arg = argv[++i];
+                       }
+                   }
+                 else if (index (option_map[j].arg_info, 'a') == 0)
+                   {
+                     if (arg != 0)
+                       error ("Extraneous argument to `%s' option",
+                              option_map[j].name);
+                     arg = 0;
+                   }
+
+                 /* Store the translation as one argv elt or as two.  */
+                 if (arg != 0 && index (option_map[j].arg_info, 'j') != 0)
+                   newv[newindex++] = concat (option_map[j].equivalent,
+                                              arg, "");
+                 else if (arg != 0)
+                   {
+                     newv[newindex++] = option_map[j].equivalent;
+                     newv[newindex++] = arg;
+                   }
+                 else
+                   newv[newindex++] = option_map[j].equivalent;
+
+                 break;
+               }
+           }
+         i++;
+       }
+      /* Handle old-fashioned options--just copy them through,
+        with their arguments.  */
+      else if (argv[i][0] == '-')
+       {
+         char *p = argv[i] + 1;
+         int c = *p;
+         int nskip = 1;
+
+         if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
+           nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
+         else if (WORD_SWITCH_TAKES_ARG (p))
+           nskip += WORD_SWITCH_TAKES_ARG (p);
+
+         while (nskip > 0)
+           {
+             newv[newindex++] = argv[i++];
+             nskip--;
+           }
+       }
+      else
+       /* Ordinary operands, or +e options.  */
+       newv[newindex++] = argv[i++];
+    }
+
+  newv[newindex] = 0;
+
+  *argvp = newv;
+  *argcp = newindex;
+}
+\f
 /* Read compilation specs from a file named FILENAME,
    replacing the default ones.
 
@@ -690,7 +919,9 @@ read_specs (filename)
            = ((struct compiler *)
               xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
          compilers[n_compilers].suffix = suffix;
-         compilers[n_compilers].spec = spec;
+         bzero (compilers[n_compilers].spec,
+                sizeof compilers[n_compilers].spec);
+         compilers[n_compilers].spec[0] = spec;
          n_compilers++;
        }
 
@@ -818,10 +1049,26 @@ static int argbuf_length;
 
 static int argbuf_index;
 
+/* This is the list of suffixes and codes (%g/%u/%U) and the associated
+   temp file.  Used only if MKTEMP_EACH_FILE.  */
+
+static struct temp_name {
+  char *suffix;                /* suffix associated with the code.  */
+  int length;          /* strlen (suffix).  */
+  int unique;          /* Indicates whether %g or %u/%U was used.  */
+  char *filename;      /* associated filename.  */
+  int filename_length; /* strlen (filename).  */
+  struct temp_name *next;
+} *temp_names;
+
 /* Number of commands executed so far.  */
 
 static int execution_count;
 
+/* Number of commands that exited with a signal.  */
+
+static int signal_count;
+
 /* Name with which this program was invoked.  */
 
 static char *programname;
@@ -902,6 +1149,12 @@ static char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
 static char *standard_startfile_prefix_1 = "/lib/";
 static char *standard_startfile_prefix_2 = "/usr/lib/";
 
+#ifndef TOOLDIR_BASE_PREFIX
+#define TOOLDIR_BASE_PREFIX "/usr/local/"
+#endif
+static char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+static char *tooldir_prefix;
+
 /* Clear out the vector of arguments (after a command is executed).  */
 
 static void
@@ -1108,6 +1361,8 @@ choose_temp_base ()
 
   mktemp (temp_filename);
   temp_filename_length = strlen (temp_filename);
+  if (temp_filename_length == 0)
+    abort ();
 }
 \f
 
@@ -1172,6 +1427,8 @@ putenv_from_prefixes (paths, env_var)
      char *env_var;
 {
   int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
+  int just_suffix_len
+    = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
   int first_time = TRUE;
   struct prefix_list *pprefix;
 
@@ -1184,7 +1441,7 @@ putenv_from_prefixes (paths, env_var)
       if (machine_suffix)
        {
          if (!first_time)
-           obstack_grow (&collect_obstack, ":", 1);
+           obstack_1grow (&collect_obstack, PATH_SEPARATOR);
            
          first_time = FALSE;
          obstack_grow (&collect_obstack, pprefix->prefix, len);
@@ -1194,23 +1451,24 @@ putenv_from_prefixes (paths, env_var)
       if (just_machine_suffix && pprefix->require_machine_suffix == 2)
        {
          if (!first_time)
-           obstack_grow (&collect_obstack, ":", 1);
+           obstack_1grow (&collect_obstack, PATH_SEPARATOR);
            
          first_time = FALSE;
          obstack_grow (&collect_obstack, pprefix->prefix, len);
-         obstack_grow (&collect_obstack, machine_suffix, suffix_len);
+         obstack_grow (&collect_obstack, just_machine_suffix,
+                       just_suffix_len);
        }
 
       if (!pprefix->require_machine_suffix)
        {
          if (!first_time)
-           obstack_grow (&collect_obstack, ":", 1);
+           obstack_1grow (&collect_obstack, PATH_SEPARATOR);
 
          first_time = FALSE;
          obstack_grow (&collect_obstack, pprefix->prefix, len);
        }
     }
-  obstack_grow (&collect_obstack, "\0", 1);
+  obstack_1grow (&collect_obstack, '\0');
   putenv (obstack_finish (&collect_obstack));
 }
 
@@ -1722,8 +1980,11 @@ execute ()
                prog = commands[j].prog;
 
            if ((status & 0x7F) != 0)
-             fatal ("Internal compiler error: program %s got fatal signal %d",
-                    prog, (status & 0x7F));
+             {
+               fatal ("Internal compiler error: program %s got fatal signal %d",
+                      prog, (status & 0x7F));
+               signal_count++;
+             }
            if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS)
              ret_code = -1;
          }
@@ -1785,7 +2046,11 @@ process_command (argc, argv)
 
   n_switches = 0;
   n_infiles = 0;
-  spec_version = version_string;
+
+  /* Default for -V is our version number, ending at first space.  */
+  spec_version = save_string (version_string, strlen (version_string));
+  for (temp = spec_version; *temp && *temp != ' '; temp++);
+  if (*temp) *temp = '\0';
 
   /* Set up the default search paths.  */
 
@@ -1902,6 +2167,9 @@ process_command (argc, argv)
        }
     }
 
+  /* Convert new-style -- options to old-style.  */
+  translate_options (&argc, &argv);
+
   /* 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).  */
@@ -2013,6 +2281,9 @@ process_command (argc, argv)
          /* Record the part after the last comma.  */
          assembler_options[n_assembler_options - 1] = argv[i] + prev;
        }
+      else if (argv[i][0] == '+' && argv[i][1] == 'e')
+       /* The +e options to the C++ front-end.  */
+       n_switches++;
       else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l')
        {
          register char *p = &argv[i][1];
@@ -2045,8 +2316,12 @@ process_command (argc, argv)
              break;
 
            case 'v':   /* Print our subcommands and print versions.  */
-             verbose_flag++;
              n_switches++;
+             /* If they do anything other than exactly `-v', don't set
+                verbose_flag; rather, continue on to give the error.  */
+             if (p[1] != 0)
+               break;
+             verbose_flag++;
              break;
 
            case 'V':
@@ -2078,6 +2353,24 @@ process_command (argc, argv)
        n_infiles++;
     }
 
+  tooldir_prefix = concat (tooldir_base_prefix, spec_machine, "/");
+
+  /* If tooldir is relative, base it on exec_prefix.  A relative
+     tooldir lets us move the installed tree as a unit.  */
+
+  if (*tooldir_prefix != '/')
+    {
+      if (gcc_exec_prefix)
+       tooldir_prefix = concat (concat (gcc_exec_prefix, spec_machine, "/"),
+                                concat (spec_version, "/", tooldir_prefix),
+                                "");
+      else
+       tooldir_prefix = concat (concat (standard_exec_prefix, spec_machine, "/"),
+                                concat (spec_version, "/", tooldir_prefix),
+                                "");
+    }
+
+
   /* Set up the search paths before we go looking for config files.  */
 
   /* These come before the md prefixes so that we will find gcc's subcommands
@@ -2090,6 +2383,11 @@ process_command (argc, argv)
   add_prefix (&startfile_prefix, standard_exec_prefix, 0, 1, NULL_PTR);
   add_prefix (&startfile_prefix, standard_exec_prefix_1, 0, 1, NULL_PTR);
 
+  add_prefix (&exec_prefix, concat (tooldir_prefix, "bin", "/"),
+             0, 0, NULL_PTR);
+  add_prefix (&startfile_prefix, concat (tooldir_prefix, "lib", "/"),
+             0, 0, NULL_PTR);
+
   /* More prefixes are enabled in main, after we read the specs file
      and determine whether this is cross-compilation or not.  */
 
@@ -2109,14 +2407,27 @@ process_command (argc, argv)
 
   for (i = 1; i < argc; i++)
     {
+      /* Just skip the switches that were handled by the preceding loop.  */
       if (!strcmp (argv[i], "-Xlinker"))
        i++;
       else if (! strncmp (argv[i], "-Wl,", 4))
-       i++;
+       ;
       else if (! strncmp (argv[i], "-Wa,", 4))
-       i++;
+       ;
       else if (! strcmp (argv[i], "-print-libgcc-file-name"))
-       i++;
+       ;
+      else if (argv[i][0] == '+' && argv[i][1] == 'e')
+       {
+         /* Compensate for the +e options to the C++ front-end;
+            they're there simply for cfront call-compatibility.  We do
+            some magic in default_compilers to pass them down properly.
+            Note we deliberately start at the `+' here, to avoid passing
+            -e0 or -e1 down into the linker.  */
+         switches[n_switches].part1 = &argv[i][0];
+         switches[n_switches].args = 0;
+         switches[n_switches].valid = 0;
+         n_switches++;
+       }
       else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l')
        {
          register char *p = &argv[i][1];
@@ -2157,6 +2468,8 @@ process_command (argc, argv)
              /* Count only the option arguments in separate argv elements.  */
              n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
            }
+           if (i + n_args >= argc)
+             fatal ("argument to `-%s' is missing", p);
            switches[n_switches].args
              = (char **) xmalloc ((n_args + 1) * sizeof (char *));
            while (j < n_args)
@@ -2181,8 +2494,17 @@ process_command (argc, argv)
        }
       else
        {
-         infiles[n_infiles].language = spec_lang;
-         infiles[n_infiles++].name = argv[i];
+         if ((argv[i][0] != '-' || argv[i][1] != 'l')
+             && access (argv[i], R_OK) < 0)
+           {
+             perror_with_name (argv[i]);
+             error_count++;
+           }
+         else
+           {
+             infiles[n_infiles].language = spec_lang;
+             infiles[n_infiles++].name = argv[i];
+           }
        }
     }
 
@@ -2241,6 +2563,9 @@ static int this_is_output_file;
    search dirs for it.  */
 static int this_is_library_file;
 
+/* Nonzero means that the input of this command is coming from a pipe.  */
+static int input_from_pipe;
+
 /* Process the spec SPEC and run the commands specified therein.
    Returns 0 if the spec is successfully processed; -1 if failed.  */
 
@@ -2255,6 +2580,7 @@ do_spec (spec)
   delete_this_arg = 0;
   this_is_output_file = 0;
   this_is_library_file = 0;
+  input_from_pipe = 0;
 
   value = do_spec_1 (spec, 0, NULL_PTR);
 
@@ -2294,6 +2620,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
   register int c;
   int i;
   char *string;
+  int value;
 
   while (c = *p++)
     /* If substituting a switch, treat all chars like letters.
@@ -2327,6 +2654,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
               Otherwise, execute now and don't pass the `|' as an arg.  */
            if (i < n_switches)
              {
+               input_from_pipe = 1;
                switches[i].valid = 1;
                break;
              }
@@ -2336,7 +2664,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
        if (argbuf_index > 0)
          {
-           int value = execute ();
+           value = execute ();
            if (value)
              return value;
          }
@@ -2346,6 +2674,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
        delete_this_arg = 0;
        this_is_output_file = 0;
        this_is_library_file = 0;
+       input_from_pipe = 0;
        break;
 
       case '|':
@@ -2489,18 +2818,60 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
          case 'g':
          case 'u':
+         case 'U':
            if (save_temps_flag)
              obstack_grow (&obstack, input_basename, basename_length);
            else
              {
+#ifdef MKTEMP_EACH_FILE
+               /* ??? This has a problem: the total number of
+                  values mktemp can return is limited.
+                  That matters for the names of object files.
+                  In 2.4, do something about that.  */
+               struct temp_name *t;
+               char *suffix = p;
+               while (*p == '.' || isalpha (*p))
+                 p++;
+
+               /* See if we already have an association of %g/%u/%U and
+                  suffix.  */
+               for (t = temp_names; t; t = t->next)
+                 if (t->length == p - suffix
+                     && strncmp (t->suffix, suffix, p - suffix) == 0
+                     && t->unique == (c != 'g'))
+                   break;
+
+               /* Make a new association if needed.  %u requires one.  */
+               if (t == 0 || c == 'u')
+                 {
+                   if (t == 0)
+                     {
+                       t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
+                       t->next = temp_names;
+                       temp_names = t;
+                     }
+                   t->length = p - suffix;
+                   t->suffix = save_string (suffix, p - suffix);
+                   t->unique = (c != 'g');
+                   choose_temp_base ();
+                   t->filename = temp_filename;
+                   t->filename_length = temp_filename_length;
+                 }
+
+               obstack_grow (&obstack, t->filename, t->filename_length);
+               delete_this_arg = 1;
+#else
                obstack_grow (&obstack, temp_filename, temp_filename_length);
-               if (c == 'u')
+               if (c == 'u' || c == 'U')
                  {
                    static int unique;
                    char buff[9];
-                   sprintf (buff, "%d", ++unique);
+                   if (c == 'u')
+                     unique++;
+                   sprintf (buff, "%d", unique);
                    obstack_grow (&obstack, buff, strlen (buff));
                  }
+#endif
                delete_this_arg = 1;
              }
            arg_going = 1;
@@ -2616,39 +2987,57 @@ do_spec_1 (spec, inswitch, soft_matched_part)
               a certain constant string as a spec.  */
 
          case '1':
-           do_spec_1 (cc1_spec, 0, NULL_PTR);
+           value = do_spec_1 (cc1_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case '2':
-           do_spec_1 (cc1plus_spec, 0, NULL_PTR);
+           value = do_spec_1 (cc1plus_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'a':
-           do_spec_1 (asm_spec, 0, NULL_PTR);
+           value = do_spec_1 (asm_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'A':
-           do_spec_1 (asm_final_spec, 0, NULL_PTR);
+           value = do_spec_1 (asm_final_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'c':
-           do_spec_1 (signed_char_spec, 0, NULL_PTR);
+           value = do_spec_1 (signed_char_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'C':
-           do_spec_1 (cpp_spec, 0, NULL_PTR);
+           value = do_spec_1 (cpp_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'E':
-           do_spec_1 (endfile_spec, 0, NULL_PTR);
+           value = do_spec_1 (endfile_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'l':
-           do_spec_1 (link_spec, 0, NULL_PTR);
+           value = do_spec_1 (link_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'L':
-           do_spec_1 (lib_spec, 0, NULL_PTR);
+           value = do_spec_1 (lib_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
          case 'p':
@@ -2675,7 +3064,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              *x = 0;
 
-             do_spec_1 (buf, 0, NULL_PTR);
+             value = do_spec_1 (buf, 0, NULL_PTR);
+             if (value != 0)
+               return value;
            }
            break;
 
@@ -2781,12 +3172,16 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              *x = 0;
 
-             do_spec_1 (buf, 0, NULL_PTR);
+             value = do_spec_1 (buf, 0, NULL_PTR);
+             if (value != 0)
+               return value;
            }
            break;
 
          case 'S':
-           do_spec_1 (startfile_spec, 0, NULL_PTR);
+           value = do_spec_1 (startfile_spec, 0, NULL_PTR);
+           if (value != 0)
+             return value;
            break;
 
            /* Here we define characters other than letters and digits.  */
@@ -2834,7 +3229,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              if (sl)
                {
                  if (c == '(')
-                   do_spec_1 (name, 0, NULL_PTR);
+                   {
+                     value = do_spec_1 (name, 0, NULL_PTR);
+                     if (value != 0)
+                       return value;
+                   }
                  else
                    {
                      char *x = (char *) alloca (strlen (name) * 2 + 1);
@@ -2867,7 +3266,9 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        }
                      *x = 0;
 
-                     do_spec_1 (buf, 0, NULL_PTR);
+                     value = do_spec_1 (buf, 0, NULL_PTR);
+                     if (value != 0)
+                       return value;
                    }
                }
 
@@ -2877,6 +3278,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            }
            break;
 
+         case '|':
+           if (input_from_pipe)
+             do_spec_1 ("-", 0, NULL_PTR);
+           break;
+
          default:
            abort ();
          }
@@ -3170,13 +3576,16 @@ main (argc, argv)
      char **argv;
 {
   register int i;
+  int j;
   int value;
-  int error_count = 0;
   int linker_was_run = 0;
   char *explicit_link_files;
   char *specs_file;
+  char *p;
 
-  programname = argv[0];
+  p = argv[0] + strlen (argv[0]);
+  while (p != argv[0] && p[-1] != '/') --p;
+  programname = p;
 
   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
     signal (SIGINT, fatal_error);
@@ -3195,10 +3604,11 @@ main (argc, argv)
   obstack_init (&obstack);
 
   /* Set up to remember the pathname of gcc and any options
-     needed for collect.  */
+     needed for collect.  We use argv[0] instead of programname because
+     we need the complete pathname.  */
   obstack_init (&collect_obstack);
   obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1);
-  obstack_grow (&collect_obstack, programname, strlen (programname)+1);
+  obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1);
   putenv (obstack_finish (&collect_obstack));
 
   /* Choose directory for temp files.  */
@@ -3323,6 +3733,7 @@ main (argc, argv)
          /* Ok, we found an applicable compiler.  Run its spec.  */
          /* First say how much of input_filename to substitute for %b  */
          register char *p;
+         int len;
 
          input_basename = input_filename;
          for (p = input_filename; *p; p++)
@@ -3342,7 +3753,23 @@ main (argc, argv)
          else
            input_suffix = "";
 
-         value = do_spec (cp->spec);
+         len = 0;
+         for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
+           if (cp->spec[j])
+             len += strlen (cp->spec[j]);
+
+         p = (char *) xmalloc (len + 1);
+
+         len = 0;
+         for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
+           if (cp->spec[j])
+             {
+               strcpy (p + len, cp->spec[j]);
+               len += strlen (cp->spec[j]);
+             }
+
+         value = do_spec (p);
+         free (p);
          if (value < 0)
            this_file_error = 1;
        }
@@ -3429,7 +3856,7 @@ main (argc, argv)
     delete_failure_queue ();
   delete_temp_files ();
 
-  exit (error_count);
+  exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
   /* NOTREACHED */
   return 0;
 }
@@ -3464,24 +3891,26 @@ lookup_compiler (name, length, language)
   /* Look for a suffix.  */
   for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
     {
-      if (strlen (cp->suffix) < length
-              /* See if the suffix matches the end of NAME.  */
-              && !strcmp (cp->suffix,
-                          name + length - strlen (cp->suffix))
-              /* The suffix `-' matches only the file name `-'.  */
-              && !(!strcmp (cp->suffix, "-") && length != 1))
+      if (/* The suffix `-' matches only the file name `-'.  */
+         (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
+         ||
+         (strlen (cp->suffix) < length
+          /* See if the suffix matches the end of NAME.  */
+          && !strcmp (cp->suffix,
+                      name + length - strlen (cp->suffix))))
        {
-         if (cp->spec[0] == '@')
+         if (cp->spec[0][0] == '@')
            {
              struct compiler *new;
              /* An alias entry maps a suffix to a language.
                 Search for the language; pass 0 for NAME and LENGTH
                 to avoid infinite recursion if language not found.
                 Construct the new compiler spec.  */
-             language = cp->spec + 1;
+             language = cp->spec[0] + 1;
              new = (struct compiler *) xmalloc (sizeof (struct compiler));
              new->suffix = cp->suffix;
-             new->spec = lookup_compiler (NULL_PTR, 0, language)->spec;
+             bcopy (lookup_compiler (NULL_PTR, 0, language)->spec,
+                    new->spec, sizeof new->spec);
              return new;
            }
          /* A non-alias entry: return it.  */
@@ -3659,17 +4088,21 @@ validate_all_switches ()
   register char c;
   struct spec_list *spec;
 
-  for (comp = compilers; comp->spec; comp++)
+  for (comp = compilers; comp->spec[0]; comp++)
     {
-      p = comp->spec;
-      while (c = *p++)
-       if (c == '%' && *p == '{')
-         /* We have a switch spec.  */
-         validate_switches (p + 1);
+      int i;
+      for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
+       {
+         p = comp->spec[i];
+         while (c = *p++)
+           if (c == '%' && *p == '{')
+             /* We have a switch spec.  */
+             validate_switches (p + 1);
+       }
     }
 
   /* look through the linked list of extra specs read from the specs file */
-  for (spec = specs ; spec ; spec = spec->next)
+  for (spec = specs; spec ; spec = spec->next)
     {
       p = spec->spec;
       while (c = *p++)