sh-quote, execute, spawn-pipe, etc.: Make better use of 'const'.
[gnulib.git] / lib / javacomp.c
blobca7a6fe6588712432fd7eacb8432005589ac56ae
1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2020 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
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 3 of the License, or
8 (at your option) any later version.
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, see <https://www.gnu.org/licenses/>. */
18 #include <config.h>
19 #include <alloca.h>
21 /* Specification. */
22 #include "javacomp.h"
24 #include <errno.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
33 #include "javaversion.h"
34 #include "execute.h"
35 #include "spawn-pipe.h"
36 #include "wait-process.h"
37 #include "classpath.h"
38 #include "xsetenv.h"
39 #include "sh-quote.h"
40 #include "binary-io.h"
41 #include "safe-read.h"
42 #include "xalloc.h"
43 #include "xmalloca.h"
44 #include "concat-filename.h"
45 #include "fwriteerror.h"
46 #include "clean-temp.h"
47 #include "error.h"
48 #include "xvasprintf.h"
49 #include "c-strstr.h"
50 #include "gettext.h"
52 #define _(str) gettext (str)
55 /* Survey of Java compilers.
57 A = does it work without CLASSPATH being set
58 C = option to set CLASSPATH, other than setting it in the environment
59 O = option for optimizing
60 g = option for debugging
61 T = test for presence
63 Program from A C O g T
65 $JAVAC unknown N n/a -O -g true
66 gcj -C GCC 3.2 Y --classpath=P -O -g gcj --version | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null
67 javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1
68 javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2
69 jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1
71 All compilers support the option "-d DIRECTORY" for the base directory
72 of the classes to be written.
74 The CLASSPATH is a colon separated list of pathnames. (On Windows: a
75 semicolon separated list of pathnames.)
77 We try the Java compilers in the following order:
78 1. getenv ("JAVAC"), because the user must be able to override our
79 preferences,
80 2. "gcj -C", because it is a completely free compiler,
81 3. "javac", because it is a standard compiler,
82 4. "jikes", comes last because it has some deviating interpretation
83 of the Java Language Specification and because it requires a
84 CLASSPATH environment variable.
86 We unset the JAVA_HOME environment variable, because a wrong setting of
87 this variable can confuse the JDK's javac.
90 /* Return the default target_version. */
91 static const char *
92 default_target_version (void)
94 /* Use a cache. Assumes that the PATH environment variable doesn't change
95 during the lifetime of the program. */
96 static const char *java_version_cache;
97 if (java_version_cache == NULL)
99 /* Determine the version from the found JVM. */
100 java_version_cache = javaexec_version ();
101 if (java_version_cache == NULL)
102 java_version_cache = "1.1";
103 else if ((java_version_cache[0] == '1'
104 && java_version_cache[1] == '.'
105 && java_version_cache[2] >= '1' && java_version_cache[2] <= '8'
106 && java_version_cache[3] == '\0')
107 || (java_version_cache[0] == '9'
108 && java_version_cache[1] == '\0')
109 || (java_version_cache[0] == '1'
110 && (java_version_cache[1] >= '0'
111 && java_version_cache[1] <= '1')
112 && java_version_cache[2] == '\0'))
113 /* It's one of the valid target version values. */
115 else if (java_version_cache[0] == '1'
116 && (java_version_cache[1] >= '2'
117 && java_version_cache[1] <= '7')
118 && java_version_cache[2] == '\0')
119 /* Assume that these (not yet released) Java versions will behave
120 like the preceding ones. */
121 java_version_cache = "11";
122 else
123 java_version_cache = "1.1";
125 return java_version_cache;
128 /* ======================= Source version dependent ======================= */
130 /* Convert a source version to an index. */
131 #define SOURCE_VERSION_BOUND 8 /* exclusive upper bound */
132 static unsigned int
133 source_version_index (const char *source_version)
135 if (source_version[0] == '1' && source_version[1] == '.')
137 if ((source_version[2] >= '3' && source_version[2] <= '5')
138 && source_version[3] == '\0')
139 return source_version[2] - '3';
140 if ((source_version[2] >= '7' && source_version[2] <= '8')
141 && source_version[3] == '\0')
142 return source_version[2] - '4';
144 else if (source_version[0] == '9' && source_version[1] == '\0')
145 return 5;
146 else if (source_version[0] == '1'
147 && (source_version[1] >= '0' && source_version[1] <= '1')
148 && source_version[2] == '\0')
149 return source_version[1] - '0' + 6;
150 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
151 return 0;
154 /* Return a snippet of code that should compile in the given source version. */
155 static const char *
156 get_goodcode_snippet (const char *source_version)
158 if (strcmp (source_version, "1.3") == 0)
159 return "class conftest {}\n";
160 if (strcmp (source_version, "1.4") == 0)
161 return "class conftest { static { assert(true); } }\n";
162 if (strcmp (source_version, "1.5") == 0)
163 return "class conftest<T> { T foo() { return null; } }\n";
164 if (strcmp (source_version, "1.7") == 0)
165 return "class conftest { void foo () { switch (\"A\") {} } }\n";
166 if (strcmp (source_version, "1.8") == 0)
167 return "class conftest { void foo () { Runnable r = () -> {}; } }\n";
168 if (strcmp (source_version, "9") == 0)
169 return "interface conftest { private void foo () {} }\n";
170 if (strcmp (source_version, "10") == 0)
171 return "class conftest { public void m() { var i = new Integer(0); } }\n";
172 if (strcmp (source_version, "11") == 0)
173 return "class conftest { Readable r = (var b) -> 0; }\n";
174 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
175 return NULL;
178 /* Return a snippet of code that should fail to compile in the given source
179 version, or NULL (standing for a snippet that would fail to compile with
180 any compiler). */
181 static const char *
182 get_failcode_snippet (const char *source_version)
184 if (strcmp (source_version, "1.3") == 0)
185 return "class conftestfail { static { assert(true); } }\n";
186 if (strcmp (source_version, "1.4") == 0)
187 return "class conftestfail<T> { T foo() { return null; } }\n";
188 if (strcmp (source_version, "1.5") == 0)
189 return "class conftestfail { void foo () { switch (\"A\") {} } }\n";
190 if (strcmp (source_version, "1.7") == 0)
191 return "class conftestfail { void foo () { Runnable r = () -> {}; } }\n";
192 if (strcmp (source_version, "1.8") == 0)
193 return "interface conftestfail { private void foo () {} }\n";
194 if (strcmp (source_version, "9") == 0)
195 return "class conftestfail { public void m() { var i = new Integer(0); } }\n";
196 if (strcmp (source_version, "10") == 0)
197 return "class conftestfail { Readable r = (var b) -> 0; }\n";
198 if (strcmp (source_version, "11") == 0)
199 return NULL;
200 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
201 return NULL;
204 /* ======================= Target version dependent ======================= */
206 /* Convert a target version to an index. */
207 #define TARGET_VERSION_BOUND 11 /* exclusive upper bound */
208 static unsigned int
209 target_version_index (const char *target_version)
211 if (target_version[0] == '1' && target_version[1] == '.'
212 && (target_version[2] >= '1' && target_version[2] <= '8')
213 && target_version[3] == '\0')
214 return target_version[2] - '1';
215 else if (target_version[0] == '9' && target_version[1] == '\0')
216 return 8;
217 else if (target_version[0] == '1'
218 && (target_version[1] >= '0' && target_version[1] <= '1')
219 && target_version[2] == '\0')
220 return target_version[1] - '0' + 9;
221 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
222 return 0;
225 /* Return the class file version number corresponding to a given target
226 version. */
227 static int
228 corresponding_classfile_version (const char *target_version)
230 if (strcmp (target_version, "1.1") == 0)
231 return 45;
232 if (strcmp (target_version, "1.2") == 0)
233 return 46;
234 if (strcmp (target_version, "1.3") == 0)
235 return 47;
236 if (strcmp (target_version, "1.4") == 0)
237 return 48;
238 if (strcmp (target_version, "1.5") == 0)
239 return 49;
240 if (strcmp (target_version, "1.6") == 0)
241 return 50;
242 if (strcmp (target_version, "1.7") == 0)
243 return 51;
244 if (strcmp (target_version, "1.8") == 0)
245 return 52;
246 if (strcmp (target_version, "9") == 0)
247 return 53;
248 if (strcmp (target_version, "10") == 0)
249 return 54;
250 if (strcmp (target_version, "11") == 0)
251 return 55;
252 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
253 return 0;
256 /* Return the source version to pass to javac. */
257 static const char *
258 get_source_version_for_javac (const char *source_version,
259 const char *target_version)
261 /* The javac option '-source 1.5' has the same meaning as '-source 1.6',
262 but since Java 9 supports only the latter, prefer the latter if a
263 target_version >= 1.6 is requested. */
264 if (strcmp (source_version, "1.5") == 0
265 && !(target_version[0] == '1' && target_version[1] == '.'
266 && (target_version[2] >= '1' && target_version[2] <= '5')
267 && target_version[3] == '\0'))
268 return "1.6";
269 return source_version;
272 /* ======================== Compilation subroutines ======================== */
274 /* Try to compile a set of Java sources with $JAVAC.
275 Return a failure indicator (true upon error). */
276 static bool
277 compile_using_envjavac (const char *javac,
278 const char * const *java_sources,
279 unsigned int java_sources_count,
280 const char *directory,
281 bool optimize, bool debug,
282 bool verbose, bool null_stderr)
284 /* Because $JAVAC may consist of a command and options, we use the
285 shell. Because $JAVAC has been set by the user, we leave all
286 environment variables in place, including JAVA_HOME, and we don't
287 erase the user's CLASSPATH. */
288 bool err;
289 unsigned int command_length;
290 char *command;
291 const char *argv[4];
292 int exitstatus;
293 unsigned int i;
294 char *p;
296 command_length = strlen (javac);
297 if (optimize)
298 command_length += 3;
299 if (debug)
300 command_length += 3;
301 if (directory != NULL)
302 command_length += 4 + shell_quote_length (directory);
303 for (i = 0; i < java_sources_count; i++)
304 command_length += 1 + shell_quote_length (java_sources[i]);
305 command_length += 1;
307 command = (char *) xmalloca (command_length);
308 p = command;
309 /* Don't shell_quote $JAVAC, because it may consist of a command
310 and options. */
311 memcpy (p, javac, strlen (javac));
312 p += strlen (javac);
313 if (optimize)
315 memcpy (p, " -O", 3);
316 p += 3;
318 if (debug)
320 memcpy (p, " -g", 3);
321 p += 3;
323 if (directory != NULL)
325 memcpy (p, " -d ", 4);
326 p += 4;
327 p = shell_quote_copy (p, directory);
329 for (i = 0; i < java_sources_count; i++)
331 *p++ = ' ';
332 p = shell_quote_copy (p, java_sources[i]);
334 *p++ = '\0';
335 /* Ensure command_length was correctly calculated. */
336 if (p - command > command_length)
337 abort ();
339 if (verbose)
340 printf ("%s\n", command);
342 argv[0] = BOURNE_SHELL;
343 argv[1] = "-c";
344 argv[2] = command;
345 argv[3] = NULL;
346 exitstatus = execute (javac, BOURNE_SHELL, argv, NULL,
347 false, false, false, null_stderr,
348 true, true, NULL);
349 err = (exitstatus != 0);
351 freea (command);
353 return err;
356 /* Try to compile a set of Java sources with gcj.
357 Return a failure indicator (true upon error). */
358 static bool
359 compile_using_gcj (const char * const *java_sources,
360 unsigned int java_sources_count,
361 bool no_assert_option,
362 bool fsource_option, const char *source_version,
363 bool ftarget_option, const char *target_version,
364 const char *directory,
365 bool optimize, bool debug,
366 bool verbose, bool null_stderr)
368 bool err;
369 unsigned int argc;
370 const char **argv;
371 const char **argp;
372 char *fsource_arg;
373 char *ftarget_arg;
374 int exitstatus;
375 unsigned int i;
377 argc =
378 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0)
379 + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
380 + (directory != NULL ? 2 : 0) + java_sources_count;
381 argv = (const char **) xmalloca ((argc + 1) * sizeof (const char *));
383 argp = argv;
384 *argp++ = "gcj";
385 *argp++ = "-C";
386 if (no_assert_option)
387 *argp++ = "-fno-assert";
388 if (fsource_option)
390 fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1);
391 memcpy (fsource_arg, "-fsource=", 9);
392 strcpy (fsource_arg + 9, source_version);
393 *argp++ = fsource_arg;
395 else
396 fsource_arg = NULL;
397 if (ftarget_option)
399 ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1);
400 memcpy (ftarget_arg, "-ftarget=", 9);
401 strcpy (ftarget_arg + 9, target_version);
402 *argp++ = ftarget_arg;
404 else
405 ftarget_arg = NULL;
406 if (optimize)
407 *argp++ = "-O";
408 if (debug)
409 *argp++ = "-g";
410 if (directory != NULL)
412 *argp++ = "-d";
413 *argp++ = directory;
415 for (i = 0; i < java_sources_count; i++)
416 *argp++ = java_sources[i];
417 *argp = NULL;
418 /* Ensure argv length was correctly calculated. */
419 if (argp - argv != argc)
420 abort ();
422 if (verbose)
424 char *command = shell_quote_argv (argv);
425 printf ("%s\n", command);
426 free (command);
429 exitstatus = execute ("gcj", "gcj", argv, NULL,
430 false, false, false, null_stderr,
431 true, true, NULL);
432 err = (exitstatus != 0);
434 if (ftarget_arg != NULL)
435 freea (ftarget_arg);
436 if (fsource_arg != NULL)
437 freea (fsource_arg);
438 freea (argv);
440 return err;
443 /* Try to compile a set of Java sources with javac.
444 Return a failure indicator (true upon error). */
445 static bool
446 compile_using_javac (const char * const *java_sources,
447 unsigned int java_sources_count,
448 bool source_option, const char *source_version,
449 bool target_option, const char *target_version,
450 const char *directory,
451 bool optimize, bool debug,
452 bool verbose, bool null_stderr)
454 bool err;
455 unsigned int argc;
456 const char **argv;
457 const char **argp;
458 int exitstatus;
459 unsigned int i;
461 argc =
462 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0)
463 + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count;
464 argv = (const char **) xmalloca ((argc + 1) * sizeof (const char *));
466 argp = argv;
467 *argp++ = "javac";
468 if (source_option)
470 *argp++ = "-source";
471 *argp++ = source_version;
473 if (target_option)
475 *argp++ = "-target";
476 *argp++ = target_version;
478 if (optimize)
479 *argp++ = "-O";
480 if (debug)
481 *argp++ = "-g";
482 if (directory != NULL)
484 *argp++ = "-d";
485 *argp++ = directory;
487 for (i = 0; i < java_sources_count; i++)
488 *argp++ = java_sources[i];
489 *argp = NULL;
490 /* Ensure argv length was correctly calculated. */
491 if (argp - argv != argc)
492 abort ();
494 if (verbose)
496 char *command = shell_quote_argv (argv);
497 printf ("%s\n", command);
498 free (command);
501 exitstatus = execute ("javac", "javac", argv, NULL,
502 false, false, false,
503 null_stderr, true, true, NULL);
504 err = (exitstatus != 0);
506 freea (argv);
508 return err;
511 /* Try to compile a set of Java sources with jikes.
512 Return a failure indicator (true upon error). */
513 static bool
514 compile_using_jikes (const char * const *java_sources,
515 unsigned int java_sources_count,
516 const char *directory,
517 bool optimize, bool debug,
518 bool verbose, bool null_stderr)
520 bool err;
521 unsigned int argc;
522 const char **argv;
523 const char **argp;
524 int exitstatus;
525 unsigned int i;
527 argc =
528 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
529 + java_sources_count;
530 argv = (const char **) xmalloca ((argc + 1) * sizeof (const char *));
532 argp = argv;
533 *argp++ = "jikes";
534 if (optimize)
535 *argp++ = "-O";
536 if (debug)
537 *argp++ = "-g";
538 if (directory != NULL)
540 *argp++ = "-d";
541 *argp++ = directory;
543 for (i = 0; i < java_sources_count; i++)
544 *argp++ = java_sources[i];
545 *argp = NULL;
546 /* Ensure argv length was correctly calculated. */
547 if (argp - argv != argc)
548 abort ();
550 if (verbose)
552 char *command = shell_quote_argv (argv);
553 printf ("%s\n", command);
554 free (command);
557 exitstatus = execute ("jikes", "jikes", argv, NULL,
558 false, false, false, null_stderr,
559 true, true, NULL);
560 err = (exitstatus != 0);
562 freea (argv);
564 return err;
567 /* ====================== Usability test subroutines ====================== */
569 /* Write a given contents to a temporary file.
570 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
571 yet.
572 Return a failure indicator (true upon error). */
573 static bool
574 write_temp_file (struct temp_dir *tmpdir, const char *file_name,
575 const char *contents)
577 FILE *fp;
579 register_temp_file (tmpdir, file_name);
580 fp = fopen_temp (file_name, "we", false);
581 if (fp == NULL)
583 error (0, errno, _("failed to create \"%s\""), file_name);
584 unregister_temp_file (tmpdir, file_name);
585 return true;
587 fputs (contents, fp);
588 if (fwriteerror_temp (fp))
590 error (0, errno, _("error while writing \"%s\" file"), file_name);
591 return true;
593 return false;
596 /* Return the class file version number of a class file on disk. */
597 static int
598 get_classfile_version (const char *compiled_file_name)
600 unsigned char header[8];
601 int fd;
603 /* Open the class file. */
604 fd = open (compiled_file_name, O_RDONLY | O_BINARY | O_CLOEXEC, 0);
605 if (fd >= 0)
607 /* Read its first 8 bytes. */
608 if (safe_read (fd, header, 8) == 8)
610 /* Verify the class file signature. */
611 if (header[0] == 0xCA && header[1] == 0xFE
612 && header[2] == 0xBA && header[3] == 0xBE)
614 close (fd);
615 return header[7];
618 close (fd);
621 /* Could not get the class file version. Return a very large one. */
622 return INT_MAX;
625 /* Return true if $JAVAC is a version of gcj. */
626 static bool
627 is_envjavac_gcj (const char *javac)
629 static bool envjavac_tested;
630 static bool envjavac_gcj;
632 if (!envjavac_tested)
634 /* Test whether $JAVAC is gcj:
635 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
636 unsigned int command_length;
637 char *command;
638 const char *argv[4];
639 pid_t child;
640 int fd[1];
641 FILE *fp;
642 char *line;
643 size_t linesize;
644 size_t linelen;
645 int exitstatus;
646 char *p;
648 /* Setup the command "$JAVAC --version". */
649 command_length = strlen (javac) + 1 + 9 + 1;
650 command = (char *) xmalloca (command_length);
651 p = command;
652 /* Don't shell_quote $JAVAC, because it may consist of a command
653 and options. */
654 memcpy (p, javac, strlen (javac));
655 p += strlen (javac);
656 memcpy (p, " --version", 1 + 9 + 1);
657 p += 1 + 9 + 1;
658 /* Ensure command_length was correctly calculated. */
659 if (p - command > command_length)
660 abort ();
662 /* Call $JAVAC --version 2>/dev/null. */
663 argv[0] = BOURNE_SHELL;
664 argv[1] = "-c";
665 argv[2] = command;
666 argv[3] = NULL;
667 child = create_pipe_in (javac, BOURNE_SHELL, argv, NULL,
668 DEV_NULL, true, true, false, fd);
669 if (child == -1)
670 goto failed;
672 /* Retrieve its result. */
673 fp = fdopen (fd[0], "r");
674 if (fp == NULL)
675 goto failed;
677 line = NULL; linesize = 0;
678 linelen = getline (&line, &linesize, fp);
679 if (linelen == (size_t)(-1))
681 fclose (fp);
682 goto failed;
684 /* It is safe to call c_strstr() instead of strstr() here; see the
685 comments in c-strstr.h. */
686 envjavac_gcj = (c_strstr (line, "gcj") != NULL);
688 fclose (fp);
690 /* Remove zombie process from process list, and retrieve exit status. */
691 exitstatus =
692 wait_subprocess (child, javac, true, true, true, false, NULL);
693 if (exitstatus != 0)
694 envjavac_gcj = false;
696 failed:
697 freea (command);
699 envjavac_tested = true;
702 return envjavac_gcj;
705 /* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
706 of gcj. */
707 static bool
708 is_envjavac_gcj43 (const char *javac)
710 static bool envjavac_tested;
711 static bool envjavac_gcj43;
713 if (!envjavac_tested)
715 /* Test whether $JAVAC is gcj:
716 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
717 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
718 unsigned int command_length;
719 char *command;
720 const char *argv[4];
721 pid_t child;
722 int fd[1];
723 FILE *fp;
724 char *line;
725 size_t linesize;
726 size_t linelen;
727 int exitstatus;
728 char *p;
730 /* Setup the command "$JAVAC --version". */
731 command_length = strlen (javac) + 1 + 9 + 1;
732 command = (char *) xmalloca (command_length);
733 p = command;
734 /* Don't shell_quote $JAVAC, because it may consist of a command
735 and options. */
736 memcpy (p, javac, strlen (javac));
737 p += strlen (javac);
738 memcpy (p, " --version", 1 + 9 + 1);
739 p += 1 + 9 + 1;
740 /* Ensure command_length was correctly calculated. */
741 if (p - command > command_length)
742 abort ();
744 /* Call $JAVAC --version 2>/dev/null. */
745 argv[0] = BOURNE_SHELL;
746 argv[1] = "-c";
747 argv[2] = command;
748 argv[3] = NULL;
749 child = create_pipe_in (javac, BOURNE_SHELL, argv, NULL,
750 DEV_NULL, true, true, false, fd);
751 if (child == -1)
752 goto failed;
754 /* Retrieve its result. */
755 fp = fdopen (fd[0], "r");
756 if (fp == NULL)
757 goto failed;
759 line = NULL; linesize = 0;
760 linelen = getline (&line, &linesize, fp);
761 if (linelen == (size_t)(-1))
763 fclose (fp);
764 goto failed;
766 p = line;
767 while (*p != '\0' && !(*p >= '0' && *p <= '9'))
768 p++;
769 envjavac_gcj43 =
770 !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2')
771 && (*p >= '4' && *p <= '9');
773 fclose (fp);
775 /* Remove zombie process from process list, and retrieve exit status. */
776 exitstatus =
777 wait_subprocess (child, javac, true, true, true, false, NULL);
778 if (exitstatus != 0)
779 envjavac_gcj43 = false;
781 failed:
782 freea (command);
784 envjavac_tested = true;
787 return envjavac_gcj43;
790 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
791 whether it needs a -fsource and/or -ftarget option.
792 Return a failure indicator (true upon error). */
793 static bool
794 is_envjavac_gcj43_usable (const char *javac,
795 const char *source_version,
796 const char *target_version,
797 bool *usablep,
798 bool *fsource_option_p, bool *ftarget_option_p)
800 /* The cache depends on the source_version and target_version. */
801 struct result_t
803 bool tested;
804 bool usable;
805 bool fsource_option;
806 bool ftarget_option;
808 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
809 struct result_t *resultp;
811 resultp = &result_cache[source_version_index (source_version)]
812 [target_version_index (target_version)];
813 if (!resultp->tested)
815 /* Try $JAVAC. */
816 struct temp_dir *tmpdir;
817 char *conftest_file_name;
818 char *compiled_file_name;
819 const char *java_sources[1];
820 struct stat statbuf;
822 tmpdir = create_temp_dir ("java", NULL, false);
823 if (tmpdir == NULL)
824 return true;
826 conftest_file_name =
827 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
828 if (write_temp_file (tmpdir, conftest_file_name,
829 get_goodcode_snippet (source_version)))
831 free (conftest_file_name);
832 cleanup_temp_dir (tmpdir);
833 return true;
836 compiled_file_name =
837 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
838 register_temp_file (tmpdir, compiled_file_name);
840 java_sources[0] = conftest_file_name;
841 if (!compile_using_envjavac (javac,
842 java_sources, 1, tmpdir->dir_name,
843 false, false, false, true)
844 && stat (compiled_file_name, &statbuf) >= 0
845 && get_classfile_version (compiled_file_name)
846 <= corresponding_classfile_version (target_version))
848 /* $JAVAC compiled conftest.java successfully. */
849 /* Try adding -fsource option if it is useful. */
850 char *javac_source =
851 xasprintf ("%s -fsource=%s", javac, source_version);
853 unlink (compiled_file_name);
855 java_sources[0] = conftest_file_name;
856 if (!compile_using_envjavac (javac_source,
857 java_sources, 1, tmpdir->dir_name,
858 false, false, false, true)
859 && stat (compiled_file_name, &statbuf) >= 0
860 && get_classfile_version (compiled_file_name)
861 <= corresponding_classfile_version (target_version))
863 const char *failcode = get_failcode_snippet (source_version);
865 if (failcode != NULL)
867 free (compiled_file_name);
868 free (conftest_file_name);
870 conftest_file_name =
871 xconcatenated_filename (tmpdir->dir_name,
872 "conftestfail.java",
873 NULL);
874 if (write_temp_file (tmpdir, conftest_file_name, failcode))
876 free (conftest_file_name);
877 free (javac_source);
878 cleanup_temp_dir (tmpdir);
879 return true;
882 compiled_file_name =
883 xconcatenated_filename (tmpdir->dir_name,
884 "conftestfail.class",
885 NULL);
886 register_temp_file (tmpdir, compiled_file_name);
888 java_sources[0] = conftest_file_name;
889 if (!compile_using_envjavac (javac,
890 java_sources, 1,
891 tmpdir->dir_name,
892 false, false, false, true)
893 && stat (compiled_file_name, &statbuf) >= 0)
895 unlink (compiled_file_name);
897 java_sources[0] = conftest_file_name;
898 if (compile_using_envjavac (javac_source,
899 java_sources, 1,
900 tmpdir->dir_name,
901 false, false, false, true))
902 /* $JAVAC compiled conftestfail.java successfully, and
903 "$JAVAC -fsource=$source_version" rejects it. So
904 the -fsource option is useful. */
905 resultp->fsource_option = true;
910 free (javac_source);
912 resultp->usable = true;
914 else
916 /* Try with -fsource and -ftarget options. */
917 char *javac_target =
918 xasprintf ("%s -fsource=%s -ftarget=%s",
919 javac, source_version, target_version);
921 unlink (compiled_file_name);
923 java_sources[0] = conftest_file_name;
924 if (!compile_using_envjavac (javac_target,
925 java_sources, 1, tmpdir->dir_name,
926 false, false, false, true)
927 && stat (compiled_file_name, &statbuf) >= 0
928 && get_classfile_version (compiled_file_name)
929 <= corresponding_classfile_version (target_version))
931 /* "$JAVAC -fsource $source_version -ftarget $target_version"
932 compiled conftest.java successfully. */
933 resultp->fsource_option = true;
934 resultp->ftarget_option = true;
935 resultp->usable = true;
938 free (javac_target);
941 free (compiled_file_name);
942 free (conftest_file_name);
944 resultp->tested = true;
947 *usablep = resultp->usable;
948 *fsource_option_p = resultp->fsource_option;
949 *ftarget_option_p = resultp->ftarget_option;
950 return false;
953 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
954 compiling with target_version = 1.4 and source_version = 1.4.
955 Return a failure indicator (true upon error). */
956 static bool
957 is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
959 static bool envjavac_tested;
960 static bool envjavac_usable;
962 if (!envjavac_tested)
964 /* Try $JAVAC. */
965 struct temp_dir *tmpdir;
966 char *conftest_file_name;
967 char *compiled_file_name;
968 const char *java_sources[1];
969 struct stat statbuf;
971 tmpdir = create_temp_dir ("java", NULL, false);
972 if (tmpdir == NULL)
973 return true;
975 conftest_file_name =
976 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
977 if (write_temp_file (tmpdir, conftest_file_name,
978 get_goodcode_snippet ("1.4")))
980 free (conftest_file_name);
981 cleanup_temp_dir (tmpdir);
982 return true;
985 compiled_file_name =
986 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
987 register_temp_file (tmpdir, compiled_file_name);
989 java_sources[0] = conftest_file_name;
990 if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name,
991 false, false, false, true)
992 && stat (compiled_file_name, &statbuf) >= 0)
993 /* Compilation succeeded. */
994 envjavac_usable = true;
996 free (compiled_file_name);
997 free (conftest_file_name);
999 cleanup_temp_dir (tmpdir);
1001 envjavac_tested = true;
1004 *usablep = envjavac_usable;
1005 return false;
1008 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
1009 compiling with target_version = 1.4 and source_version = 1.3.
1010 Return a failure indicator (true upon error). */
1011 static bool
1012 is_envjavac_oldgcj_14_13_usable (const char *javac,
1013 bool *usablep, bool *need_no_assert_option_p)
1015 static bool envjavac_tested;
1016 static bool envjavac_usable;
1017 static bool envjavac_need_no_assert_option;
1019 if (!envjavac_tested)
1021 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
1022 it makes a difference. (It could already be part of $JAVAC.) */
1023 struct temp_dir *tmpdir;
1024 char *conftest_file_name;
1025 char *compiled_file_name;
1026 const char *java_sources[1];
1027 struct stat statbuf;
1028 bool javac_works;
1029 char *javac_noassert;
1030 bool javac_noassert_works;
1032 tmpdir = create_temp_dir ("java", NULL, false);
1033 if (tmpdir == NULL)
1034 return true;
1036 conftest_file_name =
1037 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1038 if (write_temp_file (tmpdir, conftest_file_name,
1039 get_goodcode_snippet ("1.3")))
1041 free (conftest_file_name);
1042 cleanup_temp_dir (tmpdir);
1043 return true;
1046 compiled_file_name =
1047 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1048 register_temp_file (tmpdir, compiled_file_name);
1050 java_sources[0] = conftest_file_name;
1051 if (!compile_using_envjavac (javac,
1052 java_sources, 1, tmpdir->dir_name,
1053 false, false, false, true)
1054 && stat (compiled_file_name, &statbuf) >= 0)
1055 /* Compilation succeeded. */
1056 javac_works = true;
1057 else
1058 javac_works = false;
1060 unlink (compiled_file_name);
1062 javac_noassert = xasprintf ("%s -fno-assert", javac);
1064 java_sources[0] = conftest_file_name;
1065 if (!compile_using_envjavac (javac_noassert,
1066 java_sources, 1, tmpdir->dir_name,
1067 false, false, false, true)
1068 && stat (compiled_file_name, &statbuf) >= 0)
1069 /* Compilation succeeded. */
1070 javac_noassert_works = true;
1071 else
1072 javac_noassert_works = false;
1074 free (compiled_file_name);
1075 free (conftest_file_name);
1077 if (javac_works && javac_noassert_works)
1079 conftest_file_name =
1080 xconcatenated_filename (tmpdir->dir_name, "conftestfail.java",
1081 NULL);
1082 if (write_temp_file (tmpdir, conftest_file_name,
1083 get_failcode_snippet ("1.3")))
1085 free (conftest_file_name);
1086 free (javac_noassert);
1087 cleanup_temp_dir (tmpdir);
1088 return true;
1091 compiled_file_name =
1092 xconcatenated_filename (tmpdir->dir_name, "conftestfail.class",
1093 NULL);
1094 register_temp_file (tmpdir, compiled_file_name);
1096 java_sources[0] = conftest_file_name;
1097 if (!compile_using_envjavac (javac,
1098 java_sources, 1, tmpdir->dir_name,
1099 false, false, false, true)
1100 && stat (compiled_file_name, &statbuf) >= 0)
1102 /* Compilation succeeded. */
1103 unlink (compiled_file_name);
1105 java_sources[0] = conftest_file_name;
1106 if (!(!compile_using_envjavac (javac_noassert,
1107 java_sources, 1, tmpdir->dir_name,
1108 false, false, false, true)
1109 && stat (compiled_file_name, &statbuf) >= 0))
1110 /* Compilation failed. */
1111 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1112 javac_works = true;
1115 free (compiled_file_name);
1116 free (conftest_file_name);
1119 cleanup_temp_dir (tmpdir);
1121 if (javac_works)
1123 envjavac_usable = true;
1124 envjavac_need_no_assert_option = false;
1126 else if (javac_noassert_works)
1128 envjavac_usable = true;
1129 envjavac_need_no_assert_option = true;
1132 envjavac_tested = true;
1135 *usablep = envjavac_usable;
1136 *need_no_assert_option_p = envjavac_need_no_assert_option;
1137 return false;
1140 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1141 whether it needs a -source and/or -target option.
1142 Return a failure indicator (true upon error). */
1143 static bool
1144 is_envjavac_nongcj_usable (const char *javac,
1145 const char *source_version,
1146 const char *source_version_for_javac,
1147 const char *target_version,
1148 bool *usablep,
1149 bool *source_option_p, bool *target_option_p)
1151 /* The cache depends on the source_version and target_version. */
1152 struct result_t
1154 bool tested;
1155 bool usable;
1156 bool source_option;
1157 bool target_option;
1159 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1160 struct result_t *resultp;
1162 resultp = &result_cache[source_version_index (source_version)]
1163 [target_version_index (target_version)];
1164 if (!resultp->tested)
1166 /* Try $JAVAC. */
1167 struct temp_dir *tmpdir;
1168 char *conftest_file_name;
1169 char *compiled_file_name;
1170 const char *java_sources[1];
1171 struct stat statbuf;
1173 tmpdir = create_temp_dir ("java", NULL, false);
1174 if (tmpdir == NULL)
1175 return true;
1177 conftest_file_name =
1178 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1179 if (write_temp_file (tmpdir, conftest_file_name,
1180 get_goodcode_snippet (source_version)))
1182 free (conftest_file_name);
1183 cleanup_temp_dir (tmpdir);
1184 return true;
1187 compiled_file_name =
1188 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1189 register_temp_file (tmpdir, compiled_file_name);
1191 java_sources[0] = conftest_file_name;
1192 if (!compile_using_envjavac (javac,
1193 java_sources, 1, tmpdir->dir_name,
1194 false, false, false, true)
1195 && stat (compiled_file_name, &statbuf) >= 0
1196 && get_classfile_version (compiled_file_name)
1197 <= corresponding_classfile_version (target_version))
1199 /* $JAVAC compiled conftest.java successfully. */
1200 /* Try adding -source option if it is useful. */
1201 char *javac_source =
1202 xasprintf ("%s -source %s", javac, source_version_for_javac);
1204 unlink (compiled_file_name);
1206 java_sources[0] = conftest_file_name;
1207 if (!compile_using_envjavac (javac_source,
1208 java_sources, 1, tmpdir->dir_name,
1209 false, false, false, true)
1210 && stat (compiled_file_name, &statbuf) >= 0
1211 && get_classfile_version (compiled_file_name)
1212 <= corresponding_classfile_version (target_version))
1214 const char *failcode = get_failcode_snippet (source_version);
1216 if (failcode != NULL)
1218 free (compiled_file_name);
1219 free (conftest_file_name);
1221 conftest_file_name =
1222 xconcatenated_filename (tmpdir->dir_name,
1223 "conftestfail.java",
1224 NULL);
1225 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1227 free (conftest_file_name);
1228 free (javac_source);
1229 cleanup_temp_dir (tmpdir);
1230 return true;
1233 compiled_file_name =
1234 xconcatenated_filename (tmpdir->dir_name,
1235 "conftestfail.class",
1236 NULL);
1237 register_temp_file (tmpdir, compiled_file_name);
1239 java_sources[0] = conftest_file_name;
1240 if (!compile_using_envjavac (javac,
1241 java_sources, 1,
1242 tmpdir->dir_name,
1243 false, false, false, true)
1244 && stat (compiled_file_name, &statbuf) >= 0)
1246 unlink (compiled_file_name);
1248 java_sources[0] = conftest_file_name;
1249 if (compile_using_envjavac (javac_source,
1250 java_sources, 1,
1251 tmpdir->dir_name,
1252 false, false, false, true))
1253 /* $JAVAC compiled conftestfail.java successfully, and
1254 "$JAVAC -source $source_version_for_javac" rejects it.
1255 So the -source option is useful. */
1256 resultp->source_option = true;
1261 free (javac_source);
1263 resultp->usable = true;
1265 else
1267 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1268 option but no -source option.) */
1269 char *javac_target =
1270 xasprintf ("%s -target %s", javac, target_version);
1272 unlink (compiled_file_name);
1274 java_sources[0] = conftest_file_name;
1275 if (!compile_using_envjavac (javac_target,
1276 java_sources, 1, tmpdir->dir_name,
1277 false, false, false, true)
1278 && stat (compiled_file_name, &statbuf) >= 0
1279 && get_classfile_version (compiled_file_name)
1280 <= corresponding_classfile_version (target_version))
1282 /* "$JAVAC -target $target_version" compiled conftest.java
1283 successfully. */
1284 /* Try adding -source option if it is useful. */
1285 char *javac_target_source =
1286 xasprintf ("%s -source %s", javac_target, source_version_for_javac);
1288 unlink (compiled_file_name);
1290 java_sources[0] = conftest_file_name;
1291 if (!compile_using_envjavac (javac_target_source,
1292 java_sources, 1, tmpdir->dir_name,
1293 false, false, false, true)
1294 && stat (compiled_file_name, &statbuf) >= 0
1295 && get_classfile_version (compiled_file_name)
1296 <= corresponding_classfile_version (target_version))
1298 const char *failcode = get_failcode_snippet (source_version);
1300 if (failcode != NULL)
1302 free (compiled_file_name);
1303 free (conftest_file_name);
1305 conftest_file_name =
1306 xconcatenated_filename (tmpdir->dir_name,
1307 "conftestfail.java",
1308 NULL);
1309 if (write_temp_file (tmpdir, conftest_file_name,
1310 failcode))
1312 free (conftest_file_name);
1313 free (javac_target_source);
1314 free (javac_target);
1315 cleanup_temp_dir (tmpdir);
1316 return true;
1319 compiled_file_name =
1320 xconcatenated_filename (tmpdir->dir_name,
1321 "conftestfail.class",
1322 NULL);
1323 register_temp_file (tmpdir, compiled_file_name);
1325 java_sources[0] = conftest_file_name;
1326 if (!compile_using_envjavac (javac_target,
1327 java_sources, 1,
1328 tmpdir->dir_name,
1329 false, false, false, true)
1330 && stat (compiled_file_name, &statbuf) >= 0)
1332 unlink (compiled_file_name);
1334 java_sources[0] = conftest_file_name;
1335 if (compile_using_envjavac (javac_target_source,
1336 java_sources, 1,
1337 tmpdir->dir_name,
1338 false, false, false,
1339 true))
1340 /* "$JAVAC -target $target_version" compiled
1341 conftestfail.java successfully, and
1342 "$JAVAC -target $target_version -source $source_version_for_javac"
1343 rejects it. So the -source option is useful. */
1344 resultp->source_option = true;
1349 free (javac_target_source);
1351 resultp->target_option = true;
1352 resultp->usable = true;
1354 else
1356 /* Maybe this -target option requires a -source option? Try with
1357 -target and -source options. (Supported by Sun javac 1.4 and
1358 higher.) */
1359 char *javac_target_source =
1360 xasprintf ("%s -source %s", javac_target, source_version_for_javac);
1362 unlink (compiled_file_name);
1364 java_sources[0] = conftest_file_name;
1365 if (!compile_using_envjavac (javac_target_source,
1366 java_sources, 1, tmpdir->dir_name,
1367 false, false, false, true)
1368 && stat (compiled_file_name, &statbuf) >= 0
1369 && get_classfile_version (compiled_file_name)
1370 <= corresponding_classfile_version (target_version))
1372 /* "$JAVAC -target $target_version -source $source_version_for_javac"
1373 compiled conftest.java successfully. */
1374 resultp->source_option = true;
1375 resultp->target_option = true;
1376 resultp->usable = true;
1379 free (javac_target_source);
1382 free (javac_target);
1385 free (compiled_file_name);
1386 free (conftest_file_name);
1388 resultp->tested = true;
1391 *usablep = resultp->usable;
1392 *source_option_p = resultp->source_option;
1393 *target_option_p = resultp->target_option;
1394 return false;
1397 static bool
1398 is_gcj_present (void)
1400 static bool gcj_tested;
1401 static bool gcj_present;
1403 if (!gcj_tested)
1405 /* Test for presence of gcj:
1406 "gcj --version 2> /dev/null | \
1407 sed -e 's,^[^0-9]*,,' -e 1q | \
1408 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1409 const char *argv[3];
1410 pid_t child;
1411 int fd[1];
1412 int exitstatus;
1414 argv[0] = "gcj";
1415 argv[1] = "--version";
1416 argv[2] = NULL;
1417 child = create_pipe_in ("gcj", "gcj", argv, NULL,
1418 DEV_NULL, true, true, false, fd);
1419 gcj_present = false;
1420 if (child != -1)
1422 /* Read the subprocess output, drop all lines except the first,
1423 drop all characters before the first digit, and test whether
1424 the remaining string starts with a digit >= 3, but not with
1425 "3.0" or "3.1". */
1426 char c[3];
1427 size_t count = 0;
1429 while (safe_read (fd[0], &c[count], 1) > 0)
1431 if (c[count] == '\n')
1432 break;
1433 if (count == 0)
1435 if (!(c[0] >= '0' && c[0] <= '9'))
1436 continue;
1437 gcj_present = (c[0] >= '3');
1439 count++;
1440 if (count == 3)
1442 if (c[0] == '3' && c[1] == '.'
1443 && (c[2] == '0' || c[2] == '1'))
1444 gcj_present = false;
1445 break;
1448 while (safe_read (fd[0], &c[0], 1) > 0)
1451 close (fd[0]);
1453 /* Remove zombie process from process list, and retrieve exit
1454 status. */
1455 exitstatus =
1456 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1457 if (exitstatus != 0)
1458 gcj_present = false;
1461 if (gcj_present)
1463 /* See if libgcj.jar is well installed. */
1464 struct temp_dir *tmpdir;
1466 tmpdir = create_temp_dir ("java", NULL, false);
1467 if (tmpdir == NULL)
1468 gcj_present = false;
1469 else
1471 char *conftest_file_name;
1473 conftest_file_name =
1474 xconcatenated_filename (tmpdir->dir_name, "conftestlib.java",
1475 NULL);
1476 if (write_temp_file (tmpdir, conftest_file_name,
1477 "public class conftestlib {\n"
1478 " public static void main (String[] args) {\n"
1479 " }\n"
1480 "}\n"))
1481 gcj_present = false;
1482 else
1484 char *compiled_file_name;
1485 const char *java_sources[1];
1487 compiled_file_name =
1488 xconcatenated_filename (tmpdir->dir_name,
1489 "conftestlib.class",
1490 NULL);
1491 register_temp_file (tmpdir, compiled_file_name);
1493 java_sources[0] = conftest_file_name;
1494 if (compile_using_gcj (java_sources, 1, false,
1495 false, NULL, false, NULL,
1496 tmpdir->dir_name,
1497 false, false, false, true))
1498 gcj_present = false;
1500 free (compiled_file_name);
1502 free (conftest_file_name);
1504 cleanup_temp_dir (tmpdir);
1507 gcj_tested = true;
1510 return gcj_present;
1513 static bool
1514 is_gcj_43 (void)
1516 static bool gcj_tested;
1517 static bool gcj_43;
1519 if (!gcj_tested)
1521 /* Test for presence of gcj:
1522 "gcj --version 2> /dev/null | \
1523 sed -e 's,^[^0-9]*,,' -e 1q | \
1524 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1525 const char *argv[3];
1526 pid_t child;
1527 int fd[1];
1528 int exitstatus;
1530 argv[0] = "gcj";
1531 argv[1] = "--version";
1532 argv[2] = NULL;
1533 child = create_pipe_in ("gcj", "gcj", argv, NULL,
1534 DEV_NULL, true, true, false, fd);
1535 gcj_43 = false;
1536 if (child != -1)
1538 /* Read the subprocess output, drop all lines except the first,
1539 drop all characters before the first digit, and test whether
1540 the remaining string starts with a digit >= 4, but not with
1541 "4.0" or "4.1" or "4.2". */
1542 char c[3];
1543 size_t count = 0;
1545 while (safe_read (fd[0], &c[count], 1) > 0)
1547 if (c[count] == '\n')
1548 break;
1549 if (count == 0)
1551 if (!(c[0] >= '0' && c[0] <= '9'))
1552 continue;
1553 gcj_43 = (c[0] >= '4');
1555 count++;
1556 if (count == 3)
1558 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
1559 gcj_43 = false;
1560 break;
1563 while (safe_read (fd[0], &c[0], 1) > 0)
1566 close (fd[0]);
1568 /* Remove zombie process from process list, and retrieve exit
1569 status. */
1570 exitstatus =
1571 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1572 if (exitstatus != 0)
1573 gcj_43 = false;
1576 gcj_tested = true;
1579 return gcj_43;
1582 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1583 -ftarget option.
1584 Return a failure indicator (true upon error). */
1585 static bool
1586 is_gcj43_usable (const char *source_version,
1587 const char *target_version,
1588 bool *usablep,
1589 bool *fsource_option_p, bool *ftarget_option_p)
1591 /* The cache depends on the source_version and target_version. */
1592 struct result_t
1594 bool tested;
1595 bool usable;
1596 bool fsource_option;
1597 bool ftarget_option;
1599 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1600 struct result_t *resultp;
1602 resultp = &result_cache[source_version_index (source_version)]
1603 [target_version_index (target_version)];
1604 if (!resultp->tested)
1606 /* Try gcj. */
1607 struct temp_dir *tmpdir;
1608 char *conftest_file_name;
1609 char *compiled_file_name;
1610 const char *java_sources[1];
1611 struct stat statbuf;
1613 tmpdir = create_temp_dir ("java", NULL, false);
1614 if (tmpdir == NULL)
1615 return true;
1617 conftest_file_name =
1618 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1619 if (write_temp_file (tmpdir, conftest_file_name,
1620 get_goodcode_snippet (source_version)))
1622 free (conftest_file_name);
1623 cleanup_temp_dir (tmpdir);
1624 return true;
1627 compiled_file_name =
1628 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1629 register_temp_file (tmpdir, compiled_file_name);
1631 java_sources[0] = conftest_file_name;
1632 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1633 tmpdir->dir_name, false, false, false, true)
1634 && stat (compiled_file_name, &statbuf) >= 0
1635 && get_classfile_version (compiled_file_name)
1636 <= corresponding_classfile_version (target_version))
1638 /* gcj compiled conftest.java successfully. */
1639 /* Try adding -fsource option if it is useful. */
1640 unlink (compiled_file_name);
1642 java_sources[0] = conftest_file_name;
1643 if (!compile_using_gcj (java_sources, 1,
1644 false, true, source_version, false, NULL,
1645 tmpdir->dir_name, false, false, false, true)
1646 && stat (compiled_file_name, &statbuf) >= 0
1647 && get_classfile_version (compiled_file_name)
1648 <= corresponding_classfile_version (target_version))
1650 const char *failcode = get_failcode_snippet (source_version);
1652 if (failcode != NULL)
1654 free (compiled_file_name);
1655 free (conftest_file_name);
1657 conftest_file_name =
1658 xconcatenated_filename (tmpdir->dir_name,
1659 "conftestfail.java",
1660 NULL);
1661 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1663 free (conftest_file_name);
1664 cleanup_temp_dir (tmpdir);
1665 return true;
1668 compiled_file_name =
1669 xconcatenated_filename (tmpdir->dir_name,
1670 "conftestfail.class",
1671 NULL);
1672 register_temp_file (tmpdir, compiled_file_name);
1674 java_sources[0] = conftest_file_name;
1675 if (!compile_using_gcj (java_sources, 1,
1676 false, false, NULL, false, NULL,
1677 tmpdir->dir_name,
1678 false, false, false, true)
1679 && stat (compiled_file_name, &statbuf) >= 0)
1681 unlink (compiled_file_name);
1683 java_sources[0] = conftest_file_name;
1684 if (compile_using_gcj (java_sources, 1,
1685 false, true, source_version,
1686 false, NULL,
1687 tmpdir->dir_name,
1688 false, false, false, true))
1689 /* gcj compiled conftestfail.java successfully, and
1690 "gcj -fsource=$source_version" rejects it. So
1691 the -fsource option is useful. */
1692 resultp->fsource_option = true;
1697 resultp->usable = true;
1699 else
1701 /* Try with -fsource and -ftarget options. */
1702 unlink (compiled_file_name);
1704 java_sources[0] = conftest_file_name;
1705 if (!compile_using_gcj (java_sources, 1,
1706 false, true, source_version,
1707 true, target_version,
1708 tmpdir->dir_name,
1709 false, false, false, true)
1710 && stat (compiled_file_name, &statbuf) >= 0
1711 && get_classfile_version (compiled_file_name)
1712 <= corresponding_classfile_version (target_version))
1714 /* "gcj -fsource $source_version -ftarget $target_version"
1715 compiled conftest.java successfully. */
1716 resultp->fsource_option = true;
1717 resultp->ftarget_option = true;
1718 resultp->usable = true;
1722 free (compiled_file_name);
1723 free (conftest_file_name);
1725 resultp->tested = true;
1728 *usablep = resultp->usable;
1729 *fsource_option_p = resultp->fsource_option;
1730 *ftarget_option_p = resultp->ftarget_option;
1731 return false;
1734 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1735 and source_version = 1.4.
1736 Return a failure indicator (true upon error). */
1737 static bool
1738 is_oldgcj_14_14_usable (bool *usablep)
1740 static bool gcj_tested;
1741 static bool gcj_usable;
1743 if (!gcj_tested)
1745 /* Try gcj. */
1746 struct temp_dir *tmpdir;
1747 char *conftest_file_name;
1748 char *compiled_file_name;
1749 const char *java_sources[1];
1750 struct stat statbuf;
1752 tmpdir = create_temp_dir ("java", NULL, false);
1753 if (tmpdir == NULL)
1754 return true;
1756 conftest_file_name =
1757 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1758 if (write_temp_file (tmpdir, conftest_file_name,
1759 get_goodcode_snippet ("1.4")))
1761 free (conftest_file_name);
1762 cleanup_temp_dir (tmpdir);
1763 return true;
1766 compiled_file_name =
1767 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1768 register_temp_file (tmpdir, compiled_file_name);
1770 java_sources[0] = conftest_file_name;
1771 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1772 tmpdir->dir_name, false, false, false, true)
1773 && stat (compiled_file_name, &statbuf) >= 0)
1774 /* Compilation succeeded. */
1775 gcj_usable = true;
1777 free (compiled_file_name);
1778 free (conftest_file_name);
1780 cleanup_temp_dir (tmpdir);
1782 gcj_tested = true;
1785 *usablep = gcj_usable;
1786 return false;
1789 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1790 and source_version = 1.3.
1791 Return a failure indicator (true upon error). */
1792 static bool
1793 is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
1795 static bool gcj_tested;
1796 static bool gcj_usable;
1797 static bool gcj_need_no_assert_option;
1799 if (!gcj_tested)
1801 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1802 it works (not gcj < 3.3). */
1803 struct temp_dir *tmpdir;
1804 char *conftest_file_name;
1805 char *compiled_file_name;
1806 const char *java_sources[1];
1807 struct stat statbuf;
1809 tmpdir = create_temp_dir ("java", NULL, false);
1810 if (tmpdir == NULL)
1811 return true;
1813 conftest_file_name =
1814 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1815 if (write_temp_file (tmpdir, conftest_file_name,
1816 get_goodcode_snippet ("1.3")))
1818 free (conftest_file_name);
1819 cleanup_temp_dir (tmpdir);
1820 return true;
1823 compiled_file_name =
1824 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1825 register_temp_file (tmpdir, compiled_file_name);
1827 java_sources[0] = conftest_file_name;
1828 if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL,
1829 tmpdir->dir_name, false, false, false, true)
1830 && stat (compiled_file_name, &statbuf) >= 0)
1831 /* Compilation succeeded. */
1833 gcj_usable = true;
1834 gcj_need_no_assert_option = true;
1836 else
1838 unlink (compiled_file_name);
1840 java_sources[0] = conftest_file_name;
1841 if (!compile_using_gcj (java_sources, 1, false,
1842 false, NULL, false, NULL,
1843 tmpdir->dir_name, false, false, false, true)
1844 && stat (compiled_file_name, &statbuf) >= 0)
1845 /* Compilation succeeded. */
1847 gcj_usable = true;
1848 gcj_need_no_assert_option = false;
1852 free (compiled_file_name);
1853 free (conftest_file_name);
1855 cleanup_temp_dir (tmpdir);
1857 gcj_tested = true;
1860 *usablep = gcj_usable;
1861 *need_no_assert_option_p = gcj_need_no_assert_option;
1862 return false;
1865 static bool
1866 is_javac_present (void)
1868 static bool javac_tested;
1869 static bool javac_present;
1871 if (!javac_tested)
1873 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1874 const char *argv[2];
1875 int exitstatus;
1877 argv[0] = "javac";
1878 argv[1] = NULL;
1879 exitstatus = execute ("javac", "javac", argv, NULL,
1880 false, false, true, true,
1881 true, false, NULL);
1882 javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
1883 javac_tested = true;
1886 return javac_present;
1889 /* Test whether javac can be used and whether it needs a -source and/or
1890 -target option.
1891 Return a failure indicator (true upon error). */
1892 static bool
1893 is_javac_usable (const char *source_version,
1894 const char *source_version_for_javac,
1895 const char *target_version,
1896 bool *usablep, bool *source_option_p, bool *target_option_p)
1898 /* The cache depends on the source_version and target_version. */
1899 struct result_t
1901 bool tested;
1902 bool usable;
1903 bool source_option;
1904 bool target_option;
1906 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1907 struct result_t *resultp;
1909 resultp = &result_cache[source_version_index (source_version)]
1910 [target_version_index (target_version)];
1911 if (!resultp->tested)
1913 /* Try javac. */
1914 struct temp_dir *tmpdir;
1915 char *conftest_file_name;
1916 char *compiled_file_name;
1917 const char *java_sources[1];
1918 struct stat statbuf;
1920 tmpdir = create_temp_dir ("java", NULL, false);
1921 if (tmpdir == NULL)
1922 return true;
1924 conftest_file_name =
1925 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1926 if (write_temp_file (tmpdir, conftest_file_name,
1927 get_goodcode_snippet (source_version)))
1929 free (conftest_file_name);
1930 cleanup_temp_dir (tmpdir);
1931 return true;
1934 compiled_file_name =
1935 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1936 register_temp_file (tmpdir, compiled_file_name);
1938 java_sources[0] = conftest_file_name;
1939 if (!compile_using_javac (java_sources, 1,
1940 false, source_version_for_javac,
1941 false, target_version,
1942 tmpdir->dir_name, false, false, false, true)
1943 && stat (compiled_file_name, &statbuf) >= 0
1944 && get_classfile_version (compiled_file_name)
1945 <= corresponding_classfile_version (target_version))
1947 /* javac compiled conftest.java successfully. */
1948 /* Try adding -source option if it is useful. */
1949 unlink (compiled_file_name);
1951 java_sources[0] = conftest_file_name;
1952 if (!compile_using_javac (java_sources, 1,
1953 true, source_version_for_javac,
1954 false, target_version,
1955 tmpdir->dir_name, false, false, false, true)
1956 && stat (compiled_file_name, &statbuf) >= 0
1957 && get_classfile_version (compiled_file_name)
1958 <= corresponding_classfile_version (target_version))
1960 const char *failcode = get_failcode_snippet (source_version);
1962 if (failcode != NULL)
1964 free (compiled_file_name);
1965 free (conftest_file_name);
1967 conftest_file_name =
1968 xconcatenated_filename (tmpdir->dir_name,
1969 "conftestfail.java",
1970 NULL);
1971 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1973 free (conftest_file_name);
1974 cleanup_temp_dir (tmpdir);
1975 return true;
1978 compiled_file_name =
1979 xconcatenated_filename (tmpdir->dir_name,
1980 "conftestfail.class",
1981 NULL);
1982 register_temp_file (tmpdir, compiled_file_name);
1984 java_sources[0] = conftest_file_name;
1985 if (!compile_using_javac (java_sources, 1,
1986 false, source_version_for_javac,
1987 false, target_version,
1988 tmpdir->dir_name,
1989 false, false, false, true)
1990 && stat (compiled_file_name, &statbuf) >= 0)
1992 unlink (compiled_file_name);
1994 java_sources[0] = conftest_file_name;
1995 if (compile_using_javac (java_sources, 1,
1996 true, source_version_for_javac,
1997 false, target_version,
1998 tmpdir->dir_name,
1999 false, false, false, true))
2000 /* javac compiled conftestfail.java successfully, and
2001 "javac -source $source_version_for_javac" rejects it.
2002 So the -source option is useful. */
2003 resultp->source_option = true;
2008 resultp->usable = true;
2010 else
2012 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
2013 option but no -source option.) */
2014 unlink (compiled_file_name);
2016 java_sources[0] = conftest_file_name;
2017 if (!compile_using_javac (java_sources, 1,
2018 false, source_version_for_javac,
2019 true, target_version,
2020 tmpdir->dir_name,
2021 false, false, false, true)
2022 && stat (compiled_file_name, &statbuf) >= 0
2023 && get_classfile_version (compiled_file_name)
2024 <= corresponding_classfile_version (target_version))
2026 /* "javac -target $target_version" compiled conftest.java
2027 successfully. */
2028 /* Try adding -source option if it is useful. */
2029 unlink (compiled_file_name);
2031 java_sources[0] = conftest_file_name;
2032 if (!compile_using_javac (java_sources, 1,
2033 true, source_version_for_javac,
2034 true, target_version,
2035 tmpdir->dir_name,
2036 false, false, false, true)
2037 && stat (compiled_file_name, &statbuf) >= 0
2038 && get_classfile_version (compiled_file_name)
2039 <= corresponding_classfile_version (target_version))
2041 const char *failcode = get_failcode_snippet (source_version);
2043 if (failcode != NULL)
2045 free (compiled_file_name);
2046 free (conftest_file_name);
2048 conftest_file_name =
2049 xconcatenated_filename (tmpdir->dir_name,
2050 "conftestfail.java",
2051 NULL);
2052 if (write_temp_file (tmpdir, conftest_file_name,
2053 failcode))
2055 free (conftest_file_name);
2056 cleanup_temp_dir (tmpdir);
2057 return true;
2060 compiled_file_name =
2061 xconcatenated_filename (tmpdir->dir_name,
2062 "conftestfail.class",
2063 NULL);
2064 register_temp_file (tmpdir, compiled_file_name);
2066 java_sources[0] = conftest_file_name;
2067 if (!compile_using_javac (java_sources, 1,
2068 false, source_version_for_javac,
2069 true, target_version,
2070 tmpdir->dir_name,
2071 false, false, false, true)
2072 && stat (compiled_file_name, &statbuf) >= 0)
2074 unlink (compiled_file_name);
2076 java_sources[0] = conftest_file_name;
2077 if (compile_using_javac (java_sources, 1,
2078 true, source_version_for_javac,
2079 true, target_version,
2080 tmpdir->dir_name,
2081 false, false, false, true))
2082 /* "javac -target $target_version" compiled
2083 conftestfail.java successfully, and
2084 "javac -target $target_version -source $source_version_for_javac"
2085 rejects it. So the -source option is useful. */
2086 resultp->source_option = true;
2091 resultp->target_option = true;
2092 resultp->usable = true;
2094 else
2096 /* Maybe this -target option requires a -source option? Try with
2097 -target and -source options. (Supported by Sun javac 1.4 and
2098 higher.) */
2099 unlink (compiled_file_name);
2101 java_sources[0] = conftest_file_name;
2102 if (!compile_using_javac (java_sources, 1,
2103 true, source_version_for_javac,
2104 true, target_version,
2105 tmpdir->dir_name,
2106 false, false, false, true)
2107 && stat (compiled_file_name, &statbuf) >= 0
2108 && get_classfile_version (compiled_file_name)
2109 <= corresponding_classfile_version (target_version))
2111 /* "javac -target $target_version -source $source_version_for_javac"
2112 compiled conftest.java successfully. */
2113 resultp->source_option = true;
2114 resultp->target_option = true;
2115 resultp->usable = true;
2120 free (compiled_file_name);
2121 free (conftest_file_name);
2123 resultp->tested = true;
2126 *usablep = resultp->usable;
2127 *source_option_p = resultp->source_option;
2128 *target_option_p = resultp->target_option;
2129 return false;
2132 static bool
2133 is_jikes_present (void)
2135 static bool jikes_tested;
2136 static bool jikes_present;
2138 if (!jikes_tested)
2140 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2141 const char *argv[2];
2142 int exitstatus;
2144 argv[0] = "jikes";
2145 argv[1] = NULL;
2146 exitstatus = execute ("jikes", "jikes", argv, NULL,
2147 false, false, true, true,
2148 true, false, NULL);
2149 jikes_present = (exitstatus == 0 || exitstatus == 1);
2150 jikes_tested = true;
2153 return jikes_present;
2156 /* ============================= Main function ============================= */
2158 bool
2159 compile_java_class (const char * const *java_sources,
2160 unsigned int java_sources_count,
2161 const char * const *classpaths,
2162 unsigned int classpaths_count,
2163 const char *source_version,
2164 const char *target_version,
2165 const char *directory,
2166 bool optimize, bool debug,
2167 bool use_minimal_classpath,
2168 bool verbose)
2170 bool err = false;
2171 char *old_JAVA_HOME;
2174 const char *javac = getenv ("JAVAC");
2175 if (javac != NULL && javac[0] != '\0')
2177 bool usable = false;
2178 bool no_assert_option = false;
2179 bool source_option = false;
2180 bool target_option = false;
2181 bool fsource_option = false;
2182 bool ftarget_option = false;
2183 const char *source_version_for_javac;
2185 if (target_version == NULL)
2186 target_version = default_target_version ();
2188 source_version_for_javac =
2189 get_source_version_for_javac (source_version, target_version);
2191 if (is_envjavac_gcj (javac))
2193 /* It's a version of gcj. */
2194 if (is_envjavac_gcj43 (javac))
2196 /* It's a version of gcj >= 4.3. Assume the classfile versions
2197 are correct. */
2198 if (is_envjavac_gcj43_usable (javac,
2199 source_version, target_version,
2200 &usable,
2201 &fsource_option, &ftarget_option))
2203 err = true;
2204 goto done1;
2207 else
2209 /* It's a version of gcj < 4.3. Ignore the version of the
2210 class files that it creates. */
2211 if (strcmp (target_version, "1.4") == 0
2212 && strcmp (source_version, "1.4") == 0)
2214 if (is_envjavac_oldgcj_14_14_usable (javac, &usable))
2216 err = true;
2217 goto done1;
2220 else if (strcmp (target_version, "1.4") == 0
2221 && strcmp (source_version, "1.3") == 0)
2223 if (is_envjavac_oldgcj_14_13_usable (javac,
2224 &usable,
2225 &no_assert_option))
2227 err = true;
2228 goto done1;
2233 else
2235 /* It's not gcj. Assume the classfile versions are correct. */
2236 if (is_envjavac_nongcj_usable (javac,
2237 source_version,
2238 source_version_for_javac,
2239 target_version,
2240 &usable,
2241 &source_option, &target_option))
2243 err = true;
2244 goto done1;
2248 if (usable)
2250 char *old_classpath;
2251 char *javac_with_options;
2253 /* Set CLASSPATH. */
2254 old_classpath =
2255 set_classpath (classpaths, classpaths_count, false, verbose);
2257 javac_with_options =
2258 (no_assert_option
2259 ? xasprintf ("%s -fno-assert", javac)
2260 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2261 javac,
2262 source_option ? " -source " : "",
2263 source_option ? source_version_for_javac : "",
2264 target_option ? " -target " : "",
2265 target_option ? target_version : "",
2266 fsource_option ? " -fsource=" : "",
2267 fsource_option ? source_version : "",
2268 ftarget_option ? " -ftarget=" : "",
2269 ftarget_option ? target_version : ""));
2271 err = compile_using_envjavac (javac_with_options,
2272 java_sources, java_sources_count,
2273 directory, optimize, debug, verbose,
2274 false);
2276 free (javac_with_options);
2278 /* Reset CLASSPATH. */
2279 reset_classpath (old_classpath);
2281 goto done1;
2286 /* Unset the JAVA_HOME environment variable. */
2287 old_JAVA_HOME = getenv ("JAVA_HOME");
2288 if (old_JAVA_HOME != NULL)
2290 old_JAVA_HOME = xstrdup (old_JAVA_HOME);
2291 unsetenv ("JAVA_HOME");
2294 if (is_gcj_present ())
2296 /* It's a version of gcj. */
2297 bool usable = false;
2298 bool no_assert_option = false;
2299 bool fsource_option = false;
2300 bool ftarget_option = false;
2302 if (target_version == NULL)
2303 target_version = default_target_version ();
2305 if (is_gcj_43 ())
2307 /* It's a version of gcj >= 4.3. Assume the classfile versions
2308 are correct. */
2309 if (is_gcj43_usable (source_version, target_version,
2310 &usable, &fsource_option, &ftarget_option))
2312 err = true;
2313 goto done1;
2316 else
2318 /* It's a version of gcj < 4.3. Ignore the version of the class
2319 files that it creates.
2320 Test whether it supports the desired target-version and
2321 source-version. */
2322 if (strcmp (target_version, "1.4") == 0
2323 && strcmp (source_version, "1.4") == 0)
2325 if (is_oldgcj_14_14_usable (&usable))
2327 err = true;
2328 goto done1;
2331 else if (strcmp (target_version, "1.4") == 0
2332 && strcmp (source_version, "1.3") == 0)
2334 if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
2336 err = true;
2337 goto done1;
2342 if (usable)
2344 char *old_classpath;
2346 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2347 of gcj. Note that --classpath=... option is different: its
2348 argument should also contain gcj's libgcj.jar, but we don't
2349 know its location. */
2350 old_classpath =
2351 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2352 verbose);
2354 err = compile_using_gcj (java_sources, java_sources_count,
2355 no_assert_option,
2356 fsource_option, source_version,
2357 ftarget_option, target_version,
2358 directory, optimize, debug, verbose, false);
2360 /* Reset CLASSPATH. */
2361 reset_classpath (old_classpath);
2363 goto done2;
2367 if (is_javac_present ())
2369 bool usable = false;
2370 bool source_option = false;
2371 bool target_option = false;
2372 const char *source_version_for_javac;
2374 if (target_version == NULL)
2375 target_version = default_target_version ();
2377 source_version_for_javac =
2378 get_source_version_for_javac (source_version, target_version);
2380 if (is_javac_usable (source_version, source_version_for_javac,
2381 target_version,
2382 &usable, &source_option, &target_option))
2384 err = true;
2385 goto done1;
2388 if (usable)
2390 char *old_classpath;
2392 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2393 in JDK 1.1.x its argument should also contain the JDK's
2394 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2395 would work.) */
2396 old_classpath =
2397 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2398 verbose);
2400 err = compile_using_javac (java_sources, java_sources_count,
2401 source_option, source_version_for_javac,
2402 target_option, target_version,
2403 directory, optimize, debug, verbose,
2404 false);
2406 /* Reset CLASSPATH. */
2407 reset_classpath (old_classpath);
2409 goto done2;
2413 if (is_jikes_present ())
2415 /* Test whether it supports the desired target-version and
2416 source-version. */
2417 bool usable = (strcmp (source_version, "1.3") == 0);
2419 if (usable)
2421 char *old_classpath;
2423 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2424 Since jikes doesn't come with its own standard library, it
2425 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2426 To increase the chance of success, we reuse the current CLASSPATH
2427 if the user has set it. */
2428 old_classpath =
2429 set_classpath (classpaths, classpaths_count, false, verbose);
2431 err = compile_using_jikes (java_sources, java_sources_count,
2432 directory, optimize, debug, verbose,
2433 false);
2435 /* Reset CLASSPATH. */
2436 reset_classpath (old_classpath);
2438 goto done2;
2442 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2443 err = true;
2445 done2:
2446 if (old_JAVA_HOME != NULL)
2448 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
2449 free (old_JAVA_HOME);
2452 done1:
2453 return err;