Re: File path bug on windows platform

2006-11-25 Thread Eli Zaretskii
 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~12006-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  

File path bug on windows platform

2006-11-24 Thread goodmen
Hi,

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. In the body of the if-block, at line1898, the
starting_directory is copied to the result buffer, and I think it is not
right on windows system.

I can't fount any other version of abspath(), do you think it is
necessary to provide a windows version of that function?

By the way, I'm writting some cross-platform codes. I don't want to use
Cygwin because
it is too larger than my usb-disc. Could you give me some advices?
Writting the windows shell script is a painfull work .



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