/* 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 Free Software Foundation,
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
Inc.
This file is part of GCC.
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 (struct path_prefix *, const char *, int);
-static void putenv_from_prefixes (struct path_prefix *, const char *);
+static char *build_search_list (const struct path_prefix *, const char *,
+ bool, bool);
+static void putenv_from_prefixes (const struct path_prefix *, const char *,
+ bool);
static int access_check (const char *, int);
-static char *find_a_file (struct path_prefix *, const char *, int, int);
+static char *find_a_file (const struct path_prefix *, const char *, int, bool);
static void add_prefix (struct path_prefix *, const char *, const char *,
int, int, int);
static void add_sysrooted_prefix (struct path_prefix *, const char *,
static const char *handle_spec_function (const char *);
static char *save_string (const char *, int);
static void set_collect_gcc_options (void);
-static void do_spec_path (struct prefix_list *, const char *, int, int, int, const char *, const char *);
static int do_spec_1 (const char *, int, const char *);
static int do_spec_2 (const char *);
static void do_option_spec (const char *, const char *);
static void do_self_spec (const char *);
static const char *find_file (const char *);
-static int is_directory (const char *, const char *, int);
+static int is_directory (const char *, bool);
static const char *validate_switches (const char *);
static void validate_all_switches (void);
static inline void validate_switches_from_spec (const char *);
static void set_multilib_dir (void);
static void print_multilib_info (void);
static void perror_with_name (const char *);
+static void fatal_ice (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
static void display_help (void);
static void add_preprocessor_option (const char *, int);
static const char *if_exists_else_spec_function (int, const char **);
static const char *replace_outfile_spec_function (int, const char **);
static const char *version_compare_spec_function (int, const char **);
+static const char *include_spec_function (int, const char **);
\f
/* The Specs Language
SUFFIX characters following %O as they would following, for
example, `.o'.
%I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
- (made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH
- and -B options) as necessary.
+ (made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
+ and -B options) and -imultilib as necessary.
%s current argument is the name of a library or startup file of some sort.
Search for that file in a standard list of directories
and substitute the full name found.
#endif
#endif
+#ifndef LINK_GCC_MATH_SPEC
+#define LINK_GCC_MATH_SPEC ""
+#endif
+
#ifndef LINK_PIE_SPEC
#ifdef HAVE_LD_PIE
#define LINK_PIE_SPEC "%{pie:-pie} "
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!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*} %(mfwrap) %(link_libgcc) %o %(mflib)\
+ %{static:} %{L*} %(mfwrap) %{fopenmp:%:include(libgomp.spec)%(link_gomp)}\
+ %(link_libgcc) %o %(mflib)\
%{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
- %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
+ %{!nostdlib:%{!nodefaultlibs:%(link_gcc_math) %(link_ssp) %(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
#endif
static const char *cc1plus_spec = CC1PLUS_SPEC;
static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
static const char *link_ssp_spec = LINK_SSP_SPEC;
+static const char *link_gcc_math_spec = LINK_GCC_MATH_SPEC;
static const char *asm_spec = ASM_SPEC;
static const char *asm_final_spec = ASM_FINAL_SPEC;
static const char *link_spec = LINK_SPEC;
static const char *lib_spec = LIB_SPEC;
static const char *mfwrap_spec = MFWRAP_SPEC;
static const char *mflib_spec = MFLIB_SPEC;
+static const char *link_gomp_spec = "";
static const char *libgcc_spec = LIBGCC_SPEC;
static const char *endfile_spec = ENDFILE_SPEC;
static const char *startfile_spec = STARTFILE_SPEC;
#define DRIVER_SELF_SPECS ""
#endif
-static const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
+/* 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}"
+#endif
+
+static const char *const driver_self_specs[] = {
+ DRIVER_SELF_SPECS, GOMP_SELF_SPECS
+};
#ifndef OPTION_DEFAULT_SPECS
#define OPTION_DEFAULT_SPECS { "", "" }
INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec),
INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec),
+ INIT_STATIC_SPEC ("link_gcc_math", &link_gcc_math_spec),
INIT_STATIC_SPEC ("endfile", &endfile_spec),
INIT_STATIC_SPEC ("link", &link_spec),
INIT_STATIC_SPEC ("lib", &lib_spec),
INIT_STATIC_SPEC ("mfwrap", &mfwrap_spec),
INIT_STATIC_SPEC ("mflib", &mflib_spec),
+ INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec),
INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
INIT_STATIC_SPEC ("startfile", &startfile_spec),
INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces),
{ "if-exists-else", if_exists_else_spec_function },
{ "replace-outfile", replace_outfile_spec_function },
{ "version-compare", version_compare_spec_function },
+ { "include", include_spec_function },
{ 0, 0 }
};
{
char *buf;
- buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name,
- "}%{!static:%{!static-libgcc:",
+ buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, "}"
+ "%{!static:%{!static-libgcc:"
#if USE_LD_AS_NEEDED
- "%{!shared-libgcc:", static_name,
- " --as-needed ", shared_name, " --no-as-needed}"
- "%{shared-libgcc:", shared_name, "%{!shared: ", static_name,
- "}",
+ "%{!shared-libgcc:",
+ static_name, " --as-needed ", shared_name, " --no-as-needed"
+ "}"
+ "%{shared-libgcc:",
+ shared_name, "%{!shared: ", static_name, "}"
+ "}"
#else
- "%{!shared:%{!shared-libgcc:", static_name, " ",
- eh_name, "}%{shared-libgcc:", shared_name, " ",
- static_name, "}}%{shared:",
+ "%{!shared:"
+ "%{!shared-libgcc:", static_name, " ", eh_name, "}"
+ "%{shared-libgcc:", shared_name, " ", static_name, "}"
+ "}"
#ifdef LINK_EH_SPEC
- "%{shared-libgcc:", shared_name,
- "}%{!shared-libgcc:", static_name, "}",
+ "%{shared:"
+ "%{shared-libgcc:", shared_name, "}"
+ "%{!shared-libgcc:", static_name, "}"
+ "}"
#else
- shared_name,
+ "%{shared:", shared_name, "}"
#endif
#endif
- "}}}", NULL);
+ "}}", NULL);
obstack_grow (obstack, buf, strlen (buf));
free (buf);
if (!sl)
{
/* Not found - make it. */
- sl = xmalloc (sizeof (struct spec_list));
+ sl = XNEW (struct spec_list);
sl->name = xstrdup (name);
sl->name_len = name_len;
sl->ptr_spec = &sl->ptr;
alloc_args (void)
{
argbuf_length = 10;
- argbuf = xmalloc (argbuf_length * sizeof (const char *));
+ argbuf = XNEWVEC (const char *, argbuf_length);
}
/* Clear out the vector of arguments (after a command is executed). */
pfatal_with_name (filename);
/* Read contents of file into BUFFER. */
- buffer = xmalloc ((unsigned) statbuf.st_size + 1);
+ buffer = XNEWVEC (char, statbuf.st_size + 1);
readlen = read (desc, buffer, (unsigned) statbuf.st_size);
if (readlen < 0)
pfatal_with_name (filename);
buffer[readlen] = 0;
close (desc);
- specs = xmalloc (readlen + 1);
+ specs = XNEWVEC (char, readlen + 1);
specs_p = specs;
for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
{
(long) (p1 - buffer + 1));
p[-2] = '\0';
- new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
read_specs (new_filename ? new_filename : p1, FALSE);
continue;
}
(long) (p1 - buffer + 1));
p[-2] = '\0';
- new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
if (new_filename)
read_specs (new_filename, FALSE);
else if (verbose_flag)
if (! strcmp (name, temp->name))
goto already1;
- temp = xmalloc (sizeof (struct temp_file));
+ temp = XNEW (struct temp_file);
temp->next = always_delete_queue;
temp->name = name;
always_delete_queue = temp;
if (! strcmp (name, temp->name))
goto already2;
- temp = xmalloc (sizeof (struct temp_file));
+ temp = XNEW (struct temp_file);
temp->next = failure_delete_queue;
temp->name = name;
failure_delete_queue = temp;
failure_delete_queue = 0;
}
\f
-/* Build a list of search directories from PATHS.
- PREFIX is a string to prepend to the list.
- If CHECK_DIR_P is nonzero we ensure the directory exists.
- This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
- It is also used by the --print-search-dirs flag. */
-
-static char *
-build_search_list (struct path_prefix *paths, const char *prefix,
- int check_dir_p)
+/* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
+ returns non-NULL.
+ If DO_MULTI is true iterate over the paths twice, first with multilib
+ suffix then without, otherwise iterate over the paths once without
+ adding a multilib suffix. When DO_MULTI is true, some attempt is made
+ to avoid visiting the same path twice, but we could do better. For
+ instance, /usr/lib/../lib is considered different from /usr/lib.
+ At least EXTRA_SPACE chars past the end of the path passed to
+ CALLBACK are available for use by the callback.
+ CALLBACK_INFO allows extra parameters to be passed to CALLBACK.
+
+ Returns the value returned by CALLBACK. */
+
+static void *
+for_each_path (const struct path_prefix *paths,
+ bool do_multi,
+ size_t extra_space,
+ void *(*callback) (char *, void *),
+ void *callback_info)
{
- int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
- int just_suffix_len
- = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
- int first_time = TRUE;
- struct prefix_list *pprefix;
-
- obstack_grow (&collect_obstack, prefix, strlen (prefix));
- obstack_1grow (&collect_obstack, '=');
-
- for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
+ struct prefix_list *pl;
+ const char *multi_dir = NULL;
+ const char *multi_os_dir = NULL;
+ const char *multi_suffix;
+ const char *just_multi_suffix;
+ char *path = NULL;
+ void *ret = NULL;
+ bool skip_multi_dir = false;
+ bool skip_multi_os_dir = false;
+
+ multi_suffix = machine_suffix;
+ just_multi_suffix = just_machine_suffix;
+ if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
{
- int len = strlen (pprefix->prefix);
+ multi_dir = concat (multilib_dir, dir_separator_str, NULL);
+ multi_suffix = concat (multi_suffix, multi_dir, NULL);
+ just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
+ }
+ if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
+ multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
- if (machine_suffix
- && (! check_dir_p
- || is_directory (pprefix->prefix, machine_suffix, 0)))
+ while (1)
+ {
+ size_t multi_dir_len = 0;
+ size_t multi_os_dir_len = 0;
+ size_t suffix_len;
+ size_t just_suffix_len;
+ size_t len;
+
+ if (multi_dir)
+ multi_dir_len = strlen (multi_dir);
+ if (multi_os_dir)
+ multi_os_dir_len = strlen (multi_os_dir);
+ suffix_len = strlen (multi_suffix);
+ just_suffix_len = strlen (just_multi_suffix);
+
+ if (path == NULL)
{
- if (!first_time)
- obstack_1grow (&collect_obstack, PATH_SEPARATOR);
-
- first_time = FALSE;
- obstack_grow (&collect_obstack, pprefix->prefix, len);
- obstack_grow (&collect_obstack, machine_suffix, suffix_len);
+ len = paths->max_len + extra_space + 1;
+ if (suffix_len > multi_os_dir_len)
+ len += suffix_len;
+ else
+ len += multi_os_dir_len;
+ path = XNEWVEC (char, len);
}
- if (just_machine_suffix
- && pprefix->require_machine_suffix == 2
- && (! check_dir_p
- || is_directory (pprefix->prefix, just_machine_suffix, 0)))
+ for (pl = paths->plist; pl != 0; pl = pl->next)
{
- if (! first_time)
- obstack_1grow (&collect_obstack, PATH_SEPARATOR);
+ len = strlen (pl->prefix);
+ memcpy (path, pl->prefix, len);
+
+ /* Look first in MACHINE/VERSION subdirectory. */
+ if (!skip_multi_dir)
+ {
+ memcpy (path + len, multi_suffix, suffix_len + 1);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+
+ /* Some paths are tried with just the machine (ie. target)
+ subdir. This is used for finding as, ld, etc. */
+ if (!skip_multi_dir
+ && pl->require_machine_suffix == 2)
+ {
+ memcpy (path + len, just_multi_suffix, just_suffix_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))
+ {
+ const char *this_multi;
+ size_t this_multi_len;
+
+ if (pl->os_multilib)
+ {
+ this_multi = multi_os_dir;
+ this_multi_len = multi_os_dir_len;
+ }
+ else
+ {
+ this_multi = multi_dir;
+ this_multi_len = multi_dir_len;
+ }
+
+ if (this_multi_len)
+ memcpy (path + len, this_multi, this_multi_len + 1);
+ else
+ path[len] = '\0';
- first_time = FALSE;
- obstack_grow (&collect_obstack, pprefix->prefix, len);
- obstack_grow (&collect_obstack, just_machine_suffix,
- just_suffix_len);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
}
+ if (pl)
+ break;
- if (! pprefix->require_machine_suffix)
- {
- if (! first_time)
- obstack_1grow (&collect_obstack, PATH_SEPARATOR);
+ if (multi_dir == NULL && multi_os_dir == NULL)
+ break;
- first_time = FALSE;
- obstack_grow (&collect_obstack, pprefix->prefix, len);
+ /* Run through the paths again, this time without multilibs.
+ Don't repeat any we have already seen. */
+ if (multi_dir)
+ {
+ free ((char *) multi_dir);
+ multi_dir = NULL;
+ free ((char *) multi_suffix);
+ multi_suffix = machine_suffix;
+ free ((char *) just_multi_suffix);
+ just_multi_suffix = just_machine_suffix;
}
+ else
+ skip_multi_dir = true;
+ if (multi_os_dir)
+ {
+ free ((char *) multi_os_dir);
+ multi_os_dir = NULL;
+ }
+ else
+ skip_multi_os_dir = true;
}
+ if (multi_dir)
+ {
+ free ((char *) multi_dir);
+ free ((char *) multi_suffix);
+ free ((char *) just_multi_suffix);
+ }
+ if (multi_os_dir)
+ free ((char *) multi_os_dir);
+ if (ret != path)
+ free (path);
+ return ret;
+}
+
+/* Callback for build_search_list. Adds path to obstack being built. */
+
+struct add_to_obstack_info {
+ struct obstack *ob;
+ bool check_dir;
+ bool first_time;
+};
+
+static void *
+add_to_obstack (char *path, void *data)
+{
+ struct add_to_obstack_info *info = data;
+
+ if (info->check_dir && !is_directory (path, false))
+ return NULL;
+
+ if (!info->first_time)
+ obstack_1grow (info->ob, PATH_SEPARATOR);
+
+ obstack_grow (info->ob, path, strlen (path));
+
+ info->first_time = false;
+ return NULL;
+}
+
+/* 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.
+ If DO_MULTI is true, multilib paths are output first, then
+ non-multilib paths.
+ This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
+ It is also used by the --print-search-dirs flag. */
+
+static char *
+build_search_list (const struct path_prefix *paths, const char *prefix,
+ bool check_dir, bool do_multi)
+{
+ struct add_to_obstack_info info;
+
+ info.ob = &collect_obstack;
+ info.check_dir = check_dir;
+ info.first_time = true;
+
+ obstack_grow (&collect_obstack, prefix, strlen (prefix));
+ obstack_1grow (&collect_obstack, '=');
+
+ for_each_path (paths, do_multi, 0, add_to_obstack, &info);
+
obstack_1grow (&collect_obstack, '\0');
return XOBFINISH (&collect_obstack, char *);
}
for collect. */
static void
-putenv_from_prefixes (struct path_prefix *paths, const char *env_var)
+putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
+ bool do_multi)
{
- putenv (build_search_list (paths, env_var, 1));
+ putenv (build_search_list (paths, env_var, true, do_multi));
}
\f
/* Check whether NAME can be accessed in MODE. This is like access,
return access (name, mode);
}
+/* Callback for find_a_file. Appends the file name to the directory
+ path. If the resulting file exists in the right mode, return the
+ full pathname to the file. */
+
+struct file_at_path_info {
+ const char *name;
+ const char *suffix;
+ int name_len;
+ int suffix_len;
+ int mode;
+};
+
+static void *
+file_at_path (char *path, void *data)
+{
+ struct file_at_path_info *info = data;
+ size_t len = strlen (path);
+
+ memcpy (path + len, info->name, info->name_len);
+ len += info->name_len;
+
+ /* Some systems have a suffix for executable files.
+ So try appending that first. */
+ if (info->suffix_len)
+ {
+ memcpy (path + len, info->suffix, info->suffix_len + 1);
+ if (access_check (path, info->mode) == 0)
+ return path;
+ }
+
+ path[len] = '\0';
+ if (access_check (path, info->mode) == 0)
+ return path;
+
+ return NULL;
+}
+
/* Search for NAME using the prefix list PREFIXES. MODE is passed to
- access to check permissions.
+ access to check permissions. If DO_MULTI is true, search multilib
+ paths then non-multilib paths, otherwise do not search multilib paths.
Return 0 if not found, otherwise return its name, allocated with malloc. */
static char *
-find_a_file (struct path_prefix *pprefix, const char *name, int mode,
- int multilib)
+find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
+ bool do_multi)
{
- char *temp;
- const char *const file_suffix =
- ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "");
- struct prefix_list *pl;
- int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
- const char *multilib_name, *multilib_os_name;
+ struct file_at_path_info info;
#ifdef DEFAULT_ASSEMBLER
if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
return xstrdup (DEFAULT_LINKER);
#endif
- if (machine_suffix)
- len += strlen (machine_suffix);
-
- multilib_name = name;
- multilib_os_name = name;
- if (multilib && multilib_os_dir)
- {
- int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0;
- int len2 = strlen (multilib_os_dir) + 1;
-
- len += len1 > len2 ? len1 : len2;
- if (multilib_dir)
- multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name,
- NULL));
- if (strcmp (multilib_os_dir, ".") != 0)
- multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name,
- NULL));
- }
-
- temp = xmalloc (len);
-
/* Determine the filename to execute (special case for absolute paths). */
if (IS_ABSOLUTE_PATH (name))
{
if (access (name, mode) == 0)
- {
- strcpy (temp, name);
- return temp;
- }
- }
- else
- for (pl = pprefix->plist; pl; pl = pl->next)
- {
- const char *this_name
- = pl->os_multilib ? multilib_os_name : multilib_name;
+ return xstrdup (name);
- if (machine_suffix)
- {
- /* Some systems have a suffix for executable files.
- So try appending that first. */
- if (file_suffix[0] != 0)
- {
- strcpy (temp, pl->prefix);
- strcat (temp, machine_suffix);
- strcat (temp, multilib_name);
- strcat (temp, file_suffix);
- if (access_check (temp, mode) == 0)
- return temp;
- }
-
- /* Now try just the multilib_name. */
- strcpy (temp, pl->prefix);
- strcat (temp, machine_suffix);
- strcat (temp, multilib_name);
- if (access_check (temp, mode) == 0)
- return temp;
- }
-
- /* Certain prefixes are tried with just the machine type,
- not the version. This is used for finding as, ld, etc. */
- if (just_machine_suffix && pl->require_machine_suffix == 2)
- {
- /* Some systems have a suffix for executable files.
- So try appending that first. */
- if (file_suffix[0] != 0)
- {
- strcpy (temp, pl->prefix);
- strcat (temp, just_machine_suffix);
- strcat (temp, multilib_name);
- strcat (temp, file_suffix);
- if (access_check (temp, mode) == 0)
- return temp;
- }
-
- strcpy (temp, pl->prefix);
- strcat (temp, just_machine_suffix);
- strcat (temp, multilib_name);
- if (access_check (temp, mode) == 0)
- return temp;
- }
-
- /* Certain prefixes can't be used without the machine suffix
- when the machine or version is explicitly specified. */
- if (! pl->require_machine_suffix)
- {
- /* Some systems have a suffix for executable files.
- So try appending that first. */
- if (file_suffix[0] != 0)
- {
- strcpy (temp, pl->prefix);
- strcat (temp, this_name);
- strcat (temp, file_suffix);
- if (access_check (temp, mode) == 0)
- return temp;
- }
+ return NULL;
+ }
- strcpy (temp, pl->prefix);
- strcat (temp, this_name);
- if (access_check (temp, mode) == 0)
- return temp;
- }
- }
+ info.name = name;
+ info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "";
+ info.name_len = strlen (info.name);
+ info.suffix_len = strlen (info.suffix);
+ info.mode = mode;
- free (temp);
- return 0;
+ return 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
if (len > pprefix->max_len)
pprefix->max_len = len;
- pl = xmalloc (sizeof (struct prefix_list));
+ pl = XNEW (struct prefix_list);
pl->prefix = prefix;
pl->require_machine_suffix = require_machine_suffix;
pl->priority = priority;
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
- string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0);
+ string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
if (string)
commands[0].argv[0] = string;
commands[n_commands].prog = argbuf[i + 1];
commands[n_commands].argv = &argbuf[i + 1];
string = find_a_file (&exec_prefixes, commands[n_commands].prog,
- X_OK, 0);
+ X_OK, false);
if (string)
commands[n_commands].argv[0] = string;
n_commands++;
we would otherwise have succeeded. */
if (WTERMSIG (status) == SIGPIPE
&& (signal_count || greatest_status >= MIN_FATAL_STATUS))
- ;
+ {
+ signal_count++;
+ ret_code = -1;
+ }
else
#endif
- fatal ("\
+ fatal_ice ("\
Internal error: %s (program %s)\n\
Please submit a full bug report.\n\
See %s for instructions.",
- strsignal (WTERMSIG (status)), commands[i].prog,
- bug_report_url);
- signal_count++;
- ret_code = -1;
+ strsignal (WTERMSIG (status)), commands[i].prog,
+ bug_report_url);
}
else if (WIFEXITED (status)
&& WEXITSTATUS (status) >= MIN_FATAL_STATUS)
n_preprocessor_options++;
if (! preprocessor_options)
- preprocessor_options = xmalloc (n_preprocessor_options * sizeof (char *));
+ preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
else
preprocessor_options = xrealloc (preprocessor_options,
n_preprocessor_options * sizeof (char *));
n_assembler_options++;
if (! assembler_options)
- assembler_options = xmalloc (n_assembler_options * sizeof (char *));
+ assembler_options = XNEWVEC (char *, n_assembler_options);
else
assembler_options = xrealloc (assembler_options,
n_assembler_options * sizeof (char *));
n_linker_options++;
if (! linker_options)
- linker_options = xmalloc (n_linker_options * sizeof (char *));
+ linker_options = XNEWVEC (char *, n_linker_options);
else
linker_options = xrealloc (linker_options,
n_linker_options * sizeof (char *));
int lang_n_infiles = 0;
#ifdef MODIFY_TARGET_NAME
int is_modify_target_name;
- int j;
+ unsigned int j;
#endif
GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
}
/* If there is a -V or -b option (or both), process it now, before
- trying to interpret the rest of the command line.
+ trying to interpret the rest of the command line.
Use heuristic that all configuration names must have at least
one dash '-'. This allows us to pass options starting with -b. */
if (argc > 1 && argv[1][0] == '-'
- && (argv[1][1] == 'V' ||
+ && (argv[1][1] == 'V' ||
((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
{
const char *new_version = DEFAULT_TARGET_VERSION;
{
/* translate_options () has turned --version into -fversion. */
printf (_("%s (GCC) %s\n"), programname, version_string);
- printf ("Copyright %s 2005 Free Software Foundation, Inc.\n",
+ printf ("Copyright %s 2006 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"),
}
else if (strcmp (argv[i], "-specs") == 0)
{
- struct user_specs *user = xmalloc (sizeof (struct user_specs));
+ struct user_specs *user = XNEW (struct user_specs);
if (++i >= argc)
fatal ("argument to '-specs' is missing");
}
else if (strncmp (argv[i], "-specs=", 7) == 0)
{
- struct user_specs *user = xmalloc (sizeof (struct user_specs));
+ struct user_specs *user = XNEW (struct user_specs);
if (strlen (argv[i]) == 7)
fatal ("argument to '-specs=' is missing");
if appending a directory separator actually makes a
valid directory name. */
if (! IS_DIR_SEPARATOR (value [len - 1])
- && is_directory (value, "", 0))
+ && is_directory (value, false))
{
- char *tmp = xmalloc (len + 2);
+ char *tmp = XNEWVEC (char, len + 2);
strcpy (tmp, value);
tmp[len] = DIR_SEPARATOR;
tmp[++ len] = 0;
/* Then create the space for the vectors and scan again. */
- switches = xmalloc ((n_switches + 1) * sizeof (struct switchstr));
- infiles = xmalloc ((n_infiles + 1) * sizeof (struct infile));
+ switches = XNEWVEC (struct switchstr, n_switches + 1);
+ infiles = XNEWVEC (struct infile, n_infiles + 1);
n_switches = 0;
n_infiles = 0;
last_language_n_infiles = -1;
if (i + n_args >= argc)
fatal ("argument to '-%s' is missing", p);
switches[n_switches].args
- = xmalloc ((n_args + 1) * sizeof(const char *));
+ = XNEWVEC (const char *, n_args + 1);
while (j < n_args)
switches[n_switches].args[j++] = argv[++i];
/* Null-terminate the vector. */
{
/* On some systems, ld cannot handle some options without
a space. So split the option from its argument. */
- char *part1 = xmalloc (2);
+ char *part1 = XNEWVEC (char, 2);
part1[0] = c;
part1[1] = '\0';
switches[n_switches].part1 = part1;
- switches[n_switches].args = xmalloc (2 * sizeof (const char *));
+ switches[n_switches].args = XNEWVEC (const char *, 2);
switches[n_switches].args[0] = xstrdup (p+1);
switches[n_switches].args[1] = 0;
}
}
}
-void
-do_spec_path (struct prefix_list *pl, const char *option,
- int omit_if_relative, int separate_options,
- int only_subdir,
- const char *dir_for_machine_suffix,
- const char *dir_for_no_suffix)
+/* Callback for processing %D and %I specs. */
+
+struct spec_path_info {
+ const char *option;
+ const char *append;
+ size_t append_len;
+ bool omit_relative;
+ bool separate_options;
+};
+
+static void *
+spec_path (char *path, void *data)
{
- static size_t bufsize = 0;
- static char *buffer;
- int idx;
- bool multilib_p = false;
-
- /* Used on systems which record the specified -L dirs
- and use them to search for dynamic linking. */
- /* Relative directories always come from -B,
- and it is better not to use them for searching
- at run time. In particular, stage1 loses. */
- if (omit_if_relative
- && !IS_ABSOLUTE_PATH (pl->prefix))
- return;
+ struct spec_path_info *info = data;
+ size_t len = 0;
+ char save = 0;
- /* Try subdirectory if there is one. */
- if (machine_suffix && dir_for_machine_suffix)
- {
- if (strlen (pl->prefix) + strlen (machine_suffix)
- >= bufsize)
- bufsize = (strlen (pl->prefix)
- + strlen (machine_suffix)) * 2 + 1;
- buffer = xrealloc (buffer, bufsize);
- strcpy (buffer, pl->prefix);
- strcat (buffer, machine_suffix);
- if (is_directory (buffer, dir_for_machine_suffix, 1))
- {
- multilib_p = true;
- do_spec_1 (option, separate_options, NULL);
- if (separate_options)
- do_spec_1 (" ", 0, NULL);
- do_spec_1 (buffer, 1, NULL);
- do_spec_1 (dir_for_machine_suffix, 1, NULL);
- /* Make this a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
- }
- if (!pl->require_machine_suffix && dir_for_no_suffix)
+ if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
+ return NULL;
+
+ if (info->append_len != 0)
{
- if (is_directory (pl->prefix, dir_for_no_suffix, 1))
- {
- multilib_p = true;
- do_spec_1 (option, separate_options, NULL);
- if (separate_options)
- do_spec_1 (" ", 0, NULL);
- do_spec_1 (pl->prefix, 1, NULL);
- do_spec_1 (dir_for_no_suffix, 1, NULL);
- /* Make this a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
+ len = strlen (path);
+ memcpy (path + len, info->append, info->append_len + 1);
}
- if (only_subdir || multilib_p)
- return;
+ if (!is_directory (path, true))
+ return NULL;
- if (machine_suffix)
- {
- if (is_directory (pl->prefix, machine_suffix, 1))
- {
- do_spec_1 (option, separate_options, NULL);
- if (separate_options)
- do_spec_1 (" ", 0, NULL);
- do_spec_1 (pl->prefix, 1, NULL);
- /* Remove slash from machine_suffix. */
- if (strlen (machine_suffix) >= bufsize)
- bufsize = strlen (machine_suffix) * 2 + 1;
- buffer = xrealloc (buffer, bufsize);
- strcpy (buffer, machine_suffix);
- idx = strlen (buffer);
- if (IS_DIR_SEPARATOR (buffer[idx - 1]))
- buffer[idx - 1] = 0;
- do_spec_1 (buffer, 1, NULL);
- /* Make this a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
- }
- if (!pl->require_machine_suffix)
+ do_spec_1 (info->option, 1, NULL);
+ if (info->separate_options)
+ do_spec_1 (" ", 0, NULL);
+
+ if (info->append_len == 0)
{
- if (is_directory (pl->prefix, "", 1))
- {
- do_spec_1 (option, separate_options, NULL);
- if (separate_options)
- do_spec_1 (" ", 0, NULL);
- /* Remove slash from pl->prefix. */
- if (strlen (pl->prefix) >= bufsize)
- bufsize = strlen (pl->prefix) * 2 + 1;
- buffer = xrealloc (buffer, bufsize);
- strcpy (buffer, pl->prefix);
- idx = strlen (buffer);
- if (IS_DIR_SEPARATOR (buffer[idx - 1]))
- buffer[idx - 1] = 0;
- do_spec_1 (buffer, 1, NULL);
- /* Make this a separate argument. */
- do_spec_1 (" ", 0, NULL);
- }
+ len = strlen (path);
+ save = path[len - 1];
+ if (IS_DIR_SEPARATOR (path[len - 1]))
+ path[len - 1] = '\0';
}
+
+ do_spec_1 (path, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+
+ /* Must not damage the original path. */
+ if (info->append_len == 0)
+ path[len - 1] = save;
+
+ return NULL;
}
/* Process the sub-spec SPEC as a portion of a larger spec.
that we search for startfiles. */
case 'D':
{
- struct prefix_list *pl = startfile_prefixes.plist;
-
- for (; pl; pl = pl->next)
- {
- const char *no_suffix_multilib_dir;
+ struct spec_path_info info;
- no_suffix_multilib_dir = pl->os_multilib ? multilib_os_dir
- : multilib_dir;
- /* Do not separate options, include non-multilibbed variant. */
- do_spec_path (pl, "-L",
+ info.option = "-L";
+ info.append_len = 0;
#ifdef RELATIVE_PREFIX_NOT_LINKDIR
- 1,
+ /* Used on systems which record the specified -L dirs
+ and use them to search for dynamic linking.
+ Relative directories always come from -B,
+ and it is better not to use them for searching
+ at run time. In particular, stage1 loses. */
+ info.omit_relative = true;
#else
- 0,
+ info.omit_relative = false;
#endif
- 0, 0, multilib_dir, no_suffix_multilib_dir);
- }
+ info.separate_options = false;
+
+ for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
}
break;
else
{
saved_suffix
- = xmalloc (suffix_length
+ = XNEWVEC (char, suffix_length
+ strlen (TARGET_OBJECT_SUFFIX));
strncpy (saved_suffix, suffix, suffix_length);
strcpy (saved_suffix + suffix_length,
case 'I':
{
- struct prefix_list *pl = include_prefixes.plist;
+ struct spec_path_info info;
+
+ if (multilib_dir)
+ {
+ do_spec_1 ("-imultilib", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (multilib_dir, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
if (gcc_exec_prefix)
{
do_spec_1 (" ", 0, NULL);
}
- for (; pl; pl = pl->next)
- /* Separate options, don't include non-suffixed variant. */
- do_spec_path (pl, "-isystem", 0, 1, 1, "include", "include");
+ info.option = "-isystem";
+ info.append = "include";
+ info.append_len = strlen (info.append);
+ info.omit_relative = false;
+ info.separate_options = true;
+
+ for_each_path (&include_prefixes, false, info.append_len,
+ spec_path, &info);
}
break;
static const struct spec_function *
lookup_spec_function (const char *name)
{
- static const struct spec_function * const spec_function_tables[] =
- {
- static_spec_functions,
- lang_specific_spec_functions,
- };
const struct spec_function *sf;
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
- {
- for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
- if (strcmp (sf->name, name) == 0)
- return sf;
- }
+ for (sf = static_spec_functions; sf->name != NULL; sf++)
+ if (strcmp (sf->name, name) == 0)
+ return sf;
return NULL;
}
&& input_suffix[end_atom - atom] == '\0');
}
-/* Inline subroutine of handle_braces. Returns true if a switch
+/* Subroutine of handle_braces. Returns true if a switch
matching the atom bracketed by ATOM and END_ATOM appeared on the
command line. */
-static inline bool
+static bool
switch_matches (const char *atom, const char *end_atom, int starred)
{
int i;
static const char *
find_file (const char *name)
{
- char *newname;
-
- /* Try multilib_dir if it is defined. */
- if (multilib_os_dir != NULL)
- {
- newname = find_a_file (&startfile_prefixes, name, R_OK, 1);
-
- /* If we don't find it in the multi library dir, then fall
- through and look for it in the normal places. */
- if (newname != NULL)
- return newname;
- }
-
- newname = find_a_file (&startfile_prefixes, name, R_OK, 0);
+ char *newname = find_a_file (&startfile_prefixes, name, R_OK, true);
return newname ? newname : name;
}
/* Determine whether a directory exists. If LINKER, return 0 for
- certain fixed names not needed by the linker. If not LINKER, it is
- only important to return 0 if the host machine has a small ARG_MAX
- limit. */
+ certain fixed names not needed by the linker. */
static int
-is_directory (const char *path1, const char *path2, int linker)
+is_directory (const char *path1, bool linker)
{
- int len1 = strlen (path1);
- int len2 = strlen (path2);
- char *path = alloca (3 + len1 + len2);
+ int len1;
+ char *path;
char *cp;
struct stat st;
-#ifndef SMALL_ARG_MAX
- if (! linker)
- return 1;
-#endif
-
- /* Construct the path from the two parts. Ensure the string ends with "/.".
- The resulting path will be a directory even if the given path is a
- symbolic link. */
+ /* 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);
memcpy (path, path1, len1);
- memcpy (path + len1, path2, len2);
- cp = path + len1 + len2;
+ cp = path + len1;
if (!IS_DIR_SEPARATOR (cp[-1]))
*cp++ = DIR_SEPARATOR;
*cp++ = '.';
/* Exclude directories that the linker is known to search. */
if (linker
+ && IS_DIR_SEPARATOR (path[0])
&& ((cp - path == 6
- && strcmp (path, concat (dir_separator_str, "lib",
- dir_separator_str, ".", NULL)) == 0)
+ && strncmp (path + 1, "lib", 3) == 0)
|| (cp - path == 10
- && strcmp (path, concat (dir_separator_str, "usr",
- dir_separator_str, "lib",
- dir_separator_str, ".", NULL)) == 0)))
+ && strncmp (path + 1, "usr", 3) == 0
+ && IS_DIR_SEPARATOR (path[4])
+ && strncmp (path + 5, "lib", 3) == 0)))
return 0;
return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
kill (getpid (), signum);
}
-extern int main (int, const char **);
+extern int main (int, char **);
int
-main (int argc, const char **argv)
+main (int argc, char **argv)
{
size_t i;
int value;
xmalloc_set_program_name (programname);
+ expandargv (&argc, &argv);
+
#ifdef GCC_DRIVER_HOST_INITIALIZATION
/* Perform host dependent initialization when needed. */
GCC_DRIVER_HOST_INITIALIZATION;
Make a table of specified input files (infiles, n_infiles).
Decode switches that are handled locally. */
- process_command (argc, argv);
+ process_command (argc, (const char **) argv);
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
spec_version, dir_separator_str, NULL);
just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
- specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0);
+ specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
/* Read the specs file unless it is a default one. */
if (specs_file != 0 && strcmp (specs_file, "specs"))
read_specs (specs_file, TRUE);
for (uptr = user_specs_head; uptr; uptr = uptr->next)
{
char *filename = find_a_file (&startfile_prefixes, uptr->filename,
- R_OK, 0);
+ R_OK, true);
read_specs (filename ? filename : uptr->filename, FALSE);
}
if (print_search_dirs)
{
printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
- printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
- printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
+ printf (_("programs: %s\n"),
+ build_search_list (&exec_prefixes, "", false, false));
+ printf (_("libraries: %s\n"),
+ build_search_list (&startfile_prefixes, "", false, true));
return (0);
}
i = n_infiles;
i += lang_specific_extra_outfiles;
- outfiles = xcalloc (i, sizeof (char *));
+ outfiles = XCNEWVEC (const char *, i);
/* Record which files were specified explicitly as link input. */
- explicit_link_files = xcalloc (1, n_infiles);
+ explicit_link_files = XCNEWVEC (char, n_infiles);
if (combine_flag)
combine_inputs = true;
else
- combine_inputs = false;
+ combine_inputs = false;
for (i = 0; (int) i < n_infiles; i++)
{
infiles[i].compiled = false;
infiles[i].preprocessed = false;
}
-
+
if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
fatal ("cannot specify -o with -c or -S with multiple files");
/* 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, 0);
+ char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
if (s == NULL)
linker_name_spec = "ld";
}
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
- putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH");
- putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV);
+ putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
+ putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
value = do_spec (link_command_spec);
if (value < 0)
static char *
save_string (const char *s, int len)
{
- char *result = xmalloc (len + 1);
+ char *result = XNEWVEC (char, len + 1);
memcpy (result, s, len);
result[len] = 0;
void
fancy_abort (const char *file, int line, const char *func)
{
- fatal ("internal gcc abort in %s, at %s:%d", func, file, line);
+ fatal_ice ("internal gcc abort in %s, at %s:%d", func, file, line);
}
\f
/* Output an error message and exit. */
+void
+fatal_ice (const char *cmsgid, ...)
+{
+ va_list ap;
+
+ va_start (ap, cmsgid);
+
+ fprintf (stderr, "%s: ", programname);
+ vfprintf (stderr, _(cmsgid), ap);
+ va_end (ap);
+ fprintf (stderr, "\n");
+ delete_temp_files ();
+ exit (pass_exit_codes ? ICE_EXIT_CODE : 1);
+}
+
void
fatal (const char *cmsgid, ...)
{
xmalloc from calling fatal, and prevents us from re-executing this
block of code. */
mswitches
- = xmalloc (sizeof (struct mswitchstr)
- * (n_mdswitches + (n_switches ? n_switches : 1)));
+ = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
for (i = 0; i < n_switches; i++)
if (switches[i].live_cond != SWITCH_IGNORE)
{
{
int i = 0;
- mdswitches = xmalloc (sizeof (struct mdswitchstr) * n_mdswitches);
+ mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
for (start = multilib_defaults; *start != '\0'; start = end + 1)
{
while (*start == ' ' || *start == '\t')
if (this_path_len != 1
|| this_path[0] != '.')
{
- char *new_multilib_dir = xmalloc (this_path_len + 1);
+ char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
char *q;
strncpy (new_multilib_dir, this_path, this_path_len);
q++;
if (q < end)
{
- char *new_multilib_os_dir = xmalloc (end - q);
+ 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;
break;
default:
- fatal ("unknown operator %qs in %%:version-compare", argv[0]);
+ fatal ("unknown operator '%s' in %%:version-compare", argv[0]);
}
if (! result)
return NULL;
return argv[nargs + 2];
}
+
+/* %:include builtin spec function. This differs from %include in that it
+ can be nested inside a spec, and thus be conditionalized. It takes
+ one argument, the filename, and looks for it in the startfile path.
+ The result is always NULL, i.e. an empty expansion. */
+
+static const char *
+include_spec_function (int argc, const char **argv)
+{
+ char *file;
+
+ if (argc != 1)
+ abort ();
+
+ file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
+ read_specs (file ? file : argv[0], FALSE);
+
+ return NULL;
+}