/* 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, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>.
This paragraph is here to try to keep Sun CC from dying.
The number of chars here seems crucial!!!! */
/* Flag set by cppspec.c to 1. */
int is_cpp_driver;
-/* Flag set to non-zero if an @file argument has been supplied to gcc. */
+/* Flag set to nonzero if an @file argument has been supplied to gcc. */
static bool at_file_supplied;
/* Flag saying to pass the greatest exit code returned by a sub-process
static int print_multi_directory;
+static int print_sysroot;
+
/* Flag saying to print the relative path we'd use to
find OS libraries given the current compiler flags. */
static struct obstack collect_obstack;
+/* This is a list of a wrapper program and its arguments.
+ e.g. wrapper_string of "strace,-c"
+ will cause all programs to run as
+ strace -c program arguments
+ instead of just
+ program arguments */
+static const char *wrapper_string;
+
/* Forward declaration for prototypes. */
struct path_prefix;
struct prefix_list;
static void init_spec (void);
static void store_arg (const char *, int, int);
+static void insert_wrapper (const char *);
static char *load_specs (const char *);
static void read_specs (const char *, int);
static void set_spec (const char *, const char *);
static struct compiler *lookup_compiler (const char *, size_t, const char *);
static char *build_search_list (const struct path_prefix *, const char *,
bool, bool);
+static void xputenv (const char *);
static void putenv_from_prefixes (const struct path_prefix *, const char *,
bool);
static int access_check (const char *, int);
#define LINKER_NAME "collect2"
#endif
+#ifdef HAVE_AS_DEBUG_PREFIX_MAP
+#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
+#else
+#define ASM_MAP ""
+#endif
+
/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
to the assembler. */
#ifndef ASM_DEBUG_SPEC
# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
&& defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC \
- (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
- ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \
- : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
+# define ASM_DEBUG_SPEC \
+ (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
+ ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" ASM_MAP \
+ : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}" ASM_MAP)
# else
# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC "%{g*:--gstabs}"
+# define ASM_DEBUG_SPEC "%{g*:--gstabs}" ASM_MAP
# endif
# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
+# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" ASM_MAP
# endif
# endif
#endif
%(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
%{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
- %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
+ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
%{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
%{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
in turn cause preprocessor symbols to be defined specially. */
static const char *cpp_options =
"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
- %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
+ %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\
%{undef} %{save-temps:-fpch-preprocess}";
/* This contains cpp options which are not passed when the preprocessor
%{coverage:-fprofile-arcs -ftest-coverage}";
static const char *asm_options =
-"%{ftarget-help:%:print-asm-header()} \
-%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
+"%{--target-help:%:print-asm-header()} "
+#if HAVE_GNU_AS
+/* If GNU AS is used, then convert -w (no warnings), -I, and -v
+ to the assembler equivalents. */
+"%{v} %{w:-W} %{I*} "
+#endif
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
static const char *invoke_as =
#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
/* Adding -fopenmp should imply pthreads. This is particularly important
for targets that use different start files and suchlike. */
#ifndef GOMP_SELF_SPECS
-#define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
+#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
#endif
static const char *const driver_self_specs[] = {
{".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
{".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
{".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
- {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0},
- {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
- {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
- {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0},
- {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+ {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
+ {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
+ {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
+ {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
+ {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
+ {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+ {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
+ {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
{".r", "#Ratfor", 0, 0, 0},
{".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
{".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
{".s", "@assembler", 0, 1, 0},
{"@assembler",
"%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
+ {".sx", "@assembler-with-cpp", 0, 1, 0},
{".S", "@assembler-with-cpp", 0, 1, 0},
{"@assembler-with-cpp",
#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
- "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
%{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
as %(asm_debug) %(asm_options) %|.s %A }}}}"
#else
- "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
%{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
as %(asm_debug) %(asm_options) %m.s %A }}}}"
{"--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", "-print-sysroot", 0},
{"--print-sysroot-headers-suffix", "-print-sysroot-headers-suffix", 0},
{"--profile", "-p", 0},
{"--profile-blocks", "-a", 0},
/* Translate the options described by *ARGCP and *ARGVP.
Make a new vector and store it back in *ARGVP,
- and store its length in *ARGVC. */
+ and store its length in *ARGCP. */
static void
translate_options (int *argcp, const char *const **argvp)
int argc = *argcp;
const char *const *argv = *argvp;
int newvsize = (argc + 2) * 2 * sizeof (const char *);
- const char **newv = xmalloc (newvsize);
+ const char **newv = XNEWVAR (const char *, newvsize);
int newindex = 0;
i = 0;
}
newvsize += spaces * sizeof (const char *);
- newv = xrealloc (newv, newvsize);
+ newv = XRESIZEVAR (const char *, newv, newvsize);
sp = target_option_translations[tott_idx].replacements;
np = xstrdup (sp);
notice ("Using built-in specs.\n");
#ifdef EXTRA_SPECS
- extra_specs = xcalloc (sizeof (struct spec_list),
- ARRAY_SIZE (extra_specs_1));
+ extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
{
}
#endif
- /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes
- on ?: in file-scope variable initializations. */
- asm_debug = ASM_DEBUG_SPEC;
-
for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
{
sl = &static_specs[i];
/* Free the old spec. */
if (old_spec && sl->alloc_p)
- free ((void *) old_spec);
+ free (CONST_CAST(char *, old_spec));
sl->alloc_p = 1;
}
store_arg (const char *arg, int delete_always, int delete_failure)
{
if (argbuf_index + 1 == argbuf_length)
- argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
+ argbuf = XRESIZEVEC (const char *, argbuf, (argbuf_length *= 2));
argbuf[argbuf_index++] = arg;
argbuf[argbuf_index] = 0;
set_spec (p2, *(sl->ptr_spec));
if (sl->alloc_p)
- free ((void *) *(sl->ptr_spec));
+ free (CONST_CAST (char *, *(sl->ptr_spec)));
*(sl->ptr_spec) = "";
sl->alloc_p = 0;
{
/* Add this pair to the vector. */
compilers
- = xrealloc (compilers,
- (n_compilers + 2) * sizeof (struct compiler));
+ = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
compilers[n_compilers].suffix = suffix;
compilers[n_compilers].spec = spec;
Don't repeat any we have already seen. */
if (multi_dir)
{
- free ((char *) multi_dir);
+ free (CONST_CAST (char *, multi_dir));
multi_dir = NULL;
- free ((char *) multi_suffix);
+ free (CONST_CAST (char *, multi_suffix));
multi_suffix = machine_suffix;
- free ((char *) just_multi_suffix);
+ free (CONST_CAST (char *, just_multi_suffix));
just_multi_suffix = just_machine_suffix;
}
else
skip_multi_dir = true;
if (multi_os_dir)
{
- free ((char *) multi_os_dir);
+ free (CONST_CAST (char *, multi_os_dir));
multi_os_dir = NULL;
}
else
if (multi_dir)
{
- free ((char *) multi_dir);
- free ((char *) multi_suffix);
- free ((char *) just_multi_suffix);
+ free (CONST_CAST (char *, multi_dir));
+ free (CONST_CAST (char *, multi_suffix));
+ free (CONST_CAST (char *, just_multi_suffix));
}
if (multi_os_dir)
- free ((char *) multi_os_dir);
+ free (CONST_CAST (char *, multi_os_dir));
if (ret != path)
free (path);
return ret;
static void *
add_to_obstack (char *path, void *data)
{
- struct add_to_obstack_info *info = data;
+ struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
if (info->check_dir && !is_directory (path, false))
return NULL;
return NULL;
}
+/* Add or change the value of an environment variable, outputting the
+ change to standard error if in verbose mode. */
+static void
+xputenv (const char *string)
+{
+ if (verbose_flag)
+ notice ("%s\n", string);
+ putenv (CONST_CAST (char *, string));
+}
+
/* Build a list of search directories from PATHS.
PREFIX is a string to prepend to the list.
If CHECK_DIR_P is true we ensure the directory exists.
putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
bool do_multi)
{
- putenv (build_search_list (paths, env_var, true, do_multi));
+ xputenv (build_search_list (paths, env_var, true, do_multi));
}
\f
/* Check whether NAME can be accessed in MODE. This is like access,
static void *
file_at_path (char *path, void *data)
{
- struct file_at_path_info *info = data;
+ struct file_at_path_info *info = (struct file_at_path_info *) data;
size_t len = strlen (path);
memcpy (path + len, info->name, info->name_len);
info.suffix_len = strlen (info.suffix);
info.mode = mode;
- return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len,
- file_at_path, &info);
+ return (char*) for_each_path (pprefix, do_multi,
+ info.name_len + info.suffix_len,
+ file_at_path, &info);
}
/* Ranking of prefixes in the sort list. -B prefixes are put before
gcc_assert (!processing_spec_function);
+ if (wrapper_string)
+ {
+ string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false);
+ argbuf[0] = (string) ? string : argbuf[0];
+ insert_wrapper (wrapper_string);
+ }
+
/* Count # of piped commands. */
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
n_commands++;
/* Get storage for each command. */
- commands = alloca (n_commands * sizeof (struct command));
+ commands = (struct command *) alloca (n_commands * sizeof (struct command));
/* Split argbuf into its separate piped processes,
and record info about each one.
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
- string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
-
- if (string)
- commands[0].argv[0] = string;
+
+ if (!wrapper_string)
+ {
+ string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
+ commands[0].argv[0] = (string) ? string : commands[0].argv[0];
+ }
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
for (argc = 0; commands[i].argv[argc] != NULL; argc++)
;
- argv = alloca ((argc + 3) * sizeof (char *));
+ argv = XALLOCAVEC (const char *, argc + 3);
argv[0] = VALGRIND_PATH;
argv[1] = "-q";
errmsg = pex_run (pex,
((i + 1 == n_commands ? PEX_LAST : 0)
| (string == commands[i].prog ? PEX_SEARCH : 0)),
- string, (char * const *) commands[i].argv,
+ string, CONST_CAST (char **, commands[i].argv),
NULL, NULL, &err);
if (errmsg != NULL)
{
}
if (string != commands[i].prog)
- free ((void *) string);
+ free (CONST_CAST (char *, string));
}
execution_count++;
struct pex_time *times = NULL;
int ret_code = 0;
- statuses = alloca (n_commands * sizeof (int));
+ statuses = (int *) alloca (n_commands * sizeof (int));
if (!pex_get_status (pex, n_commands, statuses))
pfatal_with_name (_("failed to get exit status"));
if (report_times)
{
- times = alloca (n_commands * sizeof (struct pex_time));
+ times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
if (!pex_get_times (pex, n_commands, times))
pfatal_with_name (_("failed to get process times"));
}
If a switch uses following arguments, then the `part1' field
is the switch itself and the `args' field
is a null-terminated vector containing the following arguments.
- The `live_cond' field is:
- 0 when initialized
- 1 if the switch is true in a conditional spec,
- -1 if false (overridden by a later switch)
- -2 if this switch should be ignored (used in %<S)
+ Bits in the `live_cond' field are:
+ SWITCH_LIVE to indicate this switch is true in a conditional spec.
+ SWITCH_FALSE to indicate this switch is overridden by a later switch.
+ SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
The `validated' field is nonzero if any spec has looked at this switch;
if it remains zero at the end of the run, it must be meaningless. */
-#define SWITCH_OK 0
-#define SWITCH_FALSE -1
-#define SWITCH_IGNORE -2
-#define SWITCH_LIVE 1
+#define SWITCH_LIVE 0x1
+#define SWITCH_FALSE 0x2
+#define SWITCH_IGNORE 0x4
struct switchstr
{
const char *part1;
const char **args;
- int live_cond;
+ unsigned int live_cond;
unsigned char validated;
unsigned char ordering;
};
-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 Display the target libraries directory\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);
if (! preprocessor_options)
preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
else
- preprocessor_options = xrealloc (preprocessor_options,
- n_preprocessor_options * sizeof (char *));
+ preprocessor_options = XRESIZEVEC (char *, preprocessor_options,
+ n_preprocessor_options);
preprocessor_options [n_preprocessor_options - 1] =
save_string (option, len);
if (! assembler_options)
assembler_options = XNEWVEC (char *, n_assembler_options);
else
- assembler_options = xrealloc (assembler_options,
- n_assembler_options * sizeof (char *));
+ assembler_options = XRESIZEVEC (char *, assembler_options,
+ n_assembler_options);
assembler_options [n_assembler_options - 1] = save_string (option, len);
}
if (! linker_options)
linker_options = XNEWVEC (char *, n_linker_options);
else
- linker_options = xrealloc (linker_options,
- n_linker_options * sizeof (char *));
+ linker_options = XRESIZEVEC (char *, linker_options, n_linker_options);
linker_options [n_linker_options - 1] = save_string (option, len);
}
for (baselen = strlen (progname); baselen > 0; baselen--)
if (IS_DIR_SEPARATOR (progname[baselen-1]))
break;
- new_argv0 = xmemdup (progname, baselen,
+ new_argv0 = XDUPVAR (char, progname, baselen,
baselen + concat_length (new_version, new_machine,
"-gcc-", NULL) + 1);
strcpy (new_argv0 + baselen, new_machine);
strcat (new_argv0, "-gcc-");
strcat (new_argv0, new_version);
- new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
- (argc + 1) * sizeof (argv[0]));
+ new_argv = XDUPVEC (char *, argv, argc + 1);
new_argv[0] = new_argv0;
execvp (new_argv0, new_argv);
standard_bindir_prefix,
standard_libexec_prefix);
if (gcc_exec_prefix)
- putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
+ xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
}
else
{
if (temp)
{
const char *startp, *endp;
- char *nstore = alloca (strlen (temp) + 3);
+ char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
- char *nstore = alloca (strlen (temp) + 3);
+ char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
- char *nstore = alloca (strlen (temp) + 3);
+ char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
else if (strcmp (argv[i], "-fversion") == 0)
{
/* translate_options () has turned --version into -fversion. */
- printf (_("%s (GCC) %s\n"), programname, version_string);
- printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
+ printf (_("%s %s%s\n"), programname, pkgversion_string,
+ version_string);
+ printf ("Copyright %s 2008 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"),
print_multi_lib = 1;
else if (! strcmp (argv[i], "-print-multi-directory"))
print_multi_directory = 1;
+ else if (! strcmp (argv[i], "-print-sysroot"))
+ print_sysroot = 1;
else if (! strcmp (argv[i], "-print-multi-os-directory"))
print_multi_os_directory = 1;
else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
use_pipes = 1;
n_switches++;
}
+ else if (strcmp (argv[i], "-wrapper") == 0)
+ {
+ if (++i >= argc)
+ fatal ("argument to '-wrapper' is missing");
+
+ wrapper_string = argv[i];
+ n_switches++;
+ n_switches++;
+ }
else if (strcmp (argv[i], "-###") == 0)
{
/* This is similar to -v except that there is no execution
for (j = 0; j < ARRAY_SIZE (modify_target); j++)
if (! strcmp (argv[i], modify_target[j].sw))
{
- char *new_name = xmalloc (strlen (modify_target[j].str)
+ char *new_name = XNEWVEC (char, strlen (modify_target[j].str)
+ strlen (spec_machine));
const char *p, *r;
char *q;
;
else if (! strcmp (argv[i], "-print-multi-directory"))
;
+ else if (! strcmp (argv[i], "-print-sysroot"))
+ ;
else if (! strcmp (argv[i], "-print-multi-os-directory"))
;
else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
-e0 or -e1 down into the linker. */
switches[n_switches].part1 = &argv[i][0];
switches[n_switches].args = 0;
- switches[n_switches].live_cond = SWITCH_OK;
+ switches[n_switches].live_cond = 0;
switches[n_switches].validated = 0;
n_switches++;
}
infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i];
}
+ else if (strcmp (argv[i], "-wrapper") == 0)
+ i++;
else if (strcmp (argv[i], "-specs") == 0)
i++;
else if (strncmp (argv[i], "-specs=", 7) == 0)
else
switches[n_switches].args = 0;
- switches[n_switches].live_cond = SWITCH_OK;
+ switches[n_switches].live_cond = 0;
switches[n_switches].validated = 0;
switches[n_switches].ordering = 0;
- /* These are always valid, since gcc.c itself understands them. */
+ /* These are always valid, since gcc.c itself understands the
+ first four and gfortranspec.c understands -static-libgfortran. */
if (!strcmp (p, "save-temps")
|| !strcmp (p, "static-libgcc")
|| !strcmp (p, "shared-libgcc")
- || !strcmp (p, "pipe"))
+ || !strcmp (p, "pipe")
+ || !strcmp (p, "static-libgfortran"))
switches[n_switches].validated = 1;
else
{
first_time = FALSE;
/* Ignore elided switches. */
- if (switches[i].live_cond == SWITCH_IGNORE)
+ if ((switches[i].live_cond & SWITCH_IGNORE) != 0)
continue;
obstack_grow (&collect_obstack, "'-", 2);
}
}
obstack_grow (&collect_obstack, "\0", 1);
- putenv (XOBFINISH (&collect_obstack, char *));
+ xputenv (XOBFINISH (&collect_obstack, char *));
}
\f
/* Process a spec string, accumulating and running commands. */
arguments. */
static const char *suffix_subst;
+/* If there is an argument being accumulated, terminate it and store it. */
+
+static void
+end_going_arg (void)
+{
+ if (arg_going)
+ {
+ const char *string;
+
+ obstack_1grow (&obstack, 0);
+ string = XOBFINISH (&obstack, const char *);
+ if (this_is_library_file)
+ string = find_file (string);
+ store_arg (string, delete_this_arg, this_is_output_file);
+ if (this_is_output_file)
+ outfiles[input_file_number] = string;
+ arg_going = 0;
+ }
+}
+
+
+/* Parse the WRAPPER string which is a comma separated list of the command line
+ and insert them into the beginning of argbuf. */
+
+static void
+insert_wrapper (const char *wrapper)
+{
+ int n = 0;
+ int i;
+ char *buf = xstrdup (wrapper);
+ char *p = buf;
+
+ do
+ {
+ n++;
+ while (*p == ',')
+ p++;
+ }
+ while ((p = strchr (p, ',')) != NULL);
+
+ if (argbuf_index + n >= argbuf_length)
+ {
+ argbuf_length = argbuf_length * 2;
+ while (argbuf_length < argbuf_index + n)
+ argbuf_length *= 2;
+ argbuf = XRESIZEVEC (const char *, argbuf, argbuf_length);
+ }
+ for (i = argbuf_index - 1; i >= 0; i--)
+ argbuf[i + n] = argbuf[i];
+
+ i = 0;
+ p = buf;
+ do
+ {
+ while (*p == ',')
+ {
+ *p = 0;
+ p++;
+ }
+ argbuf[i++] = p;
+ }
+ while ((p = strchr (p, ',')) != NULL);
+ gcc_assert (i == n);
+ argbuf_index += n;
+}
+
/* Process the spec SPEC and run the commands specified therein.
Returns 0 if the spec is successfully processed; -1 if failed. */
static int
do_spec_2 (const char *spec)
{
- const char *string;
int result;
clear_args ();
result = do_spec_1 (spec, 0, NULL);
- /* End any pending argument. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- arg_going = 0;
- }
+ end_going_arg ();
return result;
}
}
/* Replace each %(VALUE) by the specified value. */
- tmp_spec = alloca (strlen (spec) + 1
+ tmp_spec = (char *) alloca (strlen (spec) + 1
+ value_count * (value_len - strlen ("%(VALUE)")));
tmp_spec_p = tmp_spec;
q = spec;
first = n_switches;
n_switches += argbuf_index;
- switches = xrealloc (switches,
- sizeof (struct switchstr) * (n_switches + 1));
+ switches = XRESIZEVEC (struct switchstr, switches, n_switches + 1);
switches[n_switches] = switches[first];
for (i = 0; i < argbuf_index; i++)
sw = &switches[i + first];
sw->part1 = &argbuf[i][1];
sw->args = 0;
- sw->live_cond = SWITCH_OK;
+ sw->live_cond = 0;
sw->validated = 0;
sw->ordering = 0;
}
static void *
spec_path (char *path, void *data)
{
- struct spec_path_info *info = data;
+ struct spec_path_info *info = (struct spec_path_info *) data;
size_t len = 0;
char save = 0;
const char *p = spec;
int c;
int i;
- const char *string;
int value;
while ((c = *p++))
switch (inswitch ? 'a' : c)
{
case '\n':
- /* End of line: finish any pending argument,
- then run the pending command if one has been started. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- }
- arg_going = 0;
+ end_going_arg ();
if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
{
break;
case '|':
- /* End any pending argument. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- }
+ end_going_arg ();
/* Use pipe */
obstack_1grow (&obstack, c);
case '\t':
case ' ':
- /* Space or tab ends an argument if one is pending. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- }
+ end_going_arg ();
+
/* Reinitialize for a new argument. */
- arg_going = 0;
delete_this_arg = 0;
this_is_output_file = 0;
this_is_library_file = 0;
char *buf;
while (*p != 0 && *p != '\n')
p++;
- buf = alloca (p - q + 1);
+ buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
error ("%s", buf);
char *buf;
while (*p != 0 && *p != '\n')
p++;
- buf = alloca (p - q + 1);
+ buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
notice ("%s\n", buf);
if (save_temps_flag)
{
+ char *tmp;
+
temp_filename_length = basename_length + suffix_length;
- temp_filename = alloca (temp_filename_length + 1);
- strncpy ((char *) temp_filename, input_basename, basename_length);
- strncpy ((char *) temp_filename + basename_length, suffix,
- suffix_length);
- *((char *) temp_filename + temp_filename_length) = '\0';
+ tmp = (char *) alloca (temp_filename_length + 1);
+ strncpy (tmp, input_basename, basename_length);
+ strncpy (tmp + basename_length, suffix, suffix_length);
+ tmp[temp_filename_length] = '\0';
+ temp_filename = tmp;
if (strcmp (temp_filename, input_filename) != 0)
{
#ifndef HOST_LACKS_INODE_NUMBERS
{
if (t == 0)
{
- t = xmalloc (sizeof (struct temp_name));
+ t = XNEW (struct temp_name);
t->next = temp_names;
temp_names = t;
}
for (n_files = 0, i = 0; i < max; i++)
n_files += outfiles[i] != NULL;
- argv = alloca (sizeof (char *) * (n_files + 1));
+ argv = (char **) alloca (sizeof (char *) * (n_files + 1));
/* Copy the strings over. */
for (i = 0, j = 0; i < max; i++)
if (outfiles[i])
{
- argv[j] = (char *) outfiles[i];
+ argv[j] = CONST_CAST (char *, outfiles[i]);
j++;
}
argv[j] = NULL;
p = handle_braces (p + 1);
if (p == 0)
return -1;
- /* End any pending argument. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- arg_going = 0;
- }
+ end_going_arg ();
/* If any args were output, mark the last one for deletion
on failure. */
if (argbuf_index != cur_index)
if (!strncmp (switches[i].part1, p, len - have_wildcard)
&& (have_wildcard || switches[i].part1[len] == '\0'))
{
- switches[i].live_cond = SWITCH_IGNORE;
+ switches[i].live_cond |= SWITCH_IGNORE;
switches[i].validated = 1;
}
}
else
{
- char *x = alloca (strlen (name) * 2 + 1);
+ char *x = (char *) alloca (strlen (name) * 2 + 1);
char *buf = x;
const char *y = name;
int flag = 0;
/* End of string. If we are processing a spec function, we need to
end any pending argument. */
- if (processing_spec_function && arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- arg_going = 0;
- }
+ if (processing_spec_function)
+ end_going_arg ();
return 0;
}
/* If we already processed this switch and determined if it was
live or not, return our past determination. */
if (switches[switchnum].live_cond != 0)
- return switches[switchnum].live_cond > 0;
+ return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
+ && (switches[switchnum].live_cond & SWITCH_FALSE) == 0);
/* Now search for duplicate in a manner that depends on the name. */
switch (*name)
}
/* Otherwise the switch is live. */
- switches[switchnum].live_cond = SWITCH_LIVE;
+ switches[switchnum].live_cond |= SWITCH_LIVE;
return 1;
}
\f
static void
give_switch (int switchnum, int omit_first_word)
{
- if (switches[switchnum].live_cond == SWITCH_IGNORE)
+ if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
return;
if (!omit_first_word)
while (length-- && !IS_DIR_SEPARATOR (arg[length]))
if (arg[length] == '.')
{
- ((char *)arg)[length] = 0;
+ (CONST_CAST(char *, arg))[length] = 0;
dot = 1;
break;
}
do_spec_1 (arg, 1, NULL);
if (dot)
- ((char *)arg)[length] = '.';
+ (CONST_CAST(char *, arg))[length] = '.';
do_spec_1 (suffix_subst, 1, NULL);
}
else
/* Ensure the string ends with "/.". The resulting path will be a
directory even if the given path is a symbolic link. */
len1 = strlen (path1);
- path = alloca (3 + len1);
+ path = (char *) alloca (3 + len1);
memcpy (path, path1, len1);
cp = path + len1;
if (!IS_DIR_SEPARATOR (cp[-1]))
struct user_specs *uptr;
char **old_argv = argv;
+ /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes
+ on ?: in file-scope variable initializations. */
+ asm_debug = ASM_DEBUG_SPEC;
+
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
--p;
obstack_init (&collect_obstack);
obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
- putenv (XOBFINISH (&collect_obstack, char *));
+ xputenv (XOBFINISH (&collect_obstack, char *));
#ifdef INIT_ENVIRONMENT
/* Set up any other necessary machine specific environment variables. */
- putenv (INIT_ENVIRONMENT);
+ xputenv (INIT_ENVIRONMENT);
#endif
/* Make a table of what switches there are (switches, n_switches).
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
- compilers = xmalloc (sizeof default_compilers);
+ compilers = XNEWVAR (struct compiler, sizeof default_compilers);
memcpy (compilers, default_compilers, sizeof default_compilers);
n_compilers = n_default_compilers;
/* We need to check standard_exec_prefix/just_machine_suffix/specs
for any override of as, ld and libraries. */
- specs_file = alloca (strlen (standard_exec_prefix)
+ specs_file = (char *) alloca (strlen (standard_exec_prefix)
+ strlen (just_machine_suffix) + sizeof ("specs"));
strcpy (specs_file, standard_exec_prefix);
return (0);
}
+ if (print_sysroot)
+ {
+ if (target_system_root)
+ {
+ if (target_sysroot_suffix)
+ printf ("%s%s\n", target_system_root, target_sysroot_suffix);
+ else
+ printf ("%s\n", target_system_root);
+ }
+ return (0);
+ }
+
if (print_multi_os_directory)
{
if (multilib_os_dir == NULL)
if (! strncmp (version_string, compiler_version, n)
&& compiler_version[n] == 0)
- notice ("gcc version %s\n", version_string);
+ notice ("gcc version %s %s\n", version_string, pkgversion_string);
else
- notice ("gcc driver version %s executing gcc version %s\n",
- version_string, compiler_version);
+ notice ("gcc driver version %s %sexecuting gcc version %s\n",
+ version_string, pkgversion_string, compiler_version);
if (n_infiles == 0)
return (0);
if (! linker_was_run && error_count == 0)
for (i = 0; (int) i < n_infiles; i++)
- if (explicit_link_files[i])
+ if (explicit_link_files[i]
+ && !(infiles[i].language && infiles[i].language[0] == '*'))
error ("%s: linker input file unused because linking not done",
outfiles[i]);
if (*q == ';')
cnt++;
- matches = alloca ((sizeof (struct mswitchstr)) * cnt);
+ matches
+ = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
i = 0;
q = multilib_matches;
while (*q != '\0')
mswitches
= XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
for (i = 0; i < n_switches; i++)
- if (switches[i].live_cond != SWITCH_IGNORE)
+ if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
{
int xlen = strlen (switches[i].part1);
for (j = 0; j < cnt; j++)
if (multilib_dir == NULL && multilib_os_dir != NULL
&& strcmp (multilib_os_dir, ".") == 0)
{
- free ((char *) multilib_os_dir);
+ free (CONST_CAST (char *, multilib_os_dir));
multilib_os_dir = NULL;
}
else if (multilib_dir != NULL && multilib_os_dir == NULL)
getenv_spec_function (int argc, const char **argv)
{
char *value;
+ char *result;
+ char *ptr;
+ size_t len;
if (argc != 2)
return NULL;
if (!value)
fatal ("environment variable \"%s\" not defined", argv[0]);
- return concat (value, argv[1], NULL);
+ /* We have to escape every character of the environment variable so
+ they are not interpreted as active spec characters. A
+ particularly painful case is when we are reading a variable
+ holding a windows path complete with \ separators. */
+ len = strlen (value) * 2 + strlen (argv[1]) + 1;
+ result = XNEWVAR (char, len);
+ for (ptr = result; *value; ptr += 2)
+ {
+ ptr[0] = '\\';
+ ptr[1] = *value++;
+ }
+
+ strcpy (ptr, argv[1]);
+
+ return result;
}
/* if-exists built-in spec function.
if (argc != 1)
abort ();
- file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
+ file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
read_specs (file ? file : argv[0], FALSE);
return NULL;