/* 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, 2008, 2009,
- 2010
+ 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
#include "coretypes.h"
#include "multilib.h" /* before tm.h */
#include "tm.h"
-#include <signal.h>
-#if ! defined( SIGCHLD ) && defined( SIGCLD )
-# define SIGCHLD SIGCLD
-#endif
#include "xregex.h"
#include "obstack.h"
#include "intl.h"
#include "diagnostic.h"
#include "flags.h"
#include "opts.h"
-
-#ifdef HAVE_MMAP_FILE
-# include <sys/mman.h>
-# ifdef HAVE_MINCORE
-/* This is on Solaris. */
-# include <sys/types.h>
-# endif
-#endif
-
-#ifndef MAP_FAILED
-# define MAP_FAILED ((void *)-1)
-#endif
+#include "params.h"
+#include "vec.h"
+#include "filenames.h"
/* By default there is no special suffix for target executables. */
/* FIXME: when autoconf is fixed, remove the host check - dj */
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
#endif
-#ifndef HAVE_KILL
-#define kill(p,s) raise(s)
-#endif
-
/* If a stage of compilation returns an exit status >= 1,
compilation of that file ceases. */
static int print_version;
-/* Flag indicating whether we should print the command and arguments */
-
-static int verbose_flag;
-
/* Flag indicating whether we should ONLY print the command and
arguments (like verbose_flag) without executing the command.
Displayed arguments are quoted so that the generated command
static void add_preprocessor_option (const char *, int);
static void add_assembler_option (const char *, int);
static void add_linker_option (const char *, int);
-static void process_command (int, const char **);
+static void process_command (unsigned int, struct cl_decoded_option *);
static int execute (void);
static void alloc_args (void);
static void clear_args (void);
static const char *compare_debug_dump_opt_spec_function (int, const char **);
static const char *compare_debug_self_opt_spec_function (int, const char **);
static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
+static const char *pass_through_libs_spec_func (int, const char **);
+static char *convert_white_space (char *);
\f
/* The Specs Language
Note - this command is position dependent. % commands in the
spec string before this one will see -S, % commands in the
spec string after this one will not.
+ %>S Similar to "%<S", but keep it in the GCC command line.
%<S* remove all occurrences of all switches beginning with -S from the
command line.
%:function(args)
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
The conditional text X in a %{S:X} or similar construct may contain
other nested % constructs or spaces, or even newlines. They are
/* XXX: should exactly match hooks provided by libmudflap.a */
#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
--wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
- --wrap=mmap --wrap=munmap --wrap=alloca\
+ --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca\
} %{fmudflapth: --wrap=pthread_create\
}} %{fmudflap|fmudflapth: --wrap=main}"
#endif
#define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}"
#endif
+/* When using -fsplit-stack we need to wrap pthread_create, in order
+ to initialize the stack guard. We always use wrapping, rather than
+ shared library ordering, and we keep the wrapper function in
+ libgcc. This is not yet a real spec, though it could become one;
+ it is currently just stuffed into LINK_SPEC. FIXME: This wrapping
+ only works with GNU ld and gold. FIXME: This is incompatible with
+ -fmudflap when linking statically, which wants to do its own
+ wrapping. */
+#define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
+
/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
included. */
#ifndef LIBGCC_SPEC
# endif
#endif
+/* Conditional to test whether the LTO plugin is used or not.
+ FIXME: For slim LTO we will need to enable plugin unconditionally. This
+ still cause problems with PLUGIN_LD != LD and when plugin is built but
+ not useable. For GCC 4.6 we don't support slim LTO and thus we can enable
+ plugin only when LTO is enabled. We still honor explicit
+ -fuse-linker-plugin if the linker used understands -plugin. */
+
+/* The linker has some plugin support. */
+#if HAVE_LTO_PLUGIN > 0
+/* The linker used has full plugin support, use LTO plugin by default. */
+#if HAVE_LTO_PLUGIN == 2
+#define PLUGIN_COND "!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin"
+#define PLUGIN_COND_CLOSE "}"
+#else
+/* The linker used has limited plugin support, use LTO plugin with explicit
+ -fuse-linker-plugin. */
+#define PLUGIN_COND "fuse-linker-plugin"
+#define PLUGIN_COND_CLOSE ""
+#endif
+#define LINK_PLUGIN_SPEC \
+ "%{"PLUGIN_COND": \
+ -plugin %(linker_plugin_file) \
+ -plugin-opt=%(lto_wrapper) \
+ -plugin-opt=-fresolution=%u.res \
+ %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
+ }"PLUGIN_COND_CLOSE
+#else
+/* The linker used doesn't support -plugin, reject -fuse-linker-plugin. */
+#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
+ %e-fuse-linker-plugin is not supported in this configuration}"
+#endif
+
/* -u* was put back because both BSD and SysV seem to support it. */
/* %{static:} simply prevents an error message if the target machine
/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
scripts which exist in user specified directories, or in standard
directories. */
-/* We pass any -flto and -fwhopr flags on to the linker, which is expected
+/* We pass any -flto flags on to the linker, which is expected
to understand them. In practice, this means it had better be collect2. */
+/* %{e*} includes -export-dynamic; see comment in common.opt. */
#ifndef LINK_COMMAND_SPEC
#define LINK_COMMAND_SPEC "\
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
- %(linker) \
- %{fuse-linker-plugin: \
- -plugin %(linker_plugin_file) \
- -plugin-opt=%(lto_wrapper) \
- -plugin-opt=-fresolution=%u.res \
- %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \
- %{static:-plugin-opt=-pass-through=-lc} \
- } \
- %{flto:%<fcompare-debug*} %{fwhopr*:%<fcompare-debug*} \
- %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
- "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
- %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
+ %(linker) " \
+ LINK_PLUGIN_SPEC \
+ "%{flto|flto=*:%<fcompare-debug*} \
+ %{flto} %{flto=*} %l " LINK_PIE_SPEC \
+ "%X %{o*} %{e*} %{N} %{n} %{r}\
+ %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
- %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
+ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+ %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
+ %(mflib) " STACK_SPLIT_SPEC "\
%{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
%{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
+ %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}"
#endif
#ifndef LINK_LIBGCC_SPEC
static const char *linker_plugin_file_spec = "";
static const char *lto_wrapper_spec = "";
static const char *lto_gcc_spec = "";
-static const char *lto_libgcc_spec = "";
static const char *link_command_spec = LINK_COMMAND_SPEC;
static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
static const char *sysroot_spec = SYSROOT_SPEC;
static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
+static const char *self_spec = "";
/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
There should be no need to override these in target dependent files,
call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
that we default the front end language better. */
static const char *trad_capable_cpp =
-"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
+"cc1 -E %{traditional|traditional-cpp:-traditional-cpp}";
/* We don't wrap .d files in %W{} since a missing .d file, and
therefore no dependency entry, confuses make into thinking a .o
%{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
%{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
%{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
- %{Qn:-fno-ident} %{-help:--help}\
+ %{Qn:-fno-ident} %{Qy:} %{-help:--help}\
%{-target-help:--target-help}\
%{-version:--version}\
%{-help=*:--help=%*}\
%{coverage:-fprofile-arcs -ftest-coverage}";
static const char *asm_options =
-"%{--target-help:%:print-asm-header()} "
+"%{-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. */
#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
#endif
+/* Likewise for -fgnu-tm. */
+#ifndef GTM_SELF_SPECS
+#define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
+#endif
+
static const char *const driver_self_specs[] = {
"%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
- DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS
+ DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
};
#ifndef OPTION_DEFAULT_SPECS
static struct user_specs *user_specs_head, *user_specs_tail;
\f
-#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
-/* This defines which switches stop a full compilation. */
-#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
- ((CHAR) == 'c' || (CHAR) == 'S' || (CHAR) == 'E')
-
-#ifndef SWITCH_CURTAILS_COMPILATION
-#define SWITCH_CURTAILS_COMPILATION(CHAR) \
- DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
-#endif
-#endif
-
/* Record the mapping from file suffixes for compilation specs. */
struct compiler
{".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
{".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
{".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
+ {".go", "#Go", 0, 1, 0},
/* Next come the entries for C. */
{".c", "@c", 0, 0, 1},
{"@c",
external preprocessor if -save-temps is given. */
"%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\
- %{traditional|ftraditional:\
+ %{traditional:\
%eGNU C no longer supports -traditional without -E}\
%{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
%(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
%W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0},
{".i", "@cpp-output", 0, 0, 0},
{"@cpp-output",
- "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
- {".s", "@assembler", 0, 1, 0},
+ "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+ {".s", "@assembler", 0, 0, 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},
+ "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
+ {".sx", "@assembler-with-cpp", 0, 0, 0},
+ {".S", "@assembler-with-cpp", 0, 0, 0},
{"@assembler-with-cpp",
#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
"%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
%{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
as %(asm_debug) %(asm_options) %m.s %A }}}}"
#endif
- , 0, 1, 0},
+ , 0, 0, 0},
#include "specs.h"
/* Mark end of table. */
static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
+typedef char *char_p; /* For DEF_VEC_P. */
+DEF_VEC_P(char_p);
+DEF_VEC_ALLOC_P(char_p,heap);
+
/* A vector of options to give to the linker.
These options are accumulated by %x,
and substituted into the linker command with %X. */
-static int n_linker_options;
-static char **linker_options;
+static VEC(char_p,heap) *linker_options;
/* A vector of options to give to the assembler.
These options are accumulated by -Wa,
and substituted into the assembler command with %Y. */
-static int n_assembler_options;
-static char **assembler_options;
+static VEC(char_p,heap) *assembler_options;
/* A vector of options to give to the preprocessor.
These options are accumulated by -Wp,
and substituted into the preprocessor command with %Z. */
-static int n_preprocessor_options;
-static char **preprocessor_options;
+static VEC(char_p,heap) *preprocessor_options;
\f
static char *
skip_whitespace (char *p)
set_multilib_dir based on the compilation options. */
static const char *multilib_os_dir;
+
+/* Subdirectory to use for locating libraries in multiarch conventions. Set by
+ set_multilib_dir based on the compilation options. */
+
+static const char *multiarch_dir;
\f
/* Structure to keep track of the specs that have been defined so far.
- These are accessed using %(specname) or %[specname] in a compiler
- or link spec. */
+ These are accessed using %(specname) in a compiler or link
+ spec. */
struct spec_list
{
INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec),
INIT_STATIC_SPEC ("lto_wrapper", <o_wrapper_spec),
INIT_STATIC_SPEC ("lto_gcc", <o_gcc_spec),
- INIT_STATIC_SPEC ("lto_libgcc", <o_libgcc_spec),
INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
INIT_STATIC_SPEC ("sysroot_spec", &sysroot_spec),
INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec),
INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
+ INIT_STATIC_SPEC ("self_spec", &self_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
{ "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
{ "compare-debug-self-opt", compare_debug_self_opt_spec_function },
{ "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
+ { "pass-through-libs", pass_through_libs_spec_func },
#ifdef EXTRA_SPEC_FUNCTIONS
EXTRA_SPEC_FUNCTIONS
#endif
"-lgcc_eh"
#ifdef USE_LIBUNWIND_EXCEPTIONS
# ifdef HAVE_LD_STATIC_DYNAMIC
- " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
+ " %{!static:" LD_STATIC_OPTION "} -lunwind"
+ " %{!static:" LD_DYNAMIC_OPTION "}"
# else
" -lunwind"
# endif
}
#endif
-#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC
+#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC || \
+ defined LINKER_HASH_STYLE
# ifdef LINK_BUILDID_SPEC
/* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before. */
obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof(LINK_BUILDID_SPEC) - 1);
/* Prepend LINK_EH_SPEC to whatever link_spec we had before. */
obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
# endif
+# ifdef LINKER_HASH_STYLE
+ /* Prepend --hash-style=LINKER_HASH_STYLE to whatever link_spec we had
+ before. */
+ {
+ static const char hash_style[] = "--hash-style=";
+ obstack_grow (&obstack, hash_style, sizeof(hash_style) - 1);
+ obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof(LINKER_HASH_STYLE) - 1);
+ obstack_1grow (&obstack, ' ');
+ }
+# endif
obstack_grow0 (&obstack, link_spec, strlen (link_spec));
link_spec = XOBFINISH (&obstack, const char *);
#endif
\f
/* Accumulate a command (program name and args), and run it. */
-/* Vector of pointers to arguments in the current line of specifications. */
-
-static const char **argbuf;
-
-/* Number of elements allocated in argbuf. */
-
-static int argbuf_length;
+typedef const char *const_char_p; /* For DEF_VEC_P. */
+DEF_VEC_P(const_char_p);
+DEF_VEC_ALLOC_P(const_char_p,heap);
-/* Number of elements in argbuf currently in use (containing args). */
+/* Vector of pointers to arguments in the current line of specifications. */
-static int argbuf_index;
+static VEC(const_char_p,heap) *argbuf;
-/* Position in the argbuf array containing the name of the output file
+/* Position in the argbuf vector containing the name of the output file
(the value associated with the "-o" flag). */
static int have_o_argbuf_index = 0;
static void
alloc_args (void)
{
- argbuf_length = 10;
- argbuf = XNEWVEC (const char *, argbuf_length);
+ argbuf = VEC_alloc (const_char_p, heap, 10);
}
/* Clear out the vector of arguments (after a command is executed). */
static void
clear_args (void)
{
- argbuf_index = 0;
+ VEC_truncate (const_char_p, argbuf, 0);
}
/* Add one argument to the vector at the end.
static void
store_arg (const char *arg, int delete_always, int delete_failure)
{
- if (argbuf_index + 1 == argbuf_length)
- argbuf = XRESIZEVEC (const char *, argbuf, (argbuf_length *= 2));
-
- argbuf[argbuf_index++] = arg;
- argbuf[argbuf_index] = 0;
+ VEC_safe_push (const_char_p, heap, argbuf, arg);
if (strcmp (arg, "-o") == 0)
- have_o_argbuf_index = argbuf_index;
+ have_o_argbuf_index = VEC_length (const_char_p, argbuf);
if (delete_always || delete_failure)
{
const char *p;
{
struct temp_file *temp;
for (temp = always_delete_queue; temp; temp = temp->next)
- if (! strcmp (name, temp->name))
+ if (! filename_cmp (name, temp->name))
goto already1;
temp = XNEW (struct temp_file);
{
struct temp_file *temp;
for (temp = failure_delete_queue; temp; temp = temp->next)
- if (! strcmp (name, temp->name))
+ if (! filename_cmp (name, temp->name))
goto already2;
temp = XNEW (struct temp_file);
struct prefix_list *pl;
const char *multi_dir = NULL;
const char *multi_os_dir = NULL;
+ const char *multiarch_suffix = NULL;
const char *multi_suffix;
const char *just_multi_suffix;
char *path = NULL;
}
if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+ if (multiarch_dir)
+ multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
while (1)
{
size_t multi_dir_len = 0;
size_t multi_os_dir_len = 0;
+ size_t multiarch_len = 0;
size_t suffix_len;
size_t just_suffix_len;
size_t len;
multi_dir_len = strlen (multi_dir);
if (multi_os_dir)
multi_os_dir_len = strlen (multi_os_dir);
+ if (multiarch_suffix)
+ multiarch_len = strlen (multiarch_suffix);
suffix_len = strlen (multi_suffix);
just_suffix_len = strlen (just_multi_suffix);
if (path == NULL)
{
len = paths->max_len + extra_space + 1;
- if (suffix_len > multi_os_dir_len)
- len += suffix_len;
- else
- len += multi_os_dir_len;
+ len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
path = XNEWVEC (char, len);
}
break;
}
+ /* Now try the multiarch path. */
+ if (!skip_multi_dir
+ && !pl->require_machine_suffix && multiarch_dir)
+ {
+ memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+
/* Now try the base path. */
if (!pl->require_machine_suffix
&& !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
if (target_system_root)
{
+ char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
+ size_t sysroot_len = strlen (target_system_root);
+
+ if (sysroot_len > 0
+ && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
+ sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+
if (target_sysroot_suffix)
prefix = concat (target_sysroot_suffix, prefix, NULL);
- prefix = concat (target_system_root, prefix, NULL);
+ prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
+ free (sysroot_no_trailing_dir_separator);
/* We have to override this because GCC's notion of sysroot
moves along with GCC. */
const char *prog; /* program name. */
const char **argv; /* vector of args. */
};
+ const char *arg;
struct command *commands; /* each command buffer with above info. */
if (wrapper_string)
{
- string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false);
- argbuf[0] = (string) ? string : argbuf[0];
+ string = find_a_file (&exec_prefixes,
+ VEC_index (const_char_p, argbuf, 0), X_OK, false);
+ if (string)
+ VEC_replace (const_char_p, argbuf, 0, string);
insert_wrapper (wrapper_string);
}
/* Count # of piped commands. */
- for (n_commands = 1, i = 0; i < argbuf_index; i++)
- if (strcmp (argbuf[i], "|") == 0)
+ for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++)
+ if (strcmp (arg, "|") == 0)
n_commands++;
/* Get storage for each command. */
and record info about each one.
Also search for the programs that are to be run. */
- commands[0].prog = argbuf[0]; /* first command. */
- commands[0].argv = &argbuf[0];
+ VEC_safe_push (const_char_p, heap, argbuf, 0);
+
+ commands[0].prog = VEC_index (const_char_p, argbuf, 0); /* first command. */
+ commands[0].argv = VEC_address (const_char_p, argbuf);
if (!wrapper_string)
{
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 (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++)
+ if (arg && strcmp (arg, "|") == 0)
{ /* each command. */
#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
fatal_error ("-pipe not supported");
#endif
- argbuf[i] = 0; /* termination of command args. */
- commands[n_commands].prog = argbuf[i + 1];
- commands[n_commands].argv = &argbuf[i + 1];
+ VEC_replace (const_char_p, argbuf, i, 0); /* Termination of
+ command args. */
+ commands[n_commands].prog = VEC_index (const_char_p, argbuf, i + 1);
+ commands[n_commands].argv
+ = &(VEC_address (const_char_p, argbuf))[i + 1];
string = find_a_file (&exec_prefixes, commands[n_commands].prog,
X_OK, false);
if (string)
n_commands++;
}
- argbuf[argbuf_index] = 0;
-
/* If -v, print what we are about to do, and maybe query. */
if (verbose_flag)
}
fputc ('"', stderr);
}
+ /* If it's empty, print "". */
+ else if (!**j)
+ fprintf (stderr, " \"\"");
else
fprintf (stderr, " %s", *j);
}
}
else
for (j = commands[i].argv; *j; j++)
- fprintf (stderr, " %s", *j);
+ /* If it's empty, print "". */
+ if (!**j)
+ fprintf (stderr, " \"\"");
+ else
+ fprintf (stderr, " %s", *j);
/* Print a pipe symbol after all but the last command. */
if (i + 1 != n_commands)
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_LIVE 0x1
-#define SWITCH_FALSE 0x2
-#define SWITCH_IGNORE 0x4
-#define SWITCH_IGNORE_PERMANENTLY 0x8
+#define SWITCH_LIVE (1 << 0)
+#define SWITCH_FALSE (1 << 1)
+#define SWITCH_IGNORE (1 << 2)
+#define SWITCH_IGNORE_PERMANENTLY (1 << 3)
+#define SWITCH_KEEP_FOR_GCC (1 << 4)
struct switchstr
{
static int n_switches_debug_check[2];
+static int n_switches_alloc_debug_check[2];
+
static char *debug_check_temp_file[2];
/* Language is one of three things:
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|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
+ fputs (_(" --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]\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 (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout);
fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout);
fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout);
+ fputs (_("\
+ -print-multiarch Display the target's normalized GNU triplet, used as\n\
+ a component in the library path\n"), stdout);
fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout);
fputs (_("\
-print-multi-lib Display the mapping between command line options and\n\
fputs (_(" -S Compile only; do not assemble or link\n"), stdout);
fputs (_(" -c Compile and assemble, but do not link\n"), stdout);
fputs (_(" -o <file> Place the output into <file>\n"), stdout);
+ fputs (_(" -pie Create a position independent executable\n"), stdout);
+ fputs (_(" -shared Create a shared library\n"), stdout);
fputs (_("\
-x <language> Specify the language of the following input files\n\
Permissible languages include: c c++ assembler none\n\
static void
add_preprocessor_option (const char *option, int len)
{
- n_preprocessor_options++;
-
- if (! preprocessor_options)
- preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
- else
- preprocessor_options = XRESIZEVEC (char *, preprocessor_options,
- n_preprocessor_options);
-
- preprocessor_options [n_preprocessor_options - 1] =
- save_string (option, len);
+ VEC_safe_push (char_p, heap, preprocessor_options,
+ save_string (option, len));
}
static void
add_assembler_option (const char *option, int len)
{
- n_assembler_options++;
-
- if (! assembler_options)
- assembler_options = XNEWVEC (char *, n_assembler_options);
- else
- assembler_options = XRESIZEVEC (char *, assembler_options,
- n_assembler_options);
-
- assembler_options [n_assembler_options - 1] = save_string (option, len);
+ VEC_safe_push (char_p, heap, assembler_options, save_string (option, len));
}
static void
add_linker_option (const char *option, int len)
{
- n_linker_options++;
-
- if (! linker_options)
- linker_options = XNEWVEC (char *, n_linker_options);
- else
- linker_options = XRESIZEVEC (char *, linker_options, n_linker_options);
-
- linker_options [n_linker_options - 1] = save_string (option, len);
+ VEC_safe_push (char_p, heap, linker_options, save_string (option, len));
}
\f
/* Allocate space for an input file in infiles. */
}
/* Handle an option DECODED that is unknown to the option-processing
- machinery, but may be known to specs. */
+ machinery. */
static bool
driver_unknown_option_callback (const struct cl_decoded_option *decoded)
{
- save_switch (decoded->canonical_option[0],
- decoded->canonical_option_num_elements - 1,
- &decoded->canonical_option[1], false);
-
- return false;
+ const char *opt = decoded->arg;
+ if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
+ && !(decoded->errors & CL_ERR_NEGATIVE))
+ {
+ /* Leave unknown -Wno-* options for the compiler proper, to be
+ diagnosed only if there are warnings. */
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], false);
+ return false;
+ }
+ else
+ return true;
}
/* Handle an option DECODED that is not marked as CL_DRIVER.
options. */
const struct cl_option *option = &cl_options[decoded->opt_index];
- if (option->flags & CL_REJECT_DRIVER)
+ if (option->cl_reject_driver)
error ("unrecognized command line option %qs",
decoded->orig_option_with_args_text);
else
- driver_unknown_option_callback (decoded);
-}
-
-/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
- has been successfully handled with a handler for mask MASK. */
-
-static void
-driver_post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
- unsigned int mask ATTRIBUTE_UNUSED)
-{
- /* Nothing to do here. */
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], false);
}
static const char *spec_lang = 0;
handle_option. */
static bool
-driver_handle_option (const struct cl_decoded_option *decoded,
+driver_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
- const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
+ location_t loc,
+ const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
+ diagnostic_context *dc)
{
size_t opt_index = decoded->opt_index;
const char *arg = decoded->arg;
bool validated = false;
bool do_save = true;
+ gcc_assert (opts == &global_options);
+ gcc_assert (opts_set == &global_options_set);
gcc_assert (kind == DK_UNSPECIFIED);
+ gcc_assert (loc == UNKNOWN_LOCATION);
+ gcc_assert (dc == global_dc);
switch (opt_index)
{
case OPT_print_multi_directory:
case OPT_print_sysroot:
case OPT_print_multi_os_directory:
+ case OPT_print_multiarch:
case OPT_print_sysroot_headers_suffix:
case OPT_time:
case OPT_wrapper:
compare_debug_with_arg:
gcc_assert (decoded->canonical_option_num_elements == 1);
gcc_assert (arg != NULL);
- if (arg)
+ if (*arg)
compare_debug = 1;
else
compare_debug = -1;
save_switch (concat ("-L", arg, NULL), 0, NULL, validated);
return true;
+ case OPT_F:
+ /* Likewise -F. */
+ save_switch (concat ("-F", arg, NULL), 0, NULL, validated);
+ return true;
+
case OPT_save_temps:
save_temps_flag = SAVE_TEMPS_CWD;
validated = true;
is intended for use in shell scripts to capture the
driver-generated command line. */
verbose_only_flag++;
- verbose_flag++;
+ verbose_flag = 1;
do_save = false;
break;
validated = true;
break;
- case OPT_v: /* Print our subcommands and print versions. */
- verbose_flag++;
- break;
-
case OPT_x:
spec_lang = arg;
if (!strcmp (spec_lang, "none"))
return true;
}
+/* Put the driver's standard set of option handlers in *HANDLERS. */
+
+static void
+set_option_handlers (struct cl_option_handlers *handlers)
+{
+ handlers->unknown_option_callback = driver_unknown_option_callback;
+ handlers->wrong_lang_callback = driver_wrong_lang_callback;
+ handlers->num_handlers = 3;
+ handlers->handlers[0].handler = driver_handle_option;
+ handlers->handlers[0].mask = CL_DRIVER;
+ handlers->handlers[1].handler = common_handle_option;
+ handlers->handlers[1].mask = CL_COMMON;
+ handlers->handlers[2].handler = target_handle_option;
+ handlers->handlers[2].mask = CL_TARGET;
+}
+
/* Create the vector `switches' and its contents.
Store its length in `n_switches'. */
static void
-process_command (int argc, const char **argv)
+process_command (unsigned int decoded_options_count,
+ struct cl_decoded_option *decoded_options)
{
const char *temp;
char *temp1;
char *(*get_relative_prefix) (const char *, const char *,
const char *) = NULL;
struct cl_option_handlers handlers;
- struct cl_decoded_option *decoded_options;
- unsigned int decoded_options_count, j;
+ unsigned int j;
- GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
+ gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
n_switches = 0;
n_infiles = 0;
}
}
- decode_cmdline_options_to_array (argc, argv, CL_DRIVER,
- &decoded_options, &decoded_options_count);
-
/* Handle any -no-canonical-prefixes flag early, to assign the function
that builds relative prefixes. This function creates default search
paths that are needed later in normal option handling. */
get_relative_prefix = make_relative_prefix;
/* Set up the default search paths. If there is no GCC_EXEC_PREFIX,
- see if we can create it from the pathname specified in argv[0]. */
+ see if we can create it from the pathname specified in
+ decoded_options[0].arg. */
gcc_libexec_prefix = standard_libexec_prefix;
#ifndef VMS
/* FIXME: make_relative_prefix doesn't yet work for VMS. */
if (!gcc_exec_prefix)
{
- gcc_exec_prefix = get_relative_prefix (argv[0],
+ gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
standard_bindir_prefix,
standard_exec_prefix);
- gcc_libexec_prefix = get_relative_prefix (argv[0],
+ gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg,
standard_bindir_prefix,
standard_libexec_prefix);
if (gcc_exec_prefix)
#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]. */
+ or an automatically created GCC_EXEC_PREFIX from
+ decoded_options[0].arg. */
/* Do language-specific adjustment/addition of flags. */
lang_specific_driver (&decoded_options, &decoded_options_count,
{
temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
if (IS_DIR_SEPARATOR (*temp)
- && strncmp (temp + 1, "lib", 3) == 0
+ && filename_ncmp (temp + 1, "lib", 3) == 0
&& IS_DIR_SEPARATOR (temp[4])
- && strncmp (temp + 5, "gcc", 3) == 0)
+ && filename_ncmp (temp + 5, "gcc", 3) == 0)
len -= sizeof ("/lib/gcc/") - 1;
}
/* COMPILER_PATH and LIBRARY_PATH have values
that are lists of directory names with colons. */
- GET_ENVIRONMENT (temp, "COMPILER_PATH");
+ temp = getenv ("COMPILER_PATH");
if (temp)
{
const char *startp, *endp;
}
}
- GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
+ temp = getenv (LIBRARY_PATH_ENV);
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
}
/* Use LPATH like LIBRARY_PATH (for the CMU build program). */
- GET_ENVIRONMENT (temp, "LPATH");
+ temp = getenv ("LPATH");
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
last_language_n_infiles = -1;
- handlers.unknown_option_callback = driver_unknown_option_callback;
- handlers.wrong_lang_callback = driver_wrong_lang_callback;
- handlers.post_handling_callback = driver_post_handling_callback;
- handlers.num_handlers = 1;
- handlers.handlers[0].handler = driver_handle_option;
- handlers.handlers[0].mask = CL_DRIVER;
+ set_option_handlers (&handlers);
for (j = 1; j < decoded_options_count; j++)
{
continue;
}
- read_cmdline_option (decoded_options + j, CL_DRIVER, &handlers);
+ read_cmdline_option (&global_options, &global_options_set,
+ decoded_options + j, UNKNOWN_LOCATION,
+ CL_DRIVER, &handlers, global_dc);
}
/* If -save-temps=obj and -o name, create the prefix to use for %b.
``make_relative_prefix'' is not compiled for VMS, so don't call it. */
if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
{
- char *tmp_prefix = get_relative_prefix (argv[0],
+ char *tmp_prefix = get_relative_prefix (decoded_options[0].arg,
standard_bindir_prefix,
target_system_root);
if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
first_time = FALSE;
/* Ignore elided switches. */
- if ((switches[i].live_cond & SWITCH_IGNORE) != 0)
+ if ((switches[i].live_cond
+ & (SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC))
+ == SWITCH_IGNORE)
continue;
obstack_grow (&collect_obstack, "'-", 2);
int i;
char *buf = xstrdup (wrapper);
char *p = buf;
+ unsigned int old_length = VEC_length (const_char_p, argbuf);
do
{
}
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];
+ VEC_safe_grow (const_char_p, heap, argbuf, old_length + n);
+ memmove (VEC_address (const_char_p, argbuf) + n,
+ VEC_address (const_char_p, argbuf),
+ old_length * sizeof (const_char_p));
i = 0;
p = buf;
*p = 0;
p++;
}
- argbuf[i++] = p;
+ VEC_replace (const_char_p, argbuf, i, p);
+ i++;
}
while ((p = strchr (p, ',')) != NULL);
gcc_assert (i == n);
- argbuf_index += n;
}
/* Process the spec SPEC and run the commands specified therein.
If -pipe, this forces out the last command if it ended in `|'. */
if (value == 0)
{
- if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
- argbuf_index--;
+ if (VEC_length (const_char_p, argbuf) > 0
+ && !strcmp (VEC_last (const_char_p, argbuf), "|"))
+ VEC_pop (const_char_p, argbuf);
set_collect_gcc_options ();
- if (argbuf_index > 0)
+ if (VEC_length (const_char_p, argbuf) > 0)
value = execute ();
}
if ((switches[i].live_cond & SWITCH_IGNORE))
switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
- if (argbuf_index > 0)
+ if (VEC_length (const_char_p, argbuf) > 0)
{
- switches = XRESIZEVEC (struct switchstr, switches,
- n_switches + argbuf_index + 1);
-
- for (i = 0; i < argbuf_index; i++)
+ const char **argbuf_copy;
+ struct cl_decoded_option *decoded_options;
+ struct cl_option_handlers handlers;
+ unsigned int decoded_options_count;
+ unsigned int j;
+
+ /* Create a copy of argbuf with a dummy argv[0] entry for
+ decode_cmdline_options_to_array. */
+ argbuf_copy = XNEWVEC (const char *,
+ VEC_length (const_char_p, argbuf) + 1);
+ argbuf_copy[0] = "";
+ memcpy (argbuf_copy + 1, VEC_address (const_char_p, argbuf),
+ VEC_length (const_char_p, argbuf) * sizeof (const char *));
+
+ decode_cmdline_options_to_array (VEC_length (const_char_p, argbuf) + 1,
+ argbuf_copy,
+ CL_DRIVER, &decoded_options,
+ &decoded_options_count);
+
+ set_option_handlers (&handlers);
+
+ for (j = 1; j < decoded_options_count; j++)
{
- struct switchstr *sw;
- const char *p = argbuf[i];
- int c = *p;
-
- /* Each switch should start with '-'. */
- if (c != '-')
- fatal_error ("switch %qs does not start with %<-%>", argbuf[i]);
-
- p++;
- c = *p;
-
- sw = &switches[n_switches++];
- sw->part1 = p;
- sw->live_cond = 0;
- sw->validated = 0;
- sw->ordering = 0;
-
- /* Deal with option arguments in separate argv elements. */
- if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
- || WORD_SWITCH_TAKES_ARG (p))
+ switch (decoded_options[j].opt_index)
{
- int j = 0;
- int n_args = WORD_SWITCH_TAKES_ARG (p);
+ case OPT_SPECIAL_input_file:
+ /* Specs should only generate options, not input
+ files. */
+ if (strcmp (decoded_options[j].arg, "-") != 0)
+ fatal_error ("switch %qs does not start with %<-%>",
+ decoded_options[j].arg);
+ else
+ fatal_error ("spec-generated switch is just %<-%>");
+ break;
- if (n_args == 0)
- {
- /* Count only the option arguments in separate argv elements. */
- n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
- }
- if (i + n_args >= argbuf_index)
- fatal_error ("argument to %<-%s%> is missing", p);
- sw->args
- = XNEWVEC (const char *, n_args + 1);
- while (j < n_args)
- sw->args[j++] = argbuf[++i];
- /* Null-terminate the vector. */
- sw->args[j] = 0;
- }
- else if (c == 'o')
- {
- /* On some systems, ld cannot handle "-o" without
- a space. So split the option from its argument. */
- char *part1 = XNEWVEC (char, 2);
- part1[0] = c;
- part1[1] = '\0';
-
- sw->part1 = part1;
- sw->args = XNEWVEC (const char *, 2);
- sw->args[0] = xstrdup (p+1);
- sw->args[1] = 0;
+ case OPT_fcompare_debug_second:
+ case OPT_fcompare_debug:
+ case OPT_fcompare_debug_:
+ case OPT_o:
+ /* Avoid duplicate processing of some options from
+ compare-debug specs; just save them here. */
+ save_switch (decoded_options[j].canonical_option[0],
+ (decoded_options[j].canonical_option_num_elements
+ - 1),
+ &decoded_options[j].canonical_option[1], false);
+ break;
+
+ default:
+ read_cmdline_option (&global_options, &global_options_set,
+ decoded_options + j, UNKNOWN_LOCATION,
+ CL_DRIVER, &handlers, global_dc);
+ break;
}
- else
- sw->args = 0;
}
+ alloc_switch ();
switches[n_switches].part1 = 0;
}
}
return false;
}
+/* Process each member of VEC as a spec. */
+
+static void
+do_specs_vec (VEC(char_p,heap) *vec)
+{
+ unsigned ix;
+ char *opt;
+
+ FOR_EACH_VEC_ELT (char_p, vec, ix, opt)
+ {
+ do_spec_1 (opt, 1, NULL);
+ /* Make each accumulated option a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ }
+}
+
/* Process the sub-spec SPEC as a portion of a larger spec.
This is like processing a whole spec except that we do
not initialize at the beginning and we do not supply a
int i;
int value;
+ /* If it's an empty string argument to a switch, keep it as is. */
+ if (inswitch && !*p)
+ arg_going = 1;
+
while ((c = *p++))
/* If substituting a switch, treat all chars like letters.
Otherwise, NL, SPC, TAB and % are special. */
case '\n':
end_going_arg ();
- if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
+ if (VEC_length (const_char_p, argbuf) > 0
+ && !strcmp (VEC_last (const_char_p, argbuf), "|"))
{
/* A `|' before the newline means use a pipe here,
but only if -pipe was specified.
break;
}
else
- argbuf_index--;
+ VEC_pop (const_char_p, argbuf);
}
set_collect_gcc_options ();
- if (argbuf_index > 0)
+ if (VEC_length (const_char_p, argbuf) > 0)
{
value = execute ();
if (value)
tmp[basename_length + suffix_length] = '\0';
temp_filename = tmp;
- if (strcmp (temp_filename, gcc_input_filename) != 0)
+ if (filename_cmp (temp_filename, gcc_input_filename) != 0)
{
#ifndef HOST_LACKS_INODE_NUMBERS
struct stat st_temp;
/* Just compare canonical pathnames. */
char* input_realname = lrealpath (gcc_input_filename);
char* temp_realname = lrealpath (temp_filename);
- bool files_differ = strcmp (input_realname, temp_realname);
+ bool files_differ = filename_cmp (input_realname, temp_realname);
free (input_realname);
free (temp_realname);
if (files_differ)
t->filename_length = temp_filename_length;
}
- if (saved_suffix)
- free (saved_suffix);
+ free (saved_suffix);
obstack_grow (&obstack, t->filename, t->filename_length);
delete_this_arg = 1;
do_spec_1 (" ", 0, NULL);
}
+ if (multiarch_dir)
+ {
+ do_spec_1 ("-imultiarch", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (multiarch_dir, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
+
if (gcc_exec_prefix)
{
do_spec_1 ("-iprefix", 1, NULL);
case 'W':
{
- int cur_index = argbuf_index;
+ unsigned int cur_index = VEC_length (const_char_p, argbuf);
/* Handle the {...} following the %W. */
if (*p != '{')
fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p);
end_going_arg ();
/* If any args were output, mark the last one for deletion
on failure. */
- if (argbuf_index != cur_index)
- record_temp_file (argbuf[argbuf_index - 1], 0, 1);
+ if (VEC_length (const_char_p, argbuf) != cur_index)
+ record_temp_file (VEC_last (const_char_p, argbuf), 0, 1);
break;
}
{
const char *p1 = p;
char *string;
+ char *opt;
+ unsigned ix;
/* Skip past the option value and make a copy. */
if (*p != '{')
string = save_string (p1 + 1, p - p1 - 2);
/* See if we already recorded this option. */
- for (i = 0; i < n_linker_options; i++)
- if (! strcmp (string, linker_options[i]))
+ FOR_EACH_VEC_ELT (char_p, linker_options, ix, opt)
+ if (! strcmp (string, opt))
{
free (string);
return 0;
/* Dump out the options accumulated previously using %x. */
case 'X':
- for (i = 0; i < n_linker_options; i++)
- {
- do_spec_1 (linker_options[i], 1, NULL);
- /* Make each accumulated option a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
+ do_specs_vec (linker_options);
break;
/* Dump out the options accumulated previously using -Wa,. */
case 'Y':
- for (i = 0; i < n_assembler_options; i++)
- {
- do_spec_1 (assembler_options[i], 1, NULL);
- /* Make each accumulated option a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
+ do_specs_vec (assembler_options);
break;
/* Dump out the options accumulated previously using -Wp,. */
case 'Z':
- for (i = 0; i < n_preprocessor_options; i++)
- {
- do_spec_1 (preprocessor_options[i], 1, NULL);
- /* Make each accumulated option a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
+ do_specs_vec (preprocessor_options);
break;
/* Here are digits and numbers that just process
/* Henceforth ignore the option(s) matching the pattern
after the %<. */
case '<':
+ case '>':
{
unsigned len = 0;
int have_wildcard = 0;
int i;
+ int switch_option;
+
+ if (c == '>')
+ switch_option = SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC;
+ else
+ switch_option = SWITCH_IGNORE;
while (p[len] && p[len] != ' ' && p[len] != '\t')
len++;
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_option;
switches[i].validated = 1;
}
case '*':
if (soft_matched_part)
{
- do_spec_1 (soft_matched_part, 1, NULL);
+ if (soft_matched_part[0])
+ do_spec_1 (soft_matched_part, 1, NULL);
do_spec_1 (" ", 0, NULL);
}
else
/* 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.
- %[...] modifies -D options the way %P does;
- %(...) uses the spec unmodified. */
- case '[':
- warning (0, "use of obsolete %%[ operator in specs");
+ to add and use their own specs. */
case '(':
{
const char *name = p;
/* The string after the S/P is the name of a spec that is to be
processed. */
- while (*p && *p != ')' && *p != ']')
+ while (*p && *p != ')')
p++;
/* See if it's in the list. */
{
name = *(sl->ptr_spec);
#ifdef DEBUG_SPECS
- fnotice (stderr, "Processing spec %c%s%c, which is '%s'\n",
- c, sl->name, (c == '(') ? ')' : ']', name);
+ fnotice (stderr, "Processing spec (%s), which is '%s'\n",
+ sl->name, name);
#endif
break;
}
if (sl)
{
- if (c == '(')
- {
- value = do_spec_1 (name, 0, NULL);
- if (value != 0)
- return value;
- }
- else
- {
- char *x = (char *) alloca (strlen (name) * 2 + 1);
- char *buf = x;
- const 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);
- if (value != 0)
- return value;
- }
+ value = do_spec_1 (name, 0, NULL);
+ if (value != 0)
+ return value;
}
- /* Discard the closing paren or bracket. */
+ /* Discard the closing paren. */
if (*p)
p++;
}
const char *funcval;
/* Saved spec processing context. */
- int save_argbuf_index;
- int save_argbuf_length;
- const char **save_argbuf;
+ VEC(const_char_p,heap) *save_argbuf;
int save_arg_going;
int save_delete_this_arg;
fatal_error ("unknown spec function %qs", func);
/* Push the spec processing context. */
- save_argbuf_index = argbuf_index;
- save_argbuf_length = argbuf_length;
save_argbuf = argbuf;
save_arg_going = arg_going;
/* argbuf_index is an index for the next argument to be inserted, and
so contains the count of the args already inserted. */
- funcval = (*sf->func) (argbuf_index, argbuf);
+ funcval = (*sf->func) (VEC_length (const_char_p, argbuf),
+ VEC_address (const_char_p, argbuf));
/* Pop the spec processing context. */
- argbuf_index = save_argbuf_index;
- argbuf_length = save_argbuf_length;
- free (argbuf);
+ VEC_free (const_char_p, heap, argbuf);
argbuf = save_argbuf;
arg_going = save_arg_going;
&& check_live_switch (i, plen))
return true;
+ /* Check if a switch with separated form matching the atom.
+ We check -D and -U switches. */
+ else if (switches[i].args != 0)
+ {
+ if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
+ && *switches[i].part1 == atom[0])
+ {
+ if (!strncmp (switches[i].args[0], &atom[1], len - 1)
+ && (starred || (switches[i].part1[1] == '\0'
+ && switches[i].args[0][len - 1] == '\0'))
+ && check_live_switch (i, (starred ? 1 : -1)))
+ return true;
+ }
+ }
+
return false;
}
if (linker
&& IS_DIR_SEPARATOR (path[0])
&& ((cp - path == 6
- && strncmp (path + 1, "lib", 3) == 0)
+ && filename_ncmp (path + 1, "lib", 3) == 0)
|| (cp - path == 10
- && strncmp (path + 1, "usr", 3) == 0
+ && filename_ncmp (path + 1, "usr", 3) == 0
&& IS_DIR_SEPARATOR (path[4])
- && strncmp (path + 5, "lib", 3) == 0)))
+ && filename_ncmp (path + 5, "lib", 3) == 0)))
return 0;
return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
int num_linker_inputs = 0;
char *explicit_link_files;
char *specs_file;
+ char *lto_wrapper_file;
const char *p;
struct user_specs *uptr;
char **old_argv = argv;
+ struct cl_decoded_option *decoded_options;
+ unsigned int decoded_options_count;
/* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes
on ?: in file-scope variable initializations. */
if (argv != old_argv)
at_file_supplied = true;
- prune_options (&argc, &argv);
+ /* Register the language-independent parameters. */
+ global_init_params ();
+ finish_params ();
+
+ init_options_struct (&global_options, &global_options_set);
+
+ decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **,
+ argv),
+ CL_DRIVER,
+ &decoded_options, &decoded_options_count);
#ifdef GCC_DRIVER_HOST_INITIALIZATION
/* Perform host dependent initialization when needed. */
signal (SIGCHLD, SIG_DFL);
#endif
+ /* Parsing and gimplification sometimes need quite large stack.
+ Increase stack size limits if possible. */
+ stack_limit_increase (64 * 1024 * 1024);
+
/* Allocate the argument vector. */
alloc_args ();
Make a table of specified input files (infiles, n_infiles).
Decode switches that are handled locally. */
- process_command (argc, CONST_CAST2 (const char **, char **, argv));
+ process_command (decoded_options_count, decoded_options);
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
do_self_spec (driver_self_specs[i]);
- if (compare_debug)
- {
- enum save_temps save;
-
- if (!compare_debug_second)
- {
- n_switches_debug_check[1] = n_switches;
- switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
- n_switches + 1);
-
- do_self_spec ("%:compare-debug-self-opt()");
- n_switches_debug_check[0] = n_switches;
- switches_debug_check[0] = switches;
-
- n_switches = n_switches_debug_check[1];
- switches = switches_debug_check[1];
- }
-
- /* Avoid crash when computing %j in this early. */
- save = save_temps_flag;
- save_temps_flag = SAVE_TEMPS_NONE;
-
- compare_debug = -compare_debug;
- do_self_spec ("%:compare-debug-self-opt()");
-
- save_temps_flag = save;
-
- if (!compare_debug_second)
- {
- n_switches_debug_check[1] = n_switches;
- switches_debug_check[1] = switches;
- compare_debug = -compare_debug;
- n_switches = n_switches_debug_check[0];
- switches = switches_debug_check[0];
- }
- }
-
/* If not cross-compiling, look for executables in the standard
places. */
if (*cross_compile == '0')
if (*sysroot_suffix_spec != 0
&& do_spec_2 (sysroot_suffix_spec) == 0)
{
- if (argbuf_index > 1)
+ if (VEC_length (const_char_p, argbuf) > 1)
error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
- else if (argbuf_index == 1)
- target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]);
+ else if (VEC_length (const_char_p, argbuf) == 1)
+ target_sysroot_suffix = xstrdup (VEC_last (const_char_p, argbuf));
}
#ifdef HAVE_LD_SYSROOT
if (*sysroot_hdrs_suffix_spec != 0
&& do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
{
- if (argbuf_index > 1)
+ if (VEC_length (const_char_p, argbuf) > 1)
error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
- else if (argbuf_index == 1)
- target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]);
+ else if (VEC_length (const_char_p, argbuf) == 1)
+ target_sysroot_hdrs_suffix = xstrdup (VEC_last (const_char_p, argbuf));
}
/* Look for startfiles in the standard places. */
&& do_spec_2 (startfile_prefix_spec) == 0
&& do_spec_1 (" ", 0, NULL) == 0)
{
+ const char *arg;
int ndx;
- for (ndx = 0; ndx < argbuf_index; ndx++)
- add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
+ FOR_EACH_VEC_ELT (const_char_p, argbuf, ndx, arg)
+ add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS",
PREFIX_PRIORITY_LAST, 0, 1);
}
/* We should eventually get rid of all these and stick to
read_specs (filename ? filename : uptr->filename, FALSE);
}
+ /* Process any user self specs. */
+ {
+ struct spec_list *sl;
+ for (sl = specs; sl; sl = sl->next)
+ if (sl->name_len == sizeof "self_spec" - 1
+ && !strcmp (sl->name, "self_spec"))
+ do_self_spec (*sl->ptr_spec);
+ }
+
+ if (compare_debug)
+ {
+ enum save_temps save;
+
+ if (!compare_debug_second)
+ {
+ n_switches_debug_check[1] = n_switches;
+ n_switches_alloc_debug_check[1] = n_switches_alloc;
+ switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
+ n_switches_alloc);
+
+ do_self_spec ("%:compare-debug-self-opt()");
+ n_switches_debug_check[0] = n_switches;
+ n_switches_alloc_debug_check[0] = n_switches_alloc;
+ switches_debug_check[0] = switches;
+
+ n_switches = n_switches_debug_check[1];
+ n_switches_alloc = n_switches_alloc_debug_check[1];
+ switches = switches_debug_check[1];
+ }
+
+ /* Avoid crash when computing %j in this early. */
+ save = save_temps_flag;
+ save_temps_flag = SAVE_TEMPS_NONE;
+
+ compare_debug = -compare_debug;
+ do_self_spec ("%:compare-debug-self-opt()");
+
+ save_temps_flag = save;
+
+ if (!compare_debug_second)
+ {
+ n_switches_debug_check[1] = n_switches;
+ n_switches_alloc_debug_check[1] = n_switches_alloc;
+ switches_debug_check[1] = switches;
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[0];
+ n_switches_alloc = n_switches_debug_check[0];
+ switches = switches_debug_check[0];
+ }
+ }
+
+
/* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
if (gcc_exec_prefix)
gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
/* Set up to remember the pathname of the lto wrapper. */
- lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
- if (lto_wrapper_spec)
+ if (have_c)
+ lto_wrapper_file = NULL;
+ else
+ lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
+ X_OK, false);
+ if (lto_wrapper_file)
{
+ lto_wrapper_file = convert_white_space (lto_wrapper_file);
+ lto_wrapper_spec = lto_wrapper_file;
obstack_init (&collect_obstack);
obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
sizeof ("COLLECT_LTO_WRAPPER=") - 1);
return (0);
}
+ if (print_multiarch)
+ {
+ if (multiarch_dir == NULL)
+ printf ("\n");
+ else
+ printf ("%s\n", multiarch_dir);
+ return (0);
+ }
+
if (print_sysroot)
{
if (target_system_root)
{
printf (_("%s %s%s\n"), progname, pkgversion_string,
version_string);
- printf ("Copyright %s 2010 Free Software Foundation, Inc.\n",
+ printf ("Copyright %s 2012 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"),
if (n_infiles == added_libraries)
fatal_error ("no input files");
+ if (seen_error ())
+ goto out;
+
/* Make a place to record the compiler output file names
that correspond to the input files. */
{
if (compare_debug)
{
- if (debug_check_temp_file[0])
- free (debug_check_temp_file[0]);
+ free (debug_check_temp_file[0]);
debug_check_temp_file[0] = NULL;
- if (debug_check_temp_file[1])
- free (debug_check_temp_file[1]);
+ free (debug_check_temp_file[1]);
debug_check_temp_file[1] = NULL;
}
compare_debug = -compare_debug;
n_switches = n_switches_debug_check[1];
+ n_switches_alloc = n_switches_alloc_debug_check[1];
switches = switches_debug_check[1];
value = do_spec (input_file_compiler->spec);
compare_debug = -compare_debug;
n_switches = n_switches_debug_check[0];
+ n_switches_alloc = n_switches_alloc_debug_check[0];
switches = switches_debug_check[0];
if (value < 0)
}
gcc_assert (debug_check_temp_file[1]
- && strcmp (debug_check_temp_file[0],
- debug_check_temp_file[1]));
+ && filename_cmp (debug_check_temp_file[0],
+ debug_check_temp_file[1]));
if (verbose_flag)
inform (0, "comparing final insns dumps");
if (compare_debug)
{
- if (debug_check_temp_file[0])
- free (debug_check_temp_file[0]);
+ free (debug_check_temp_file[0]);
debug_check_temp_file[0] = NULL;
- if (debug_check_temp_file[1])
- free (debug_check_temp_file[1]);
+ free (debug_check_temp_file[1]);
debug_check_temp_file[1] = NULL;
}
}
int i;
for (i = 0; i < n_infiles ; i++)
- if (infiles[i].language && infiles[i].language[0] != '*')
+ if (infiles[i].incompiler
+ || (infiles[i].language && infiles[i].language[0] != '*'))
{
set_input (infiles[i].name);
break;
if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
{
int tmp = execution_count;
- const char *fuse_linker_plugin = "fuse-linker-plugin";
- /* We'll use ld if we can't find collect2. */
- if (! strcmp (linker_name_spec, "collect2"))
+ if (! have_c)
{
- char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
- if (s == NULL)
- linker_name_spec = "ld";
- }
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
+ const char *fno_use_linker_plugin = "fno-use-linker-plugin";
+#else
+ const char *fuse_linker_plugin = "fuse-linker-plugin";
+#endif
+#endif
- if (switch_matches (fuse_linker_plugin,
- fuse_linker_plugin + strlen (fuse_linker_plugin), 0))
- {
- linker_plugin_file_spec = find_a_file (&exec_prefixes,
- "liblto_plugin.so", R_OK,
- false);
- if (!linker_plugin_file_spec)
- fatal_error ("-fuse-linker-plugin, but liblto_plugin.so not found");
-
- lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a",
- R_OK, true);
- if (!lto_libgcc_spec)
- fatal_error ("could not find libgcc.a");
+ /* We'll use ld if we can't find collect2. */
+ if (! strcmp (linker_name_spec, "collect2"))
+ {
+ char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
+ if (s == NULL)
+ linker_name_spec = "ld";
+ }
+
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
+ if (!switch_matches (fno_use_linker_plugin,
+ fno_use_linker_plugin
+ + strlen (fno_use_linker_plugin), 0))
+#else
+ if (switch_matches (fuse_linker_plugin,
+ fuse_linker_plugin
+ + strlen (fuse_linker_plugin), 0))
+#endif
+ {
+ char *temp_spec = find_a_file (&exec_prefixes,
+ LTOPLUGINSONAME, R_OK,
+ false);
+ if (!temp_spec)
+ fatal_error ("-fuse-linker-plugin, but %s not found",
+ LTOPLUGINSONAME);
+ linker_plugin_file_spec = convert_white_space (temp_spec);
+ }
+#endif
+ lto_gcc_spec = argv[0];
}
- lto_gcc_spec = argv[0];
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
printf ("%s\n", bug_report_url);
}
+ out:
return (signal_count != 0 ? 2
: seen_error () ? (pass_exit_codes ? greatest_status : 1)
: 0);
options are present, then we will ignore this completely. Passing
that, gcc will consider each multilib_select in turn using the same
rules for matching the options. If a match is found, that subdirectory
- will be used. */
+ will be used.
+ A subdirectory name is optionally followed by a colon and the corresponding
+ multiarch name. */
static void
set_multilib_dir (void)
q++;
if (q < end)
{
- char *new_multilib_os_dir = XNEWVEC (char, end - q);
- memcpy (new_multilib_os_dir, q + 1, end - q - 1);
- new_multilib_os_dir[end - q - 1] = '\0';
- multilib_os_dir = new_multilib_os_dir;
+ const char *q2 = q + 1, *ml_end = end;
+ char *new_multilib_os_dir;
+
+ while (q2 < end && *q2 != ':')
+ q2++;
+ if (*q2 == ':')
+ ml_end = q2;
+ new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+ memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+ new_multilib_os_dir[ml_end - q - 1] = '\0';
+ multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+
+ if (q2 < end && *q2 == ':')
+ {
+ char *new_multiarch_dir = XNEWVEC (char, end - q2);
+ memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+ new_multiarch_dir[end - q2 - 1] = '\0';
+ multiarch_dir = new_multiarch_dir;
+ }
break;
}
}
}
/* When --disable-multilib was used but target defines
- MULTILIB_OSDIRNAMES, entries starting with .: are there just
- to find multilib_os_dir, so skip them from output. */
- if (this_path[0] == '.' && this_path[1] == ':')
+ MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
+ with .:: for multiarch configurations) are there just to find
+ multilib_os_dir, so skip them from output. */
+ if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
skip = 1;
/* Check for matches with the multilib_exclusions. We don't bother
/* If this is a duplicate, skip it. */
skip = (last_path != 0
&& (unsigned int) (p - this_path) == last_path_len
- && ! strncmp (last_path, this_path, last_path_len));
+ && ! filename_ncmp (last_path, this_path, last_path_len));
last_path = this_path;
last_path_len = p - this_path;
for (i = 0; i < n_infiles; i++)
{
- if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
+ if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
outfiles[i] = xstrdup (argv[1]);
}
return NULL;
for (i = 0; i < n_infiles; i++)
{
- if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
+ if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
outfiles[i] = NULL;
}
return NULL;
return NULL;
}
-/* Compute a timestamp to initialize flag_random_seed. */
+/* Get a random number for -frandom-seed */
-static unsigned
-get_local_tick (void)
+static unsigned HOST_WIDE_INT
+get_random_number (void)
{
- unsigned ret = 0;
+ unsigned HOST_WIDE_INT ret = 0;
+ int fd;
+
+ fd = open ("/dev/urandom", O_RDONLY);
+ if (fd >= 0)
+ {
+ read (fd, &ret, sizeof (HOST_WIDE_INT));
+ close (fd);
+ if (ret)
+ return ret;
+ }
/* Get some more or less random data. */
#ifdef HAVE_GETTIMEOFDAY
}
#endif
- return ret;
+ return ret ^ getpid();
}
/* %:compare-debug-dump-opt spec function. Save the last argument,
do_spec_2 ("%{fdump-final-insns=*:%*}");
do_spec_1 (" ", 0, NULL);
- if (argbuf_index > 0 && strcmp (argv[argbuf_index - 1], "."))
+ if (VEC_length (const_char_p, argbuf) > 0
+ && strcmp (argv[VEC_length (const_char_p, argbuf) - 1], "."))
{
if (!compare_debug)
return NULL;
- name = xstrdup (argv[argbuf_index - 1]);
+ name = xstrdup (argv[VEC_length (const_char_p, argbuf) - 1]);
ret = NULL;
}
else
{
const char *ext = NULL;
- if (argbuf_index > 0)
+ if (VEC_length (const_char_p, argbuf) > 0)
{
do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}");
ext = ".gkd";
do_spec_1 (" ", 0, NULL);
- gcc_assert (argbuf_index > 0);
+ gcc_assert (VEC_length (const_char_p, argbuf) > 0);
- name = concat (argbuf[argbuf_index - 1], ext, NULL);
+ name = concat (VEC_last (const_char_p, argbuf), ext, NULL);
ret = concat ("-fdump-final-insns=", name, NULL);
}
if (!which)
{
- unsigned HOST_WIDE_INT value = get_local_tick () ^ getpid ();
+ unsigned HOST_WIDE_INT value = get_random_number ();
sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
}
do_spec_2 ("%{c|S:%{o*:%*}}");
do_spec_1 (" ", 0, NULL);
- if (argbuf_index > 0)
+ if (VEC_length (const_char_p, argbuf) > 0)
debug_auxbase_opt = concat ("-auxbase-strip ",
- argbuf[argbuf_index - 1],
+ VEC_last (const_char_p, argbuf),
NULL);
else
debug_auxbase_opt = NULL;
return name;
}
+
+/* %:pass-through-libs spec function. Finds all -l options and input
+ file names in the lib spec passed to it, and makes a list of them
+ prepended with the plugin option to cause them to be passed through
+ to the final link after all the new object files have been added. */
+
+const char *
+pass_through_libs_spec_func (int argc, const char **argv)
+{
+ char *prepended = xstrdup (" ");
+ int n;
+ /* Shlemiel the painter's algorithm. Innately horrible, but at least
+ we know that there will never be more than a handful of strings to
+ concat, and it's only once per run, so it's not worth optimising. */
+ for (n = 0; n < argc; n++)
+ {
+ char *old = prepended;
+ /* Anything that isn't an option is a full path to an output
+ file; pass it through if it ends in '.a'. Among options,
+ pass only -l. */
+ if (argv[n][0] == '-' && argv[n][1] == 'l')
+ {
+ const char *lopt = argv[n] + 2;
+ /* Handle both joined and non-joined -l options. If for any
+ reason there's a trailing -l with no joined or following
+ arg just discard it. */
+ if (!*lopt && ++n >= argc)
+ break;
+ else if (!*lopt)
+ lopt = argv[n];
+ prepended = concat (prepended, "-plugin-opt=-pass-through=-l",
+ lopt, " ", NULL);
+ }
+ else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2))
+ {
+ prepended = concat (prepended, "-plugin-opt=-pass-through=",
+ argv[n], " ", NULL);
+ }
+ if (prepended != old)
+ free (old);
+ }
+ return prepended;
+}
+
+/* Insert backslash before spaces in ORIG (usually a file path), to
+ avoid being broken by spec parser.
+
+ This function is needed as do_spec_1 treats white space (' ' and '\t')
+ as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
+ the file name should be treated as a single argument rather than being
+ broken into multiple. Solution is to insert '\\' before the space in a
+ file name.
+
+ This function converts and only converts all occurrence of ' '
+ to '\\' + ' ' and '\t' to '\\' + '\t'. For example:
+ "a b" -> "a\\ b"
+ "a b" -> "a\\ \\ b"
+ "a\tb" -> "a\\\tb"
+ "a\\ b" -> "a\\\\ b"
+
+ orig: input null-terminating string that was allocated by xalloc. The
+ memory it points to might be freed in this function. Behavior undefined
+ if ORIG wasn't xalloced or was freed already at entry.
+
+ Return: ORIG if no conversion needed. Otherwise a newly allocated string
+ that was converted from ORIG. */
+
+static char *
+convert_white_space (char *orig)
+{
+ int len, number_of_space = 0;
+
+ for (len = 0; orig[len]; len++)
+ if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
+
+ if (number_of_space)
+ {
+ char *new_spec = (char *) xmalloc (len + number_of_space + 1);
+ int j, k;
+ for (j = 0, k = 0; j <= len; j++, k++)
+ {
+ if (orig[j] == ' ' || orig[j] == '\t')
+ new_spec[k++] = '\\';
+ new_spec[k] = orig[j];
+ }
+ free (orig);
+ return new_spec;
+ }
+ else
+ return orig;
+}