This source file includes following definitions.
- default_target_version
- source_version_index
- get_goodcode_snippet
- get_failcode_snippet
- target_version_index
- corresponding_classfile_version
- get_source_version_for_javac
- compile_using_envjavac
- compile_using_gcj
- compile_using_javac
- compile_using_jikes
- write_temp_file
- get_classfile_version
- is_envjavac_gcj
- is_envjavac_gcj43
- is_envjavac_gcj43_usable
- is_envjavac_oldgcj_14_14_usable
- is_envjavac_oldgcj_14_13_usable
- is_envjavac_nongcj_usable
- is_gcj_present
- is_gcj_43
- is_gcj43_usable
- is_oldgcj_14_14_usable
- is_oldgcj_14_13_usable
- is_javac_present
- is_javac_usable
- is_jikes_present
- compile_java_class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <config.h>
19 #include <alloca.h>
20
21
22 #include "javacomp.h"
23
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>
32
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"
51
52 #define _(str) gettext (str)
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 static const char *
92 default_target_version (void)
93 {
94
95
96 static const char *java_version_cache;
97 if (java_version_cache == NULL)
98 {
99
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
114 ;
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
120
121 java_version_cache = "11";
122 else
123 java_version_cache = "1.1";
124 }
125 return java_version_cache;
126 }
127
128
129
130
131 #define SOURCE_VERSION_BOUND 8
132 static unsigned int
133 source_version_index (const char *source_version)
134 {
135 if (source_version[0] == '1' && source_version[1] == '.')
136 {
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';
143 }
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;
152 }
153
154
155 static const char *
156 get_goodcode_snippet (const char *source_version)
157 {
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;
176 }
177
178
179
180
181 static const char *
182 get_failcode_snippet (const char *source_version)
183 {
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;
202 }
203
204
205
206
207 #define TARGET_VERSION_BOUND 11
208 static unsigned int
209 target_version_index (const char *target_version)
210 {
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;
223 }
224
225
226
227 static int
228 corresponding_classfile_version (const char *target_version)
229 {
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;
254 }
255
256
257 static const char *
258 get_source_version_for_javac (const char *source_version,
259 const char *target_version)
260 {
261
262
263
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;
270 }
271
272
273
274
275
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)
283 {
284
285
286
287
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;
295
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;
306
307 command = (char *) xmalloca (command_length);
308 p = command;
309
310
311 memcpy (p, javac, strlen (javac));
312 p += strlen (javac);
313 if (optimize)
314 {
315 memcpy (p, " -O", 3);
316 p += 3;
317 }
318 if (debug)
319 {
320 memcpy (p, " -g", 3);
321 p += 3;
322 }
323 if (directory != NULL)
324 {
325 memcpy (p, " -d ", 4);
326 p += 4;
327 p = shell_quote_copy (p, directory);
328 }
329 for (i = 0; i < java_sources_count; i++)
330 {
331 *p++ = ' ';
332 p = shell_quote_copy (p, java_sources[i]);
333 }
334 *p++ = '\0';
335
336 if (p - command > command_length)
337 abort ();
338
339 if (verbose)
340 printf ("%s\n", command);
341
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);
350
351 freea (command);
352
353 return err;
354 }
355
356
357
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)
367 {
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;
376
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 *));
382
383 argp = argv;
384 *argp++ = "gcj";
385 *argp++ = "-C";
386 if (no_assert_option)
387 *argp++ = "-fno-assert";
388 if (fsource_option)
389 {
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;
394 }
395 else
396 fsource_arg = NULL;
397 if (ftarget_option)
398 {
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;
403 }
404 else
405 ftarget_arg = NULL;
406 if (optimize)
407 *argp++ = "-O";
408 if (debug)
409 *argp++ = "-g";
410 if (directory != NULL)
411 {
412 *argp++ = "-d";
413 *argp++ = directory;
414 }
415 for (i = 0; i < java_sources_count; i++)
416 *argp++ = java_sources[i];
417 *argp = NULL;
418
419 if (argp - argv != argc)
420 abort ();
421
422 if (verbose)
423 {
424 char *command = shell_quote_argv (argv);
425 printf ("%s\n", command);
426 free (command);
427 }
428
429 exitstatus = execute ("gcj", "gcj", argv, NULL,
430 false, false, false, null_stderr,
431 true, true, NULL);
432 err = (exitstatus != 0);
433
434 if (ftarget_arg != NULL)
435 freea (ftarget_arg);
436 if (fsource_arg != NULL)
437 freea (fsource_arg);
438 freea (argv);
439
440 return err;
441 }
442
443
444
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)
453 {
454 bool err;
455 unsigned int argc;
456 const char **argv;
457 const char **argp;
458 int exitstatus;
459 unsigned int i;
460
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 *));
465
466 argp = argv;
467 *argp++ = "javac";
468 if (source_option)
469 {
470 *argp++ = "-source";
471 *argp++ = source_version;
472 }
473 if (target_option)
474 {
475 *argp++ = "-target";
476 *argp++ = target_version;
477 }
478 if (optimize)
479 *argp++ = "-O";
480 if (debug)
481 *argp++ = "-g";
482 if (directory != NULL)
483 {
484 *argp++ = "-d";
485 *argp++ = directory;
486 }
487 for (i = 0; i < java_sources_count; i++)
488 *argp++ = java_sources[i];
489 *argp = NULL;
490
491 if (argp - argv != argc)
492 abort ();
493
494 if (verbose)
495 {
496 char *command = shell_quote_argv (argv);
497 printf ("%s\n", command);
498 free (command);
499 }
500
501 exitstatus = execute ("javac", "javac", argv, NULL,
502 false, false, false,
503 null_stderr, true, true, NULL);
504 err = (exitstatus != 0);
505
506 freea (argv);
507
508 return err;
509 }
510
511
512
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)
519 {
520 bool err;
521 unsigned int argc;
522 const char **argv;
523 const char **argp;
524 int exitstatus;
525 unsigned int i;
526
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 *));
531
532 argp = argv;
533 *argp++ = "jikes";
534 if (optimize)
535 *argp++ = "-O";
536 if (debug)
537 *argp++ = "-g";
538 if (directory != NULL)
539 {
540 *argp++ = "-d";
541 *argp++ = directory;
542 }
543 for (i = 0; i < java_sources_count; i++)
544 *argp++ = java_sources[i];
545 *argp = NULL;
546
547 if (argp - argv != argc)
548 abort ();
549
550 if (verbose)
551 {
552 char *command = shell_quote_argv (argv);
553 printf ("%s\n", command);
554 free (command);
555 }
556
557 exitstatus = execute ("jikes", "jikes", argv, NULL,
558 false, false, false, null_stderr,
559 true, true, NULL);
560 err = (exitstatus != 0);
561
562 freea (argv);
563
564 return err;
565 }
566
567
568
569
570
571
572
573 static bool
574 write_temp_file (struct temp_dir *tmpdir, const char *file_name,
575 const char *contents)
576 {
577 FILE *fp;
578
579 register_temp_file (tmpdir, file_name);
580 fp = fopen_temp (file_name, "we", false);
581 if (fp == NULL)
582 {
583 error (0, errno, _("failed to create \"%s\""), file_name);
584 unregister_temp_file (tmpdir, file_name);
585 return true;
586 }
587 fputs (contents, fp);
588 if (fwriteerror_temp (fp))
589 {
590 error (0, errno, _("error while writing \"%s\" file"), file_name);
591 return true;
592 }
593 return false;
594 }
595
596
597 static int
598 get_classfile_version (const char *compiled_file_name)
599 {
600 unsigned char header[8];
601 int fd;
602
603
604 fd = open (compiled_file_name, O_RDONLY | O_BINARY | O_CLOEXEC, 0);
605 if (fd >= 0)
606 {
607
608 if (safe_read (fd, header, 8) == 8)
609 {
610
611 if (header[0] == 0xCA && header[1] == 0xFE
612 && header[2] == 0xBA && header[3] == 0xBE)
613 {
614 close (fd);
615 return header[7];
616 }
617 }
618 close (fd);
619 }
620
621
622 return INT_MAX;
623 }
624
625
626 static bool
627 is_envjavac_gcj (const char *javac)
628 {
629 static bool envjavac_tested;
630 static bool envjavac_gcj;
631
632 if (!envjavac_tested)
633 {
634
635
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;
647
648
649 command_length = strlen (javac) + 1 + 9 + 1;
650 command = (char *) xmalloca (command_length);
651 p = command;
652
653
654 memcpy (p, javac, strlen (javac));
655 p += strlen (javac);
656 memcpy (p, " --version", 1 + 9 + 1);
657 p += 1 + 9 + 1;
658
659 if (p - command > command_length)
660 abort ();
661
662
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;
671
672
673 fp = fdopen (fd[0], "r");
674 if (fp == NULL)
675 goto failed;
676
677 line = NULL; linesize = 0;
678 linelen = getline (&line, &linesize, fp);
679 if (linelen == (size_t)(-1))
680 {
681 fclose (fp);
682 goto failed;
683 }
684
685
686 envjavac_gcj = (c_strstr (line, "gcj") != NULL);
687
688 fclose (fp);
689
690
691 exitstatus =
692 wait_subprocess (child, javac, true, true, true, false, NULL);
693 if (exitstatus != 0)
694 envjavac_gcj = false;
695
696 failed:
697 freea (command);
698
699 envjavac_tested = true;
700 }
701
702 return envjavac_gcj;
703 }
704
705
706
707 static bool
708 is_envjavac_gcj43 (const char *javac)
709 {
710 static bool envjavac_tested;
711 static bool envjavac_gcj43;
712
713 if (!envjavac_tested)
714 {
715
716
717
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;
729
730
731 command_length = strlen (javac) + 1 + 9 + 1;
732 command = (char *) xmalloca (command_length);
733 p = command;
734
735
736 memcpy (p, javac, strlen (javac));
737 p += strlen (javac);
738 memcpy (p, " --version", 1 + 9 + 1);
739 p += 1 + 9 + 1;
740
741 if (p - command > command_length)
742 abort ();
743
744
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;
753
754
755 fp = fdopen (fd[0], "r");
756 if (fp == NULL)
757 goto failed;
758
759 line = NULL; linesize = 0;
760 linelen = getline (&line, &linesize, fp);
761 if (linelen == (size_t)(-1))
762 {
763 fclose (fp);
764 goto failed;
765 }
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');
772
773 fclose (fp);
774
775
776 exitstatus =
777 wait_subprocess (child, javac, true, true, true, false, NULL);
778 if (exitstatus != 0)
779 envjavac_gcj43 = false;
780
781 failed:
782 freea (command);
783
784 envjavac_tested = true;
785 }
786
787 return envjavac_gcj43;
788 }
789
790
791
792
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)
799 {
800
801 struct result_t
802 {
803 bool tested;
804 bool usable;
805 bool fsource_option;
806 bool ftarget_option;
807 };
808 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
809 struct result_t *resultp;
810
811 resultp = &result_cache[source_version_index (source_version)]
812 [target_version_index (target_version)];
813 if (!resultp->tested)
814 {
815
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;
821
822 tmpdir = create_temp_dir ("java", NULL, false);
823 if (tmpdir == NULL)
824 return true;
825
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)))
830 {
831 free (conftest_file_name);
832 cleanup_temp_dir (tmpdir);
833 return true;
834 }
835
836 compiled_file_name =
837 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
838 register_temp_file (tmpdir, compiled_file_name);
839
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))
847 {
848
849
850 char *javac_source =
851 xasprintf ("%s -fsource=%s", javac, source_version);
852
853 unlink (compiled_file_name);
854
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))
862 {
863 const char *failcode = get_failcode_snippet (source_version);
864
865 if (failcode != NULL)
866 {
867 free (compiled_file_name);
868 free (conftest_file_name);
869
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))
875 {
876 free (conftest_file_name);
877 free (javac_source);
878 cleanup_temp_dir (tmpdir);
879 return true;
880 }
881
882 compiled_file_name =
883 xconcatenated_filename (tmpdir->dir_name,
884 "conftestfail.class",
885 NULL);
886 register_temp_file (tmpdir, compiled_file_name);
887
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)
894 {
895 unlink (compiled_file_name);
896
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
903
904
905 resultp->fsource_option = true;
906 }
907 }
908 }
909
910 free (javac_source);
911
912 resultp->usable = true;
913 }
914 else
915 {
916
917 char *javac_target =
918 xasprintf ("%s -fsource=%s -ftarget=%s",
919 javac, source_version, target_version);
920
921 unlink (compiled_file_name);
922
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))
930 {
931
932
933 resultp->fsource_option = true;
934 resultp->ftarget_option = true;
935 resultp->usable = true;
936 }
937
938 free (javac_target);
939 }
940
941 free (compiled_file_name);
942 free (conftest_file_name);
943
944 resultp->tested = true;
945 }
946
947 *usablep = resultp->usable;
948 *fsource_option_p = resultp->fsource_option;
949 *ftarget_option_p = resultp->ftarget_option;
950 return false;
951 }
952
953
954
955
956 static bool
957 is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
958 {
959 static bool envjavac_tested;
960 static bool envjavac_usable;
961
962 if (!envjavac_tested)
963 {
964
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;
970
971 tmpdir = create_temp_dir ("java", NULL, false);
972 if (tmpdir == NULL)
973 return true;
974
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")))
979 {
980 free (conftest_file_name);
981 cleanup_temp_dir (tmpdir);
982 return true;
983 }
984
985 compiled_file_name =
986 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
987 register_temp_file (tmpdir, compiled_file_name);
988
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
994 envjavac_usable = true;
995
996 free (compiled_file_name);
997 free (conftest_file_name);
998
999 cleanup_temp_dir (tmpdir);
1000
1001 envjavac_tested = true;
1002 }
1003
1004 *usablep = envjavac_usable;
1005 return false;
1006 }
1007
1008
1009
1010
1011 static bool
1012 is_envjavac_oldgcj_14_13_usable (const char *javac,
1013 bool *usablep, bool *need_no_assert_option_p)
1014 {
1015 static bool envjavac_tested;
1016 static bool envjavac_usable;
1017 static bool envjavac_need_no_assert_option;
1018
1019 if (!envjavac_tested)
1020 {
1021
1022
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;
1031
1032 tmpdir = create_temp_dir ("java", NULL, false);
1033 if (tmpdir == NULL)
1034 return true;
1035
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")))
1040 {
1041 free (conftest_file_name);
1042 cleanup_temp_dir (tmpdir);
1043 return true;
1044 }
1045
1046 compiled_file_name =
1047 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1048 register_temp_file (tmpdir, compiled_file_name);
1049
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
1056 javac_works = true;
1057 else
1058 javac_works = false;
1059
1060 unlink (compiled_file_name);
1061
1062 javac_noassert = xasprintf ("%s -fno-assert", javac);
1063
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
1070 javac_noassert_works = true;
1071 else
1072 javac_noassert_works = false;
1073
1074 free (compiled_file_name);
1075 free (conftest_file_name);
1076
1077 if (javac_works && javac_noassert_works)
1078 {
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")))
1084 {
1085 free (conftest_file_name);
1086 free (javac_noassert);
1087 cleanup_temp_dir (tmpdir);
1088 return true;
1089 }
1090
1091 compiled_file_name =
1092 xconcatenated_filename (tmpdir->dir_name, "conftestfail.class",
1093 NULL);
1094 register_temp_file (tmpdir, compiled_file_name);
1095
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)
1101 {
1102
1103 unlink (compiled_file_name);
1104
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
1111
1112 javac_works = true;
1113 }
1114
1115 free (compiled_file_name);
1116 free (conftest_file_name);
1117 }
1118
1119 cleanup_temp_dir (tmpdir);
1120
1121 if (javac_works)
1122 {
1123 envjavac_usable = true;
1124 envjavac_need_no_assert_option = false;
1125 }
1126 else if (javac_noassert_works)
1127 {
1128 envjavac_usable = true;
1129 envjavac_need_no_assert_option = true;
1130 }
1131
1132 envjavac_tested = true;
1133 }
1134
1135 *usablep = envjavac_usable;
1136 *need_no_assert_option_p = envjavac_need_no_assert_option;
1137 return false;
1138 }
1139
1140
1141
1142
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)
1150 {
1151
1152 struct result_t
1153 {
1154 bool tested;
1155 bool usable;
1156 bool source_option;
1157 bool target_option;
1158 };
1159 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1160 struct result_t *resultp;
1161
1162 resultp = &result_cache[source_version_index (source_version)]
1163 [target_version_index (target_version)];
1164 if (!resultp->tested)
1165 {
1166
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;
1172
1173 tmpdir = create_temp_dir ("java", NULL, false);
1174 if (tmpdir == NULL)
1175 return true;
1176
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)))
1181 {
1182 free (conftest_file_name);
1183 cleanup_temp_dir (tmpdir);
1184 return true;
1185 }
1186
1187 compiled_file_name =
1188 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1189 register_temp_file (tmpdir, compiled_file_name);
1190
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))
1198 {
1199
1200
1201 char *javac_source =
1202 xasprintf ("%s -source %s", javac, source_version_for_javac);
1203
1204 unlink (compiled_file_name);
1205
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))
1213 {
1214 const char *failcode = get_failcode_snippet (source_version);
1215
1216 if (failcode != NULL)
1217 {
1218 free (compiled_file_name);
1219 free (conftest_file_name);
1220
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))
1226 {
1227 free (conftest_file_name);
1228 free (javac_source);
1229 cleanup_temp_dir (tmpdir);
1230 return true;
1231 }
1232
1233 compiled_file_name =
1234 xconcatenated_filename (tmpdir->dir_name,
1235 "conftestfail.class",
1236 NULL);
1237 register_temp_file (tmpdir, compiled_file_name);
1238
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)
1245 {
1246 unlink (compiled_file_name);
1247
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
1254
1255
1256 resultp->source_option = true;
1257 }
1258 }
1259 }
1260
1261 free (javac_source);
1262
1263 resultp->usable = true;
1264 }
1265 else
1266 {
1267
1268
1269 char *javac_target =
1270 xasprintf ("%s -target %s", javac, target_version);
1271
1272 unlink (compiled_file_name);
1273
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))
1281 {
1282
1283
1284
1285 char *javac_target_source =
1286 xasprintf ("%s -source %s", javac_target, source_version_for_javac);
1287
1288 unlink (compiled_file_name);
1289
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))
1297 {
1298 const char *failcode = get_failcode_snippet (source_version);
1299
1300 if (failcode != NULL)
1301 {
1302 free (compiled_file_name);
1303 free (conftest_file_name);
1304
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))
1311 {
1312 free (conftest_file_name);
1313 free (javac_target_source);
1314 free (javac_target);
1315 cleanup_temp_dir (tmpdir);
1316 return true;
1317 }
1318
1319 compiled_file_name =
1320 xconcatenated_filename (tmpdir->dir_name,
1321 "conftestfail.class",
1322 NULL);
1323 register_temp_file (tmpdir, compiled_file_name);
1324
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)
1331 {
1332 unlink (compiled_file_name);
1333
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
1341
1342
1343
1344 resultp->source_option = true;
1345 }
1346 }
1347 }
1348
1349 free (javac_target_source);
1350
1351 resultp->target_option = true;
1352 resultp->usable = true;
1353 }
1354 else
1355 {
1356
1357
1358
1359 char *javac_target_source =
1360 xasprintf ("%s -source %s", javac_target, source_version_for_javac);
1361
1362 unlink (compiled_file_name);
1363
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))
1371 {
1372
1373
1374 resultp->source_option = true;
1375 resultp->target_option = true;
1376 resultp->usable = true;
1377 }
1378
1379 free (javac_target_source);
1380 }
1381
1382 free (javac_target);
1383 }
1384
1385 free (compiled_file_name);
1386 free (conftest_file_name);
1387
1388 resultp->tested = true;
1389 }
1390
1391 *usablep = resultp->usable;
1392 *source_option_p = resultp->source_option;
1393 *target_option_p = resultp->target_option;
1394 return false;
1395 }
1396
1397 static bool
1398 is_gcj_present (void)
1399 {
1400 static bool gcj_tested;
1401 static bool gcj_present;
1402
1403 if (!gcj_tested)
1404 {
1405
1406
1407
1408
1409 const char *argv[3];
1410 pid_t child;
1411 int fd[1];
1412 int exitstatus;
1413
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)
1421 {
1422
1423
1424
1425
1426 char c[3];
1427 size_t count = 0;
1428
1429 while (safe_read (fd[0], &c[count], 1) > 0)
1430 {
1431 if (c[count] == '\n')
1432 break;
1433 if (count == 0)
1434 {
1435 if (!(c[0] >= '0' && c[0] <= '9'))
1436 continue;
1437 gcj_present = (c[0] >= '3');
1438 }
1439 count++;
1440 if (count == 3)
1441 {
1442 if (c[0] == '3' && c[1] == '.'
1443 && (c[2] == '0' || c[2] == '1'))
1444 gcj_present = false;
1445 break;
1446 }
1447 }
1448 while (safe_read (fd[0], &c[0], 1) > 0)
1449 ;
1450
1451 close (fd[0]);
1452
1453
1454
1455 exitstatus =
1456 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1457 if (exitstatus != 0)
1458 gcj_present = false;
1459 }
1460
1461 if (gcj_present)
1462 {
1463
1464 struct temp_dir *tmpdir;
1465
1466 tmpdir = create_temp_dir ("java", NULL, false);
1467 if (tmpdir == NULL)
1468 gcj_present = false;
1469 else
1470 {
1471 char *conftest_file_name;
1472
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
1483 {
1484 char *compiled_file_name;
1485 const char *java_sources[1];
1486
1487 compiled_file_name =
1488 xconcatenated_filename (tmpdir->dir_name,
1489 "conftestlib.class",
1490 NULL);
1491 register_temp_file (tmpdir, compiled_file_name);
1492
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;
1499
1500 free (compiled_file_name);
1501 }
1502 free (conftest_file_name);
1503 }
1504 cleanup_temp_dir (tmpdir);
1505 }
1506
1507 gcj_tested = true;
1508 }
1509
1510 return gcj_present;
1511 }
1512
1513 static bool
1514 is_gcj_43 (void)
1515 {
1516 static bool gcj_tested;
1517 static bool gcj_43;
1518
1519 if (!gcj_tested)
1520 {
1521
1522
1523
1524
1525 const char *argv[3];
1526 pid_t child;
1527 int fd[1];
1528 int exitstatus;
1529
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)
1537 {
1538
1539
1540
1541
1542 char c[3];
1543 size_t count = 0;
1544
1545 while (safe_read (fd[0], &c[count], 1) > 0)
1546 {
1547 if (c[count] == '\n')
1548 break;
1549 if (count == 0)
1550 {
1551 if (!(c[0] >= '0' && c[0] <= '9'))
1552 continue;
1553 gcj_43 = (c[0] >= '4');
1554 }
1555 count++;
1556 if (count == 3)
1557 {
1558 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
1559 gcj_43 = false;
1560 break;
1561 }
1562 }
1563 while (safe_read (fd[0], &c[0], 1) > 0)
1564 ;
1565
1566 close (fd[0]);
1567
1568
1569
1570 exitstatus =
1571 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1572 if (exitstatus != 0)
1573 gcj_43 = false;
1574 }
1575
1576 gcj_tested = true;
1577 }
1578
1579 return gcj_43;
1580 }
1581
1582
1583
1584
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)
1590 {
1591
1592 struct result_t
1593 {
1594 bool tested;
1595 bool usable;
1596 bool fsource_option;
1597 bool ftarget_option;
1598 };
1599 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1600 struct result_t *resultp;
1601
1602 resultp = &result_cache[source_version_index (source_version)]
1603 [target_version_index (target_version)];
1604 if (!resultp->tested)
1605 {
1606
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;
1612
1613 tmpdir = create_temp_dir ("java", NULL, false);
1614 if (tmpdir == NULL)
1615 return true;
1616
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)))
1621 {
1622 free (conftest_file_name);
1623 cleanup_temp_dir (tmpdir);
1624 return true;
1625 }
1626
1627 compiled_file_name =
1628 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1629 register_temp_file (tmpdir, compiled_file_name);
1630
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))
1637 {
1638
1639
1640 unlink (compiled_file_name);
1641
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))
1649 {
1650 const char *failcode = get_failcode_snippet (source_version);
1651
1652 if (failcode != NULL)
1653 {
1654 free (compiled_file_name);
1655 free (conftest_file_name);
1656
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))
1662 {
1663 free (conftest_file_name);
1664 cleanup_temp_dir (tmpdir);
1665 return true;
1666 }
1667
1668 compiled_file_name =
1669 xconcatenated_filename (tmpdir->dir_name,
1670 "conftestfail.class",
1671 NULL);
1672 register_temp_file (tmpdir, compiled_file_name);
1673
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)
1680 {
1681 unlink (compiled_file_name);
1682
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
1690
1691
1692 resultp->fsource_option = true;
1693 }
1694 }
1695 }
1696
1697 resultp->usable = true;
1698 }
1699 else
1700 {
1701
1702 unlink (compiled_file_name);
1703
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))
1713 {
1714
1715
1716 resultp->fsource_option = true;
1717 resultp->ftarget_option = true;
1718 resultp->usable = true;
1719 }
1720 }
1721
1722 free (compiled_file_name);
1723 free (conftest_file_name);
1724
1725 resultp->tested = true;
1726 }
1727
1728 *usablep = resultp->usable;
1729 *fsource_option_p = resultp->fsource_option;
1730 *ftarget_option_p = resultp->ftarget_option;
1731 return false;
1732 }
1733
1734
1735
1736
1737 static bool
1738 is_oldgcj_14_14_usable (bool *usablep)
1739 {
1740 static bool gcj_tested;
1741 static bool gcj_usable;
1742
1743 if (!gcj_tested)
1744 {
1745
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;
1751
1752 tmpdir = create_temp_dir ("java", NULL, false);
1753 if (tmpdir == NULL)
1754 return true;
1755
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")))
1760 {
1761 free (conftest_file_name);
1762 cleanup_temp_dir (tmpdir);
1763 return true;
1764 }
1765
1766 compiled_file_name =
1767 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1768 register_temp_file (tmpdir, compiled_file_name);
1769
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
1775 gcj_usable = true;
1776
1777 free (compiled_file_name);
1778 free (conftest_file_name);
1779
1780 cleanup_temp_dir (tmpdir);
1781
1782 gcj_tested = true;
1783 }
1784
1785 *usablep = gcj_usable;
1786 return false;
1787 }
1788
1789
1790
1791
1792 static bool
1793 is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
1794 {
1795 static bool gcj_tested;
1796 static bool gcj_usable;
1797 static bool gcj_need_no_assert_option;
1798
1799 if (!gcj_tested)
1800 {
1801
1802
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;
1808
1809 tmpdir = create_temp_dir ("java", NULL, false);
1810 if (tmpdir == NULL)
1811 return true;
1812
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")))
1817 {
1818 free (conftest_file_name);
1819 cleanup_temp_dir (tmpdir);
1820 return true;
1821 }
1822
1823 compiled_file_name =
1824 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1825 register_temp_file (tmpdir, compiled_file_name);
1826
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
1832 {
1833 gcj_usable = true;
1834 gcj_need_no_assert_option = true;
1835 }
1836 else
1837 {
1838 unlink (compiled_file_name);
1839
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
1846 {
1847 gcj_usable = true;
1848 gcj_need_no_assert_option = false;
1849 }
1850 }
1851
1852 free (compiled_file_name);
1853 free (conftest_file_name);
1854
1855 cleanup_temp_dir (tmpdir);
1856
1857 gcj_tested = true;
1858 }
1859
1860 *usablep = gcj_usable;
1861 *need_no_assert_option_p = gcj_need_no_assert_option;
1862 return false;
1863 }
1864
1865 static bool
1866 is_javac_present (void)
1867 {
1868 static bool javac_tested;
1869 static bool javac_present;
1870
1871 if (!javac_tested)
1872 {
1873
1874 const char *argv[2];
1875 int exitstatus;
1876
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;
1884 }
1885
1886 return javac_present;
1887 }
1888
1889
1890
1891
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)
1897 {
1898
1899 struct result_t
1900 {
1901 bool tested;
1902 bool usable;
1903 bool source_option;
1904 bool target_option;
1905 };
1906 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1907 struct result_t *resultp;
1908
1909 resultp = &result_cache[source_version_index (source_version)]
1910 [target_version_index (target_version)];
1911 if (!resultp->tested)
1912 {
1913
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;
1919
1920 tmpdir = create_temp_dir ("java", NULL, false);
1921 if (tmpdir == NULL)
1922 return true;
1923
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)))
1928 {
1929 free (conftest_file_name);
1930 cleanup_temp_dir (tmpdir);
1931 return true;
1932 }
1933
1934 compiled_file_name =
1935 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1936 register_temp_file (tmpdir, compiled_file_name);
1937
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))
1946 {
1947
1948
1949 unlink (compiled_file_name);
1950
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))
1959 {
1960 const char *failcode = get_failcode_snippet (source_version);
1961
1962 if (failcode != NULL)
1963 {
1964 free (compiled_file_name);
1965 free (conftest_file_name);
1966
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))
1972 {
1973 free (conftest_file_name);
1974 cleanup_temp_dir (tmpdir);
1975 return true;
1976 }
1977
1978 compiled_file_name =
1979 xconcatenated_filename (tmpdir->dir_name,
1980 "conftestfail.class",
1981 NULL);
1982 register_temp_file (tmpdir, compiled_file_name);
1983
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)
1991 {
1992 unlink (compiled_file_name);
1993
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
2001
2002
2003 resultp->source_option = true;
2004 }
2005 }
2006 }
2007
2008 resultp->usable = true;
2009 }
2010 else
2011 {
2012
2013
2014 unlink (compiled_file_name);
2015
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))
2025 {
2026
2027
2028
2029 unlink (compiled_file_name);
2030
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))
2040 {
2041 const char *failcode = get_failcode_snippet (source_version);
2042
2043 if (failcode != NULL)
2044 {
2045 free (compiled_file_name);
2046 free (conftest_file_name);
2047
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))
2054 {
2055 free (conftest_file_name);
2056 cleanup_temp_dir (tmpdir);
2057 return true;
2058 }
2059
2060 compiled_file_name =
2061 xconcatenated_filename (tmpdir->dir_name,
2062 "conftestfail.class",
2063 NULL);
2064 register_temp_file (tmpdir, compiled_file_name);
2065
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)
2073 {
2074 unlink (compiled_file_name);
2075
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
2083
2084
2085
2086 resultp->source_option = true;
2087 }
2088 }
2089 }
2090
2091 resultp->target_option = true;
2092 resultp->usable = true;
2093 }
2094 else
2095 {
2096
2097
2098
2099 unlink (compiled_file_name);
2100
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))
2110 {
2111
2112
2113 resultp->source_option = true;
2114 resultp->target_option = true;
2115 resultp->usable = true;
2116 }
2117 }
2118 }
2119
2120 free (compiled_file_name);
2121 free (conftest_file_name);
2122
2123 resultp->tested = true;
2124 }
2125
2126 *usablep = resultp->usable;
2127 *source_option_p = resultp->source_option;
2128 *target_option_p = resultp->target_option;
2129 return false;
2130 }
2131
2132 static bool
2133 is_jikes_present (void)
2134 {
2135 static bool jikes_tested;
2136 static bool jikes_present;
2137
2138 if (!jikes_tested)
2139 {
2140
2141 const char *argv[2];
2142 int exitstatus;
2143
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;
2151 }
2152
2153 return jikes_present;
2154 }
2155
2156
2157
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)
2169 {
2170 bool err = false;
2171 char *old_JAVA_HOME;
2172
2173 {
2174 const char *javac = getenv ("JAVAC");
2175 if (javac != NULL && javac[0] != '\0')
2176 {
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;
2184
2185 if (target_version == NULL)
2186 target_version = default_target_version ();
2187
2188 source_version_for_javac =
2189 get_source_version_for_javac (source_version, target_version);
2190
2191 if (is_envjavac_gcj (javac))
2192 {
2193
2194 if (is_envjavac_gcj43 (javac))
2195 {
2196
2197
2198 if (is_envjavac_gcj43_usable (javac,
2199 source_version, target_version,
2200 &usable,
2201 &fsource_option, &ftarget_option))
2202 {
2203 err = true;
2204 goto done1;
2205 }
2206 }
2207 else
2208 {
2209
2210
2211 if (strcmp (target_version, "1.4") == 0
2212 && strcmp (source_version, "1.4") == 0)
2213 {
2214 if (is_envjavac_oldgcj_14_14_usable (javac, &usable))
2215 {
2216 err = true;
2217 goto done1;
2218 }
2219 }
2220 else if (strcmp (target_version, "1.4") == 0
2221 && strcmp (source_version, "1.3") == 0)
2222 {
2223 if (is_envjavac_oldgcj_14_13_usable (javac,
2224 &usable,
2225 &no_assert_option))
2226 {
2227 err = true;
2228 goto done1;
2229 }
2230 }
2231 }
2232 }
2233 else
2234 {
2235
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))
2242 {
2243 err = true;
2244 goto done1;
2245 }
2246 }
2247
2248 if (usable)
2249 {
2250 char *old_classpath;
2251 char *javac_with_options;
2252
2253
2254 old_classpath =
2255 set_classpath (classpaths, classpaths_count, false, verbose);
2256
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 : ""));
2270
2271 err = compile_using_envjavac (javac_with_options,
2272 java_sources, java_sources_count,
2273 directory, optimize, debug, verbose,
2274 false);
2275
2276 free (javac_with_options);
2277
2278
2279 reset_classpath (old_classpath);
2280
2281 goto done1;
2282 }
2283 }
2284 }
2285
2286
2287 old_JAVA_HOME = getenv ("JAVA_HOME");
2288 if (old_JAVA_HOME != NULL)
2289 {
2290 old_JAVA_HOME = xstrdup (old_JAVA_HOME);
2291 unsetenv ("JAVA_HOME");
2292 }
2293
2294 if (is_gcj_present ())
2295 {
2296
2297 bool usable = false;
2298 bool no_assert_option = false;
2299 bool fsource_option = false;
2300 bool ftarget_option = false;
2301
2302 if (target_version == NULL)
2303 target_version = default_target_version ();
2304
2305 if (is_gcj_43 ())
2306 {
2307
2308
2309 if (is_gcj43_usable (source_version, target_version,
2310 &usable, &fsource_option, &ftarget_option))
2311 {
2312 err = true;
2313 goto done1;
2314 }
2315 }
2316 else
2317 {
2318
2319
2320
2321
2322 if (strcmp (target_version, "1.4") == 0
2323 && strcmp (source_version, "1.4") == 0)
2324 {
2325 if (is_oldgcj_14_14_usable (&usable))
2326 {
2327 err = true;
2328 goto done1;
2329 }
2330 }
2331 else if (strcmp (target_version, "1.4") == 0
2332 && strcmp (source_version, "1.3") == 0)
2333 {
2334 if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
2335 {
2336 err = true;
2337 goto done1;
2338 }
2339 }
2340 }
2341
2342 if (usable)
2343 {
2344 char *old_classpath;
2345
2346
2347
2348
2349
2350 old_classpath =
2351 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2352 verbose);
2353
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);
2359
2360
2361 reset_classpath (old_classpath);
2362
2363 goto done2;
2364 }
2365 }
2366
2367 if (is_javac_present ())
2368 {
2369 bool usable = false;
2370 bool source_option = false;
2371 bool target_option = false;
2372 const char *source_version_for_javac;
2373
2374 if (target_version == NULL)
2375 target_version = default_target_version ();
2376
2377 source_version_for_javac =
2378 get_source_version_for_javac (source_version, target_version);
2379
2380 if (is_javac_usable (source_version, source_version_for_javac,
2381 target_version,
2382 &usable, &source_option, &target_option))
2383 {
2384 err = true;
2385 goto done1;
2386 }
2387
2388 if (usable)
2389 {
2390 char *old_classpath;
2391
2392
2393
2394
2395
2396 old_classpath =
2397 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2398 verbose);
2399
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);
2405
2406
2407 reset_classpath (old_classpath);
2408
2409 goto done2;
2410 }
2411 }
2412
2413 if (is_jikes_present ())
2414 {
2415
2416
2417 bool usable = (strcmp (source_version, "1.3") == 0);
2418
2419 if (usable)
2420 {
2421 char *old_classpath;
2422
2423
2424
2425
2426
2427
2428 old_classpath =
2429 set_classpath (classpaths, classpaths_count, false, verbose);
2430
2431 err = compile_using_jikes (java_sources, java_sources_count,
2432 directory, optimize, debug, verbose,
2433 false);
2434
2435
2436 reset_classpath (old_classpath);
2437
2438 goto done2;
2439 }
2440 }
2441
2442 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2443 err = true;
2444
2445 done2:
2446 if (old_JAVA_HOME != NULL)
2447 {
2448 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
2449 free (old_JAVA_HOME);
2450 }
2451
2452 done1:
2453 return err;
2454 }