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]

strip out ".." from gcc search paths


How many times have you run a new version of gcc from its build dir,
only to find you've picked up the wrong assembler?  This sort of
problem is due to gcc search paths being like:

/usr/local/lib/gcc-lib/powerpc64-linux/3.1.1/../../../../powerpc64-linux/bin/

which is fine after gcc has been installed.  Prior to installation,
the 3.1.1 dir might not exist, leading to gcc not being able to find
the correct assembler etc.

This patch also fixes a bug in the UPDATE_PATH_HOST_CANONICALIZE
invocation.

	* prefix.c (update_path): Strip ".." components when prior dir
	doesn't exist.  Pass correct var to UPDATE_PATH_HOST_CANONICALIZE.

Index: gcc/prefix.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/prefix.c,v
retrieving revision 1.34
diff -u -p -r1.34 prefix.c
--- gcc/prefix.c	20 May 2002 18:06:54 -0000	1.34
+++ gcc/prefix.c	17 Jul 2002 02:27:14 -0000
@@ -251,7 +251,7 @@ update_path (path, key)
   const char *path;
   const char *key;
 {
-  char *result;
+  char *result, *p;
 
   if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0)
     {
@@ -271,9 +271,67 @@ update_path (path, key)
   else
     result = xstrdup (path);
 
+#ifndef ALWAYS_STRIP_DOTDOT
+#define ALWAYS_STRIP_DOTDOT 0
+#endif
+
+  p = result;
+  while (1)
+    {
+      char *src, *dest;
+
+      p = strchr (p, '.');
+      if (p == NULL)
+	break;
+      /* Get rid of a leading `./' and replace `/./' with `/'.  */
+      if (p[1] == '/' && (p == result || p[-1] == '/'))
+	{
+	  src = p + 2;
+	  /* Be careful about .//foo  */
+	  while (*src == '/')
+	    ++src;
+	  dest = p;
+	  while ((*dest++ = *src++) != 0)
+	    ;
+	}
+      /* Look for `/../'  */
+      else if (p[1] == '.' && p[2] == '/' && (p != result && p[-1] == '/'))
+	{
+	  *p = 0;
+	  if (!ALWAYS_STRIP_DOTDOT && access (result, X_OK) == 0)
+	    {
+	      *p = '.';
+	      p += 3;
+	    }
+	  else
+	    {
+	      /* We can't access the dir, so we won't be able to
+		 access dir/.. either.  Strip out dir/..  We know dir
+		 isn't `.' because we've rid ourselves of `.' path
+		 components above.  */
+	      dest = p - 1;
+	      while (dest != result && *dest == '/')
+		--dest;
+	      while (dest != result && dest[-1] != '/')
+		--dest;
+	      /* Don't strip leading `/'.  */
+	      while (*dest == '/')
+		++dest;
+	      src = p + 3;
+	      while (*src == '/')
+		++src;
+	      p = dest;
+	      while ((*dest++ = *src++) != 0)
+		;
+	    }
+	}
+      else
+	++p;
+    }
+
 #ifdef UPDATE_PATH_HOST_CANONICALIZE
   /* Perform host dependent canonicalization when needed.  */
-  UPDATE_PATH_HOST_CANONICALIZE (path);
+  UPDATE_PATH_HOST_CANONICALIZE (result);
 #endif
 
 #ifdef DIR_SEPARATOR_2

-- 
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]