+/* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
+ of gcj. */
+static bool
+is_envjavac_gcj43 (const char *javac)
+{
+ static bool envjavac_tested;
+ static bool envjavac_gcj43;
+
+ if (!envjavac_tested)
+ {
+ /* Test whether $JAVAC is gcj:
+ "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
+ | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
+ unsigned int command_length;
+ char *command;
+ char *argv[4];
+ pid_t child;
+ int fd[1];
+ FILE *fp;
+ char *line;
+ size_t linesize;
+ size_t linelen;
+ int exitstatus;
+ char *p;
+
+ /* Setup the command "$JAVAC --version". */
+ command_length = strlen (javac) + 1 + 9 + 1;
+ command = (char *) xmalloca (command_length);
+ p = command;
+ /* Don't shell_quote $JAVAC, because it may consist of a command
+ and options. */
+ memcpy (p, javac, strlen (javac));
+ p += strlen (javac);
+ memcpy (p, " --version", 1 + 9 + 1);
+ p += 1 + 9 + 1;
+ /* Ensure command_length was correctly calculated. */
+ if (p - command > command_length)
+ abort ();
+
+ /* Call $JAVAC --version 2>/dev/null. */
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = command;
+ argv[3] = NULL;
+ child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true,
+ false, fd);
+ if (child == -1)
+ goto failed;
+
+ /* Retrieve its result. */
+ fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ goto failed;
+
+ line = NULL; linesize = 0;
+ linelen = getline (&line, &linesize, fp);
+ if (linelen == (size_t)(-1))
+ {
+ fclose (fp);
+ goto failed;
+ }
+ p = line;
+ while (*p != '\0' && !(*p >= '0' && *p <= '9'))
+ p++;
+ envjavac_gcj43 =
+ !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2')
+ && (*p >= '4' && *p <= '9');
+
+ fclose (fp);
+
+ /* Remove zombie process from process list, and retrieve exit status. */
+ exitstatus =
+ wait_subprocess (child, javac, true, true, true, false, NULL);
+ if (exitstatus != 0)
+ envjavac_gcj43 = false;
+
+ failed:
+ freea (command);
+
+ envjavac_tested = true;
+ }
+
+ return envjavac_gcj43;
+}
+
+/* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
+ whether it needs a -fsource and/or -ftarget option.
+ Return a failure indicator (true upon error). */
+static bool
+is_envjavac_gcj43_usable (const char *javac,
+ const char *source_version,
+ const char *target_version,
+ bool *usablep,
+ bool *fsource_option_p, bool *ftarget_option_p)
+{
+ /* The cache depends on the source_version and target_version. */
+ struct result_t
+ {
+ bool tested;
+ bool usable;
+ bool fsource_option;
+ bool ftarget_option;
+ };
+ static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
+ struct result_t *resultp;
+
+ resultp = &result_cache[source_version_index (source_version)]
+ [target_version_index (target_version)];
+ if (!resultp->tested)
+ {
+ /* Try $JAVAC. */
+ struct temp_dir *tmpdir;
+ char *conftest_file_name;
+ char *compiled_file_name;
+ const char *java_sources[1];
+ struct stat statbuf;
+
+ tmpdir = create_temp_dir ("java", NULL, false);
+ if (tmpdir == NULL)
+ return true;
+
+ conftest_file_name =
+ xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
+ if (write_temp_file (tmpdir, conftest_file_name,
+ get_goodcode_snippet (source_version)))
+ {
+ free (conftest_file_name);
+ cleanup_temp_dir (tmpdir);
+ return true;
+ }
+
+ compiled_file_name =
+ xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
+ register_temp_file (tmpdir, compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_envjavac (javac,
+ java_sources, 1, tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0
+ && get_classfile_version (compiled_file_name)
+ <= corresponding_classfile_version (target_version))
+ {
+ /* $JAVAC compiled conftest.java successfully. */
+ /* Try adding -fsource option if it is useful. */
+ char *javac_source =
+ xasprintf ("%s -fsource=%s", javac, source_version);
+
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_envjavac (javac_source,
+ java_sources, 1, tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0
+ && get_classfile_version (compiled_file_name)
+ <= corresponding_classfile_version (target_version))
+ {
+ const char *failcode = get_failcode_snippet (source_version);
+
+ if (failcode != NULL)
+ {
+ free (compiled_file_name);
+ free (conftest_file_name);
+
+ conftest_file_name =
+ xconcatenated_filename (tmpdir->dir_name,
+ "conftestfail.java",
+ NULL);
+ if (write_temp_file (tmpdir, conftest_file_name, failcode))
+ {
+ free (conftest_file_name);
+ free (javac_source);
+ cleanup_temp_dir (tmpdir);
+ return true;
+ }
+
+ compiled_file_name =
+ xconcatenated_filename (tmpdir->dir_name,
+ "conftestfail.class",
+ NULL);
+ register_temp_file (tmpdir, compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_envjavac (javac,
+ java_sources, 1,
+ tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0)
+ {
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (compile_using_envjavac (javac_source,
+ java_sources, 1,
+ tmpdir->dir_name,
+ false, false, false, true))
+ /* $JAVAC compiled conftestfail.java successfully, and
+ "$JAVAC -fsource=$source_version" rejects it. So
+ the -fsource option is useful. */
+ resultp->fsource_option = true;
+ }
+ }
+ }
+
+ free (javac_source);
+
+ resultp->usable = true;
+ }
+ else
+ {
+ /* Try with -fsource and -ftarget options. */
+ char *javac_target =
+ xasprintf ("%s -fsource=%s -ftarget=%s",
+ javac, source_version, target_version);
+
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_envjavac (javac_target,
+ java_sources, 1, tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0
+ && get_classfile_version (compiled_file_name)
+ <= corresponding_classfile_version (target_version))
+ {
+ /* "$JAVAC -fsource $source_version -ftarget $target_version"
+ compiled conftest.java successfully. */
+ resultp->fsource_option = true;
+ resultp->ftarget_option = true;
+ resultp->usable = true;
+ }
+
+ free (javac_target);
+ }
+
+ free (compiled_file_name);
+ free (conftest_file_name);
+
+ resultp->tested = true;
+ }
+
+ *usablep = resultp->usable;
+ *fsource_option_p = resultp->fsource_option;
+ *ftarget_option_p = resultp->ftarget_option;
+ return false;
+}
+
+/* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for