[Top][All Lists]
[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;
}
--------------------------------------------
- Bug in builtin function abspath,
Andreas Buening <=