static int target_system_root_changed;
+/* Nonzero means append this string to target_system_root. */
+
+static const char *target_sysroot_suffix = 0;
+
+/* Nonzero means append this string to target_system_root for headers. */
+
+static const char *target_sysroot_hdrs_suffix = 0;
+
/* Nonzero means write "temp" files in source directory
and use the source file's name in them, and don't delete them. */
static void set_collect_gcc_options PARAMS ((void));
static int do_spec_1 PARAMS ((const char *, int, const char *));
static int do_spec_2 PARAMS ((const char *));
+static void do_option_spec PARAMS ((const char *, const char *));
static void do_self_spec PARAMS ((const char *));
static const char *find_file PARAMS ((const char *));
static int is_directory PARAMS ((const char *, const char *, int));
#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
#endif
+#ifndef LINK_PIE_SPEC
+#ifdef HAVE_LD_PIE
+#define LINK_PIE_SPEC "%{pie:-pie} "
+#else
+#define LINK_PIE_SPEC "%{pie:} "
+#endif
+#endif
+
/* -u* was put back because both BSD and SysV seem to support it. */
/* %{static:} simply prevents an error message if the target machine
doesn't handle -static. */
#ifndef LINK_COMMAND_SPEC
#define LINK_COMMAND_SPEC "\
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
- %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\
- %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
+ %(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*} %(link_libgcc) %o %{fprofile-arcs:-lgcov}\
%{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
# define STARTFILE_PREFIX_SPEC ""
#endif
+#ifndef SYSROOT_SUFFIX_SPEC
+# define SYSROOT_SUFFIX_SPEC ""
+#endif
+
+#ifndef SYSROOT_HEADERS_SUFFIX_SPEC
+# define SYSROOT_HEADERS_SUFFIX_SPEC ""
+#endif
+
static const char *asm_debug;
static const char *cpp_spec = CPP_SPEC;
static const char *cc1_spec = CC1_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_suffix_spec = SYSROOT_SUFFIX_SPEC;
+static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_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,
static const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
+#ifndef OPTION_DEFAULT_SPECS
+#define OPTION_DEFAULT_SPECS { "", "" }
+#endif
+
+struct default_spec
+{
+ const char *name;
+ const char *spec;
+};
+
+static const struct default_spec
+ option_default_specs[] = { OPTION_DEFAULT_SPECS };
+
struct user_specs
{
struct user_specs *next;
, 0},
#include "specs.h"
- /* Mark end of table */
+ /* Mark end of table. */
{0, 0, 0}
};
{"--param", "--param", "a"},
{"--pedantic", "-pedantic", 0},
{"--pedantic-errors", "-pedantic-errors", 0},
+ {"--pie", "-pie", 0},
{"--pipe", "-pipe", 0},
{"--prefix", "-B", "a"},
{"--preprocess", "-E", 0},
INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1),
INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec),
+ INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec),
+ INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
/* Free the old spec. */
if (old_spec && sl->alloc_p)
- free ((PTR) old_spec);
+ free ((void *) old_spec);
sl->alloc_p = 1;
}
set_spec (p2, *(sl->ptr_spec));
if (sl->alloc_p)
- free ((PTR) *(sl->ptr_spec));
+ free ((void *) *(sl->ptr_spec));
*(sl->ptr_spec) = "";
sl->alloc_p = 0;
prev = &(*prev)->next)
;
- /* Keep track of the longest prefix */
+ /* Keep track of the longest prefix. */
prefix = update_path (prefix, component);
len = strlen (prefix);
if (warn)
*warn = 0;
- /* Insert after PREV */
+ /* Insert after PREV. */
pl->next = (*prev);
(*prev) = pl;
}
if (target_system_root)
{
+ if (target_sysroot_suffix)
+ prefix = concat (target_sysroot_suffix, prefix, NULL);
prefix = concat (target_system_root, prefix, NULL);
+
/* We have to override this because GCC's notion of sysroot
moves along with GCC. */
component = "GCC";
pfatal_pexecute (errmsg_fmt, errmsg_arg);
if (string != commands[i].prog)
- free ((PTR) string);
+ free ((void *) string);
}
execution_count++;
of the switches/n_switches array. */
static void
+do_option_spec (name, spec)
+ const char *name;
+ const char *spec;
+{
+ unsigned int i, value_count, value_len;
+ const char *p, *q, *value;
+ char *tmp_spec, *tmp_spec_p;
+
+ if (configure_default_options[0].name == NULL)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
+ if (strcmp (configure_default_options[i].name, name) == 0)
+ break;
+ if (i == ARRAY_SIZE (configure_default_options))
+ return;
+
+ value = configure_default_options[i].value;
+ value_len = strlen (value);
+
+ /* Compute the size of the final spec. */
+ value_count = 0;
+ p = spec;
+ while ((p = strstr (p, "%(VALUE)")) != NULL)
+ {
+ p ++;
+ value_count ++;
+ }
+
+ /* Replace each %(VALUE) by the specified value. */
+ tmp_spec = alloca (strlen (spec) + 1
+ + value_count * (value_len - strlen ("%(VALUE)")));
+ tmp_spec_p = tmp_spec;
+ q = spec;
+ while ((p = strstr (q, "%(VALUE)")) != NULL)
+ {
+ memcpy (tmp_spec_p, q, p - q);
+ tmp_spec_p = tmp_spec_p + (p - q);
+ memcpy (tmp_spec_p, value, value_len);
+ tmp_spec_p += value_len;
+ q = p + strlen ("%(VALUE)");
+ }
+ strcpy (tmp_spec_p, q);
+
+ do_self_spec (tmp_spec);
+}
+
+/* Process the given spec string and add any new options to the end
+ of the switches/n_switches array. */
+
+static void
do_self_spec (spec)
const char *spec;
{
do_spec_1 (" ", 0, NULL);
}
- if (target_system_root_changed)
+ if (target_system_root_changed ||
+ (target_system_root && target_sysroot_hdrs_suffix))
{
do_spec_1 ("-isysroot", 1, NULL);
/* Make this a separate argument. */
do_spec_1 (" ", 0, NULL);
do_spec_1 (target_system_root, 1, NULL);
+ if (target_sysroot_hdrs_suffix)
+ do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
do_spec_1 (" ", 0, NULL);
}
/* We assume there is a directory
separator at the end of this string. */
if (target_system_root)
- obstack_grow (&obstack, target_system_root,
- strlen (target_system_root));
+ {
+ obstack_grow (&obstack, target_system_root,
+ strlen (target_system_root));
+ if (target_sysroot_suffix)
+ obstack_grow (&obstack, target_sysroot_suffix,
+ strlen (target_sysroot_suffix));
+ }
break;
case 'S':
if (access (specs_file, R_OK) == 0)
read_specs (specs_file, TRUE);
+ /* Process any configure-time defaults specified for the command line
+ options, via OPTION_DEFAULT_SPECS. */
+ for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
+ do_option_spec (option_default_specs[i].name,
+ option_default_specs[i].spec);
+
/* Process DRIVER_SELF_SPECS, adding any new options to the end
of the command line. */
}
}
+ /* Process sysroot_suffix_spec. */
+ if (*sysroot_suffix_spec != 0
+ && do_spec_2 (sysroot_suffix_spec) == 0)
+ {
+ if (argbuf_index > 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]);
+ }
+
+ /* Process sysroot_hdrs_suffix_spec. */
+ if (*sysroot_hdrs_suffix_spec != 0
+ && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
+ {
+ if (argbuf_index > 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]);
+ }
+
/* Look for startfiles in the standard places. */
if (*startfile_prefix_spec != 0
&& do_spec_2 (startfile_prefix_spec) == 0
pfatal_with_name (errmsg_fmt);
}
-/* Output an error message and exit */
+/* Output an error message and exit. */
void
fancy_abort ()
fatal ("internal gcc abort");
}
\f
-/* Output an error message and exit */
+/* Output an error message and exit. */
void
fatal (const char *msgid, ...)