make-w32
[Top][All Lists]
Advanced

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

Bug in builtin function abspath


From: Andreas Büning
Subject: Bug in builtin function abspath
Date: Fri, 26 May 2006 21:52:05 +0200

Hello!

make 3.81 has a new builtin function 'abspath' which doesn't support
drive letters. I mailed this to the bug-make mailing list but I got
redirected here by the maintainer:


---------------------------------------------
%% Andreas Büning <address@hidden> writes:

>  ab> In July 2005 I sent an email to this list because the new builtin
>  ab> function abspath does not support drive letters. I also sent a patch
>  ab> to fix this. The last information I got about this issue was the
>  ab> following email (24th of July, 2005) by Paul Smith stating that he
>  ab> wanted to find a different solution:

> You need to work with the folks on the address@hidden mailing list to
> resolve these issues and come up with a patch which is acceptable to
> those folks (and to me... which mainly means it doesn't impact the POSIX
> versions much or at all).
---------------------------------------------

I attached a patch which works for me. I'm using OS/2, not Windows, so
if any code is added to the w32 subdirectory it won't solve the problem
for me.

Btw, I haven't subscribed to this list, so please cc all answers to me.


Thank you!

Andreas Büning
--- old/make-3.81/function.c    Sat Apr  1 08:36:40 2006
+++ gnu/make-3.81/function.c    Fri May 26 20:38:16 2006
@@ -1875,6 +1875,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 ('/').   */
 
@@ -1884,12 +1900,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)
@@ -1901,8 +1921,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)
@@ -1910,11 +1957,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;
@@ -1926,13 +1973,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;
@@ -1948,6 +2010,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]