Index: patches/gcc-4.1.2-PR20425-1.patch
===================================================================
--- patches/gcc-4.1.2-PR20425-1.patch	(revision 277483d94db74a4a1dfd8a82ffc6232b5ce6c975)
+++ patches/gcc-4.1.2-PR20425-1.patch	(revision 277483d94db74a4a1dfd8a82ffc6232b5ce6c975)
@@ -0,0 +1,1069 @@
+Submitted By: Ryan Oliver <ryan at pha dot com dot au>
+Date: 2006-03-10
+Initial Package Version: 4.1.0
+Origin: GCC SVN Revision 108635 (diffed against 4.1.0 release)
+Upstream Status: In GCC trunk
+Description: Fix for PR20425
+
+Modified by Jim Gifford for 4.1.1
+
+From http://gcc.gnu.org/ml/gcc-patches/2005-12/msg00818.html
+---------------------------------8<------------------------------------
+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.
+---------------------------------8<------------------------------------
+
+diff -uNr gcc-4.1.0/gcc/config.build gcc-4.1.0-PR20425/gcc/config.build
+--- gcc-4.1.0/gcc/config.build	2005-06-25 12:02:01.000000000 +1000
++++ gcc-4.1.0-PR20425/gcc/config.build	2006-03-10 23:47:02.000000000 +1100
+@@ -90,15 +90,10 @@
+     build_install_headers_dir=install-headers-cpio
+     ;;
+   i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4* )
+-    build_xm_defines="SMALL_ARG_MAX"
+     build_install_headers_dir=install-headers-cpio
+     ;;
+-  i[34567]86-*-solaris2*)
+-    build_xm_defines="SMALL_ARG_MAX"
+-    ;;
+   i[34567]86-*-sysv4*) 
+     # Intel x86 running system V r4
+-    build_xm_defines="SMALL_ARG_MAX"
+     build_install_headers_dir=install-headers-cpio
+     ;;
+   i[34567]86-*-udk*) 
+diff -uNr gcc-4.1.0/gcc/config.gcc gcc-4.1.0-PR20425/gcc/config.gcc
+--- gcc-4.1.0/gcc/config.gcc	2006-02-07 03:07:46.000000000 +1100
++++ gcc-4.1.0-PR20425/gcc/config.gcc	2006-03-10 23:47:20.000000000 +1100
+@@ -994,7 +994,6 @@
+ 	then
+ 		tm_file="${tm_file} usegas.h"
+ 	fi
+-	xm_defines="SMALL_ARG_MAX"
+ 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ptx4.h i386/ptx4-i.h"
+ 	tmake_file=t-svr4
+ 	extra_parts="crtbegin.o crtend.o"
+@@ -1125,7 +1124,6 @@
+ 	use_fixproto=yes
+ 	;;
+ i[34567]86-*-solaris2*)
+-	xm_defines="SMALL_ARG_MAX"
+ 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h sol2.h"
+ 	case ${target} in
+ 	*-*-solaris2.[0-6] | *-*-solaris2.[0-6].*)
+@@ -1192,7 +1190,6 @@
+ 	use_fixproto=yes
+        ;;
+ i[34567]86-*-sysv4*)		# Intel 80386's running system V.4
+-	xm_defines="SMALL_ARG_MAX"
+ 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv4-cpp.h"
+ 	if test x$stabs = xyes
+ 	then
+diff -uNr gcc-4.1.0/gcc/config.host gcc-4.1.0-PR20425/gcc/config.host
+--- gcc-4.1.0/gcc/config.host	2006-02-06 03:18:20.000000000 +1100
++++ gcc-4.1.0-PR20425/gcc/config.host	2006-03-10 23:47:52.000000000 +1100
+@@ -135,17 +135,10 @@
+   i370-*-opened* | i370-*-mvs* ) # IBM 360/370/390 Architecture
+     host_xm_defines='FATAL_EXIT_CODE=12'
+     ;;
+-  i[34567]86-sequent-ptx4*)
+-    host_xm_defines="SMALL_ARG_MAX"
+-    ;;
+   i[34567]86-*-solaris2*)
+-    host_xm_defines="SMALL_ARG_MAX"
+     out_host_hook_obj=host-solaris.o
+     host_xmake_file=x-solaris
+     ;;
+-  i[34567]86-*-sysv4*) # Intel 80386's running System V Release 4
+-    host_xm_defines="SMALL_ARG_MAX"
+-    ;;
+   i[34567]86-pc-msdosdjgpp*)
+     host_xm_file=i386/xm-djgpp.h
+     host_exeext=.exe
+diff -uNr gcc-4.1.0/gcc/doc/hostconfig.texi gcc-4.1.0-PR20425/gcc/doc/hostconfig.texi
+--- gcc-4.1.0/gcc/doc/hostconfig.texi	2004-11-24 15:31:58.000000000 +1100
++++ gcc-4.1.0-PR20425/gcc/doc/hostconfig.texi	2006-03-10 23:48:20.000000000 +1100
+@@ -208,11 +208,6 @@
+ If defined, a C statement (sans semicolon) that performs host-dependent
+ initialization when a compilation driver is being initialized.
+ 
+-@item SMALL_ARG_MAX
+-Define this macro if the host system has a small limit on the total
+-size of an argument vector.  This causes the driver to take more care
+-not to pass unnecessary arguments to subprocesses.
+-
+ @item HOST_LONG_LONG_FORMAT
+ If defined, the string used to indicate an argument of type @code{long
+ long} to functions like @code{printf}.  The default value is
+diff -uNr gcc-4.1.0/gcc/gcc.c gcc-4.1.0-PR20425/gcc/gcc.c
+--- gcc-4.1.0/gcc/gcc.c	2006-01-22 05:29:08.000000000 +1100
++++ gcc-4.1.0-PR20425/gcc/gcc.c	2006-03-10 22:14:35.000000000 +1100
+@@ -287,10 +287,12 @@
+ 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 *,
+@@ -313,13 +315,12 @@
+ 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 *);
+@@ -2036,7 +2037,7 @@
+ 		       (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;
+ 	    }
+@@ -2055,7 +2056,7 @@
+ 		       (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)
+@@ -2352,65 +2353,214 @@
+   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)
++/* 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, '=');
++  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);
+ 
+-  for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
++  while (1)
+     {
+-      int len = strlen (pprefix->prefix);
++      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);
++	}
+ 
+-      if (machine_suffix
+-	  && (! check_dir_p
+-	      || is_directory (pprefix->prefix, 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);
+ 
+-	  first_time = FALSE;
+-	  obstack_grow (&collect_obstack, pprefix->prefix, len);
+-	  obstack_grow (&collect_obstack, machine_suffix, suffix_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;
++	    }
+ 
+-      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);
++	  /* 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;
++		}
+ 
+-	  first_time = FALSE;
+-	  obstack_grow (&collect_obstack, pprefix->prefix, len);
+-	  obstack_grow (&collect_obstack, just_machine_suffix,
+-			just_suffix_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 (! 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 *);
+ }
+@@ -2419,9 +2569,10 @@
+    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));
+ }
+ 
+
+ /* Check whether NAME can be accessed in MODE.  This is like access,
+@@ -2442,20 +2593,53 @@
+   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)
+@@ -2467,112 +2651,24 @@
+     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
+@@ -2691,7 +2787,7 @@
+ 
+   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;
+@@ -2706,7 +2802,7 @@
+ 	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++;
+@@ -3643,7 +3739,7 @@
+ 		   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);
+ 		    strcpy (tmp, value);
+@@ -4391,108 +4487,55 @@
+     }
+ }
+ 
+-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;
++/* Callback for processing %D and %I specs.  */
+ 
+-  /* 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)
++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)
+     {
+-      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;
++
++  do_spec_1 (info->option, 1, NULL);
++  if (info->separate_options)
++    do_spec_1 (" ", 0, NULL);
+ 
+-  if (machine_suffix)
++  if (info->append_len == 0)
+     {
+-      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);
+-	}
++      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.
+@@ -4630,23 +4673,23 @@
+ 	     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;
+ 
+@@ -4883,7 +4926,7 @@
+ 
+ 	  case 'I':
+ 	    {
+-	      struct prefix_list *pl = include_prefixes.plist;
++	      struct spec_path_info info;
+ 
+ 	      if (gcc_exec_prefix)
+ 		{
+@@ -4906,9 +4949,14 @@
+ 		  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;
+ 
+@@ -5894,48 +5942,27 @@
+ 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++ = '.';
+@@ -5943,13 +5970,13 @@
+ 
+   /* 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));
+@@ -6139,7 +6166,7 @@
+ 			   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);
+@@ -6275,7 +6302,7 @@
+   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);
+     }
+ 
+@@ -6304,8 +6331,10 @@
+   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);
+     }
+ 
+@@ -6622,14 +6651,14 @@
+       /* 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)
+diff -uNr gcc-4.1.0/gcc/system.h gcc-4.1.0-PR20425/gcc/system.h
+--- gcc-4.1.0/gcc/system.h	2005-08-16 10:13:53.000000000 +1000
++++ gcc-4.1.0-PR20425/gcc/system.h	2006-03-10 23:51:31.000000000 +1100
+@@ -728,7 +728,8 @@
+         TARGET_ESC TARGET_FF TARGET_NEWLINE TARGET_TAB TARGET_VT	   \
+         LINK_LIBGCC_SPECIAL DONT_ACCESS_GBLS_AFTER_EPILOGUE		   \
+ 	TARGET_OPTIONS TARGET_SWITCHES EXTRA_CC_MODES FINALIZE_PIC	   \
+-	PREDICATE_CODES SPECIAL_MODE_PREDICATES HOST_PTR_PRINTF
++	PREDICATE_CODES SPECIAL_MODE_PREDICATES HOST_PTR_PRINTF		   \
++	SMALL_ARG_MAX
+ 
+ /* Hooks that are no longer used.  */
+  #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE	\
