This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]