OSDN Git Service

* rtl.h (addr_diff_vec_flags): New typedef.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 4be2f62..5f53c24 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,5 +1,5 @@
 /* Compiler driver program that can handle many languages.
-   Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -31,37 +31,27 @@ 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 <sys/types.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#ifndef NO_SYS_FILE_H
-#include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
-#endif
-
 #include "config.h"
-#include "obstack.h"
+
 #include "gansidecl.h"
+#include "system.h"
 
+#include <signal.h>
+#include <sys/stat.h>
 #ifdef __STDC__
 #include <stdarg.h>
 #else
 #include <varargs.h>
 #endif
-#include <stdio.h>
 
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#endif
+#include "obstack.h"
+
 
 /* ??? Need to find a GCC header to put these in.  */
 extern int pexecute PROTO ((const char *, char * const *, const char *,
                            const char *, char **, char **, int));
 extern int pwait PROTO ((int, int *, int));
+extern char *update_path PROTO((char *, char *));
 /* Flag arguments to pexecute.  */
 #define PEXECUTE_FIRST   1
 #define PEXECUTE_LAST    2
@@ -132,26 +122,19 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0};
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-extern void free ();
-extern char *getenv ();
-
 extern char *choose_temp_base PROTO((void));
 
-#ifndef errno
-extern int errno;
-#endif
-
 #ifndef HAVE_STRERROR
 extern int sys_nerr;
-#if defined(bsd4_4)
-extern const char *const sys_errlist[];
-#else
 extern char *sys_errlist[];
-#endif
 #else
 extern char *strerror();
 #endif
 
+#ifndef HAVE_KILL
+#define kill(p,s) raise(s)
+#endif
+
 /* If a stage of compilation returns an exit status >= 1,
    compilation of that file ceases.  */
 
@@ -231,13 +214,15 @@ extern char *version_string;
 /* Forward declaration for prototypes.  */
 struct path_prefix;
 
-static void init_spec          PROTO((int));
+static void init_spec          PROTO((void));
+static void read_specs         PROTO((char *, int));
 static void set_spec           PROTO((char *, char *));
 static struct compiler *lookup_compiler PROTO((char *, int, char *));
 static char *build_search_list PROTO((struct path_prefix *, char *, int));
 static void putenv_from_prefixes PROTO((struct path_prefix *, char *));
 static char *find_a_file       PROTO((struct path_prefix *, char *, int));
-static void add_prefix         PROTO((struct path_prefix *, char *, int, int, int *));
+static void add_prefix         PROTO((struct path_prefix *, char *, char *,
+                                      int, int, int *));
 static char *skip_whitespace   PROTO((char *));
 static void record_temp_file   PROTO((char *, int, int));
 static void delete_if_ordinary PROTO((char *));
@@ -524,11 +509,12 @@ static struct user_specs *user_specs_head, *user_specs_tail;
 
 /* This defines which switch letters take arguments.  */
 
-#define DEFAULT_SWITCH_TAKES_ARG(CHAR)      \
+#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
   ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
    || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
    || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
-   || (CHAR) == 'L' || (CHAR) == 'A')
+   || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
+   || (CHAR) == 'B' || (CHAR) == 'b')
 
 #ifndef SWITCH_TAKES_ARG
 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
@@ -579,13 +565,14 @@ 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
+     were not present when we built the driver, we will hit these copies
+     and be given a more meaningful error than "file not used since
      linking is not done".  */
   {".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"}, {".c++", "#C++"},
   {".C", "#C++"}, {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
   {".f", "#Fortran"}, {".for", "#Fortran"}, {".F", "#Fortran"},
   {".fpp", "#Fortran"},
+  {".p", "#Pascal"}, {".pas", "#Pascal"},
   /* Next come the entries for C.  */
   {".c", "@c"},
   {"@c",
@@ -595,7 +582,8 @@ static struct compiler default_compilers[] =
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
        %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs} \
-        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+        %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
@@ -616,7 +604,8 @@ static struct compiler default_compilers[] =
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
        %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
-        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+        %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}}\
@@ -629,7 +618,8 @@ static struct compiler default_compilers[] =
         -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
         %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
-        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+        %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
@@ -653,7 +643,8 @@ static struct compiler default_compilers[] =
         -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
         %{ansi:-trigraphs -D__STRICT_ANSI__}\
        %{!undef:%{!ansi:%p} %P} %{trigraphs}\
-        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+        %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}"},
@@ -679,7 +670,8 @@ 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} %{trigraphs}\
         -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
-        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+        %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
@@ -1026,126 +1018,6 @@ my_strerror(e)
 #endif
 }
 \f
-/* Read compilation specs from a file named FILENAME,
-   replacing the default ones.
-
-   A suffix which starts with `*' is a definition for
-   one of the machine-specific sub-specs.  The "suffix" should be
-   *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
-   The corresponding spec is stored in asm_spec, etc.,
-   rather than in the `compilers' vector.
-
-   Anything invalid in the file is a fatal error.  */
-
-static void
-read_specs (filename)
-     char *filename;
-{
-  int desc;
-  int readlen;
-  struct stat statbuf;
-  char *buffer;
-  register char *p;
-
-  if (verbose_flag)
-    fprintf (stderr, "Reading specs from %s\n", filename);
-
-  /* Open and stat the file.  */
-  desc = open (filename, O_RDONLY, 0);
-  if (desc < 0)
-    pfatal_with_name (filename);
-  if (stat (filename, &statbuf) < 0)
-    pfatal_with_name (filename);
-
-  /* Read contents of file into BUFFER.  */
-  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
-  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
-  if (readlen < 0)
-    pfatal_with_name (filename);
-  buffer[readlen] = 0;
-  close (desc);
-
-  /* Scan BUFFER for specs, putting them in the vector.  */
-  p = buffer;
-  while (1)
-    {
-      char *suffix;
-      char *spec;
-      char *in, *out, *p1, *p2;
-
-      /* Advance P in BUFFER to the next nonblank nocomment line.  */
-      p = skip_whitespace (p);
-      if (*p == 0)
-       break;
-
-      /* Find the colon that should end the suffix.  */
-      p1 = p;
-      while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
-      /* The colon shouldn't be missing.  */
-      if (*p1 != ':')
-       fatal ("specs file malformed after %d characters", p1 - buffer);
-      /* Skip back over trailing whitespace.  */
-      p2 = p1;
-      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
-      /* Copy the suffix to a string.  */
-      suffix = save_string (p, p2 - p);
-      /* Find the next line.  */
-      p = skip_whitespace (p1 + 1);
-      if (p[1] == 0)
-       fatal ("specs file malformed after %d characters", p - buffer);
-      p1 = p;
-      /* Find next blank line.  */
-      while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
-      /* Specs end at the blank line and do not include the newline.  */
-      spec = save_string (p, p1 - p);
-      p = p1;
-
-      /* Delete backslash-newline sequences from the spec.  */
-      in = spec;
-      out = spec;
-      while (*in != 0)
-       {
-         if (in[0] == '\\' && in[1] == '\n')
-           in += 2;
-         else if (in[0] == '#')
-           {
-             while (*in && *in != '\n') in++;
-           }
-         else
-           *out++ = *in++;
-       }
-      *out = 0;
-
-      if (suffix[0] == '*')
-       {
-         if (! strcmp (suffix, "*link_command"))
-           link_command_spec = spec;
-         else
-           set_spec (suffix + 1, spec);
-       }
-      else
-       {
-         /* Add this pair to the vector.  */
-         compilers
-           = ((struct compiler *)
-              xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
-         compilers[n_compilers].suffix = suffix;
-         bzero ((char *) compilers[n_compilers].spec,
-                sizeof compilers[n_compilers].spec);
-         compilers[n_compilers].spec[0] = spec;
-         n_compilers++;
-         bzero ((char *) &compilers[n_compilers],
-                sizeof compilers[n_compilers]);
-       }
-
-      if (*suffix == 0)
-       link_command_spec = spec;
-    }
-
-  if (link_command_spec == 0)
-    fatal ("spec file has no spec for linking");
-}
-
 static char *
 skip_whitespace (p)
      char *p;
@@ -1227,8 +1099,7 @@ static struct spec_list *specs = (struct spec_list *)0;
 /* Initialize the specs lookup routines.  */
 
 static void
-init_spec (use_extra_p)
-     int use_extra_p;
+init_spec ()
 {
   struct spec_list *next = (struct spec_list *)0;
   struct spec_list *sl   = (struct spec_list *)0;
@@ -1237,16 +1108,18 @@ init_spec (use_extra_p)
   if (specs)
     return;                    /* already initialized */
 
+  if (verbose_flag)
+    fprintf (stderr, "Using builtin specs.\n");
+
 #ifdef EXTRA_SPECS
-  if (use_extra_p)
-    for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
-      {
-       sl = &extra_specs[i];
-       sl->next = next;
-       sl->name_len = strlen (sl->name);
-       sl->ptr_spec = &sl->ptr;
-       next = sl;
-      }
+  for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
+    {
+      sl = &extra_specs[i];
+      sl->next = next;
+      sl->name_len = strlen (sl->name);
+      sl->ptr_spec = &sl->ptr;
+      next = sl;
+    }
 #endif
 
   for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--)
@@ -1274,7 +1147,19 @@ set_spec (name, spec)
   int name_len = strlen (name);
   int i;
 
-  /* See if the
+  /* If this is the first call, initialize the statically allocated specs */
+  if (!specs)
+    {
+      struct spec_list *next = (struct spec_list *)0;
+      for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1;
+          i >= 0; i--)
+       {
+         sl = &static_specs[i];
+         sl->next = next;
+         next = sl;
+       }
+      specs = sl;
+    }
 
   /* See if the spec already exists */
   for (sl = specs; sl; sl = sl->next)
@@ -1295,10 +1180,15 @@ set_spec (name, spec)
     }
 
   old_spec = *(sl->ptr_spec);
-  *(sl->ptr_spec) = ((spec[0] == '+' && isspace (spec[1]))
+  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE (spec[1]))
                     ? concat (old_spec, spec + 1, NULL_PTR)
                     : save_string (spec, strlen (spec)));
 
+#ifdef DEBUG_SPECS
+  if (verbose_flag)
+    fprintf (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+#endif
+
   /* Free the old spec */
   if (old_spec && sl->alloc_p)
     free (old_spec);
@@ -1452,9 +1342,8 @@ store_arg (arg, delete_always, delete_failure)
      int delete_always, delete_failure;
 {
   if (argbuf_index + 1 == argbuf_length)
-    {
-      argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
-    }
+    argbuf
+      = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
 
   argbuf[argbuf_index++] = arg;
   argbuf[argbuf_index] = 0;
@@ -1463,6 +1352,262 @@ store_arg (arg, delete_always, delete_failure)
     record_temp_file (arg, delete_always, delete_failure);
 }
 \f
+/* Read compilation specs from a file named FILENAME,
+   replacing the default ones.
+
+   A suffix which starts with `*' is a definition for
+   one of the machine-specific sub-specs.  The "suffix" should be
+   *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
+   The corresponding spec is stored in asm_spec, etc.,
+   rather than in the `compilers' vector.
+
+   Anything invalid in the file is a fatal error.  */
+
+static void
+read_specs (filename, main_p)
+     char *filename;
+     int main_p;
+{
+  int desc;
+  int readlen;
+  struct stat statbuf;
+  char *buffer;
+  register char *p;
+
+  if (verbose_flag)
+    fprintf (stderr, "Reading specs from %s\n", filename);
+
+  /* Open and stat the file.  */
+  desc = open (filename, O_RDONLY, 0);
+  if (desc < 0)
+    pfatal_with_name (filename);
+  if (stat (filename, &statbuf) < 0)
+    pfatal_with_name (filename);
+
+  /* Read contents of file into BUFFER.  */
+  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
+  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
+  if (readlen < 0)
+    pfatal_with_name (filename);
+  buffer[readlen] = 0;
+  close (desc);
+
+  /* Scan BUFFER for specs, putting them in the vector.  */
+  p = buffer;
+  while (1)
+    {
+      char *suffix;
+      char *spec;
+      char *in, *out, *p1, *p2, *p3;
+
+      /* Advance P in BUFFER to the next nonblank nocomment line.  */
+      p = skip_whitespace (p);
+      if (*p == 0)
+       break;
+
+      /* Is this a special command that starts with '%'? */
+      /* Don't allow this for the main specs file, since it would
+        encourage people to overwrite it.  */
+      if (*p == '%' && !main_p)
+       {
+         p1 = p;
+         while (*p && *p != '\n')
+           p++;
+
+         p++;                  /* Skip '\n' */
+
+         if (!strncmp (p1, "%include", sizeof ("%include")-1)
+             && (p1[sizeof "%include" - 1] == ' '
+                 || p1[sizeof "%include" - 1] == '\t'))
+           {
+             char *new_filename;
+
+             p1 += sizeof ("%include");
+             while (*p1 == ' ' || *p1 == '\t')
+               p1++;
+
+             if (*p1++ != '<' || p[-2] != '>')
+               fatal ("specs %%include syntax malformed after %d characters",
+                      p1 - buffer + 1);
+
+             p[-2] = '\0';
+             new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
+             read_specs (new_filename ? new_filename : p1, FALSE);
+             continue;
+           }
+         else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
+                  && (p1[sizeof "%include_noerr" - 1] == ' '
+                      || p1[sizeof "%include_noerr" - 1] == '\t'))
+           {
+             char *new_filename;
+
+             p1 += sizeof "%include_noerr";
+             while (*p1 == ' ' || *p1 == '\t') p1++;
+
+             if (*p1++ != '<' || p[-2] != '>')
+               fatal ("specs %%include syntax malformed after %d characters",
+                      p1 - buffer + 1);
+
+             p[-2] = '\0';
+             new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
+             if (new_filename)
+               read_specs (new_filename, FALSE);
+             else if (verbose_flag)
+               fprintf (stderr, "Could not find specs file %s\n", p1);
+             continue;
+           }
+         else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
+                  && (p1[sizeof "%rename" - 1] == ' '
+                      || p1[sizeof "%rename" - 1] == '\t'))
+           {
+             int name_len;
+             struct spec_list *sl;
+
+             /* Get original name */
+             p1 += sizeof "%rename";
+             while (*p1 == ' ' || *p1 == '\t')
+               p1++;
+
+             if (! ISALPHA (*p1))
+               fatal ("specs %%rename syntax malformed after %d characters",
+                      p1 - buffer);
+
+             p2 = p1;
+             while (*p2 && !ISSPACE (*p2))
+               p2++;
+
+             if (*p2 != ' ' && *p2 != '\t')
+               fatal ("specs %%rename syntax malformed after %d characters",
+                      p2 - buffer);
+
+             name_len = p2 - p1;
+             *p2++ = '\0';
+             while (*p2 == ' ' || *p2 == '\t')
+               p2++;
+
+             if (! ISALPHA (*p2))
+               fatal ("specs %%rename syntax malformed after %d characters",
+                      p2 - buffer);
+
+             /* Get new spec name */
+             p3 = p2;
+             while (*p3 && !ISSPACE (*p3))
+               p3++;
+
+             if (p3 != p-1)
+               fatal ("specs %%rename syntax malformed after %d characters",
+                      p3 - buffer);
+             *p3 = '\0';
+
+             for (sl = specs; sl; sl = sl->next)
+               if (name_len == sl->name_len && !strcmp (sl->name, p1))
+                 break;
+
+             if (!sl)
+               fatal ("specs %s spec was not found to be renamed", p1);
+
+             if (strcmp (p1, p2) == 0)
+               continue;
+
+             if (verbose_flag)
+               {
+                 fprintf (stderr, "rename spec %s to %s\n", p1, p2);
+#ifdef DEBUG_SPECS
+                 fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+#endif
+               }
+
+             set_spec (p2, *(sl->ptr_spec));
+             if (sl->alloc_p)
+               free (*(sl->ptr_spec));
+
+             *(sl->ptr_spec) = "";
+             sl->alloc_p = 0;
+             continue;
+           }
+         else
+           fatal ("specs unknown %% command after %d characters",
+                  p1 - buffer);
+       }
+
+      /* Find the colon that should end the suffix.  */
+      p1 = p;
+      while (*p1 && *p1 != ':' && *p1 != '\n')
+       p1++;
+
+      /* The colon shouldn't be missing.  */
+      if (*p1 != ':')
+       fatal ("specs file malformed after %d characters", p1 - buffer);
+
+      /* Skip back over trailing whitespace.  */
+      p2 = p1;
+      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
+       p2--;
+
+      /* Copy the suffix to a string.  */
+      suffix = save_string (p, p2 - p);
+      /* Find the next line.  */
+      p = skip_whitespace (p1 + 1);
+      if (p[1] == 0)
+       fatal ("specs file malformed after %d characters", p - buffer);
+
+      p1 = p;
+      /* Find next blank line.  */
+      while (*p1 && !(*p1 == '\n' && p1[1] == '\n'))
+       p1++;
+
+      /* Specs end at the blank line and do not include the newline.  */
+      spec = save_string (p, p1 - p);
+      p = p1;
+
+      /* Delete backslash-newline sequences from the spec.  */
+      in = spec;
+      out = spec;
+      while (*in != 0)
+       {
+         if (in[0] == '\\' && in[1] == '\n')
+           in += 2;
+         else if (in[0] == '#')
+           while (*in && *in != '\n')
+             in++;
+
+         else
+           *out++ = *in++;
+       }
+      *out = 0;
+
+      if (suffix[0] == '*')
+       {
+         if (! strcmp (suffix, "*link_command"))
+           link_command_spec = spec;
+         else
+           set_spec (suffix + 1, spec);
+       }
+      else
+       {
+         /* Add this pair to the vector.  */
+         compilers
+           = ((struct compiler *)
+              xrealloc (compilers,
+                        (n_compilers + 2) * sizeof (struct compiler)));
+
+         compilers[n_compilers].suffix = suffix;
+         bzero ((char *) compilers[n_compilers].spec,
+                sizeof compilers[n_compilers].spec);
+         compilers[n_compilers].spec[0] = spec;
+         n_compilers++;
+         bzero ((char *) &compilers[n_compilers],
+                sizeof compilers[n_compilers]);
+       }
+
+      if (*suffix == 0)
+       link_command_spec = spec;
+    }
+
+  if (link_command_spec == 0)
+    fatal ("spec file has no spec for linking");
+}
+\f
 /* Record the names of temporary files we tell compilers to write,
    and delete them at the end of the run.  */
 
@@ -1518,10 +1663,12 @@ record_temp_file (filename, always_delete, fail_delete)
       for (temp = always_delete_queue; temp; temp = temp->next)
        if (! strcmp (name, temp->name))
          goto already1;
+
       temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
       temp->next = always_delete_queue;
       temp->name = name;
       always_delete_queue = temp;
+
     already1:;
     }
 
@@ -1531,10 +1678,12 @@ record_temp_file (filename, always_delete, fail_delete)
       for (temp = failure_delete_queue; temp; temp = temp->next)
        if (! strcmp (name, temp->name))
          goto already2;
+
       temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
       temp->next = failure_delete_queue;
       temp->name = name;
       failure_delete_queue = temp;
+
     already2:;
     }
 }
@@ -1553,7 +1702,9 @@ delete_if_ordinary (name)
   fflush (stdout);
   i = getchar ();
   if (i != '\n')
-    while ((c = getchar ()) != '\n' && c != EOF) ;
+    while ((c = getchar ()) != '\n' && c != EOF)
+      ;
+
   if (i == 'y' || i == 'Y')
 #endif /* DEBUG */
     if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
@@ -1669,7 +1820,7 @@ build_search_list (paths, prefix, check_dir_p)
       int len = strlen (pprefix->prefix);
 
       if (machine_suffix
-         && (!check_dir_p
+         && (! check_dir_p
              || is_directory (pprefix->prefix, machine_suffix, 0)))
        {
          if (!first_time)
@@ -1682,10 +1833,10 @@ build_search_list (paths, prefix, check_dir_p)
 
       if (just_machine_suffix
          && pprefix->require_machine_suffix == 2
-         && (!check_dir_p
+         && (! check_dir_p
              || is_directory (pprefix->prefix, just_machine_suffix, 0)))
        {
-         if (!first_time)
+         if (! first_time)
            obstack_1grow (&collect_obstack, PATH_SEPARATOR);
            
          first_time = FALSE;
@@ -1694,15 +1845,16 @@ build_search_list (paths, prefix, check_dir_p)
                        just_suffix_len);
        }
 
-      if (!pprefix->require_machine_suffix)
+      if (! pprefix->require_machine_suffix)
        {
-         if (!first_time)
+         if (! first_time)
            obstack_1grow (&collect_obstack, PATH_SEPARATOR);
 
          first_time = FALSE;
          obstack_grow (&collect_obstack, pprefix->prefix, len);
        }
     }
+
   obstack_1grow (&collect_obstack, '\0');
   return obstack_finish (&collect_obstack);
 }
@@ -1740,7 +1892,10 @@ find_a_file (pprefix, name, mode)
 
   /* Determine the filename to execute (special case for absolute paths).  */
 
-  if (*name == '/' || *name == DIR_SEPARATOR)
+  if (*name == '/' || *name == DIR_SEPARATOR
+      /* Check for disk name on MS-DOS-based systems.  */
+      || (DIR_SEPARATOR == '\\' && name[1] == ':'
+         && (name[2] == DIR_SEPARATOR || name[2] == '/')))
     {
       if (access (name, mode))
        {
@@ -1814,7 +1969,7 @@ find_a_file (pprefix, name, mode)
 
        /* Certain prefixes can't be used without the machine suffix
           when the machine or version is explicitly specified.  */
-       if (!pl->require_machine_suffix)
+       if (! pl->require_machine_suffix)
          {
            /* Some systems have a suffix for executable files.
               So try appending that first.  */
@@ -1853,14 +2008,17 @@ find_a_file (pprefix, name, mode)
    through this prefix.  WARN should point to an int
    which will be set to 1 if this entry is used.
 
+   COMPONENT is the value to be passed to update_path.
+
    REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
    the complete value of machine_suffix.
    2 means try both machine_suffix and just_machine_suffix.  */
 
 static void
-add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
+add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
      struct path_prefix *pprefix;
      char *prefix;
+     char *component;
      int first;
      int require_machine_suffix;
      int *warn;
@@ -1868,7 +2026,7 @@ add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
   struct prefix_list *pl, **prev;
   int len;
 
-  if (!first && pprefix->plist)
+  if (! first && pprefix->plist)
     {
       for (pl = pprefix->plist; pl->next; pl = pl->next)
        ;
@@ -1879,6 +2037,7 @@ add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
 
   /* Keep track of the longest prefix */
 
+  prefix = update_path (prefix, component);
   len = strlen (prefix);
   if (len > pprefix->max_len)
     pprefix->max_len = len;
@@ -1918,28 +2077,11 @@ unused_prefix_warnings (pprefix)
          /* Prevent duplicate warnings.  */
          *pl->used_flag_ptr = 1;
        }
-      pl = pl->next;
-    }
-}
-
-/* Get rid of all prefixes built up so far in *PLISTP.  */
-
-static void
-free_path_prefix (pprefix)
-     struct path_prefix *pprefix;
-{
-  struct prefix_list *pl = pprefix->plist;
-  struct prefix_list *temp;
 
-  while (pl)
-    {
-      temp = pl;
       pl = pl->next;
-      free (temp->prefix);
-      free ((char *) temp);
     }
-  pprefix->plist = (struct prefix_list *) 0;
 }
+
 \f
 /* Execute the command specified by the arguments on the current line of spec.
    When using pipes, this includes several piped-together commands
@@ -1984,7 +2126,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 (__CYGWIN32__)) || defined (OS2)
+#if defined (__MSDOS__) || (defined (_WIN32) && defined (__CYGWIN32_)) || defined (OS2) || defined (VMS)
         fatal ("-pipe not supported");
 #endif
        argbuf[i] = 0;  /* termination of command args.  */
@@ -2021,7 +2163,9 @@ execute ()
       fflush (stderr);
       i = getchar ();
       if (i != '\n')
-       while (getchar () != '\n') ;
+       while (getchar () != '\n')
+         ;
+
       if (i != 'y' && i != 'Y')
        return 0;
 #endif /* DEBUG */
@@ -2163,7 +2307,7 @@ convert_filename (name, do_exe)
       && name[len - 2] == '.'
       && name[len - 1] == 'o')
     {
-      obstack_grow (&obstack, name[i], len - 2);
+      obstack_grow (&obstack, name, len - 2);
       obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
       name = obstack_finish (&obstack);
     }
@@ -2229,8 +2373,8 @@ process_command (argc, argv)
 
   if (gcc_exec_prefix)
     {
-      add_prefix (&exec_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR);
-      add_prefix (&startfile_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR);
+      add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
+      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
     }
 
   /* COMPILER_PATH and LIBRARY_PATH have values
@@ -2257,7 +2401,10 @@ process_command (argc, argv)
                }
              else
                nstore[endp-startp] = 0;
-             add_prefix (&exec_prefixes, nstore, 0, 0, NULL_PTR);
+             add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR);
+             add_prefix (&include_prefixes,
+                         concat (nstore, "include", NULL_PTR),
+                         0, 0, 0, NULL_PTR);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -2288,7 +2435,8 @@ process_command (argc, argv)
                }
              else
                nstore[endp-startp] = 0;
-             add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR);
+             add_prefix (&startfile_prefixes, nstore, NULL_PTR,
+                         0, 0, NULL_PTR);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -2320,7 +2468,8 @@ process_command (argc, argv)
                }
              else
                nstore[endp-startp] = 0;
-             add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR);
+             add_prefix (&startfile_prefixes, nstore, NULL_PTR,
+                         0, 0, NULL_PTR);
              if (*endp == 0)
                break;
              endp = startp = endp + 1;
@@ -2335,7 +2484,7 @@ process_command (argc, argv)
 
 #ifdef LANG_SPECIFIC_DRIVER
   /* Do language-specific adjustment/addition of flags.  */
-  lang_specific_driver (&fatal, &argc, &argv);
+  lang_specific_driver (fatal, &argc, &argv);
 #endif
 
   /* Scan argv twice.  Here, the first time, just count how many switches
@@ -2347,7 +2496,7 @@ process_command (argc, argv)
       if (! strcmp (argv[i], "-dumpspecs"))
        {
          struct spec_list *sl;
-         init_spec (TRUE);
+         init_spec ();
          for (sl = specs; sl; sl = sl->next)
            printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
          exit (0);
@@ -2497,6 +2646,7 @@ process_command (argc, argv)
          switch (c)
            {
            case 'b':
+              n_switches++;
              if (p[1] == 0 && i + 1 == argc)
                fatal ("argument to `-b' is missing");
              if (p[1] == 0)
@@ -2509,7 +2659,6 @@ process_command (argc, argv)
 
            case 'B':
              {
-               int *temp = (int *) xmalloc (sizeof (int));
                char *value;
                if (p[1] == 0 && i + 1 == argc)
                  fatal ("argument to `-B' is missing");
@@ -2517,10 +2666,12 @@ process_command (argc, argv)
                  value = argv[++i];
                else
                  value = p + 1;
-               add_prefix (&exec_prefixes, value, 1, 0, &warn_B);
-               add_prefix (&startfile_prefixes, value, 1, 0, &warn_B);
-               add_prefix (&include_prefixes, concat (value, "include", NULL_PTR),
-                           1, 0, NULL_PTR);
+               add_prefix (&exec_prefixes, value, NULL_PTR, 1, 0, &warn_B);
+               add_prefix (&startfile_prefixes, value, NULL_PTR,
+                           1, 0, &warn_B);
+               add_prefix (&include_prefixes, concat (value, "include",
+                                                      NULL_PTR),
+                           NULL_PTR, 1, 0, NULL_PTR);
 
                /* As a kludge, if the arg is "[foo/]stageN/", just add
                   "[foo/]include" to the include prefix.  */
@@ -2531,23 +2682,24 @@ process_command (argc, argv)
                           && (value[len - 8] == '/'
                               || value[len - 8] == DIR_SEPARATOR)))
                      && strncmp (value + len - 7, "stage", 5) == 0
-                     && isdigit (value[len - 2])
+                     && ISDIGIT (value[len - 2])
                      && (value[len - 1] == '/'
                          || value[len - 1] == DIR_SEPARATOR))
                    {
                      if (len == 7)
-                       add_prefix (&include_prefixes, "include",
+                       add_prefix (&include_prefixes, "include", NULL_PTR,
                                    1, 0, NULL_PTR);
                      else
                        {
                          char *string = xmalloc (len + 1);
                          strncpy (string, value, len-7);
                          strcpy (string+len-7, "include");
-                         add_prefix (&include_prefixes, string,
+                         add_prefix (&include_prefixes, string, NULL_PTR,
                                      1, 0, NULL_PTR);
                        }
                    }
                }
+                n_switches++;
              }
              break;
 
@@ -2561,6 +2713,7 @@ process_command (argc, argv)
              break;
 
            case 'V':
+             n_switches++;
              if (p[1] == 0 && i + 1 == argc)
                fatal ("argument to `-V' is missing");
              if (p[1] == 0)
@@ -2616,12 +2769,16 @@ process_command (argc, argv)
   /* Use 2 as fourth arg meaning try just the machine as a suffix,
      as well as trying the machine and the version.  */
 #ifndef OS2
-  add_prefix (&exec_prefixes, standard_exec_prefix, 0, 2, warn_std_ptr);
-  add_prefix (&exec_prefixes, standard_exec_prefix_1, 0, 2, warn_std_ptr);
+  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
+             0, 2, warn_std_ptr);
+  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
+             0, 2, warn_std_ptr);
 #endif
 
-  add_prefix (&startfile_prefixes, standard_exec_prefix, 0, 1, warn_std_ptr);
-  add_prefix (&startfile_prefixes, standard_exec_prefix_1, 0, 1, warn_std_ptr);
+  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
+             0, 1, warn_std_ptr);
+  add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS",
+             0, 1, warn_std_ptr);
 
   tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 
                           dir_separator_str, NULL_PTR);
@@ -2644,11 +2801,11 @@ process_command (argc, argv)
          add_prefix (&exec_prefixes,
                      concat (gcc_exec_tooldir_prefix, "bin", 
                              dir_separator_str, NULL_PTR),
-                     0, 0, NULL_PTR);
+                     NULL_PTR, 0, 0, NULL_PTR);
          add_prefix (&startfile_prefixes,
                      concat (gcc_exec_tooldir_prefix, "lib", 
                              dir_separator_str, NULL_PTR),
-                     0, 0, NULL_PTR);
+                     NULL_PTR, 0, 0, NULL_PTR);
        }
 
       tooldir_prefix = concat (standard_exec_prefix, spec_machine,
@@ -2658,10 +2815,10 @@ process_command (argc, argv)
 
   add_prefix (&exec_prefixes, 
               concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR),
-             0, 0, NULL_PTR);
+             "BINUTILS", 0, 0, NULL_PTR);
   add_prefix (&startfile_prefixes,
              concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR),
-             0, 0, NULL_PTR);
+             "BINUTILS", 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.  */
@@ -2743,18 +2900,14 @@ process_command (argc, argv)
        i++;
       else if (strncmp (argv[i], "-specs=", 7) == 0)
        ;
+      /* -save-temps overrides -pipe, so that temp files are produced */
+      else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0)
+       error ("Warning: -pipe ignored since -save-temps specified");
       else if (argv[i][0] == '-' && argv[i][1] != 0)
        {
          register char *p = &argv[i][1];
          register int c = *p;
 
-         if (c == 'B' || c == 'b' || c == 'V')
-           {
-             /* Skip a separate arg, if any.  */
-             if (p[1] == 0)
-               i++;
-             continue;
-           }
          if (c == 'x')
            {
              if (p[1] == 0 && i + 1 == argc)
@@ -2816,6 +2969,12 @@ process_command (argc, argv)
          /* This is always valid, since gcc.c itself understands it.  */
          if (!strcmp (p, "save-temps"))
            switches[n_switches].valid = 1;
+          else
+            {
+              char ch = switches[n_switches].part1[0];
+              if (ch == 'V' || ch == 'b' || ch == 'B')
+                switches[n_switches].valid = 1;
+            }
          n_switches++;
        }
       else
@@ -2938,7 +3097,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
   char *string;
   int value;
 
-  while (c = *p++)
+  while ((c = *p++))
     /* If substituting a switch, treat all chars like letters.
        Otherwise, NL, SPC, TAB and % are special.  */
     switch (inswitch ? 'a' : c)
@@ -3187,7 +3346,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                   In 2.4, do something about that.  */
                struct temp_name *t;
                char *suffix = p;
-               while (*p == '.' || isalpha (*p)
+               while (*p == '.' || ISALPHA (*p)
                       || (p[0] == '%' && p[1] == 'O'))
                  p++;
 
@@ -3476,7 +3635,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      *x++ = *y++;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! isupper (*(y+1))))
+                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
                        {
                          /* Stick __ at front of macro name.  */
                          *x++ = '_';
@@ -3518,7 +3677,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      y += 2;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! isupper (*(y+1))))
+                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
                        {
                          /* Stick -D__ at front of macro name.  */
                          *x++ = '-';
@@ -3619,6 +3778,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                if (sl->name_len == len && !strncmp (sl->name, name, len))
                  {
                    name = *(sl->ptr_spec);
+#ifdef DEBUG_SPECS
+                   fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
+                            c, sl->name, (c == '(') ? ')' : ']', name);
+#endif
                    break;
                  }
 
@@ -3688,7 +3851,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                 ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?  */
 
              /* Ignore leading non-digits.  i.e. "foo-" in "foo-2.7.2".  */
-             while (! isdigit (*v))
+             while (! ISDIGIT (*v))
                v++;
              if (v > compiler_version && v[-1] != '-')
                abort ();
@@ -3697,7 +3860,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              if (c1 == '2')
                {
                  /* Set V after the first period.  */
-                 while (isdigit (*v))
+                 while (ISDIGIT (*v))
                    v++;
                  if (*v != '.')
                    abort ();
@@ -3706,7 +3869,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              /* Set Q at the next period or at the end.  */
              q = v;
-             while (isdigit (*q))
+             while (ISDIGIT (*q))
                q++;
              if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
                abort ();
@@ -4228,6 +4391,53 @@ main (argc, argv)
 
   process_command (argc, argv);
 
+  {
+    int i;
+    int first_time;
+
+    /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
+       the compiler.  */
+    obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
+                 sizeof ("COLLECT_GCC_OPTIONS=")-1);
+
+    first_time = TRUE;
+    for (i = 0; i < n_switches; i++)
+      {
+       char **args;
+       char *p, *q;
+       if (!first_time)
+         obstack_grow (&collect_obstack, " ", 1);
+
+       first_time = FALSE;
+       obstack_grow (&collect_obstack, "'-", 2);
+        q = switches[i].part1;
+       while ((p = (char *) index (q,'\'')))
+          {
+            obstack_grow (&collect_obstack, q, p-q);
+            obstack_grow (&collect_obstack, "'\\''", 4);
+            q = ++p;
+          }
+        obstack_grow (&collect_obstack, q, strlen (q));
+       obstack_grow (&collect_obstack, "'", 1);
+
+       for (args = switches[i].args; args && *args; args++)
+         {
+           obstack_grow (&collect_obstack, " '", 2);
+           q = *args;
+           while ((p = (char *) index (q,'\'')))
+             {
+               obstack_grow (&collect_obstack, q, p-q);
+               obstack_grow (&collect_obstack, "'\\''", 4);
+               q = ++p;
+             }
+           obstack_grow (&collect_obstack, q, strlen (q));
+           obstack_grow (&collect_obstack, "'", 1);
+         }
+      }
+    obstack_grow (&collect_obstack, "\0", 1);
+    putenv (obstack_finish (&collect_obstack));
+  }
+
   /* Initialize the vector of specs to just the default.
      This means one element containing 0s, as a terminator.  */
 
@@ -4245,19 +4455,28 @@ main (argc, argv)
   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
   /* Read the specs file unless it is a default one.  */
   if (specs_file != 0 && strcmp (specs_file, "specs"))
-    {
-      init_spec (TRUE);
-      read_specs (specs_file);
-    }
+    read_specs (specs_file, TRUE);
   else
-    init_spec (FALSE);
-
+    init_spec ();
+
+  /* We need to check standard_exec_prefix/just_machine_suffix/specs
+     for any override of as, ld and libraries. */
+  specs_file = (char *) alloca (strlen (standard_exec_prefix)
+                               + strlen (just_machine_suffix)
+                               + sizeof ("specs"));
+
+  strcpy (specs_file, standard_exec_prefix);
+  strcat (specs_file, just_machine_suffix);
+  strcat (specs_file, "specs");
+  if (access (specs_file, R_OK) == 0)
+    read_specs (specs_file, TRUE);
   /* 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);
+      read_specs (filename ? filename : uptr->filename, FALSE);
     }
 
   /* If not cross-compiling, look for startfiles in the standard places.  */
@@ -4267,16 +4486,18 @@ main (argc, argv)
   if (*cross_compile == '0')
     {
 #ifdef MD_EXEC_PREFIX
-      add_prefix (&exec_prefixes, md_exec_prefix, 0, 0, NULL_PTR);
-      add_prefix (&startfile_prefixes, md_exec_prefix, 0, 0, NULL_PTR);
+      add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
+      add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
 #endif
 
 #ifdef MD_STARTFILE_PREFIX
-      add_prefix (&startfile_prefixes, md_startfile_prefix, 0, 0, NULL_PTR);
+      add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
+                 0, 0, NULL_PTR);
 #endif
 
 #ifdef MD_STARTFILE_PREFIX_1
-      add_prefix (&startfile_prefixes, md_startfile_prefix_1, 0, 0, NULL_PTR);
+      add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
+                 0, 0, NULL_PTR);
 #endif
 
       /* If standard_startfile_prefix is relative, base it on
@@ -4285,28 +4506,28 @@ main (argc, argv)
         standard_startfile_prefix on that as well.  */
       if (*standard_startfile_prefix == '/'
          || *standard_startfile_prefix == DIR_SEPARATOR)
-       add_prefix (&startfile_prefixes, standard_startfile_prefix, 0, 0,
-                   NULL_PTR);
+       add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
+                   0, 0, NULL_PTR);
       else
        {
          if (gcc_exec_prefix)
            add_prefix (&startfile_prefixes,
                        concat (gcc_exec_prefix, machine_suffix,
                                standard_startfile_prefix, NULL_PTR),
-                       0, 0, NULL_PTR);
+                       NULL_PTR, 0, 0, NULL_PTR);
          add_prefix (&startfile_prefixes,
                      concat (standard_exec_prefix,
                              machine_suffix,
                              standard_startfile_prefix, NULL_PTR),
-                     0, 0, NULL_PTR);
+                     NULL_PTR, 0, 0, NULL_PTR);
        }                      
 
-      add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 0, 0,
-                 NULL_PTR);
-      add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 0, 0,
-                 NULL_PTR);
+      add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
+                 "BINUTILS", 0, 0, NULL_PTR);
+      add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
+                 "BINUTILS", 0, 0, NULL_PTR);
 #if 0 /* Can cause surprises, and one can use -B./ instead.  */
-      add_prefix (&startfile_prefixes, "./", 0, 1, NULL_PTR);
+      add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR);
 #endif
     }
   else
@@ -4315,7 +4536,7 @@ main (argc, argv)
        add_prefix (&startfile_prefixes,
                    concat (gcc_exec_prefix, machine_suffix,
                            standard_startfile_prefix, NULL_PTR),
-                   0, 0, NULL_PTR);
+                   "BINUTILS", 0, 0, NULL_PTR);
     }
 
   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
@@ -4387,7 +4608,17 @@ main (argc, argv)
 
   if (verbose_flag)
     {
-      if (! strcmp (version_string, compiler_version))
+      int n;
+
+      /* compiler_version is truncated at the first space when initialized
+        from version string, so truncate version_string at the first space
+        before comparing.  */
+      for (n = 0; version_string[n]; n++)
+       if (version_string[n] == ' ')
+         break;
+
+      if (! strncmp (version_string, compiler_version, n)
+         && compiler_version[n] == 0)
        fprintf (stderr, "gcc version %s\n", version_string);
       else
        fprintf (stderr, "gcc driver version %s executing gcc version %s\n",
@@ -4504,40 +4735,12 @@ main (argc, argv)
   if (error_count == 0)
     {
       int tmp = execution_count;
-      int i;
-      int first_time;
 
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
         for collect.  */
       putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
       putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH=");
 
-      /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
-        the compiler.  */
-      obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
-                   sizeof ("COLLECT_GCC_OPTIONS=")-1);
-
-      first_time = TRUE;
-      for (i = 0; i < n_switches; i++)
-       {
-         char **args;
-         if (!first_time)
-           obstack_grow (&collect_obstack, " ", 1);
-
-         first_time = FALSE;
-         obstack_grow (&collect_obstack, "-", 1);
-         obstack_grow (&collect_obstack, switches[i].part1,
-                       strlen (switches[i].part1));
-
-         for (args = switches[i].args; args && *args; args++)
-           {
-             obstack_grow (&collect_obstack, " ", 1);
-             obstack_grow (&collect_obstack, *args, strlen (*args));
-           }
-       }
-      obstack_grow (&collect_obstack, "\0", 1);
-      putenv (obstack_finish (&collect_obstack));
-
       value = do_spec (link_command_spec);
       if (value < 0)
        error_count = 1;
@@ -4846,7 +5049,7 @@ validate_all_switches ()
       for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
        {
          p = comp->spec[i];
-         while (c = *p++)
+         while ((c = *p++))
            if (c == '%' && *p == '{')
              /* We have a switch spec.  */
              validate_switches (p + 1);
@@ -4857,14 +5060,14 @@ validate_all_switches ()
   for (spec = specs; spec ; spec = spec->next)
     {
       p = *(spec->ptr_spec);
-      while (c = *p++)
+      while ((c = *p++))
        if (c == '%' && *p == '{')
          /* We have a switch spec.  */
          validate_switches (p + 1);
     }
 
   p = link_command_spec;
-  while (c = *p++)
+  while ((c = *p++))
     if (c == '%' && *p == '{')
       /* We have a switch spec.  */
       validate_switches (p + 1);
@@ -4917,7 +5120,7 @@ validate_switches (start)
 }
 \f
 /* Check whether a particular argument was used.  The first time we
-   canonialize the switches to keep only the ones we care about.  */
+   canonicalize the switches to keep only the ones we care about.  */
 
 static int
 used_arg (p, len)
@@ -5013,7 +5216,6 @@ default_arg (p, len)
      int len;
 {
   char *start, *end;
-  int i;
 
   for (start = multilib_defaults; *start != '\0'; start = end+1)
     {