Some C# implementations (from Microsoft) can be used on Cygwin. In this environment, file names need to be translated from Cygwin syntax to Windows syntax. These patches do so.
2024-10-07 Bruno Haible <[email protected]> csharpcomp: Improve Cygwin support. * lib/csharpcomp.c: Include cygpath.h. (compile_csharp_using_sscli): Convert the file names passed to 'csc' to native Windows syntax. * modules/csharpcomp (Depends-on): Add cygpath. csharpcomp-script: Improve Cygwin support. * build-aux/csharpcomp.sh.in: Convert the file names passed to 'csc' to native Windows syntax. 2024-10-07 Bruno Haible <[email protected]> csharpexec: Improve Cygwin support. * lib/csharpexec.c: Include cygpath.h. (execute_csharp_using_sscli): Convert the first 'clix' argument to native Windows syntax. * modules/csharpexec (Depends-on): Add cygpath. csharpexec-script: Improve Cygwin support. * build-aux/csharpexec.sh.in: Convert the first 'clix' argument to native Windows syntax. 2024-10-07 Bruno Haible <[email protected]> cygpath: New module. * lib/cygpath.h: New file. * lib/cygpath.c: New file, based on lib/javaversion.c. * modules/cygpath: New file.
>From 5312d8c4b3331315cb424b6e3ffb509b7416daaf Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 7 Oct 2024 20:10:16 +0200 Subject: [PATCH 1/5] cygpath: New module. * lib/cygpath.h: New file. * lib/cygpath.c: New file, based on lib/javaversion.c. * modules/cygpath: New file. --- ChangeLog | 7 +++ lib/cygpath.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/cygpath.h | 37 +++++++++++ modules/cygpath | 25 ++++++++ 4 files changed, 232 insertions(+) create mode 100644 lib/cygpath.c create mode 100644 lib/cygpath.h create mode 100644 modules/cygpath diff --git a/ChangeLog b/ChangeLog index bee63a802f..301543072c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2024-10-07 Bruno Haible <[email protected]> + + cygpath: New module. + * lib/cygpath.h: New file. + * lib/cygpath.c: New file, based on lib/javaversion.c. + * modules/cygpath: New file. + 2024-10-07 Bruno Haible <[email protected]> mntent: Fix syntax error when module 'hasmntopt' is not in use. diff --git a/lib/cygpath.c b/lib/cygpath.c new file mode 100644 index 0000000000..7461706089 --- /dev/null +++ b/lib/cygpath.c @@ -0,0 +1,163 @@ +/* Convert file names between Cygwin syntax and Windows syntax. + Copyright (C) 2024 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2024. */ + +#include <config.h> + +/* Specification. */ +#include "cygpath.h" + +#include <stdlib.h> + +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + +#ifdef __CYGWIN__ + +/* Since Cygwin has its own notion of mount points (which can be defined by the + user), it would be wrong to blindly convert '/cygdrive/c/foo' to 'C:\foo'. + We really need to use the Cygwin API or the 'cygpath' program. */ + +# include <errno.h> +# include <error.h> + +# if 1 + +/* Documentation: + https://cygwin.com/cygwin-api/func-cygwin-conv-path.html */ + +# include <sys/cygwin.h> + +char * +cygpath_w (const char *filename) +{ + int repeat; + + /* Try several times, since there is a small time window during which the + size returned by the previous call may not be sufficient, namely when a + directory gets renamed. */ + for (repeat = 3; repeat > 0; repeat--) + { + ssize_t size = cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, filename, NULL, 0); + if (size < 0) + error (EXIT_FAILURE, errno, _("cannot convert file name '%s' to Windows syntax"), filename); + char *result = (char *) xmalloc (size); + if (cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, filename, result, size) == 0) + return result; + free (result); + } + error (EXIT_FAILURE, errno, _("cygwin_conv_path failed")); + return NULL; +} + +# else +/* Alternative implementation (slower) */ + +/* Documentation: + https://cygwin.com/cygwin-ug-net/cygpath.html */ + +# include <stdio.h> + +# include "spawn-pipe.h" +# include "wait-process.h" + +/* Executes a program. + Returns the first line of its output, as a freshly allocated string, or + NULL. */ +static char * +execute_and_read_line (const char *progname, + const char *prog_path, const char * const *prog_argv) +{ + pid_t child; + int fd[1]; + FILE *fp; + char *line; + size_t linesize; + size_t linelen; + + /* Open a pipe to the program. */ + child = create_pipe_in (progname, prog_path, prog_argv, NULL, + DEV_NULL, false, true, false, fd); + + if (child == -1) + return NULL; + + /* Retrieve its result. */ + fp = fdopen (fd[0], "r"); + if (fp == NULL) + error (EXIT_FAILURE, errno, _("fdopen() failed")); + + line = NULL; linesize = 0; + linelen = getline (&line, &linesize, fp); + if (linelen == (size_t)(-1)) + { + error (0, 0, _("%s subprocess I/O error"), progname); + fclose (fp); + wait_subprocess (child, progname, true, false, true, false, NULL); + } + else + { + int exitstatus; + + if (linelen > 0 && line[linelen - 1] == '\n') + line[linelen - 1] = '\0'; + + /* Read until EOF (otherwise the child process may get a SIGPIPE signal). */ + while (getc (fp) != EOF) + ; + + fclose (fp); + + /* Remove zombie process from process list, and retrieve exit status. */ + exitstatus = + wait_subprocess (child, progname, true, false, true, false, NULL); + if (exitstatus == 0) + return line; + } + free (line); + return NULL; +} + +char * +cygpath_w (const char *filename) +{ + const char *argv[4]; + + argv[0] = "cygpath"; + argv[1] = "-w"; + argv[2] = filename; + argv[3] = NULL; + + char *line = execute_and_read_line ("cygpath", "cygpath", argv); + if (line == NULL || line[0] == '\0') + error (EXIT_FAILURE, 0, _("%s invocation failed"), "cygpath"); + return line; +} + +# endif + +#else + +char * +cygpath_w (const char *filename) +{ + return xstrdup (filename); +} + +#endif diff --git a/lib/cygpath.h b/lib/cygpath.h new file mode 100644 index 0000000000..0843347f7a --- /dev/null +++ b/lib/cygpath.h @@ -0,0 +1,37 @@ +/* Convert file names between Cygwin syntax and Windows syntax. + Copyright (C) 2024 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <[email protected]>, 2024. */ + +#ifndef _CYGPATH_H +#define _CYGPATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* On Cygwin, this function converts a file name from Cygwin syntax to + native Windows syntax, like 'cygpath -w' does. + Returns a freshly allocated file name. + On the other platforms, it returns a freshly allocated copy of the + argument file name. */ +extern char *cygpath_w (const char *filename); + +#ifdef __cplusplus +} +#endif + +#endif /* _CYGPATH_H */ diff --git a/modules/cygpath b/modules/cygpath new file mode 100644 index 0000000000..dc48848a98 --- /dev/null +++ b/modules/cygpath @@ -0,0 +1,25 @@ +Description: +Convert file names between Cygwin syntax and Windows syntax. + +Files: +lib/cygpath.h +lib/cygpath.c + +Depends-on: +xalloc +free-posix +gettext-h + +configure.ac: + +Makefile.am: +lib_SOURCES += cygpath.c + +Include: +"cygpath.h" + +License: +GPL + +Maintainer: +all -- 2.34.1
>From a4bd0d3ee8a64a2d465d72f105208ffc97b28c78 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 7 Oct 2024 20:14:04 +0200 Subject: [PATCH 2/5] csharpexec-script: Improve Cygwin support. * build-aux/csharpexec.sh.in: Convert the first 'clix' argument to native Windows syntax. --- ChangeLog | 6 ++++++ build-aux/csharpexec.sh.in | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 301543072c..7e9b3754b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-10-07 Bruno Haible <[email protected]> + + csharpexec-script: Improve Cygwin support. + * build-aux/csharpexec.sh.in: Convert the first 'clix' argument to + native Windows syntax. + 2024-10-07 Bruno Haible <[email protected]> cygpath: New module. diff --git a/build-aux/csharpexec.sh.in b/build-aux/csharpexec.sh.in index 2ef677c10a..83d60ca870 100644 --- a/build-aux/csharpexec.sh.in +++ b/build-aux/csharpexec.sh.in @@ -79,8 +79,16 @@ else @CLIX_PATH_VAR@="$CONF_CLIX_PATH" fi export @CLIX_PATH_VAR@ - test -z "$CSHARP_VERBOSE" || echo clix "$@" - exec clix "$@" + shift + # On Windows, assume that 'clix' is a native Windows program, + # not a Cygwin program. + case "@build_os@" in + cygwin*) + prog=`cygpath -w "$prog"` + ;; + esac + test -z "$CSHARP_VERBOSE" || echo clix "$prog" "$@" + exec clix "$prog" "$@" else echo 'C# virtual machine not found, try installing mono, then reconfigure' 1>&2 exit 1 -- 2.34.1
>From 04b68d47326b154bac143370bf7804592969942e Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 7 Oct 2024 20:15:44 +0200 Subject: [PATCH 3/5] csharpexec: Improve Cygwin support. * lib/csharpexec.c: Include cygpath.h. (execute_csharp_using_sscli): Convert the first 'clix' argument to native Windows syntax. * modules/csharpexec (Depends-on): Add cygpath. --- ChangeLog | 6 ++++++ lib/csharpexec.c | 9 +++++++-- modules/csharpexec | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7e9b3754b1..926802e4c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2024-10-07 Bruno Haible <[email protected]> + csharpexec: Improve Cygwin support. + * lib/csharpexec.c: Include cygpath.h. + (execute_csharp_using_sscli): Convert the first 'clix' argument to + native Windows syntax. + * modules/csharpexec (Depends-on): Add cygpath. + csharpexec-script: Improve Cygwin support. * build-aux/csharpexec.sh.in: Convert the first 'clix' argument to native Windows syntax. diff --git a/lib/csharpexec.c b/lib/csharpexec.c index 88f9441381..c7e3fe5ae5 100644 --- a/lib/csharpexec.c +++ b/lib/csharpexec.c @@ -24,10 +24,11 @@ #include <stdio.h> #include <stdlib.h> +#include <error.h> +#include "cygpath.h" #include "execute.h" #include "sh-quote.h" #include "xmalloca.h" -#include <error.h> #include "gettext.h" /* Handling of MONO_PATH is just like Java CLASSPATH. */ @@ -178,6 +179,9 @@ execute_csharp_using_sscli (const char *assembly_path, if (clix_present) { + /* Here, we assume that 'clix' is a native Windows program, therefore + we need to use cygpath_w. */ + char *assembly_path_converted = cygpath_w (assembly_path); char *old_clixpath; const char **argv = (const char **) xmalloca ((2 + nargs + 1) * sizeof (const char *)); @@ -188,7 +192,7 @@ execute_csharp_using_sscli (const char *assembly_path, old_clixpath = set_clixpath (libdirs, libdirs_count, false, verbose); argv[0] = "clix"; - argv[1] = assembly_path; + argv[1] = assembly_path_converted; for (i = 0; i <= nargs; i++) argv[2 + i] = args[i]; @@ -205,6 +209,7 @@ execute_csharp_using_sscli (const char *assembly_path, reset_clixpath (old_clixpath); freea (argv); + free (assembly_path_converted); return err; } diff --git a/modules/csharpexec b/modules/csharpexec index cb30c938fb..11dcf49edb 100644 --- a/modules/csharpexec +++ b/modules/csharpexec @@ -9,6 +9,7 @@ lib/classpath.c Depends-on: stdbool +cygpath execute xsetenv sh-quote -- 2.34.1
>From 1976ad3bbedba2ab9475a63c2cfc742b75a1c209 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 7 Oct 2024 20:20:14 +0200 Subject: [PATCH 4/5] csharpcomp-script: Improve Cygwin support. * build-aux/csharpcomp.sh.in: Convert the file names passed to 'csc' to native Windows syntax. --- ChangeLog | 6 ++++++ build-aux/csharpcomp.sh.in | 44 +++++++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 926802e4c4..43894cdf54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-10-07 Bruno Haible <[email protected]> + + csharpcomp-script: Improve Cygwin support. + * build-aux/csharpcomp.sh.in: Convert the file names passed to 'csc' to + native Windows syntax. + 2024-10-07 Bruno Haible <[email protected]> csharpexec: Improve Cygwin support. diff --git a/build-aux/csharpcomp.sh.in b/build-aux/csharpcomp.sh.in index 0ffbb480a3..9febcddd72 100644 --- a/build-aux/csharpcomp.sh.in +++ b/build-aux/csharpcomp.sh.in @@ -68,6 +68,7 @@ sed_quote_subst='s/\([|&;<>()$`"'"'"'*?[#~=% \\]\)/\\\1/g' options_mcs= options_csc="-nologo" sources= +sources_csc= while test $# != 0; do case "$1" in -o) @@ -81,12 +82,28 @@ while test $# != 0; do ;; esac options_mcs="$options_mcs -out:"`echo "$2" | sed -e "$sed_quote_subst"` - options_csc="$options_csc -out:"`echo "$2" | sed -e "$sed_quote_subst"` + # On Windows, assume that 'csc' is a native Windows program, + # not a Cygwin program. + arg="$2" + case "@build_os@" in + cygwin*) + arg=`cygpath -w "$arg"` + ;; + esac + options_csc="$options_csc -out:"`echo "$arg" | sed -e "$sed_quote_subst"` shift ;; -L) options_mcs="$options_mcs -lib:"`echo "$2" | sed -e "$sed_quote_subst"` - options_csc="$options_csc -lib:"`echo "$2" | sed -e "$sed_quote_subst"` + # On Windows, assume that 'csc' is a native Windows program, + # not a Cygwin program. + arg="$2" + case "@build_os@" in + cygwin*) + arg=`cygpath -w "$arg"` + ;; + esac + options_csc="$options_csc -lib:"`echo "$arg" | sed -e "$sed_quote_subst"` shift ;; -l) @@ -107,10 +124,27 @@ while test $# != 0; do ;; *.resources) options_mcs="$options_mcs -resource:"`echo "$1" | sed -e "$sed_quote_subst"` - options_csc="$options_csc -resource:"`echo "$1" | sed -e "$sed_quote_subst"` + # On Windows, assume that 'csc' is a native Windows program, + # not a Cygwin program. + arg="$1" + case "@build_os@" in + cygwin*) + arg=`cygpath -w "$arg"` + ;; + esac + options_csc="$options_csc -resource:"`echo "$arg" | sed -e "$sed_quote_subst"` ;; *.cs) sources="$sources "`echo "$1" | sed -e "$sed_quote_subst"` + # On Windows, assume that 'csc' is a native Windows program, + # not a Cygwin program. + arg="$1" + case "@build_os@" in + cygwin*) + arg=`cygpath -w "$arg"` + ;; + esac + sources_csc="$sources_csc "`echo "$arg" | sed -e "$sed_quote_subst"` ;; *) echo "csharpcomp: unknown type of argument '$1'" 1>&2 @@ -136,8 +170,8 @@ if test -n "@HAVE_MCS@"; then exit $result else if test -n "@HAVE_CSC@"; then - test -z "$CSHARP_VERBOSE" || echo csc $options_csc $sources - exec csc $options_csc $sources + test -z "$CSHARP_VERBOSE" || echo csc $options_csc $sources_csc + exec csc $options_csc $sources_csc else echo 'C# compiler not found, try installing mono, then reconfigure' 1>&2 exit 1 -- 2.34.1
>From 2529243503f93aed2ddb249e4b459c5afda78add Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 7 Oct 2024 20:25:06 +0200 Subject: [PATCH 5/5] csharpcomp: Improve Cygwin support. * lib/csharpcomp.c: Include cygpath.h. (compile_csharp_using_sscli): Convert the file names passed to 'csc' to native Windows syntax. * modules/csharpcomp (Depends-on): Add cygpath. --- ChangeLog | 6 ++++++ lib/csharpcomp.c | 43 +++++++++++++++++++++++++++++++++---------- modules/csharpcomp | 1 + 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43894cdf54..27e1dca18c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2024-10-07 Bruno Haible <[email protected]> + csharpcomp: Improve Cygwin support. + * lib/csharpcomp.c: Include cygpath.h. + (compile_csharp_using_sscli): Convert the file names passed to 'csc' to + native Windows syntax. + * modules/csharpcomp (Depends-on): Add cygpath. + csharpcomp-script: Improve Cygwin support. * build-aux/csharpcomp.sh.in: Convert the file names passed to 'csc' to native Windows syntax. diff --git a/lib/csharpcomp.c b/lib/csharpcomp.c index 54b1aa4804..a0139c5b85 100644 --- a/lib/csharpcomp.c +++ b/lib/csharpcomp.c @@ -26,13 +26,14 @@ #include <stdlib.h> #include <string.h> +#include <error.h> +#include "cygpath.h" #include "execute.h" #include "spawn-pipe.h" #include "wait-process.h" #include "sh-quote.h" #include "safe-read.h" #include "xmalloca.h" -#include <error.h> #include "gettext.h" #define _(str) gettext (str) @@ -311,12 +312,21 @@ compile_csharp_using_sscli (const char * const *sources, if (csc_present) { + char **malloced; + char **mallocedp; unsigned int argc; const char **argv; const char **argp; int exitstatus; unsigned int i; + /* Here, we assume that 'csc' is a native Windows program, therefore + we need to use cygpath_w. */ + malloced = + (char **) + xmalloca ((1 + libdirs_count + sources_count) * sizeof (char *)); + mallocedp = malloced; + argc = 1 + 1 + 1 + libdirs_count + libraries_count + (optimize ? 1 : 0) + (debug ? 1 : 0) + sources_count; @@ -326,16 +336,21 @@ compile_csharp_using_sscli (const char * const *sources, *argp++ = "csc"; *argp++ = (output_is_library ? "-target:library" : "-target:exe"); { - char *option = (char *) xmalloca (5 + strlen (output_file) + 1); + char *output_file_converted = cygpath_w (output_file); + *mallocedp++ = output_file_converted; + char *option = (char *) xmalloca (5 + strlen (output_file_converted) + 1); memcpy (option, "-out:", 5); - strcpy (option + 5, output_file); + strcpy (option + 5, output_file_converted); *argp++ = option; } for (i = 0; i < libdirs_count; i++) { - char *option = (char *) xmalloca (5 + strlen (libdirs[i]) + 1); + const char *libdir = libdirs[i]; + char *libdir_converted = cygpath_w (libdir); + *mallocedp++ = libdir_converted; + char *option = (char *) xmalloca (5 + strlen (libdir_converted) + 1); memcpy (option, "-lib:", 5); - strcpy (option + 5, libdirs[i]); + strcpy (option + 5, libdir_converted); *argp++ = option; } for (i = 0; i < libraries_count; i++) @@ -353,18 +368,23 @@ compile_csharp_using_sscli (const char * const *sources, for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; - if (strlen (source_file) >= 10 - && memcmp (source_file + strlen (source_file) - 10, ".resources", + char *source_file_converted = cygpath_w (source_file); + *mallocedp++ = source_file_converted; + if (strlen (source_file_converted) >= 10 + && memcmp (source_file_converted + + strlen (source_file_converted) - 10, + ".resources", 10) == 0) { - char *option = (char *) xmalloca (10 + strlen (source_file) + 1); + char *option = + (char *) xmalloca (10 + strlen (source_file_converted) + 1); memcpy (option, "-resource:", 10); - strcpy (option + 10, source_file); + strcpy (option + 10, source_file_converted); *argp++ = option; } else - *argp++ = source_file; + *argp++ = source_file_converted; } *argp = NULL; /* Ensure argv length was correctly calculated. */ @@ -387,7 +407,10 @@ compile_csharp_using_sscli (const char * const *sources, for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freea ((char *) argv[argc - sources_count + i]); + while (mallocedp > malloced) + free (*--mallocedp); freea (argv); + freea (malloced); return (exitstatus != 0); } diff --git a/modules/csharpcomp b/modules/csharpcomp index 97783d67c2..ea996fe81d 100644 --- a/modules/csharpcomp +++ b/modules/csharpcomp @@ -8,6 +8,7 @@ lib/csharpcomp.c Depends-on: stdbool xmalloca +cygpath execute spawn-pipe wait-process -- 2.34.1
