> Date: Fri, 24 Nov 2006 00:44:42 +0800
> From: goodmen <[EMAIL PROTECTED]>
> 
> I'm using gnu make version 3.81. I compile the soucre using msvc7.
> Please run this script on ms windows of any version.
> ===============================================================================
> __this_file := $(lastword $(MAKEFILE_LIST))
> __this_file := $(abspath $(__this_file))
> __sub_dir_path := $(realpath $(dir $(__this_file))/sub_dir)
> 
> $(warning $(__this_file))
> $(warning $(__sub_dir_path))
> 
> all :
> @ echo Please run this gnumake script on M$-windows
> ===============================================================================
> 
> the realpath do not work as the doc described.
> I'm tried to fix this bug, but I trust the skills of the authors than mine.
> Here is some info:
> in the file function.c , abspath() ,line 1892 says : "if (name[0] != '/')"
> but on windows system, this condition is not an indicator of whether a
> string is absolute path.

Thank you for your report.

As of Make 3.81, the functions abspath and realpath are not yet
supported on MS-Windows.  They currently only work on Posix platforms.

I hope to have that fixed in the next release.

In fact, I have a preliminary patch to fix that, so if you need this
ASAP, and can rebuild Make from sources on your machine, please try
the patch below and tell me if it works for you.


2006-05-27  Eli Zaretskii  <[EMAIL PROTECTED]>

        * 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.  Use IS_ABSOLUTE and ROOT_LEN.


--- function.c~1        2006-05-27 15:58:26.984375000 +0300
+++ function.c  2006-05-27 17:37:47.453125000 +0300
@@ -1890,6 +1890,14 @@ func_not (char *o, char **argv, char *fu
 #endif
 
 
+#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 ('/').   */
 
@@ -1898,13 +1906,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)
@@ -1912,12 +1921,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)
@@ -1925,11 +1962,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;
@@ -1941,12 +1978,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)
@@ -1959,7 +1996,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';


_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-make

Reply via email to