From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.lisp.guile.devel Subject: Re: Windows file name separators Date: Thu, 03 Jul 2014 18:10:28 +0300 Message-ID: <83d2dm32cb.fsf@gnu.org> References: <83lht730k8.fsf@gnu.org> <87k38p6f9v.fsf@gnu.org> <83egyw21qd.fsf@gnu.org> <87ioni1wdb.fsf@gnu.org> <834mz25tuq.fsf@gnu.org> <87vbrh1kv3.fsf@gnu.org> <83k37x3xm6.fsf@gnu.org> <877g3xozs3.fsf@gnu.org> <83tx6z3fx9.fsf@gnu.org> <87a98rfph6.fsf@gnu.org> Reply-To: Eli Zaretskii NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE X-Trace: ger.gmane.org 1404400276 11865 80.91.229.3 (3 Jul 2014 15:11:16 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 3 Jul 2014 15:11:16 +0000 (UTC) Cc: guile-devel@gnu.org To: ludo@gnu.org (Ludovic =?utf-8?Q?Court=C3=A8s?=) Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Jul 03 17:11:10 2014 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1X2ifE-00079n-S2 for guile-devel@m.gmane.org; Thu, 03 Jul 2014 17:11:09 +0200 Original-Received: from localhost ([::1]:60250 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X2ifE-00029T-3i for guile-devel@m.gmane.org; Thu, 03 Jul 2014 11:11:08 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:60408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X2if2-00028B-3m for guile-devel@gnu.org; Thu, 03 Jul 2014 11:11:02 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X2ies-0006F0-0Q for guile-devel@gnu.org; Thu, 03 Jul 2014 11:10:56 -0400 Original-Received: from mtaout27.012.net.il ([80.179.55.183]:37363) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X2ier-0006Ed-Gt; Thu, 03 Jul 2014 11:10:45 -0400 Original-Received: from conversion-daemon.mtaout27.012.net.il by mtaout27.012.net.il (HyperSendmail v2007.08) id <0N8500B005U21X00@mtaout27.012.net.il>; Thu, 03 Jul 2014 18:07:06 +0300 (IDT) Original-Received: from HOME-C4E4A596F7 ([87.69.4.28]) by mtaout27.012.net.il (HyperSendmail v2007.08) with ESMTPA id <0N85006QX5ZTK950@mtaout27.012.net.il>; Thu, 03 Jul 2014 18:07:05 +0300 (IDT) In-reply-to: <87a98rfph6.fsf@gnu.org> X-012-Sender: halo1@inter.net.il X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 80.179.55.183 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:17280 Archived-At: > From: ludo@gnu.org (Ludovic Court=C3=A8s) > Cc: guile-devel@gnu.org > Date: Wed, 02 Jul 2014 22:57:41 +0200 >=20 > Eli Zaretskii skribis: >=20 > >> From: ludo@gnu.org (Ludovic Court=C3=A8s) > >> Cc: guile-devel@gnu.org > >> Date: Tue, 01 Jul 2014 17:38:04 +0200 >=20 > [...] >=20 > >> 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 pu= sh. > > (This supersedes what I sent in > > http://lists.gnu.org/archive/html/guile-devel/2014-06/msg00066.ht= ml.) >=20 > Also, could you add tests for that? Namely, a =E2=80=98search-path= =E2=80=99 use that > currently returns a file name with backslashes, and will now return= a > file name with forward slashes. Is the below OK? --- libguile/load.c~0=092014-02-28 23:01:27 +0200 +++ libguile/load.c=092014-07-03 09:58:29 +0300 @@ -277,6 +277,41 @@ SCM_DEFINE (scm_parse_path_with_ellipsis } #undef FUNC_NAME =20 +/* On Posix hosts, just return PATH unaltered. On Windows, + destructively replace all backslashes in PATH with Unix-style + 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, if PATH is result of a call to 'getenv', this + destructively modifies the environment variables, so both + scm_getenv and subprocesses will afterwards see the values with + forward slashes. That is OK as long as applied to Guile-specific + environment variables, since having scm_getenv return the same + value as used by the callers of this function is good for + consistency and file-name comparison. Avoid using this function = on + values returned by 'getenv' for general-purpose environment + variables; instead, make a copy of the value and work on that. *= / +SCM_INTERNAL char * +scm_i_mirror_backslashes (char *path) +{ +#ifdef __MINGW32__ + if (path) + { + char *p =3D path; + + while (*p) +=09{ +=09 if (*p =3D=3D '\\') +=09 *p =3D '/'; +=09 p++; +=09} + } +#endif + + return path; +} =20 /* Initialize the global variable %load-path, given the value of the SCM_SITE_DIR and SCM_LIBRARY_DIR preprocessor symbols and the @@ -289,7 +324,7 @@ scm_init_load_path () SCM cpath =3D SCM_EOL; =20 #ifdef SCM_LIBRARY_DIR - env =3D getenv ("GUILE_SYSTEM_PATH"); + env =3D scm_i_mirror_backslashes (getenv ("GUILE_SYSTEM_PATH")); if (env && strcmp (env, "") =3D=3D 0) /* special-case interpret system-path=3D=3D"" as meaning no syst= em path instead of '("") */ @@ -302,7 +337,7 @@ scm_init_load_path () scm_from_locale_string (SCM_GLOBAL_SITE_DIR), scm_from_locale_string (SCM_PKGDATA_DIR)); =20 - env =3D getenv ("GUILE_SYSTEM_COMPILED_PATH"); + env =3D scm_i_mirror_backslashes (getenv ("GUILE_SYSTEM_COMPILED_P= ATH")); if (env && strcmp (env, "") =3D=3D 0) /* like above */ ;=20 @@ -345,14 +380,17 @@ scm_init_load_path () cachedir[0] =3D 0; =20 if (cachedir[0]) - *scm_loc_compile_fallback_path =3D scm_from_locale_string (cac= hedir); + { +=09scm_i_mirror_backslashes (cachedir); +=09*scm_loc_compile_fallback_path =3D scm_from_locale_string (cached= ir); + } } =20 - env =3D getenv ("GUILE_LOAD_PATH"); + env =3D scm_i_mirror_backslashes (getenv ("GUILE_LOAD_PATH")); if (env) path =3D scm_parse_path_with_ellipsis (scm_from_locale_string (e= nv), path); =20 - env =3D getenv ("GUILE_LOAD_COMPILED_PATH"); + env =3D scm_i_mirror_backslashes (getenv ("GUILE_LOAD_COMPILED_PAT= H")); if (env) cpath =3D scm_parse_path_with_ellipsis (scm_from_locale_string (= env), cpath); =20 @@ -452,11 +490,10 @@ scm_c_string_has_an_ext (char *str, size return 0; } =20 -#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-sty= le + forward slashes as directory separators. */ #define FILE_NAME_SEPARATOR_STRING "/" -#endif =20 static int is_file_name_separator (SCM c) @@ -877,7 +914,7 @@ canonical_suffix (SCM fname) =20 /* CANON should be absolute. */ canon =3D scm_canonicalize_path (fname); - =20 + #ifdef __MINGW32__ { size_t len =3D scm_c_string_length (canon); --- libguile/load.h~0=092013-03-19 00:30:13 +0200 +++ libguile/load.h=092014-07-03 09:59:17 +0300 @@ -44,6 +44,7 @@ SCM_INTERNAL void scm_init_load_path (vo SCM_INTERNAL void scm_init_load (void); SCM_INTERNAL void scm_init_load_should_auto_compile (void); SCM_INTERNAL void scm_init_eval_in_scheme (void); +SCM_INTERNAL char *scm_i_mirror_backslashes (char *path); =20 #endif /* SCM_LOAD_H */ =20 --- libguile/filesys.c~0=092014-02-28 23:01:27 +0200 +++ libguile/filesys.c=092014-07-03 10:03:25 +0300 @@ -51,6 +51,7 @@ =20 #include "libguile/validate.h" #include "libguile/filesys.h" +#include "libguile/load.h"=09/* for scm_i_mirror_backslashes */ =20 =0C #ifdef HAVE_IO_H @@ -1235,6 +1248,9 @@ SCM_DEFINE (scm_getcwd, "getcwd", 0, 0, errno =3D save_errno; SCM_SYSERROR; } + /* On Windows, convert backslashes in current directory to forward + slashes. */ + scm_i_mirror_backslashes (wd); result =3D scm_from_locale_stringn (wd, strlen (wd)); free (wd); return result; --- libguile/init.c~0=092014-02-28 23:01:27 +0200 +++ libguile/init.c=092014-07-03 10:02:03 +0300 @@ -311,6 +311,9 @@ scm_boot_guile (int argc, char ** argv, void *res; struct main_func_closure c; =20 + /* On Windows, convert backslashes in argv[0] to forward + slashes. */ + scm_i_mirror_backslashes (argv[0]); c.main_func =3D main_func; c.closure =3D closure; c.argc =3D argc; --- module/ice-9/boot-9.scm~=092014-02-15 01:00:33 +0200 +++ module/ice-9/boot-9.scm=092014-06-29 16:15:07 +0300 @@ -1657,7 +1657,7 @@ (or (char=3D? c #\/) (char=3D? c #\\))) =20 - (define file-name-separator-string "\\") + (define file-name-separator-string "/") =20 (define (absolute-file-name? file-name) (define (file-name-separator-at-index? idx) --- test-suite/tests/ports.test~2=092014-06-29 16:06:51 +0300 +++ test-suite/tests/ports.test=092014-07-03 10:55:30 +0300 @@ -1866,6 +1865,17 @@ (with-fluids ((%file-port-name-canonicalization 'absolute)) (port-filename (open-input-file (%search-load-path "ice-9/q.sc= m")))))) =20 +(with-test-prefix "file name separators" + + (pass-if "no backslash separators in Windows file names" + ;; In Guile 2.0.11 and earlier, %load-path on Windows could + ;; include file names with backslashes, and `getcwd' on Windows + ;; would always return a directory name with backslashes. + (or (not (file-name-separator? #\\)) +=09(with-load-path (cons (getcwd) %load-path) +=09 (not (string-index (%search-load-path (basename (test-file))) +=09=09=09 #\\)))))) + (delete-file (test-file)) =20 ;;; Local Variables: