/* 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.
static int print_help_list;
+/* Flag saying to print the sysroot suffix used for searching for
+ headers. */
+
+static int print_sysroot_headers_suffix;
+
/* Flag indicating whether we should print the command and arguments */
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). */
/* 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";
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 **);
part of that switch that matched the '*'.
%{.S:X} substitutes X, if processing a file with suffix S.
%{!.S:X} substitutes X, if NOT processing a file with suffix S.
-
+ %{,S:X} substitutes X, if processing a file which will use spec S.
+ %{!,S:X} substitutes X, if NOT processing a file which will use spec S.
+
%{S|T:X} substitutes X if either -S or -T was given to CC. This may be
- combined with !, ., and * as above binding stronger than the OR.
+ combined with '!', '.', ',', and '*' as above binding stronger
+ than the OR.
If %* appears in X, all of the alternatives must be starred, and
only the first matching alternative is substituted.
%{S:X; if S was given to CC, substitutes X;
T:Y; else if T was given to CC, substitutes Y;
:D} else substitutes D. There can be as many clauses as you need.
- This may be combined with ., !, |, and * as above.
+ This may be combined with '.', '!', ',', '|', and '*' as above.
%(Spec) processes a specification defined in a specs file as *Spec:
%[Spec] as above, but put __ around -D arguments
%{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
%{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\
+ %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
+ %{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*}}";
%{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}\
{"--print-multi-directory", "-print-multi-directory", 0},
{"--print-multi-os-directory", "-print-multi-os-directory", 0},
{"--print-prog-name", "-print-prog-name=", "aj"},
+ {"--print-sysroot-headers-suffix", "-print-sysroot-headers-suffix", 0},
{"--profile", "-p", 0},
{"--profile-blocks", "-a", 0},
{"--quiet", "-q", 0},
#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
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_1
+static const char *const standard_startfile_prefix_1
= STANDARD_STARTFILE_PREFIX_1;
static const char *const standard_startfile_prefix_2
= STANDARD_STARTFILE_PREFIX_2;
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 },
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);
-print-multi-lib Display the mapping between command line options and\n\
multiple library search directories\n"), stdout);
fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
+ fputs (_(" -print-sysroot-headers-suffix Display the sysroot suffix used to find headers\n"), stdout);
fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout);
fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout);
fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout);
{
/* translate_options () has turned --version into -fversion. */
printf (_("%s (GCC) %s\n"), programname, version_string);
- printf ("Copyright %s 2006 Free Software Foundation, Inc.\n",
+ printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
_("(C)"));
fputs (_("This is free software; see the source for copying conditions. There is NO\n\
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++;
print_multi_directory = 1;
else if (! strcmp (argv[i], "-print-multi-os-directory"))
print_multi_os_directory = 1;
+ else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
+ print_sysroot_headers_suffix = 1;
else if (! strncmp (argv[i], "-Wa,", 4))
{
int prev, j;
value = tmp;
}
- /* As a kludge, if the arg is "[foo/]stageN/", just
- add "[foo/]include" to the include prefix. */
- if ((len == 7
- || (len > 7
- && (IS_DIR_SEPARATOR (value[len - 8]))))
- && strncmp (value + len - 7, "stage", 5) == 0
- && ISDIGIT (value[len - 2])
- && (IS_DIR_SEPARATOR (value[len - 1])))
- {
- if (len == 7)
- add_prefix (&include_prefixes, "./", NULL,
- PREFIX_PRIORITY_B_OPT, 0, 0);
- else
- {
- char *string = xmalloc (len - 6);
- memcpy (string, value, len - 7);
- string[len - 7] = 0;
- add_prefix (&include_prefixes, string, NULL,
- PREFIX_PRIORITY_B_OPT, 0, 0);
- }
- }
-
add_prefix (&exec_prefixes, value, NULL,
PREFIX_PRIORITY_B_OPT, 0, 0);
add_prefix (&startfile_prefixes, value, NULL,
;
else if (! strcmp (argv[i], "-print-multi-os-directory"))
;
- else if (! strcmp (argv[i], "-ftarget-help"))
- ;
- else if (! strcmp (argv[i], "-fhelp"))
+ else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
;
else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")))
{
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;
for_each_path (&include_prefixes, false, info.append_len,
spec_path, &info);
+
+ info.append = "include-fixed";
+ if (*sysroot_hdrs_suffix_spec)
+ info.append = concat (info.append, dir_separator_str,
+ multilib_dir, NULL);
+ info.append_len = strlen (info.append);
+ for_each_path (&include_prefixes, false, info.append_len,
+ spec_path, &info);
}
break;
static inline bool
input_suffix_matches (const char *atom, const char *end_atom)
{
- /* We special case the semantics of {.s:...} and {.S:...} and their
- negative variants. Instead of testing the input filename suffix,
- we test whether the input source file is an assembler file or an
- assembler-with-cpp file respectively. This allows us to correctly
- handle the -x command line option. */
-
- if (atom + 1 == end_atom
- && input_file_compiler
- && input_file_compiler->suffix)
- {
- if (*atom == 's')
- return !strcmp (input_file_compiler->suffix, "@assembler");
- if (*atom == 'S')
- return !strcmp (input_file_compiler->suffix, "@assembler-with-cpp");
- }
-
return (input_suffix
&& !strncmp (input_suffix, atom, end_atom - atom)
&& input_suffix[end_atom - atom] == '\0');
}
+/* Subroutine of handle_braces. Returns true if the current
+ input file's spec name matches the atom bracketed by ATOM and END_ATOM. */
+static bool
+input_spec_matches (const char *atom, const char *end_atom)
+{
+ return (input_file_compiler
+ && input_file_compiler->suffix
+ && input_file_compiler->suffix[0] != '\0'
+ && !strncmp (input_file_compiler->suffix + 1, atom,
+ end_atom - atom)
+ && input_file_compiler->suffix[end_atom - atom + 1] == '\0');
+}
+
/* Subroutine of handle_braces. Returns true if a switch
matching the atom bracketed by ATOM and END_ATOM appeared on the
command line. */
const char *orig = p;
bool a_is_suffix;
+ bool a_is_spectype;
bool a_is_starred;
bool a_is_negated;
bool a_matched;
goto invalid;
/* Scan one "atom" (S in the description above of %{}, possibly
- with !, ., or * modifiers). */
- a_matched = a_is_suffix = a_is_starred = a_is_negated = false;
+ with '!', '.', '@', ',', or '*' modifiers). */
+ a_matched = false;
+ a_is_suffix = false;
+ a_is_starred = false;
+ a_is_negated = false;
+ a_is_spectype = false;
SKIP_WHITE();
if (*p == '!')
SKIP_WHITE();
if (*p == '.')
p++, a_is_suffix = true;
+ else if (*p == ',')
+ p++, a_is_spectype = true;
atom = p;
while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
/* Substitute the switch(es) indicated by the current atom. */
ordered_set = true;
if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
- || atom == end_atom)
+ || a_is_spectype || atom == end_atom)
goto invalid;
mark_matching_switches (atom, end_atom, a_is_starred);
if (atom == end_atom)
{
if (!n_way_choice || disj_matched || *p == '|'
- || a_is_negated || a_is_suffix || a_is_starred)
+ || a_is_negated || a_is_suffix || a_is_spectype
+ || a_is_starred)
goto invalid;
/* An empty term may appear as the last choice of an
}
else
{
- if (a_is_suffix && a_is_starred)
- goto invalid;
-
- if (!a_is_starred)
- disj_starred = false;
-
- /* Don't bother testing this atom if we already have a
- match. */
- if (!disj_matched && !n_way_matched)
- {
- if (a_is_suffix)
- a_matched = input_suffix_matches (atom, end_atom);
- else
- a_matched = switch_matches (atom, end_atom, a_is_starred);
-
- if (a_matched != a_is_negated)
- {
- disj_matched = true;
- d_atom = atom;
- d_end_atom = end_atom;
- }
- }
+ if ((a_is_suffix || a_is_spectype) && a_is_starred)
+ goto invalid;
+
+ if (!a_is_starred)
+ disj_starred = false;
+
+ /* Don't bother testing this atom if we already have a
+ match. */
+ if (!disj_matched && !n_way_matched)
+ {
+ if (a_is_suffix)
+ a_matched = input_suffix_matches (atom, end_atom);
+ else if (a_is_spectype)
+ a_matched = input_spec_matches (atom, end_atom);
+ else
+ a_matched = switch_matches (atom, end_atom, a_is_starred);
+
+ if (a_matched != a_is_negated)
+ {
+ disj_matched = true;
+ d_atom = atom;
+ d_end_atom = end_atom;
+ }
+ }
}
if (*p == ':')
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_sysroot_headers_suffix)
+ {
+ if (*sysroot_hdrs_suffix_spec)
+ {
+ printf("%s\n", (target_sysroot_hdrs_suffix
+ ? target_sysroot_hdrs_suffix
+ : ""));
+ return (0);
+ }
+ else
+ /* The error status indicates that only one set of fixed
+ headers should be built. */
+ fatal ("not configured with sysroot headers suffix");
}
if (print_help_list)
p++;
SKIP_WHITE ();
- if (*p == '.')
+ if (*p == '.' || *p == ',')
suffix = true, p++;
atom = p;
}
}
\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