* function.c (IS_ABSOLUTE, ROOT_LEN): New macros.
authorEli Zaretskii <eliz@gnu.org>
Sat, 4 Jul 2009 11:15:14 +0000 (11:15 +0000)
committerEli Zaretskii <eliz@gnu.org>
Sat, 4 Jul 2009 11:15:14 +0000 (11:15 +0000)
(abspath): Support systems that define HAVE_DOS_PATHS (have
drive letters in their file names).  Use IS_PATHSEP instead of a
literal '/' comparison.

ChangeLog
function.c

index bbc0d63..ebf241b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-07-04  Eli Zaretskii  <eliz@gnu.org>
+
+       * function.c (IS_ABSOLUTE, ROOT_LEN): New macros.
+       (abspath): Support systems that define HAVE_DOS_PATHS (have
+       drive letters in their file names).  Use IS_PATHSEP instead of a
+       literal '/' comparison.
+
 2009-06-14  Paul Smith  <psmith@gnu.org>
 
        * remake.c (update_file_1): Remember the original file we marked
index 8c4a45d..bb2f116 100644 (file)
@@ -1875,6 +1875,14 @@ func_not (char *o, char **argv, char *funcname)
 #endif
 \f
 
+#ifdef HAVE_DOS_PATHS
+#define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
+#define ROOT_LEN 3
+#else
+#define IS_ABSOLUTE(n) (n[0] == '/')
+#define ROOT_LEN 1
+#endif
+
 /* Return the absolute name of file NAME which does not contain any `.',
    `..' components nor any repeated path separators ('/').   */
 
@@ -1883,13 +1891,14 @@ abspath (const char *name, char *apath)
 {
   char *dest;
   const char *start, *end, *apath_limit;
+  unsigned long root_len = ROOT_LEN;
 
   if (name[0] == '\0' || apath == NULL)
     return NULL;
 
   apath_limit = apath + GET_PATH_MAX;
 
-  if (name[0] != '/')
+  if (!IS_ABSOLUTE(name))
     {
       /* It is unlikely we would make it until here but just to make sure. */
       if (!starting_directory)
@@ -1897,12 +1906,40 @@ abspath (const char *name, char *apath)
 
       strcpy (apath, starting_directory);
 
+#ifdef HAVE_DOS_PATHS
+      if (IS_PATHSEP(name[0]))
+       {
+         /* We have /foo, an absolute file name except for the drive
+            letter.  Assume the missing drive letter is the current
+            drive, which we can get if we remove from starting_directory
+            everything past the root directory.  */
+         apath[root_len] = '\0';
+       }
+#endif
+
       dest = strchr (apath, '\0');
     }
   else
     {
-      apath[0] = '/';
-      dest = apath + 1;
+      strncpy (apath, name, root_len);
+      apath[root_len] = '\0';
+      dest = apath + root_len;
+      /* Get past the root, since we already copied it.  */
+      name += root_len;
+#ifdef HAVE_DOS_PATHS
+      if (!IS_PATHSEP(apath[2]))
+       {
+         /* Convert d:foo into d:./foo and increase root_len.  */
+         apath[2] = '.';
+         apath[3] = '/';
+         dest++;
+         root_len++;
+         /* strncpy above copied one character too many.  */
+         name--;
+       }
+      else
+       apath[2] = '/'; /* make sure it's a forward slash */
+#endif
     }
 
   for (start = end = name; *start != '\0'; start = end)
@@ -1910,11 +1947,11 @@ abspath (const char *name, char *apath)
       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,12 +1963,12 @@ abspath (const char *name, char *apath)
       else if (len == 2 && start[0] == '.' && start[1] == '.')
        {
          /* Back up to previous component, ignore if at root already.  */
-         if (dest > apath + 1)
-           while ((--dest)[-1] != '/');
+         if (dest > apath + root_len)
+           for (--dest; !IS_PATHSEP(dest[-1]); --dest);
        }
       else
        {
-         if (dest[-1] != '/')
+         if (!IS_PATHSEP(dest[-1]))
             *dest++ = '/';
 
          if (dest + len >= apath_limit)
@@ -1944,7 +1981,7 @@ abspath (const char *name, char *apath)
     }
 
   /* Unless it is root strip trailing separator.  */
-  if (dest > apath + 1 && dest[-1] == '/')
+  if (dest > apath + root_len && IS_PATHSEP(dest[-1]))
     --dest;
 
   *dest = '\0';