OSDN Git Service

fix SIGCHLD handling
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 70cb6be..7fb57ef 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,6 +1,6 @@
 /* Compiler driver program that can handle many languages.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -268,6 +268,9 @@ static int execute                  PARAMS ((void));
 static void clear_args                 PARAMS ((void));
 static void fatal_error                        PARAMS ((int));
 static void set_input                  PARAMS ((const char *));
+static void init_gcc_specs              PARAMS ((struct obstack *,
+                                                const char *,
+                                                const char *));
 \f
 /* Specs are strings containing lines, each of which (if not blank)
 is made up of a program name, and arguments separated by spaces.
@@ -318,6 +321,10 @@ or with constant text in a single argument.
         of a temporary file, just like %u.  This temporary file is not
         meant for communication between processes, but rather as a junk
         disposal mechanism.
+ %.SUFFIX
+        substitutes .SUFFIX for the suffixes of a matched switch's args when
+        it is subsequently output with %*. SUFFIX is terminated by the next
+        space or %.
  %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.
@@ -353,6 +360,7 @@ or with constant text in a single argument.
        and substitute the full name found.
  %eSTR  Print STR as an error message.  STR is terminated by a newline.
         Use this when inconsistent options are detected.
+ %nSTR  Print STR as an notice.  STR is terminated by a newline.
  %x{OPTION}    Accumulate an option for %X.
  %X    Output the accumulated linker options specified by compilations.
  %Y    Output the accumulated assembler options specified by compilations.
@@ -373,10 +381,12 @@ or with constant text in a single argument.
  %l     process LINK_SPEC as a spec.
  %L     process LIB_SPEC as a spec.
  %G     process LIBGCC_SPEC as a spec.
+ %M     output multilib_dir with directory separators replaced with "_";
+       if multilib_dir is not set or is ".", output "".
  %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
  %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
  %c    process SIGNED_CHAR_SPEC as a spec.
- %C     process CPP_SPEC as a spec.  A capital C is actually used here.
+ %C     process CPP_SPEC as a spec.
  %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.
@@ -584,7 +594,9 @@ static const char *cpp_options =
 "%{C:%{!E:%eGNU C does not support -C without using -E}}\
  %{std*} %{nostdinc*}\
  %{C} %{v} %{I*} %{P} %{$} %I\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ %{MD:-M -MF %W{!o: %b.d}%W{o*:%.d%*}}\
+ %{MMD:-MM -MF %W{!o: %b.d}%W{o*:%.d%*}}\
+ %{M} %{MM} %W{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{M|MD|MM|MMD:%{o*:-MQ %*}}\
  %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
  %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
  %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
@@ -595,8 +607,8 @@ static const char *cpp_options =
  %{fshow-column} %{fno-show-column}\
  %{fleading-underscore} %{fno-leading-underscore}\
  %{fno-operator-names} %{ftabstop=*} %{remap}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*&U*&A*} %{i*} %Z %i\
- %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}";
+ %{g3:-dD} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{E:%{!M*:%W{o*}}}";
 
 /* NB: This is shared amongst all front-ends.  */
 static const char *cc1_options =
@@ -663,7 +675,7 @@ static struct user_specs *user_specs_head, *user_specs_tail;
   || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
   || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
   || !strcmp (STR, "isystem") || !strcmp (STR, "specs") \
-  || !strcmp (STR, "MF") || !strcmp (STR, "MT"))
+  || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
 
 #ifndef WORD_SWITCH_TAKES_ARG
 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
@@ -688,6 +700,10 @@ struct compiler
                                   whose names end in this suffix.  */
 
   const char *spec;            /* To use this compiler, run this spec.  */
+
+  const char *cpp_spec;         /* If non-NULL, substitute this spec
+                                  for `%C', rather than the usual
+                                  cpp_spec.  */
 };
 
 /* Pointer to a vector of `struct compiler' that gives the spec for
@@ -1245,6 +1261,35 @@ static struct spec_list *extra_specs = (struct spec_list *) 0;
 
 static struct spec_list *specs = (struct spec_list *) 0;
 \f
+/* Add appropriate libgcc specs to OBSTACK, taking into account
+   various permutations of -shared-libgcc, -shared, and such.  */
+
+static void
+init_gcc_specs (obstack, shared_name, static_name)
+     struct obstack *obstack;
+     const char *shared_name;
+     const char *static_name;
+{
+  char buffer[128];
+
+  /* If we see -shared-libgcc, then use the shared version.  */
+  sprintf (buffer, "%%{shared-libgcc:%s}", shared_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* If we see -static-libgcc, then use the shared version.  */
+  sprintf (buffer, "%%{static-libgcc:%s}", static_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* Otherwise, if we see -shared, then use the shared version.  */
+  sprintf (buffer,
+          "%%{!shared-libgcc:%%{!static-libgcc:%%{shared:%s}}}", 
+          shared_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+  /* Otherwise, use the static version.  */
+  sprintf (buffer, 
+          "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s}}}", 
+          static_name);
+  obstack_grow (obstack, buffer, strlen (buffer));
+}
+
 /* Initialize the specs lookup routines.  */
 
 static void
@@ -1283,6 +1328,83 @@ init_spec ()
       next = sl;
     }
 
+#ifdef ENABLE_SHARED_LIBGCC
+  /* ??? If neither -shared-libgcc nor --static-libgcc was
+     seen, then we should be making an educated guess.  Some proposed
+     heuristics for ELF include:
+
+       (1) If "-Wl,--export-dynamic", then it's a fair bet that the
+           program will be doing dynamic loading, which will likely
+           need the shared libgcc.
+
+       (2) If "-ldl", then it's also a fair bet that we're doing
+           dynamic loading.
+
+       (3) For each ET_DYN we're linking against (either through -lfoo
+           or /some/path/foo.so), check to see whether it or one of
+           its dependancies depends on a shared libgcc.
+
+       (4) If "-shared"
+
+           If the runtime is fixed to look for program headers instead
+           of calling __register_frame_info at all, for each object,
+           use the shared libgcc if any EH symbol referenced.
+
+           If crtstuff is fixed to not invoke __register_frame_info
+           automatically, for each object, use the shared libgcc if
+           any non-empty unwind section found.
+
+     Doing any of this probably requires invoking an external program to
+     do the actual object file scanning.  */
+  {
+    const char *p = libgcc_spec;
+    int in_sep = 1;
+    /* Transform the extant libgcc_spec into one that uses the shared libgcc
+       when given the proper command line arguments.  */
+    while (*p)
+      {
+        if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
+         {
+           init_gcc_specs (&obstack,
+#ifdef NO_SHARED_LIBGCC_MULTILIB
+                           "-lgcc_s"
+#else
+                           "-lgcc_s%M"
+#endif
+                           ,
+                           "-lgcc");
+           p += 5;
+           in_sep = 0;
+         }
+       else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
+         {
+           /* Ug.  We don't know shared library extensions.  Hope that
+              systems that use this form don't do shared libraries.  */
+           init_gcc_specs (&obstack,
+#ifdef NO_SHARED_LIBGCC_MULTILIB
+                           "-lgcc_s"
+#else
+                           "-lgcc_s%M"
+#endif
+                           ,
+                           "libgcc.a%s");
+           p += 10;
+           in_sep = 0;
+         }
+       else
+         {
+           obstack_1grow (&obstack, *p);
+           in_sep = (*p == ' ');
+           p += 1;
+         }
+      }
+
+    obstack_1grow (&obstack, '\0');
+    libgcc_spec = obstack_finish (&obstack);
+  }
+#endif
+
   specs = sl;
 }
 \f
@@ -2727,7 +2849,7 @@ convert_filename (name, do_exe)
     }
 #endif
 
-#ifdef HAVE_EXECUTABLE_SUFFIX
+#if defined(HAVE_EXECUTABLE_SUFFIX) && !defined(NO_AUTO_EXE_SUFFIX)
   /* If there is no filetype, make it the executable suffix (which includes
      the ".").  But don't get confused if we have just "-o".  */
   if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
@@ -3552,7 +3674,7 @@ process_command (argc, argv)
            switches[n_switches].part1     = "--target-help";
            switches[n_switches].args      = 0;
            switches[n_switches].live_cond = SWITCH_OK;
-           switches[n_switches].validated     = 0;
+           switches[n_switches].validated = 0;
 
            n_switches++;
         }
@@ -3570,7 +3692,7 @@ process_command (argc, argv)
              switches[n_switches].part1     = "--help";
              switches[n_switches].args      = 0;
              switches[n_switches].live_cond = SWITCH_OK;
-             switches[n_switches].validated     = 0;
+             switches[n_switches].validated = 0;
 
              n_switches++;
            }
@@ -3697,8 +3819,11 @@ process_command (argc, argv)
 
          switches[n_switches].live_cond = SWITCH_OK;
          switches[n_switches].validated = 0;
-         /* This is always valid, since gcc.c itself understands it.  */
-         if (!strcmp (p, "save-temps"))
+         switches[n_switches].ordering = 0;
+         /* These are always valid, since gcc.c itself understands it.  */
+         if (!strcmp (p, "save-temps")
+             || !strcmp (p, "static-libgcc")
+             || !strcmp (p, "shared-libgcc"))
            switches[n_switches].validated = 1;
          else
            {
@@ -3751,6 +3876,9 @@ static int suffixed_basename_length;
 static const char *input_basename;
 static const char *input_suffix;
 
+/* The compiler used to process the current input file.  */
+static struct compiler *input_file_compiler;
+
 /* These are variables used within do_spec and do_spec_1.  */
 
 /* Nonzero if an arg has been started and not yet terminated
@@ -3773,6 +3901,10 @@ static int this_is_library_file;
 /* Nonzero means that the input of this command is coming from a pipe.  */
 static int input_from_pipe;
 
+/* Nonnull means substitute this for any suffix when outputting a switches
+   arguments. */
+static const char *suffix_subst;
+
 /* Process the spec SPEC and run the commands specified therein.
    Returns 0 if the spec is successfully processed; -1 if failed.  */
 
@@ -3788,6 +3920,7 @@ do_spec (spec)
   this_is_output_file = 0;
   this_is_library_file = 0;
   input_from_pipe = 0;
+  suffix_subst = NULL;
 
   value = do_spec_1 (spec, 0, NULL_PTR);
 
@@ -4064,6 +4197,21 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              return -1;
            }
            break;
+         case 'n':
+           /* %nfoo means report an notice with `foo' on stderr.  */
+           {
+             const char *q = p;
+             char *buf;
+             while (*p != 0 && *p != '\n')
+               p++;
+             buf = (char *) alloca (p - q + 1);
+             strncpy (buf, q, p - q);
+             buf[p - q] = 0;
+             notice ("%s\n", buf);
+             if (*p)
+               p++;
+           }
+           break;
 
          case 'j':
            {
@@ -4317,9 +4465,15 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            break;
 
          case 'C':
-           value = do_spec_1 (cpp_spec, 0, NULL_PTR);
-           if (value != 0)
-             return value;
+           {
+             const char* spec 
+               = (input_file_compiler->cpp_spec 
+                  ? input_file_compiler->cpp_spec 
+                  : cpp_spec);
+             value = do_spec_1 (spec, 0, NULL_PTR);
+             if (value != 0)
+               return value;
+           }
            break;
 
          case 'E':
@@ -4346,6 +4500,23 @@ do_spec_1 (spec, inswitch, soft_matched_part)
              return value;
            break;
 
+         case 'M':
+           if (multilib_dir && strcmp (multilib_dir, ".") != 0)
+             {
+               char *p;
+               const char *q;
+               size_t len;
+
+               len = strlen (multilib_dir);
+               obstack_blank (&obstack, len + 1);
+               p = obstack_next_free (&obstack) - (len + 1);
+
+               *p++ = '_';
+               for (q = multilib_dir; *q ; ++q, ++p)
+                 *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
+             }
+           break;
+
          case 'p':
            {
              char *x = (char *) alloca (strlen (cpp_predefines) + 1);
@@ -4525,6 +4696,17 @@ do_spec_1 (spec, inswitch, soft_matched_part)
            obstack_1grow (&obstack, '%');
            break;
 
+         case '.':
+          {
+            unsigned len = 0;
+
+            while (p[len] && p[len] != ' ' && p[len] != '%')
+              len++;
+             suffix_subst = save_string (p - 1, len + 1);
+             p += len;
+           }
+          break;
+          
          case '*':
            if (soft_matched_part)
              {
@@ -4875,6 +5057,7 @@ next_member:
                    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
                    /* Pass any arguments this switch has.  */
                    give_switch (i, 1, 1);
+                   suffix_subst = NULL;
                  }
 
              /* We didn't match.  Try again.  */
@@ -5082,9 +5265,29 @@ give_switch (switchnum, omit_first_word, include_blanks)
       const char **p;
       for (p = switches[switchnum].args; *p; p++)
        {
+         const char *arg = *p;
+
          if (include_blanks)
            do_spec_1 (" ", 0, NULL_PTR);
-         do_spec_1 (*p, 1, NULL_PTR);
+         if (suffix_subst)
+           {
+             unsigned length = strlen (arg);
+
+             while (length-- && !IS_DIR_SEPARATOR (arg[length]))
+               if (arg[length] == '.')
+                 {
+                   ((char *)arg)[length] = 0;
+                   break;
+                 }
+             do_spec_1 (arg, 1, NULL_PTR);
+             if (!arg[length])
+               {
+                 ((char *)arg)[length] = '.';
+                 do_spec_1 (suffix_subst, 1, NULL_PTR);
+               }
+           }
+         else
+           do_spec_1 (arg, 1, NULL_PTR);
        }
     }
 
@@ -5275,6 +5478,9 @@ main (argc, argv)
   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
     signal (SIGPIPE, fatal_error);
 #endif
+  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+     receive the signal.  A different setting is inheritable */
+  signal (SIGCHLD, SIG_DFL);
 
   argbuf_length = 10;
   argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
@@ -5622,7 +5828,6 @@ main (argc, argv)
 
   for (i = 0; (int) i < n_infiles; i++)
     {
-      register struct compiler *cp = 0;
       int this_file_error = 0;
 
       /* Tell do_spec what to substitute for %i.  */
@@ -5636,17 +5841,18 @@ main (argc, argv)
 
       /* Figure out which compiler from the file's suffix.  */
 
-      cp = lookup_compiler (infiles[i].name, input_filename_length,
-                           infiles[i].language);
-
-      if (cp)
+      input_file_compiler
+       = lookup_compiler (infiles[i].name, input_filename_length,
+                          infiles[i].language);
+      
+      if (input_file_compiler)
        {
          /* Ok, we found an applicable compiler.  Run its spec.  */
 
-         if (cp->spec[0] == '#')
+         if (input_file_compiler->spec[0] == '#')
            error ("%s: %s compiler not installed on this system",
-                  input_filename, &cp->spec[1]);
-         value = do_spec (cp->spec);
+                  input_filename, &input_file_compiler->spec[1]);
+         value = do_spec (input_file_compiler->spec);
          if (value < 0)
            this_file_error = 1;
        }