OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index da3bdc5..a7eb71e 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -32,12 +32,6 @@ Once it knows which kind of compilation to perform, the procedure for
 compilation is specified by a string called a "spec".  */
 \f
 #include "config.h"
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
 #include "system.h"
 #include <signal.h>
 #include <sys/stat.h>
@@ -117,8 +111,8 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0};
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
 #endif
 
 extern char *my_strerror PROTO((int));
@@ -241,14 +235,14 @@ static int used_arg               PROTO((char *, int));
 static int default_arg         PROTO((char *, int));
 static void set_multilib_dir   PROTO((void));
 static void print_multilib_info        PROTO((void));
-static void pfatal_with_name   PROTO((char *));
+static void pfatal_with_name   PROTO((char *)) ATTRIBUTE_NORETURN;
 static void perror_with_name   PROTO((char *));
-static void pfatal_pexecute    PROTO((char *, char *));
-static void fatal              PVPROTO((char *, ...));
+static void pfatal_pexecute    PROTO((char *, char *)) ATTRIBUTE_NORETURN;
+static void fatal              PVPROTO((char *, ...)) ATTRIBUTE_NORETURN;
 static void error              PVPROTO((char *, ...));
 static void display_help       PROTO((void));
 
-void fancy_abort ();
+void fancy_abort               PROTO((void)) ATTRIBUTE_NORETURN;
 char *xmalloc ();
 char *xrealloc ();
 
@@ -281,12 +275,30 @@ or with constant text in a single argument.
  %b     substitute the basename of the input file being processed.
        This is the substring up to (and not including) the last period
        and not including the directory.
- %g     substitute the temporary-file-name-base.  This is a string chosen
-       once per compilation.  Different temporary file names are made by
-       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.
+ %gSUFFIX
+       substitute a file name that has suffix SUFFIX and is chosen
+       once per compilation, and mark the argument a la %d.  To reduce
+       exposure to denial-of-service attacks, the file name is now
+       chosen in a way that is hard to predict even when previously
+       chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
+       might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
+       the regexp "[.A-Za-z]*" or the special string "%O", which is
+       treated exactly as if %O had been pre-processed.  Previously, %g
+       was simply substituted with a file name chosen once per compilation,
+       without regard to any appended suffix (which was therefore treated
+       just like ordinary text), making such attacks more likely to succeed.
+ %uSUFFIX
+       like %g, but generates a new temporary file name even if %uSUFFIX
+       was already seen.
+ %USUFFIX
+       substitutes the last file name generated with %uSUFFIX, generating a
+       new one if there is no such last file name.  In the absence of any
+       %uSUFFIX, this is just like %gSUFFIX, except they don't share
+       the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
+       would involve the generation of two distinct file names, one
+       for each `%g.s' and another for each `%U.s'.  Previously, %U was
+       simply substituted with a file name chosen for the previous %u,
+       without regard to any appended suffix.
  %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.
@@ -303,7 +315,13 @@ or with constant text in a single argument.
        Input files whose names have no recognized suffix are not compiled
        at all, but they are included among the output files, so they will
        be linked.
- %O    substitutes the suffix for object files.
+ %O    substitutes the suffix for object files.  Note that this is
+       handled specially when it immediately follows %g, %u, or %U,
+       because of the need for those to form complete file names.  The
+       handling is such that %O is treated exactly as if it had already
+       been substituted, except that %g, %u, and %U do not currently
+       support additional SUFFIX characters following %O as they would
+       following, for example, `.o'.
  %p    substitutes the standard macro predefinitions for the
        current target machine.  Use this when running cpp.
  %P    like %p, but puts `__' before and after the name of each macro.
@@ -365,6 +383,7 @@ or with constant text in a single argument.
  %{S|P:X} substitutes X if either -S or -P was given to CC.  This may be
          combined with ! and . as above binding stronger than the OR.
  %(Spec) processes a specification defined in a specs file as *Spec:
+ %[Spec] as above, but put __ around -D arguments
 
 The conditional text X in a %{S:X} or %{!S:X} construct may contain
 other nested % constructs or spaces, or even newlines.  They are
@@ -609,6 +628,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
       %{!E:%{!M:%{!MM:cc1 %i %1 \
@@ -642,6 +662,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{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",
    "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
@@ -667,6 +688,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}}\
     %{!E:%e-E required when input is from standard input}"}},
@@ -681,6 +703,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{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",
     "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
@@ -706,6 +729,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
         %i %W{o*}"}},
   {".i", {"@cpp-output"}},
@@ -733,6 +757,7 @@ static struct compiler default_compilers[] =
         %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
         %{traditional} %{ftraditional:-traditional}\
         %{traditional-cpp:-traditional}\
+       %{fleading-underscore} %{fno-leading-underscore}\
        %{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",
     "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
@@ -833,6 +858,8 @@ struct option_map option_map[] =
    {"--ansi", "-ansi", 0},
    {"--assemble", "-S", 0},
    {"--assert", "-A", "a"},
+   {"--classpath", "-fclasspath=", "aj"},
+   {"--CLASSPATH", "-fCLASSPATH=", "aj"},
    {"--comments", "-C", 0},
    {"--compile", "-c", 0},
    {"--debug", "-g", "oj"},
@@ -911,7 +938,7 @@ translate_options (argcp, argvp)
      int *argcp;
      char ***argvp;
 {
-  int i, j, k;
+  int i;
   int argc = *argcp;
   char **argv = *argvp;
   char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
@@ -925,6 +952,7 @@ translate_options (argcp, argvp)
       /* Translate -- options.  */
       if (argv[i][0] == '-' && argv[i][1] == '-')
        {
+         size_t j;
          /* Find a mapping that applies to this option.  */
          for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
            {
@@ -942,6 +970,7 @@ translate_options (argcp, argvp)
 
                  if (arglen < optlen)
                    {
+                     size_t k;
                      for (k = j + 1;
                           k < sizeof (option_map) / sizeof (option_map[0]);
                           k++)
@@ -1110,7 +1139,8 @@ skip_whitespace (p)
 }
 \f
 /* Structure to keep track of the specs that have been defined so far.
-   These are accessed using %(specname) in a compiler or link spec.  */
+   These are accessed using %(specname) or %[specname] in a compiler
+   or link spec.  */
 
 struct spec_list
 {
@@ -1155,7 +1185,16 @@ static struct spec_list static_specs[] = {
 };
 
 #ifdef EXTRA_SPECS             /* additional specs needed */
-static struct spec_list extra_specs[] = { EXTRA_SPECS };
+/* Structure to keep track of just the first two args of a spec_list.
+   That is all that the EXTRA_SPECS macro gives us. */
+struct spec_list_1
+{
+  char *name;
+  char *ptr;
+};
+
+static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+static struct spec_list * extra_specs = (struct spec_list *)0;
 #endif
 
 /* List of dynamically allocates specs that have been defined so far.  */
@@ -1179,9 +1218,17 @@ init_spec ()
     fprintf (stderr, "Using builtin specs.\n");
 
 #ifdef EXTRA_SPECS
-  for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
+  extra_specs = (struct spec_list *)
+    xmalloc (sizeof(struct spec_list) *
+            (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
+  bzero ((PTR) extra_specs, sizeof(struct spec_list) *
+        (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
+  
+  for (i = (sizeof(extra_specs_1) / sizeof(extra_specs_1[0])) - 1; i >= 0; i--)
     {
       sl = &extra_specs[i];
+      sl->name = extra_specs_1[i].name;
+      sl->ptr = extra_specs_1[i].ptr;
       sl->next = next;
       sl->name_len = strlen (sl->name);
       sl->ptr_spec = &sl->ptr;
@@ -1247,7 +1294,7 @@ set_spec (name, spec)
     }
 
   old_spec = *(sl->ptr_spec);
-  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE (spec[1]))
+  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
                     ? concat (old_spec, spec + 1, NULL_PTR)
                     : save_string (spec, strlen (spec)));
 
@@ -1546,12 +1593,12 @@ read_specs (filename, main_p)
              while (*p1 == ' ' || *p1 == '\t')
                p1++;
 
-             if (! ISALPHA (*p1))
+             if (! ISALPHA ((unsigned char)*p1))
                fatal ("specs %%rename syntax malformed after %d characters",
                       p1 - buffer);
 
              p2 = p1;
-             while (*p2 && !ISSPACE (*p2))
+             while (*p2 && !ISSPACE ((unsigned char)*p2))
                p2++;
 
              if (*p2 != ' ' && *p2 != '\t')
@@ -1563,13 +1610,13 @@ read_specs (filename, main_p)
              while (*p2 == ' ' || *p2 == '\t')
                p2++;
 
-             if (! ISALPHA (*p2))
+             if (! ISALPHA ((unsigned char)*p2))
                fatal ("specs %%rename syntax malformed after %d characters",
                       p2 - buffer);
 
              /* Get new spec name */
              p3 = p2;
-             while (*p3 && !ISSPACE (*p3))
+             while (*p3 && !ISSPACE ((unsigned char)*p3))
                p3++;
 
              if (p3 != p-1)
@@ -1864,7 +1911,7 @@ putenv (str)
   /* Add a new environment variable */
   environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
   *environ = str;
-  bcopy ((char *) old_environ, (char *) (environ + 1),
+  memcpy ((char *) (environ + 1), (char *) old_environ,
         sizeof (char *) * (num_envs+1));
 
 #endif /* VMS */
@@ -1963,6 +2010,26 @@ find_a_file (pprefix, name, mode)
   struct prefix_list *pl;
   int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
 
+#ifdef DEFAULT_ASSEMBLER
+  if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) {
+    name = DEFAULT_ASSEMBLER;
+    len = strlen(name)+1;
+    temp = xmalloc (len);
+    strcpy (temp, name);
+    return temp;
+  }
+#endif
+
+#ifdef DEFAULT_LINKER
+  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) {
+    name = DEFAULT_LINKER;
+    len = strlen(name)+1;
+    temp = xmalloc (len);
+    strcpy (temp, name);
+    return temp;
+  }
+#endif
+
   if (machine_suffix)
     len += strlen (machine_suffix);
 
@@ -1975,7 +2042,7 @@ find_a_file (pprefix, name, mode)
       || (DIR_SEPARATOR == '\\' && name[1] == ':'
          && (name[2] == DIR_SEPARATOR || name[2] == '/')))
     {
-      if (access (name, mode))
+      if (access (name, mode) == 0)
        {
          strcpy (temp, name);
          return temp;
@@ -2482,11 +2549,11 @@ add_preprocessor_option (option, len)
                                                                        
   if (! preprocessor_options)                                          
     preprocessor_options                                                       
-      = (char **) xmalloc (n_preprocessor_options * sizeof (char **)); 
+      = (char **) xmalloc (n_preprocessor_options * sizeof (char *));  
   else                                                                 
     preprocessor_options                                                       
       = (char **) xrealloc (preprocessor_options,                              
-                           n_preprocessor_options * sizeof (char **)); 
+                           n_preprocessor_options * sizeof (char *));  
                                                                        
   preprocessor_options [n_preprocessor_options - 1] = save_string (option, len);  
 }
@@ -2500,11 +2567,11 @@ add_assembler_option (option, len)
                                                                        
   if (! assembler_options)                                             
     assembler_options                                                  
-      = (char **) xmalloc (n_assembler_options * sizeof (char **));    
+      = (char **) xmalloc (n_assembler_options * sizeof (char *));     
   else                                                                 
     assembler_options                                                  
       = (char **) xrealloc (assembler_options,                         
-                           n_assembler_options * sizeof (char **));    
+                           n_assembler_options * sizeof (char *));     
                                                                        
   assembler_options [n_assembler_options - 1] = save_string (option, len);  
 }
@@ -2518,11 +2585,11 @@ add_linker_option (option, len)
                                                                        
   if (! linker_options)                                                
     linker_options                                                     
-      = (char **) xmalloc (n_linker_options * sizeof (char **));       
+      = (char **) xmalloc (n_linker_options * sizeof (char *));        
   else                                                                 
     linker_options                                                     
       = (char **) xrealloc (linker_options,                            
-                           n_linker_options * sizeof (char **));       
+                           n_linker_options * sizeof (char *));        
                                                                        
   linker_options [n_linker_options - 1] = save_string (option, len);  
 }
@@ -2543,7 +2610,7 @@ process_command (argc, argv)
   int have_o = 0;
   int lang_n_infiles = 0;
 
-  GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
+  GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
 
   n_switches = 0;
   n_infiles = 0;
@@ -2566,7 +2633,7 @@ process_command (argc, argv)
   if (gcc_exec_prefix)
     {
       int len = strlen (gcc_exec_prefix);
-      if (len > sizeof ("/lib/gcc-lib/")-1
+      if (len > (int) sizeof ("/lib/gcc-lib/")-1
          && (gcc_exec_prefix[len-1] == '/'
              || gcc_exec_prefix[len-1] == DIR_SEPARATOR))
        {
@@ -2586,7 +2653,7 @@ process_command (argc, argv)
   /* COMPILER_PATH and LIBRARY_PATH have values
      that are lists of directory names with colons.  */
 
-  GET_ENVIRONMENT (temp, "COMPILER_PATH");
+  GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
   if (temp)
     {
       char *startp, *endp;
@@ -2620,7 +2687,7 @@ process_command (argc, argv)
        }
     }
 
-  GET_ENVIRONMENT (temp, "LIBRARY_PATH");
+  GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
   if (temp && *cross_compile == '0')
     {
       char *startp, *endp;
@@ -2653,7 +2720,7 @@ process_command (argc, argv)
     }
 
   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
-  GET_ENVIRONMENT (temp, "LPATH");
+  GET_ENV_PATH_LIST (temp, "LPATH");
   if (temp && *cross_compile == '0')
     {
       char *startp, *endp;
@@ -3618,16 +3685,30 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                   That matters for the names of object files.
                   In 2.4, do something about that.  */
                struct temp_name *t;
+               int suffix_length;
                char *suffix = p;
-               while (*p == '.' || ISALPHA (*p)
-                      || (p[0] == '%' && p[1] == 'O'))
-                 p++;
+
+               if (p[0] == '%' && p[1] == 'O')
+                 {
+                   /* We don't support extra suffix characters after %O.  */
+                   if (*p == '.' || ISALPHA ((unsigned char)*p))
+                     abort ();
+                   suffix = OBJECT_SUFFIX;
+                   suffix_length = strlen (OBJECT_SUFFIX);
+                   p += 2;
+                 }
+               else
+                 {
+                   while (*p == '.' || ISALPHA ((unsigned char)*p))
+                     p++;
+                   suffix_length = p - suffix;
+                 }
 
                /* 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
+                 if (t->length == suffix_length
+                     && strncmp (t->suffix, suffix, suffix_length) == 0
                      && t->unique == (c != 'g'))
                    break;
 
@@ -3640,21 +3721,10 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                        t->next = temp_names;
                        temp_names = t;
                      }
-                   if (strncmp (suffix, "%O", 2) == 0)
-                     {
-                       t->length = strlen(OBJECT_SUFFIX);
-                       t->suffix = save_string (OBJECT_SUFFIX,
-                                                strlen(OBJECT_SUFFIX));
-                       t->unique = (c != 'g');
-                       temp_filename = make_temp_file (OBJECT_SUFFIX);
-                     }
-                   else
-                     {
-                       t->length = p - suffix;
-                       t->suffix = save_string (suffix, p - suffix);
-                       t->unique = (c != 'g');
-                       temp_filename = make_temp_file (t->suffix);
-                     }
+                   t->length = suffix_length;
+                   t->suffix = save_string (suffix, suffix_length);
+                   t->unique = (c != 'g');
+                   temp_filename = make_temp_file (t->suffix);
                    temp_filename_length = strlen (temp_filename);
                    t->filename = temp_filename;
                    t->filename_length = temp_filename_length;
@@ -3709,9 +3779,16 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case 'o':
-           for (i = 0; i < n_infiles; i++)
-             store_arg (outfiles[i], 0, 0);
-           break;
+           {
+             int max = n_infiles;
+#ifdef LANG_SPECIFIC_DRIVER
+             max += lang_specific_extra_outfiles;
+#endif
+             for (i = 0; i < max; i++)
+               if (outfiles[i])
+                 store_arg (outfiles[i], 0, 0);
+             break;
+           }
 
          case 'O':
            obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
@@ -3910,7 +3987,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      *x++ = *y++;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+                         || (*(y+1) != '_'
+                             && ! ISUPPER ((unsigned char)*(y+1))))
                        {
                          /* Stick __ at front of macro name.  */
                          *x++ = '_';
@@ -3952,7 +4030,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                      y += 2;
 
                      if (*y != '_'
-                         || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+                         || (*(y+1) != '_'
+                             && ! ISUPPER ((unsigned char)*(y+1))))
                        {
                          /* Stick -D__ at front of macro name.  */
                          *x++ = '-';
@@ -4033,7 +4112,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
            /* Process a string found as the value of a spec given by name.
               This feature allows individual machine descriptions
-              to add and use their own specs.  */
+              to add and use their own specs.
+              %[...] modifies -D options the way %P does;
+              %(...) uses the spec unmodified.  */
+         case '[':
+           error ("Warning: use of obsolete %%[ operator in specs");
          case '(':
            {
              char *name = p;
@@ -4042,7 +4125,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
 
              /* The string after the S/P is the name of a spec that is to be
                 processed.  */
-             while (*p && *p != ')')
+             while (*p && *p != ')' && *p != ']')
                p++;
 
              /* See if it's in the list */
@@ -4051,32 +4134,67 @@ do_spec_1 (spec, inswitch, soft_matched_part)
                  {
                    name = *(sl->ptr_spec);
 #ifdef DEBUG_SPECS
-                   fprintf (stderr, "Processing spec %s, which is '%s'\n",
-                            sl->name, name);
+                   fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
+                            c, sl->name, (c == '(') ? ')' : ']', name);
 #endif
                    break;
                  }
 
              if (sl)
                {
-                 value = do_spec_1 (name, 0, NULL_PTR);
-                 if (value != 0)
-                   return value;
+                 if (c == '(')
+                   {
+                     value = do_spec_1 (name, 0, NULL_PTR);
+                     if (value != 0)
+                       return value;
+                   }
+                 else
+                   {
+                     char *x = (char *) alloca (strlen (name) * 2 + 1);
+                     char *buf = x;
+                     char *y = name;
+                     int flag = 0;
+
+                     /* Copy all of NAME into BUF, but put __ after
+                        every -D and at the end of each arg,  */
+                     while (1)
+                       {
+                         if (! strncmp (y, "-D", 2))
+                           {
+                             *x++ = '-';
+                             *x++ = 'D';
+                             *x++ = '_';
+                             *x++ = '_';
+                             y += 2;
+                             flag = 1;
+                             continue;
+                           }
+                          else if (flag && (*y == ' ' || *y == '\t' || *y == '='
+                                            || *y == '}' || *y == 0))
+                           {
+                             *x++ = '_';
+                             *x++ = '_';
+                             flag = 0;
+                           }
+                          if (*y == 0)
+                           break;
+                         else
+                           *x++ = *y++;
+                       }
+                     *x = 0;
+
+                     value = do_spec_1 (buf, 0, NULL_PTR);
+                     if (value != 0)
+                       return value;
+                   }
                }
 
-             /* Discard the closing paren.  */
+             /* Discard the closing paren or bracket.  */
              if (*p)
                p++;
            }
            break;
 
-           /* This used to be like %(, except that it modified -D options
-              the same way as %P.  This has been obsoleted, as it was not
-              useful for obtaining correct ISO C semantics for defines.  */
-         case '[':
-           error ("use of obsolete %[ operator in specs");
-           return -1;
-
          case 'v':
            {
              int c1 = *p++;  /* Select first or second version number.  */
@@ -4215,7 +4333,7 @@ next_member:
   if (suffix)
     {
       int found = (input_suffix != 0
-                  && strlen (input_suffix) == p - filter
+                  && (long) strlen (input_suffix) == (long)(p - filter)
                   && strncmp (input_suffix, filter, p - filter) == 0);
 
       if (body[0] == '}')
@@ -4515,8 +4633,8 @@ is_directory (path1, path2, linker)
   /* Construct the path from the two parts.  Ensure the string ends with "/.".
      The resulting path will be a directory even if the given path is a
      symbolic link.  */
-  bcopy (path1, path, len1);
-  bcopy (path2, path + len1, len2);
+  memcpy (path, path1, len1);
+  memcpy (path + len1, path2, len2);
   cp = path + len1 + len2;
   if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR)
     *cp++ = DIR_SEPARATOR;
@@ -4659,7 +4777,7 @@ main (argc, argv)
                  sizeof ("COLLECT_GCC_OPTIONS=")-1);
 
     first_time = TRUE;
-    for (i = 0; i < n_switches; i++)
+    for (i = 0; (int)i < n_switches; i++)
       {
        char **args;
        char *p, *q;
@@ -4830,7 +4948,7 @@ main (argc, argv)
 
   /* Warn about any switches that no pass was interested in.  */
 
-  for (i = 0; i < n_switches; i++)
+  for (i = 0; (int)i < n_switches; i++)
     if (! switches[i].valid)
       error ("unrecognized option `-%s'", switches[i].part1);
 
@@ -4922,14 +5040,14 @@ main (argc, argv)
   i += lang_specific_extra_outfiles;
 #endif
   outfiles = (char **) xmalloc (i * sizeof (char *));
-  bzero ((char *) outfiles, n_infiles * sizeof (char *));
+  bzero ((char *) outfiles, i * sizeof (char *));
 
   /* Record which files were specified explicitly as link input.  */
 
   explicit_link_files = xmalloc (n_infiles);
   bzero (explicit_link_files, n_infiles);
 
-  for (i = 0; i < n_infiles; i++)
+  for (i = 0; (int)i < n_infiles; i++)
     {
       register struct compiler *cp = 0;
       int this_file_error = 0;
@@ -5018,9 +5136,14 @@ main (argc, argv)
     }
 
 #ifdef LANG_SPECIFIC_DRIVER
-  if (error_count == 0
-      && lang_specific_pre_link ())
-    error_count++;
+  if (error_count == 0)
+    {
+      /* Make sure INPUT_FILE_NUMBER points to first available open
+        slot.  */
+      input_file_number = n_infiles;
+      if (lang_specific_pre_link ())
+       error_count++;
+    }
 #endif
 
   /* Run ld to link all the compiler output files.  */
@@ -5055,7 +5178,7 @@ main (argc, argv)
      complain about input files to be given to the linker.  */
 
   if (! linker_was_run && error_count == 0)
-    for (i = 0; i < n_infiles; i++)
+    for (i = 0; (int)i < n_infiles; i++)
       if (explicit_link_files[i])
        error ("%s: linker input file unused since linking not done",
               outfiles[i]);