guile-devel
[Top][All Lists]
Advanced

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

Re: Windows file name separators


From: Eli Zaretskii
Subject: Re: Windows file name separators
Date: Wed, 02 Jul 2014 19:04:50 +0300

> From: address@hidden (Ludovic Courtès)
> Cc: address@hidden
> Date: Tue, 01 Jul 2014 17:38:04 +0200
> 
> Eli Zaretskii <address@hidden> skribis:
> 
> >> From: address@hidden (Ludovic Courtès)
> >> Cc: address@hidden
> >> Date: Tue, 01 Jul 2014 11:36:32 +0200
> >> 
> >> Eli Zaretskii <address@hidden> skribis:
> >> 
> >> > In Emacs, some of the file and directory names recorded during the
> >> > build and startup come from argv[0] and from prefix-relative directory
> >> > names computed by configure.  Is there something similar in Guile, and
> >> > if so, where do I find that?
> >> 
> >> The default %load-path uses absolute directory names based on what
> >> ./configure computed.
> >
> > Thanks.  Where do I find the code which does that?  I'd like to review
> > it with the issue at hand in mind.
> 
> You can look at load.c, and in particular scm_init_load_path.

OK, thanks for the pointer.

I've reviewed the related code, and below is what I suggest to push.
(This supersedes what I sent in
http://lists.gnu.org/archive/html/guile-devel/2014-06/msg00066.html.)

--- libguile/load.c~0   2014-02-28 23:01:27 +0200
+++ libguile/load.c     2014-07-02 19:00:50 +0300
@@ -277,6 +277,37 @@ SCM_DEFINE (scm_parse_path_with_ellipsis
 }
 #undef FUNC_NAME
 
+static char *
+getenv_path (const char *name)
+{
+  char *val = getenv (name);
+
+#ifdef __MINGW32__
+  if (val)
+    {
+      char *p = val;
+
+      /* Replace backslashes with forward slashes, so that Scheme code
+        always gets d:/foo/bar style file names.  This avoids
+        multiple subtle problems with comparing file names as strings
+        and with redirections in /bin/sh command lines.  Note that
+        this destructively modifies the environment variables, so
+        both scm_getenv and subprocesses will see the values with
+        forward slashes.  But that is OK, since these variables are
+        Guile-specific, and having scm_getenv return the same value
+        as used by the callers of getenv_path is good for
+        consistency and file-name comparison.  */
+      while (*p)
+       {
+         if (*p == '\\')
+           *p = '/';
+         p++;
+       }
+    }
+#endif
+
+  return val;
+}
 
 /* Initialize the global variable %load-path, given the value of the
    SCM_SITE_DIR and SCM_LIBRARY_DIR preprocessor symbols and the
@@ -289,7 +320,7 @@ scm_init_load_path ()
   SCM cpath = SCM_EOL;
 
 #ifdef SCM_LIBRARY_DIR
-  env = getenv ("GUILE_SYSTEM_PATH");
+  env = getenv_path ("GUILE_SYSTEM_PATH");
   if (env && strcmp (env, "") == 0)
     /* special-case interpret system-path=="" as meaning no system path instead
        of '("") */
@@ -302,7 +333,7 @@ scm_init_load_path ()
                        scm_from_locale_string (SCM_GLOBAL_SITE_DIR),
                        scm_from_locale_string (SCM_PKGDATA_DIR));
 
-  env = getenv ("GUILE_SYSTEM_COMPILED_PATH");
+  env = getenv_path ("GUILE_SYSTEM_COMPILED_PATH");
   if (env && strcmp (env, "") == 0)
     /* like above */
     ; 
@@ -345,14 +376,30 @@ scm_init_load_path ()
       cachedir[0] = 0;
 
     if (cachedir[0])
-      *scm_loc_compile_fallback_path = scm_from_locale_string (cachedir);
+      {
+#ifdef __MINGW32__
+       /* We don't use getenv_path for FALLBACK_DIR because those
+          variables are not Guile-specific, so we want to leave them
+          intact in the environment.  This is especially relevant for
+          LOCALAPPDATA and APPDATA.  */
+       char *p = cachedir;
+
+       while (*p)
+         {
+           if (*p == '\\')
+             *p = '/';
+           p++;
+         }
+#endif
+       *scm_loc_compile_fallback_path = scm_from_locale_string (cachedir);
+      }
   }
 
-  env = getenv ("GUILE_LOAD_PATH");
+  env = getenv_path ("GUILE_LOAD_PATH");
   if (env)
     path = scm_parse_path_with_ellipsis (scm_from_locale_string (env), path);
 
-  env = getenv ("GUILE_LOAD_COMPILED_PATH");
+  env = getenv_path ("GUILE_LOAD_COMPILED_PATH");
   if (env)
     cpath = scm_parse_path_with_ellipsis (scm_from_locale_string (env), cpath);
 
@@ -452,11 +499,10 @@ scm_c_string_has_an_ext (char *str, size
   return 0;
 }
 
-#ifdef __MINGW32__
-#define FILE_NAME_SEPARATOR_STRING "\\"
-#else
+/* Defined as "/" for Unix and Windows alike, so that file names
+   constructed by the functions in this module wind up with Unix-style
+   forward slashes as directory separators.  */
 #define FILE_NAME_SEPARATOR_STRING "/"
-#endif
 
 static int
 is_file_name_separator (SCM c)
@@ -877,7 +923,7 @@ canonical_suffix (SCM fname)
 
   /* CANON should be absolute.  */
   canon = scm_canonicalize_path (fname);
-  
+
 #ifdef __MINGW32__
   {
     size_t len = scm_c_string_length (canon);



--- libguile/filesys.c~0        2014-02-28 23:01:27 +0200
+++ libguile/filesys.c  2014-06-29 18:13:30 +0300
@@ -1235,6 +1235,19 @@ SCM_DEFINE (scm_getcwd, "getcwd", 0, 0,
       errno = save_errno;
       SCM_SYSERROR;
     }
+#ifdef __MINGW32__
+  if (rv)
+    {
+      char *p = wd;
+
+      while (*p)
+       {
+         if (*p == '\\')
+           *p = '/';
+         p++;
+       }
+    }
+#endif
   result = scm_from_locale_stringn (wd, strlen (wd));
   free (wd);
   return result;


--- module/ice-9/boot-9.scm~    2014-02-15 01:00:33 +0200
+++ module/ice-9/boot-9.scm     2014-06-29 18:15:07 +0300
@@ -1657,7 +1657,7 @@
        (or (char=? c #\/)
            (char=? c #\\)))
 
-     (define file-name-separator-string "\\")
+     (define file-name-separator-string "/")
 
      (define (absolute-file-name? file-name)
        (define (file-name-separator-at-index? idx)



--- libguile/init.c~0   2014-02-28 23:01:27 +0200
+++ libguile/init.c     2014-07-02 18:51:04 +0300
@@ -310,6 +310,17 @@ scm_boot_guile (int argc, char ** argv,
 {
   void *res;
   struct main_func_closure c;
+#ifdef __MINGW32__
+  /* Convert backslashes in argv[0] to forward slashes.  */
+  char *p = argv[0];
+
+  while (*p)
+    {
+      if (*p == '\\')
+       *p = '/';
+      p++;
+    }
+#endif
 
   c.main_func = main_func;
   c.closure = closure;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]