bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bug in builtin function abspath


From: Andreas Buening
Subject: Bug in builtin function abspath
Date: Sun, 24 Jul 2005 16:20:05 +0200

Hello!

The builtin function abspath does not consider drive letters.
Therefore, I think it will break not only on OS/2 but also on DOS
or Win* systems. And I suspect it won't work on VMS, too.

I've written a patch to handle drive letters. If anybody has a better
solution, please let me know.

Just for curiosity: I found this bug after I was told that a specific
Makefile worked with 3.81 beta 1 but not 3.81 beta 3. That Makefile
defines abspath as

abspath = $(if $(findstring :,$(1)),$(1),$(if $(filter 
/%,$(1)),$(1),$(PWD)/$(1)))

but this definition seems to be ignored by 3.81 beta 3?
(I don't understand what that line is exactly doing, though).


Andreas


--------------------------------------------
--- old/make-3.81beta3/function.c       Mon Jun 27 03:01:06 2005
+++ gnu/make-3.81beta3/function.c       Sun Jul 24 16:02:08 2005
@@ -1758,6 +1758,22 @@
 #endif
 
 
+
+/* Return 1 if NAME is a relative file name and contains no drive letter */
+static int
+is_relpath (const char *name)
+{
+#if HAVE_DOS_PATHS
+  if (isalpha((unsigned char) name[0]) && name[1] == ':') {
+    /* it's a drive letter */
+    return 0;
+  }
+#endif
+
+  return !IS_PATHSEP(name[0]);
+}
+
+
 /* Return the absolute name of file NAME which does not contain any `.',
    `..' components nor any repeated path separators ('/').   */
 
@@ -1767,12 +1783,16 @@
   char *dest;
   const char *start, *end, *apath_limit;
 
+#if HAVE_DOS_PATHS
+  char *apath_orig = apath;
+#endif
+
   if (name[0] == '\0' || apath == NULL)
     return NULL;
 
   apath_limit = apath + GET_PATH_MAX;
 
-  if (name[0] != '/')
+  if (is_relpath(name))
     {
       /* It is unlikely we would make it until here but just to make sure. */
       if (!starting_directory)
@@ -1784,8 +1804,35 @@
     }
   else
     {
+#if HAVE_DOS_PATHS
+      if (name[1] == ':')
+       { /* it's a drive letter */
+         apath[0] = name[0];
+         apath[1] = ':';
+         /* "hide" the drive letter so that we don't have to care about it 
below */
+         apath += 2;
+         name += 2; /* also "remove" the drive letter from name */
+       }
+
+      dest = apath;
+
+      /* We have to consider also names like "c:foo/bar". Unfortunately, this 
is
+         not a "real" absolute filename and it's not simple to find out its 
absolute
+        equivalent. For now we keep it as is.
+        note: apath[0] != '/' in this case! */
+      if (IS_PATHSEP(name[0]))
+       {
+         apath[0] = '/';
+         dest++;
+       }
+      else
+       {
+
+       }
+#else
       apath[0] = '/';
       dest = apath + 1;
+#endif
     }
 
   for (start = end = name; *start != '\0'; start = end)
@@ -1793,11 +1840,11 @@
       unsigned long len;
 
       /* Skip sequence of multiple path-separators.  */
-      while (*start == '/')
+      while (IS_PATHSEP(*start))
        ++start;
 
       /* Find end of path component.  */
-      for (end = start; *end != '\0' && *end != '/'; ++end)
+      for (end = start; *end != '\0' && !IS_PATHSEP(*end); ++end)
         ;
 
       len = end - start;
@@ -1809,13 +1856,28 @@
       else if (len == 2 && start[0] == '.' && start[1] == '.')
        {
          /* Back up to previous component, ignore if at root already.  */
+#if HAVE_DOS_PATHS
+         /* note that apath[0] != '/' in some very special case */
+         while(dest > apath + 1 && (--dest)[-1] != '/');
+
+         if (dest == apath + 1 && apath[0] != '/')
+           {
+             /* We can not (yet) handle this case, any volunteers to implement 
a solution? ;-) */
+             return NULL;
+           }
+
+#else
          if (dest > apath + 1)
            while ((--dest)[-1] != '/');
+#endif
        }
       else
        {
-         if (dest[-1] != '/')
-            *dest++ = '/';
+#if HAVE_DOS_PATHS
+         if (dest != apath)
+#endif
+           if (dest[-1] != '/')
+             *dest++ = '/';
 
          if (dest + len >= apath_limit)
             return NULL;
@@ -1831,6 +1893,10 @@
     --dest;
 
   *dest = '\0';
+
+#if HAVE_DOS_PATHS
+  apath = apath_orig;
+#endif
 
   return apath;
 }
--------------------------------------------




reply via email to

[Prev in Thread] Current Thread [Next in Thread]