OSDN Git Service

* gcc.c (getenv_spec_function): New function.
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 380f165..d2f479b 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,7 +1,7 @@
 /* Compiler driver program that can handle many languages.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-   Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -179,9 +179,9 @@ static int verbose_flag;
    shell scripts to capture the driver-generated command line.  */
 static int verbose_only_flag;
 
-/* Flag indicating to print target specific command line options.  */
+/* Flag indicating how to print command line options of sub-processes.  */
 
-static int target_help_flag;
+static int print_subprocess_help;
 
 /* Flag indicating whether we should report subprocess execution times
    (if this is supported by the system - see pexecute.c).  */
@@ -238,7 +238,7 @@ static const char *spec_machine = DEFAULT_TARGET_MACHINE;
 /* Nonzero if cross-compiling.
    When -b is used, the value comes from the `specs' file.  */
 
-#ifdef CROSS_COMPILE
+#ifdef CROSS_DIRECTORY_STRUCTURE
 static const char *cross_compile = "1";
 #else
 static const char *cross_compile = "0";
@@ -350,6 +350,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
 static const char *replace_outfile_spec_function (int, const char **);
@@ -776,7 +777,8 @@ static const char *cpp_unique_options =
  %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
  %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
  %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
- %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\
+ %{H} %C %{D*&U*&A*} %{i*} %Z %i\
  %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
  %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
  %{E|M|MM:%W{o*}}";
@@ -804,6 +806,7 @@ static const char *cc1_options =
  %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
  %{Qn:-fno-ident} %{--help:--help}\
  %{--target-help:--target-help}\
+ %{--help=*:--help=%(VALUE)}\
  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
  %{fsyntax-only:-o %j} %{-param*}\
  %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
@@ -1455,7 +1458,7 @@ static const char *gcc_libexec_prefix;
 #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
 #endif
 
-#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
+#ifdef CROSS_DIRECTORY_STRUCTURE  /* Don't use these prefixes for a cross compiler.  */
 #undef MD_EXEC_PREFIX
 #undef MD_STARTFILE_PREFIX
 #undef MD_STARTFILE_PREFIX_1
@@ -1472,25 +1475,33 @@ static const char *gcc_libexec_prefix;
 #define MD_STARTFILE_PREFIX_1 ""
 #endif
 
+/* These directories are locations set at configure-time based on the
+   --prefix option provided to configure.  Their initializers are
+   defined in Makefile.in.  These paths are not *directly* used when
+   gcc_exec_prefix is set because, in that case, we know where the
+   compiler has been installed, and use paths relative to that
+   location instead.  */
 static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
+static const char *const standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
+static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
+
+/* For native compilers, these are well-known paths containing
+   components that may be provided by the system.  For cross
+   compilers, these paths are not used.  */
 static const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
 static const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
 static const char *md_exec_prefix = MD_EXEC_PREFIX;
-
 static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
 static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
-static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
 static const char *const standard_startfile_prefix_1
   = STANDARD_STARTFILE_PREFIX_1;
 static const char *const standard_startfile_prefix_2
   = STANDARD_STARTFILE_PREFIX_2;
 
+/* A relative path to be used in finding the location of tools
+   relative to the driver.  */
 static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
-static const char *tooldir_prefix;
-
-static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
-
-static const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
 
 /* Subdirectory to use for locating libraries.  Set by
    set_multilib_dir based on the compilation options.  */
@@ -1591,6 +1602,7 @@ static struct spec_list *specs = (struct spec_list *) 0;
 
 static const struct spec_function static_spec_functions[] =
 {
+  { "getenv",                   getenv_spec_function },
   { "if-exists",               if_exists_spec_function },
   { "if-exists-else",          if_exists_else_spec_function },
   { "replace-outfile",         replace_outfile_spec_function },
@@ -2749,6 +2761,7 @@ add_prefix (struct path_prefix *pprefix, const char *prefix,
 }
 
 /* Same as add_prefix, but prepending target_system_root to prefix.  */
+/* The target_system_root prefix has been relocated by gcc_exec_prefix.  */
 static void
 add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
                      const char *component,
@@ -3164,6 +3177,8 @@ display_help (void)
   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
   fputs (_("  --help                   Display this information\n"), stdout);
   fputs (_("  --target-help            Display target specific command line options\n"), stdout);
+  fputs (_("  --help={target|optimizers|warnings|undocumented|params}[,{[^]joined|[^]separate}]\n"), stdout);
+  fputs (_("                           Display specific types of command line options\n"), stdout);
   if (! verbose_flag)
     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
   fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
@@ -3192,7 +3207,7 @@ display_help (void)
   fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
   fputs (_("\
   --sysroot=<directory>    Use <directory> as the root directory for headers\n\
-                           for headers and libraries\n"), stdout);
+                           and libraries\n"), stdout);
   fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
   fputs (_("  -b <machine>             Run gcc for target <machine>, if installed\n"), stdout);
   fputs (_("  -V <version>             Run gcc version number <version>, if installed\n"), stdout);
@@ -3278,6 +3293,7 @@ process_command (int argc, const char **argv)
   int is_modify_target_name;
   unsigned int j;
 #endif
+  const char *tooldir_prefix;
 
   GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
 
@@ -3383,10 +3399,18 @@ process_command (int argc, const char **argv)
       gcc_libexec_prefix = make_relative_prefix (tmp_prefix,
                                                 standard_exec_prefix,
                                                 standard_libexec_prefix);
+
+      /* The path is unrelocated, so fallback to the original setting.  */
+      if (!gcc_libexec_prefix)
+       gcc_libexec_prefix = standard_libexec_prefix;
+
       free (tmp_prefix);
     }
 #else
 #endif
+  /* From this point onward, gcc_exec_prefix is non-null if the toolchain
+     is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
+     or an automatically created GCC_EXEC_PREFIX from argv[0].  */
 
   if (gcc_exec_prefix)
     {
@@ -3570,10 +3594,19 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          add_assembler_option ("--help", 6);
          add_linker_option ("--help", 6);
        }
+      else if (strncmp (argv[i], "-fhelp=", 7) == 0)
+       {
+         /* translate_options () has turned --help into -fhelp.  */
+         print_subprocess_help = 2;
+
+         /* We will be passing a dummy file on to the sub-processes.  */
+         n_infiles++;
+         n_switches++;
+       }
       else if (strcmp (argv[i], "-ftarget-help") == 0)
        {
          /* translate_options() has turned --target-help into -ftarget-help.  */
-         target_help_flag = 1;
+         print_subprocess_help = 1;
 
          /* We will be passing a dummy file on to the sub-processes.  */
          n_infiles++;
@@ -3744,7 +3777,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
          switch (c)
            {
            case 'b':
-             if (NULL == strchr(argv[i] + 2, '-')) break;
+             if (NULL == strchr(argv[i] + 2, '-'))
+               goto normal_switch;
+
+             /* Fall through.  */
            case 'V':
              fatal ("'-%c' must come at the start of the command line", c);
              break;
@@ -3933,62 +3969,50 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
       use_pipes = 0;
     }
 
-  /* Set up the search paths before we go looking for config files.  */
+  /* Set up the search paths.  We add directories that we expect to
+     contain GNU Toolchain components before directories specified by
+     the machine description so that we will find GNU components (like
+     the GNU assembler) before those of the host system.  */ 
 
-  /* These come before the md prefixes so that we will find gcc's subcommands
-     (such as cpp) rather than those of the host system.  */
-  /* Use 2 as fourth arg meaning try just the machine as a suffix,
-     as well as trying the machine and the version.  */
+  /* If we don't know where the toolchain has been installed, use the
+     configured-in locations.  */
+  if (!gcc_exec_prefix)
+    {
 #ifndef OS2
-  add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
-             PREFIX_PRIORITY_LAST, 1, 0);
-  add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
-             PREFIX_PRIORITY_LAST, 2, 0);
-  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
-             PREFIX_PRIORITY_LAST, 2, 0);
-  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
-             PREFIX_PRIORITY_LAST, 2, 0);
-  add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
-             PREFIX_PRIORITY_LAST, 2, 0);
+      add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
+                 PREFIX_PRIORITY_LAST, 1, 0);
+      add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
+                 PREFIX_PRIORITY_LAST, 2, 0);
+      add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
+                 PREFIX_PRIORITY_LAST, 2, 0);
 #endif
+      add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
+                 PREFIX_PRIORITY_LAST, 1, 0);
+    }
 
-  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
-             PREFIX_PRIORITY_LAST, 1, 0);
-  add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
-             PREFIX_PRIORITY_LAST, 1, 0);
+  /* If not cross-compiling, search well-known system locations.  */
+  if (*cross_compile == '0')
+    {
+#ifndef OS2
+      add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
+                 PREFIX_PRIORITY_LAST, 2, 0);
+      add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
+                 PREFIX_PRIORITY_LAST, 2, 0);
+#endif
+      add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
+                 PREFIX_PRIORITY_LAST, 1, 0);
+    }
 
+  gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
   tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
                           dir_separator_str, NULL);
 
-  /* If tooldir is relative, base it on exec_prefixes.  A relative
-     tooldir lets us move the installed tree as a unit.
-
-     If GCC_EXEC_PREFIX is defined, then we want to add two relative
-     directories, so that we can search both the user specified directory
-     and the standard place.  */
-
-  if (!IS_ABSOLUTE_PATH (tooldir_prefix))
-    {
-      if (gcc_exec_prefix)
-       {
-         char *gcc_exec_tooldir_prefix
-           = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
-                     spec_version, dir_separator_str, tooldir_prefix, NULL);
-
-         add_prefix (&exec_prefixes,
-                     concat (gcc_exec_tooldir_prefix, "bin",
-                             dir_separator_str, NULL),
-                     NULL, PREFIX_PRIORITY_LAST, 0, 0);
-         add_prefix (&startfile_prefixes,
-                     concat (gcc_exec_tooldir_prefix, "lib",
-                             dir_separator_str, NULL),
-                     NULL, PREFIX_PRIORITY_LAST, 0, 1);
-       }
-
-      tooldir_prefix = concat (standard_exec_prefix, spec_machine,
-                              dir_separator_str, spec_version,
-                              dir_separator_str, tooldir_prefix, NULL);
-    }
+  /* Look for tools relative to the location from which the driver is
+     running, or, if that is not available, the configured prefix.  */
+  tooldir_prefix
+    = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
+             spec_machine, dir_separator_str,
+             spec_version, dir_separator_str, tooldir_prefix, NULL);
 
   add_prefix (&exec_prefixes,
              concat (tooldir_prefix, "bin", dir_separator_str, NULL),
@@ -4064,10 +4088,6 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
        ;
       else if (! strcmp (argv[i], "-print-multi-os-directory"))
        ;
-      else if (! strcmp (argv[i], "-ftarget-help"))
-       ;
-      else if (! strcmp (argv[i], "-fhelp"))
-       ;
       else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")))
        {
          target_system_root = argv[i] + strlen ("--sysroot=");
@@ -4233,34 +4253,14 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
     error ("warning: '-x %s' after last input file has no effect", spec_lang);
 
   /* Ensure we only invoke each subprocess once.  */
-  if (target_help_flag || print_help_list)
+  if (print_subprocess_help || print_help_list)
     {
       n_infiles = 1;
 
-      /* Create a dummy input file, so that we can pass --target-help on to
-        the various sub-processes.  */
+      /* Create a dummy input file, so that we can pass
+        the help option on to the various sub-processes.  */
       infiles[0].language = "c";
       infiles[0].name   = "help-dummy";
-
-      if (target_help_flag)
-       {
-         switches[n_switches].part1     = "--target-help";
-         switches[n_switches].args      = 0;
-         switches[n_switches].live_cond = SWITCH_OK;
-         switches[n_switches].validated = 0;
-
-         n_switches++;
-       }
-
-      if (print_help_list)
-       {
-         switches[n_switches].part1     = "--help";
-         switches[n_switches].args      = 0;
-         switches[n_switches].live_cond = SWITCH_OK;
-         switches[n_switches].validated = 0;
-
-         n_switches++;
-       }
     }
 
   switches[n_switches].part1 = 0;
@@ -6311,18 +6311,16 @@ main (int argc, char **argv)
                              PREFIX_PRIORITY_LAST, 0, 1);
       else if (*cross_compile == '0')
        {
-         if (gcc_exec_prefix)
-           add_prefix (&startfile_prefixes,
-                       concat (gcc_exec_prefix, machine_suffix,
-                               standard_startfile_prefix, NULL),
-                       NULL, PREFIX_PRIORITY_LAST, 0, 1);
          add_prefix (&startfile_prefixes,
-                     concat (standard_exec_prefix,
-                             machine_suffix,
+                     concat (gcc_exec_prefix 
+                             ? gcc_exec_prefix : standard_exec_prefix, 
+                             machine_suffix, 
                              standard_startfile_prefix, NULL),
                      NULL, PREFIX_PRIORITY_LAST, 0, 1);
        }
 
+      /* Sysrooted prefixes are relocated because target_system_root is
+        also relocated by gcc_exec_prefix.  */
       if (*standard_startfile_prefix_1)
        add_sysrooted_prefix (&startfile_prefixes,
                              standard_startfile_prefix_1, "BINUTILS",
@@ -6366,7 +6364,9 @@ main (int argc, char **argv)
 
   if (print_search_dirs)
     {
-      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
+      printf (_("install: %s%s\n"),
+             gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
+             gcc_exec_prefix ? "" : machine_suffix);
       printf (_("programs: %s\n"),
              build_search_list (&exec_prefixes, "", false, false));
       printf (_("libraries: %s\n"),
@@ -6411,16 +6411,6 @@ main (int argc, char **argv)
       return (0);
     }
 
-  if (target_help_flag)
-   {
-      /* Print if any target specific options.  */
-
-      /* We do not exit here. Instead we have created a fake input file
-         called 'target-dummy' which needs to be compiled, and we pass this
-         on to the various sub-processes, along with the --target-help
-         switch.  */
-    }
-
   if (print_help_list)
     {
       display_help ();
@@ -7657,6 +7647,27 @@ print_multilib_info (void)
     }
 }
 \f
+/* getenv built-in spec function.
+
+   Returns the value of the environment variable given by its first
+   argument, concatenated with the second argument.  If the
+   environment variable is not defined, a fatal error is issued.  */
+
+static const char *
+getenv_spec_function (int argc, const char **argv)
+{
+  char *value;
+
+  if (argc != 2)
+    return NULL;
+
+  value = getenv (argv[0]);
+  if (!value)
+    fatal ("environment variable \"%s\" not defined", argv[0]);
+
+  return concat (value, argv[1], NULL);
+}
+
 /* if-exists built-in spec function.
 
    Checks to see if the file specified by the absolute pathname in