1 /* Execute a C# program.
2 Copyright (C) 2003-2005 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 #include "csharpexec.h"
36 /* Handling of MONO_PATH is just like Java CLASSPATH. */
37 #define CLASSPATHVAR "MONO_PATH"
38 #define new_classpath new_monopath
39 #define set_classpath set_monopath
40 #define reset_classpath reset_monopath
41 #include "classpath.h"
42 #include "classpath.c"
43 #undef reset_classpath
48 /* Handling of clix' PATH variable is just like Java CLASSPATH. */
49 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
51 #define CLASSPATHVAR "PATH"
52 #elif defined __APPLE__ && defined __MACH__
54 #define CLASSPATHVAR "DYLD_LIBRARY_PATH"
57 #define CLASSPATHVAR "LD_LIBRARY_PATH"
59 #define new_classpath new_clixpath
60 #define set_classpath set_clixpath
61 #define reset_classpath reset_clixpath
62 #include "classpath.h"
63 #include "classpath.c"
64 #undef reset_classpath
69 #define _(str) gettext (str)
72 /* Survey of CIL interpreters.
80 With Mono, the MONO_PATH is a colon separated list of pathnames. (On
81 Windows: semicolon separated list of pathnames.)
83 We try the CIL interpreters in the following order:
84 1. "ilrun", because it is a completely free system.
85 2. "mono", because it is a partially free system but doesn't integrate
87 3. "clix", although it is not free, because it is a kind of "reference
88 implementation" of C#.
89 But the order can be changed through the --enable-csharp configuration
94 execute_csharp_using_pnet (const char *assembly_path,
95 const char * const *libdirs,
96 unsigned int libdirs_count,
97 const char * const *args, unsigned int nargs,
98 bool verbose, bool quiet,
99 execute_fn *executer, void *private_data)
101 static bool ilrun_tested;
102 static bool ilrun_present;
106 /* Test for presence of ilrun:
107 "ilrun --version >/dev/null 2>/dev/null" */
112 argv[1] = "--version";
114 exitstatus = execute ("ilrun", "ilrun", argv, false, false, true, true,
116 ilrun_present = (exitstatus == 0);
128 argc = 1 + 2 * libdirs_count + 1 + nargs;
129 argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
133 for (i = 0; i < libdirs_count; i++)
136 *argp++ = (char *) libdirs[i];
138 *argp++ = (char *) assembly_path;
139 for (i = 0; i < nargs; i++)
140 *argp++ = (char *) args[i];
142 /* Ensure argv length was correctly calculated. */
143 if (argp - argv != argc)
148 char *command = shell_quote_argv (argv);
149 printf ("%s\n", command);
153 err = executer ("ilrun", "ilrun", argv, private_data);
164 execute_csharp_using_mono (const char *assembly_path,
165 const char * const *libdirs,
166 unsigned int libdirs_count,
167 const char * const *args, unsigned int nargs,
168 bool verbose, bool quiet,
169 execute_fn *executer, void *private_data)
171 static bool mono_tested;
172 static bool mono_present;
176 /* Test for presence of mono:
177 "mono --version >/dev/null 2>/dev/null" */
182 argv[1] = "--version";
184 exitstatus = execute ("mono", "mono", argv, false, false, true, true,
186 mono_present = (exitstatus == 0);
193 char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
198 old_monopath = set_monopath (libdirs, libdirs_count, false, verbose);
201 argv[1] = (char *) assembly_path;
202 for (i = 0; i <= nargs; i++)
203 argv[2 + i] = (char *) args[i];
207 char *command = shell_quote_argv (argv);
208 printf ("%s\n", command);
212 err = executer ("mono", "mono", argv, private_data);
214 /* Reset MONO_PATH. */
215 reset_monopath (old_monopath);
226 execute_csharp_using_sscli (const char *assembly_path,
227 const char * const *libdirs,
228 unsigned int libdirs_count,
229 const char * const *args, unsigned int nargs,
230 bool verbose, bool quiet,
231 execute_fn *executer, void *private_data)
233 static bool clix_tested;
234 static bool clix_present;
238 /* Test for presence of clix:
239 "clix >/dev/null 2>/dev/null ; test $? = 1" */
245 exitstatus = execute ("clix", "clix", argv, false, false, true, true,
247 clix_present = (exitstatus == 0 || exitstatus == 1);
254 char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
258 /* Set clix' PATH variable. */
259 old_clixpath = set_clixpath (libdirs, libdirs_count, false, verbose);
262 argv[1] = (char *) assembly_path;
263 for (i = 0; i <= nargs; i++)
264 argv[2 + i] = (char *) args[i];
268 char *command = shell_quote_argv (argv);
269 printf ("%s\n", command);
273 err = executer ("clix", "clix", argv, private_data);
275 /* Reset clix' PATH variable. */
276 reset_clixpath (old_clixpath);
287 execute_csharp_program (const char *assembly_path,
288 const char * const *libdirs,
289 unsigned int libdirs_count,
290 const char * const *args,
291 bool verbose, bool quiet,
292 execute_fn *executer, void *private_data)
299 const char * const *arg;
301 for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++)
305 /* First try the C# implementation specified through --enable-csharp. */
306 #if CSHARP_CHOICE_PNET
307 result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count,
308 args, nargs, verbose, quiet,
309 executer, private_data);
311 return (bool) result;
314 #if CSHARP_CHOICE_MONO
315 result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count,
316 args, nargs, verbose, quiet,
317 executer, private_data);
319 return (bool) result;
322 /* Then try the remaining C# implementations in our standard order. */
323 #if !CSHARP_CHOICE_PNET
324 result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count,
325 args, nargs, verbose, quiet,
326 executer, private_data);
328 return (bool) result;
331 #if !CSHARP_CHOICE_MONO
332 result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count,
333 args, nargs, verbose, quiet,
334 executer, private_data);
336 return (bool) result;
339 result = execute_csharp_using_sscli (assembly_path, libdirs, libdirs_count,
340 args, nargs, verbose, quiet,
341 executer, private_data);
343 return (bool) result;
346 error (0, 0, _("C# virtual machine not found, try installing pnet"));