This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Fix PR20425, multilib paths for -print-search-dirs
This gives the gcc driver a new path iteration function, for_each_path,
and uses it everywhere, making path iteration a little more consistent.
for_each_path uses the same path ordering as the existing find_file
function. I've also tweaked some of the existing find_a_file calls for
consistency, and uncovered and fixed some other bugs..
Functional changes are:
o %D library paths are printed in the same order as gcc uses elsewhere
when searching library directories, ie. all multilib paths are first.
http://gcc.gnu.org/ml/gcc-patches/2005-03/msg02044.html effectively
reverted by the rewrite because I believe the same speedup is gained
by searching the right dirs first.
o gcc -print-search-dirs prints library multilib paths followed by
non-multilib paths where before we just printed non-multilib paths.
o LIBRARY_PATH_ENV similarly includes multilib directories.
o All searches of startfile_prefixes now look in multilib dirs first
followed by non-multilib dirs. This changes the dirs we search for
spec files, and %include and %include_noerr in specs. Previously
we only searched the non-multilib dirs for specs files. I think this
change is worthwhile just for consistency, and the extension is
reasonable. For instance, it would allow different spec files to be
used for gcc -m64 vs. gcc -m32. However, if others think this wrong,
I won't argue. Consistency isn't everything.
o Some attempt made to prevent searching of duplicate paths. The old
find_file would search some paths twice (when multilib_dir was NULL
but multilib_os_dir non-NULL). We still search twice in some cases,
eg. /usr/lib/../lib and /usr/lib are considered different paths.
o find_a_file with last param (do_multi) true now searches both
multilib and non-multilib paths. Before, do_multi (well, the old
param name was multilib) meant just search multilib paths. This
isn't a user-visible change as the only place where find_a_file was
invoked with the last param true was from find_file, where we
immediately followed with a non-multilib find_a_file.
o Memory leaks fixed in is_directory.
o LIBRARY_PATH_ENV and COMPILER_PATH now only have existing
directories, making LIBRARY_PATH_ENV closer to %D paths. The
following lines (which I remove) in is_directory meant that
is_directory didn't do much for LIBRARY_PATH_ENV, except on
SMALL_ARG_MAX machines.
4278 ian #ifndef SMALL_ARG_MAX
4278 ian if (! linker)
4278 ian return 1;
4278 ian #endif
I'll also remove mention of SMALL_ARG_MAX in config and doc files
when I commit this change as this is the only place it is used.
o gcc -Bnon-dir-prefix- now works properly. The previously mentioned
is_directory peculiarity affected the following code.
43664 nickc /* Catch the case where the user has forgotten to append a
46063 jsm28 directory separator to the path. Note, they may be using
43664 nickc -B to add an executable name prefix, eg "i386-elf-", in
43664 nickc order to distinguish between multiple installations of
43664 nickc GCC in the same directory. Hence we must check to see
43664 nickc if appending a directory separator actually makes a
43664 nickc valid directory name. */
43664 nickc if (! IS_DIR_SEPARATOR (value [len - 1])
43664 nickc && is_directory (value, "", 0))
43664 nickc {
43767 ghazi char *tmp = xmalloc (len + 2);
43767 ghazi strcpy (tmp, value);
43767 ghazi tmp[len] = DIR_SEPARATOR;
43767 ghazi tmp[++ len] = 0;
43767 ghazi value = tmp;
43664 nickc }
Bootstrapped and regression tested powerpc64-linux and powerpc-linux on
a previous iteration of this patch missing is_directory fixes.
Currently running tests on this patch.
* gcc.c (for_each_path): New function.
(add_to_obstack, file_at_path): New functions.
(struct file_at_path_info, struct add_to_obstack_info): New.
(build_search_list): Rewrite using for_each_path. Constify struct
path_prefix pointer. Add do_multi param. Adjust all callers.
(find_a_file): Similarly, but just change existing param to bool.
(putenv_from_prefixes): Add do_multi param, make "paths" const.
(do_spec_path): Delete.
(struct spec_path_info): New.
(spec_path): New function.
(do_spec_1): Use for_each_path for %D and %I.
(find_file): Adjust for find_a_file changes.
(main): Search multilibs for specs. Print multilib lib path for
-print-search-dirs. Likewise add multilibs to LIBRARY_PATH_ENV.
(read_specs): Search multilibs for %include and %include_noerr.
(is_directory): Remove second string param. Change last param
to a bool. Don't use concat. Remove SMALL_ARG_MAX test, always
check path is a dir. Update all callers.
Index: gcc/gcc.c
===================================================================
*** gcc/gcc.c (revision 108381)
--- gcc/gcc.c (working copy)
*************** static char *load_specs (const char *);
*** 287,296 ****
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 int access_check (const char *, int);
! static char *find_a_file (struct path_prefix *, const char *, int, int);
static void add_prefix (struct path_prefix *, const char *, const char *,
int, int, int);
static void add_sysrooted_prefix (struct path_prefix *, const char *,
--- 287,298 ----
static void read_specs (const char *, int);
static void set_spec (const char *, const char *);
static struct compiler *lookup_compiler (const char *, size_t, const char *);
! static char *build_search_list (const struct path_prefix *, const char *,
! bool, bool);
! static void putenv_from_prefixes (const struct path_prefix *, const char *,
! bool);
static int access_check (const char *, 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 *eval_spec_function (c
*** 313,325 ****
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 const char *validate_switches (const char *);
static void validate_all_switches (void);
static inline void validate_switches_from_spec (const char *);
--- 315,326 ----
static const char *handle_spec_function (const char *);
static char *save_string (const char *, int);
static void set_collect_gcc_options (void);
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 *, bool);
static const char *validate_switches (const char *);
static void validate_all_switches (void);
static inline void validate_switches_from_spec (const char *);
*************** read_specs (const char *filename, int ma
*** 2041,2047 ****
(long) (p1 - buffer + 1));
p[-2] = '\0';
! new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
read_specs (new_filename ? new_filename : p1, FALSE);
continue;
}
--- 2042,2048 ----
(long) (p1 - buffer + 1));
p[-2] = '\0';
! new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
read_specs (new_filename ? new_filename : p1, FALSE);
continue;
}
*************** read_specs (const char *filename, int ma
*** 2060,2066 ****
(long) (p1 - buffer + 1));
p[-2] = '\0';
! new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
if (new_filename)
read_specs (new_filename, FALSE);
else if (verbose_flag)
--- 2061,2067 ----
(long) (p1 - buffer + 1));
p[-2] = '\0';
! new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
if (new_filename)
read_specs (new_filename, FALSE);
else if (verbose_flag)
*************** clear_failure_queue (void)
*** 2357,2421 ****
failure_delete_queue = 0;
}
! /* 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)
{
! 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)
{
! int len = strlen (pprefix->prefix);
! if (machine_suffix
! && (! check_dir_p
! || is_directory (pprefix->prefix, machine_suffix, 0)))
{
! 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);
! }
! if (just_machine_suffix
! && pprefix->require_machine_suffix == 2
! && (! check_dir_p
! || is_directory (pprefix->prefix, just_machine_suffix, 0)))
! {
! if (! first_time)
! obstack_1grow (&collect_obstack, PATH_SEPARATOR);
! first_time = FALSE;
! obstack_grow (&collect_obstack, pprefix->prefix, len);
! obstack_grow (&collect_obstack, just_machine_suffix,
! just_suffix_len);
}
! if (! pprefix->require_machine_suffix)
! {
! if (! first_time)
! obstack_1grow (&collect_obstack, PATH_SEPARATOR);
! first_time = FALSE;
! obstack_grow (&collect_obstack, pprefix->prefix, len);
}
}
obstack_1grow (&collect_obstack, '\0');
return XOBFINISH (&collect_obstack, char *);
}
--- 2358,2571 ----
failure_delete_queue = 0;
}
! /* 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)
{
! 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)
! {
! 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);
! 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)
! {
! len = paths->max_len + extra_space + 1;
! if (suffix_len > multi_os_dir_len)
! len += suffix_len;
! else
! len += multi_os_dir_len;
! path = xmalloc (len);
! }
! for (pl = paths->plist; pl != 0; pl = pl->next)
{
! 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';
!
! ret = callback (path, callback_info);
! if (ret)
! break;
! }
}
+ if (pl)
+ break;
! if (multi_dir == NULL && multi_os_dir == NULL)
! break;
! /* 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 *);
}
*************** build_search_list (struct path_prefix *p
*** 2424,2432 ****
for collect. */
static void
! putenv_from_prefixes (struct path_prefix *paths, const char *env_var)
{
! putenv (build_search_list (paths, env_var, 1));
}
/* Check whether NAME can be accessed in MODE. This is like access,
--- 2574,2583 ----
for collect. */
static void
! putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
! bool do_multi)
{
! putenv (build_search_list (paths, env_var, true, do_multi));
}
/* Check whether NAME can be accessed in MODE. This is like access,
*************** access_check (const char *name, int mode
*** 2447,2466 ****
return access (name, mode);
}
/* Search for NAME using the prefix list PREFIXES. MODE is passed to
! access to check permissions.
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)
{
! 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;
#ifdef DEFAULT_ASSEMBLER
if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
--- 2598,2650 ----
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. 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 (const struct path_prefix *pprefix, const char *name, int mode,
! bool do_multi)
{
! struct file_at_path_info info;
#ifdef DEFAULT_ASSEMBLER
if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
*************** find_a_file (struct path_prefix *pprefix
*** 2472,2583 ****
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;
! 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;
! }
! strcpy (temp, pl->prefix);
! strcat (temp, this_name);
! if (access_check (temp, mode) == 0)
! return temp;
! }
! }
! free (temp);
! return 0;
}
/* Ranking of prefixes in the sort list. -B prefixes are put before
--- 2656,2679 ----
return xstrdup (DEFAULT_LINKER);
#endif
/* Determine the filename to execute (special case for absolute paths). */
if (IS_ABSOLUTE_PATH (name))
{
if (access (name, mode) == 0)
! return xstrdup (name);
! return NULL;
! }
! 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;
! 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
*************** execute (void)
*** 2696,2702 ****
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
! string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0);
if (string)
commands[0].argv[0] = string;
--- 2792,2798 ----
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
! string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
if (string)
commands[0].argv[0] = string;
*************** execute (void)
*** 2711,2717 ****
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);
if (string)
commands[n_commands].argv[0] = string;
n_commands++;
--- 2807,2813 ----
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, false);
if (string)
commands[n_commands].argv[0] = string;
n_commands++;
*************** warranty; not even for MERCHANTABILITY o
*** 3649,3655 ****
if appending a directory separator actually makes a
valid directory name. */
if (! IS_DIR_SEPARATOR (value [len - 1])
! && is_directory (value, "", 0))
{
char *tmp = xmalloc (len + 2);
strcpy (tmp, value);
--- 3745,3751 ----
if appending a directory separator actually makes a
valid directory name. */
if (! IS_DIR_SEPARATOR (value [len - 1])
! && is_directory (value, false))
{
char *tmp = xmalloc (len + 2);
strcpy (tmp, value);
*************** do_self_spec (const char *spec)
*** 4397,4504 ****
}
}
! 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)
! {
! 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;
! /* 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 (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);
! }
}
! if (only_subdir || multilib_p)
! return;
! 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)
! {
! 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);
! }
}
}
/* Process the sub-spec SPEC as a portion of a larger spec.
--- 4493,4547 ----
}
}
! /* 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)
! {
! struct spec_path_info *info = data;
! size_t len = 0;
! char save = 0;
!
! if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
! return NULL;
!
! if (info->append_len != 0)
{
! len = strlen (path);
! memcpy (path + len, info->append, info->append_len + 1);
}
! if (!is_directory (path, true))
! return NULL;
!
! do_spec_1 (info->option, 1, NULL);
! if (info->separate_options)
! do_spec_1 (" ", 0, NULL);
! if (info->append_len == 0)
{
! 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.
*************** do_spec_1 (const char *spec, int inswitc
*** 4636,4658 ****
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;
! 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",
#ifdef RELATIVE_PREFIX_NOT_LINKDIR
! 1,
#else
! 0,
#endif
! 0, 0, multilib_dir, no_suffix_multilib_dir);
! }
}
break;
--- 4679,4701 ----
that we search for startfiles. */
case 'D':
{
! struct spec_path_info info;
! info.option = "-L";
! info.append_len = 0;
#ifdef RELATIVE_PREFIX_NOT_LINKDIR
! /* 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
! info.omit_relative = false;
#endif
! info.separate_options = false;
!
! for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
}
break;
*************** do_spec_1 (const char *spec, int inswitc
*** 4889,4895 ****
case 'I':
{
! struct prefix_list *pl = include_prefixes.plist;
if (gcc_exec_prefix)
{
--- 4932,4938 ----
case 'I':
{
! struct spec_path_info info;
if (gcc_exec_prefix)
{
*************** do_spec_1 (const char *spec, int inswitc
*** 4912,4920 ****
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");
}
break;
--- 4955,4968 ----
do_spec_1 (" ", 0, NULL);
}
! 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;
*************** give_switch (int switchnum, int omit_fir
*** 5900,5947 ****
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);
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. */
static int
! is_directory (const char *path1, const char *path2, int linker)
{
! int len1 = strlen (path1);
! int len2 = strlen (path2);
! char *path = alloca (3 + len1 + len2);
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. */
memcpy (path, path1, len1);
! memcpy (path + len1, path2, len2);
! cp = path + len1 + len2;
if (!IS_DIR_SEPARATOR (cp[-1]))
*cp++ = DIR_SEPARATOR;
*cp++ = '.';
--- 5948,5974 ----
static const char *
find_file (const char *name)
{
! 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. */
static int
! is_directory (const char *path1, bool linker)
{
! int len1;
! char *path;
char *cp;
struct stat st;
! /* 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);
! cp = path + len1;
if (!IS_DIR_SEPARATOR (cp[-1]))
*cp++ = DIR_SEPARATOR;
*cp++ = '.';
*************** is_directory (const char *path1, const c
*** 5949,5961 ****
/* Exclude directories that the linker is known to search. */
if (linker
&& ((cp - path == 6
! && strcmp (path, concat (dir_separator_str, "lib",
! dir_separator_str, ".", NULL)) == 0)
|| (cp - path == 10
! && strcmp (path, concat (dir_separator_str, "usr",
! dir_separator_str, "lib",
! dir_separator_str, ".", NULL)) == 0)))
return 0;
return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
--- 5976,5988 ----
/* Exclude directories that the linker is known to search. */
if (linker
+ && IS_DIR_SEPARATOR (path[0])
&& ((cp - path == 6
! && strncmp (path + 1, "lib", 3) == 0)
|| (cp - path == 10
! && 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));
*************** main (int argc, char **argv)
*** 6147,6153 ****
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);
/* Read the specs file unless it is a default one. */
if (specs_file != 0 && strcmp (specs_file, "specs"))
read_specs (specs_file, TRUE);
--- 6174,6180 ----
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, true);
/* Read the specs file unless it is a default one. */
if (specs_file != 0 && strcmp (specs_file, "specs"))
read_specs (specs_file, TRUE);
*************** main (int argc, char **argv)
*** 6283,6289 ****
for (uptr = user_specs_head; uptr; uptr = uptr->next)
{
char *filename = find_a_file (&startfile_prefixes, uptr->filename,
! R_OK, 0);
read_specs (filename ? filename : uptr->filename, FALSE);
}
--- 6310,6316 ----
for (uptr = user_specs_head; uptr; uptr = uptr->next)
{
char *filename = find_a_file (&startfile_prefixes, uptr->filename,
! R_OK, true);
read_specs (filename ? filename : uptr->filename, FALSE);
}
*************** main (int argc, char **argv)
*** 6312,6319 ****
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));
return (0);
}
--- 6339,6348 ----
if (print_search_dirs)
{
printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
! printf (_("programs: %s\n"),
! build_search_list (&exec_prefixes, "", false, false));
! printf (_("libraries: %s\n"),
! build_search_list (&startfile_prefixes, "", false, true));
return (0);
}
*************** main (int argc, char **argv)
*** 6630,6643 ****
/* 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);
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);
value = do_spec (link_command_spec);
if (value < 0)
--- 6659,6672 ----
/* 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";
}
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
! 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)
--
Alan Modra
IBM OzLabs - Linux Technology Centre