changeset 7022:987fd3cc122a

Update from GNU gettext 0.15. Accept source and target versions.
author Bruno Haible <bruno@clisp.org>
date Sat, 22 Jul 2006 16:03:47 +0000
parents 6bb3860fbc5b
children d78abd0c0b70
files ChangeLog build-aux/javacomp.sh.in lib/ChangeLog lib/javacomp.c lib/javacomp.h m4/ChangeLog m4/javacomp.m4
diffstat 7 files changed, 2237 insertions(+), 401 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2006-05-01  Bruno Haible  <bruno@clisp.org>
+
+	* build-aux/javacomp.sh.in: Update for changed javacomp.m4.
+
 2006-07-22  Bruno Haible  <bruno@clisp.org>
 
 	* modules/javaversion: New file.
--- a/build-aux/javacomp.sh.in
+++ b/build-aux/javacomp.sh.in
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Compile a Java program.
 
-# Copyright (C) 2001-2002 Free Software Foundation, Inc.
+# Copyright (C) 2001-2002, 2006 Free Software Foundation, Inc.
 # Written by Bruno Haible <haible@clisp.cons.org>, 2001.
 #
 # This program is free software; you can redistribute it and/or modify
@@ -16,7 +16,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 # This uses the same choices as javacomp.c, but instead of relying on the
 # environment settings at run time, it uses the environment variables
@@ -28,9 +28,9 @@
 # The extra CLASSPATH must have been set prior to calling this script.
 # Options that can be passed are -O, -g and "-d DIRECTORY".
 
-CONF_JAVAC='@JAVAC@'
+CONF_JAVAC='@CONF_JAVAC@'
 CONF_CLASSPATH='@CLASSPATH@'
-if test -n "$CONF_JAVAC"; then
+if test -n "@HAVE_JAVAC_ENVVAR@"; then
   # Combine given CLASSPATH and configured CLASSPATH.
   if test -n "$CLASSPATH"; then
     CLASSPATH="$CLASSPATH${CONF_CLASSPATH:+@CLASSPATH_SEPARATOR@$CONF_CLASSPATH}"
@@ -43,18 +43,21 @@
 else
   unset JAVA_HOME
   if test -n "@HAVE_GCJ_C@"; then
+    # In this case, $CONF_JAVAC starts with "gcj -C".
     CLASSPATH="$CLASSPATH"
     export CLASSPATH
-    test -z "$JAVA_VERBOSE" || echo gcj -C "$@"
-    exec gcj -C "$@"
+    test -z "$JAVA_VERBOSE" || echo "$CONF_JAVAC $@"
+    exec $CONF_JAVAC "$@"
   else
     if test -n "@HAVE_JAVAC@"; then
+      # In this case, $CONF_JAVAC starts with "javac".
       CLASSPATH="$CLASSPATH"
       export CLASSPATH
-      test -z "$JAVA_VERBOSE" || echo javac "$@"
-      exec javac "$@"
+      test -z "$JAVA_VERBOSE" || echo "$CONF_JAVAC $@"
+      exec $CONF_JAVAC "$@"
     else
       if test -n "@HAVE_JIKES@"; then
+        # In this case, $CONF_JAVAC starts with "jikes".
         # Combine given CLASSPATH and configured CLASSPATH.
         if test -n "$CLASSPATH"; then
           CLASSPATH="$CLASSPATH${CONF_CLASSPATH:+@CLASSPATH_SEPARATOR@$CONF_CLASSPATH}"
@@ -62,8 +65,8 @@
           CLASSPATH="$CONF_CLASSPATH"
         fi
         export CLASSPATH
-        test -z "$JAVA_VERBOSE" || echo jikes "$@"
-        exec jikes "$@"
+        test -z "$JAVA_VERBOSE" || echo "$CONF_JAVAC $@"
+        exec $CONF_JAVAC "$@"
       else
         echo 'Java compiler not found, try installing gcj or set $JAVAC, then reconfigure' 1>&2
         exit 1
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,15 @@
+2006-07-11  Bruno Haible  <bruno@clisp.org>
+
+	* javacomp.c: Fix a comment.
+	Reported by Jim Meyering.
+
+2006-04-30  Bruno Haible  <bruno@clisp.org>
+
+	* javacomp.h (compile_java_class): Add source_version, target_version
+	arguments.
+	* javacomp.c: Rewritten to choose only a compiler that respects the
+	specified source_version and target_version.
+
 2006-06-27  Bruno Haible  <bruno@clisp.org>
 
 	Assume correct S_ISDIR macro.
--- a/lib/javacomp.c
+++ b/lib/javacomp.c
@@ -24,20 +24,33 @@
 /* Specification.  */
 #include "javacomp.h"
 
+#include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
+#include "javaversion.h"
 #include "execute.h"
 #include "pipe.h"
 #include "wait-process.h"
 #include "classpath.h"
 #include "xsetenv.h"
 #include "sh-quote.h"
+#include "binary-io.h"
 #include "safe-read.h"
 #include "xalloc.h"
 #include "xallocsa.h"
+#include "getline.h"
+#include "pathname.h"
+#include "fwriteerror.h"
+#include "clean-temp.h"
 #include "error.h"
+#include "xvasprintf.h"
+#include "strstr.h"
 #include "gettext.h"
 
 #define _(str) gettext (str)
@@ -78,11 +91,1487 @@
    this variable can confuse the JDK's javac.
  */
 
+/* Return the default target_version.  */
+static const char *
+default_target_version (void)
+{
+  /* Use a cache.  Assumes that the PATH environment variable doesn't change
+     during the lifetime of the program.  */
+  static const char *java_version_cache;
+  if (java_version_cache == NULL)
+    {
+      /* Determine the version from the found JVM.  */
+      java_version_cache = javaexec_version ();
+      if (java_version_cache == NULL
+	  || !(java_version_cache[0] == '1' && java_version_cache[1] == '.'
+	       && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6')
+	       && java_version_cache[3] == '\0'))
+	java_version_cache = "1.1";
+    }
+  return java_version_cache;
+}
+
+/* ======================= Source version dependent ======================= */
+
+/* Convert a source version to an index.  */
+#define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */
+static unsigned int
+source_version_index (const char *source_version)
+{
+  if (source_version[0] == '1' && source_version[1] == '.'
+      && (source_version[2] >= '3' && source_version[2] <= '5')
+      && source_version[3] == '\0')
+    return source_version[2] - '3';
+  error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
+  return 0;
+}
+
+/* Return a snippet of code that should compile in the given source version.  */
+static const char *
+get_goodcode_snippet (const char *source_version)
+{
+  if (strcmp (source_version, "1.3") == 0)
+    return "class conftest {}\n";
+  if (strcmp (source_version, "1.4") == 0)
+    return "class conftest { static { assert(true); } }\n";
+  if (strcmp (source_version, "1.5") == 0)
+    return "class conftest<T> { T foo() { return null; } }\n";
+  error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
+  return NULL;
+}
+
+/* Return a snippet of code that should fail to compile in the given source
+   version, or NULL (standing for a snippet that would fail to compile with
+   any compiler).  */
+static const char *
+get_failcode_snippet (const char *source_version)
+{
+  if (strcmp (source_version, "1.3") == 0)
+    return "class conftestfail { static { assert(true); } }\n";
+  if (strcmp (source_version, "1.4") == 0)
+    return "class conftestfail<T> { T foo() { return null; } }\n";
+  if (strcmp (source_version, "1.5") == 0)
+    return NULL;
+  error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
+  return NULL;
+}
+
+/* ======================= Target version dependent ======================= */
+
+/* Convert a target version to an index.  */
+#define TARGET_VERSION_BOUND 6 /* exclusive upper bound */
+static unsigned int
+target_version_index (const char *target_version)
+{
+  if (target_version[0] == '1' && target_version[1] == '.'
+      && (target_version[2] >= '1' && target_version[2] <= '6')
+      && target_version[3] == '\0')
+    return target_version[2] - '1';
+  error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
+  return 0;
+}
+
+/* Return the class file version number corresponding to a given target
+   version.  */
+static int
+corresponding_classfile_version (const char *target_version)
+{
+  if (strcmp (target_version, "1.1") == 0)
+    return 45;
+  if (strcmp (target_version, "1.2") == 0)
+    return 46;
+  if (strcmp (target_version, "1.3") == 0)
+    return 47;
+  if (strcmp (target_version, "1.4") == 0)
+    return 48;
+  if (strcmp (target_version, "1.5") == 0)
+    return 49;
+  if (strcmp (target_version, "1.6") == 0)
+    return 50;
+  error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
+  return 0;
+}
+
+/* ======================== Compilation subroutines ======================== */
+
+/* Try to compile a set of Java sources with $JAVAC.
+   Return a failure indicator (true upon error).  */
+static bool
+compile_using_envjavac (const char *javac,
+			const char * const *java_sources,
+			unsigned int java_sources_count,
+			const char *directory,
+			bool optimize, bool debug,
+			bool verbose, bool null_stderr)
+{
+  /* Because $JAVAC may consist of a command and options, we use the
+     shell.  Because $JAVAC has been set by the user, we leave all
+     environment variables in place, including JAVA_HOME, and we don't
+     erase the user's CLASSPATH.  */
+  bool err;
+  unsigned int command_length;
+  char *command;
+  char *argv[4];
+  int exitstatus;
+  unsigned int i;
+  char *p;
+
+  command_length = strlen (javac);
+  if (optimize)
+    command_length += 3;
+  if (debug)
+    command_length += 3;
+  if (directory != NULL)
+    command_length += 4 + shell_quote_length (directory);
+  for (i = 0; i < java_sources_count; i++)
+    command_length += 1 + shell_quote_length (java_sources[i]);
+  command_length += 1;
+
+  command = (char *) xallocsa (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);
+  if (optimize)
+    {
+      memcpy (p, " -O", 3);
+      p += 3;
+    }
+  if (debug)
+    {
+      memcpy (p, " -g", 3);
+      p += 3;
+    }
+  if (directory != NULL)
+    {
+      memcpy (p, " -d ", 4);
+      p += 4;
+      p = shell_quote_copy (p, directory);
+    }
+  for (i = 0; i < java_sources_count; i++)
+    {
+      *p++ = ' ';
+      p = shell_quote_copy (p, java_sources[i]);
+    }
+  *p++ = '\0';
+  /* Ensure command_length was correctly calculated.  */
+  if (p - command > command_length)
+    abort ();
+
+  if (verbose)
+    printf ("%s\n", command);
+
+  argv[0] = "/bin/sh";
+  argv[1] = "-c";
+  argv[2] = command;
+  argv[3] = NULL;
+  exitstatus = execute (javac, "/bin/sh", argv, false, false, false,
+			null_stderr, true, true);
+  err = (exitstatus != 0);
+
+  freesa (command);
+
+  return err;
+}
+
+/* Try to compile a set of Java sources with gcj.
+   Return a failure indicator (true upon error).  */
+static bool
+compile_using_gcj (const char * const *java_sources,
+		   unsigned int java_sources_count,
+		   bool no_assert_option,
+		   const char *directory,
+		   bool optimize, bool debug,
+		   bool verbose, bool null_stderr)
+{
+  bool err;
+  unsigned int argc;
+  char **argv;
+  char **argp;
+  int exitstatus;
+  unsigned int i;
+
+  argc =
+    2 + (no_assert_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
+    + (directory != NULL ? 2 : 0) + java_sources_count;
+  argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
+
+  argp = argv;
+  *argp++ = "gcj";
+  *argp++ = "-C";
+  if (no_assert_option)
+    *argp++ = "-fno-assert";
+  if (optimize)
+    *argp++ = "-O";
+  if (debug)
+    *argp++ = "-g";
+  if (directory != NULL)
+    {
+      *argp++ = "-d";
+      *argp++ = (char *) directory;
+    }
+  for (i = 0; i < java_sources_count; i++)
+    *argp++ = (char *) java_sources[i];
+  *argp = NULL;
+  /* Ensure argv length was correctly calculated.  */
+  if (argp - argv != argc)
+    abort ();
+
+  if (verbose)
+    {
+      char *command = shell_quote_argv (argv);
+      printf ("%s\n", command);
+      free (command);
+    }
+
+  exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr,
+			true, true);
+  err = (exitstatus != 0);
+
+  freesa (argv);
+
+  return err;
+}
+
+/* Try to compile a set of Java sources with javac.
+   Return a failure indicator (true upon error).  */
+static bool
+compile_using_javac (const char * const *java_sources,
+		     unsigned int java_sources_count,
+		     bool source_option, const char *source_version,
+		     bool target_option, const char *target_version,
+		     const char *directory,
+		     bool optimize, bool debug,
+		     bool verbose, bool null_stderr)
+{
+  bool err;
+  unsigned int argc;
+  char **argv;
+  char **argp;
+  int exitstatus;
+  unsigned int i;
+
+  argc =
+    1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0)
+    + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count;
+  argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
+
+  argp = argv;
+  *argp++ = "javac";
+  if (source_option)
+    {
+      *argp++ = "-source";
+      *argp++ = (char *) source_version;
+    }
+  if (target_option)
+    {
+      *argp++ = "-target";
+      *argp++ = (char *) target_version;
+    }
+  if (optimize)
+    *argp++ = "-O";
+  if (debug)
+    *argp++ = "-g";
+  if (directory != NULL)
+    {
+      *argp++ = "-d";
+      *argp++ = (char *) directory;
+    }
+  for (i = 0; i < java_sources_count; i++)
+    *argp++ = (char *) java_sources[i];
+  *argp = NULL;
+  /* Ensure argv length was correctly calculated.  */
+  if (argp - argv != argc)
+    abort ();
+
+  if (verbose)
+    {
+      char *command = shell_quote_argv (argv);
+      printf ("%s\n", command);
+      free (command);
+    }
+
+  exitstatus = execute ("javac", "javac", argv, false, false, false,
+			null_stderr, true, true);
+  err = (exitstatus != 0);
+
+  freesa (argv);
+
+  return err;
+}
+
+/* Try to compile a set of Java sources with jikes.
+   Return a failure indicator (true upon error).  */
+static bool
+compile_using_jikes (const char * const *java_sources,
+		     unsigned int java_sources_count,
+		     const char *directory,
+		     bool optimize, bool debug,
+		     bool verbose, bool null_stderr)
+{
+  bool err;
+  unsigned int argc;
+  char **argv;
+  char **argp;
+  int exitstatus;
+  unsigned int i;
+
+  argc =
+    1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
+    + java_sources_count;
+  argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
+
+  argp = argv;
+  *argp++ = "jikes";
+  if (optimize)
+    *argp++ = "-O";
+  if (debug)
+    *argp++ = "-g";
+  if (directory != NULL)
+    {
+      *argp++ = "-d";
+      *argp++ = (char *) directory;
+    }
+  for (i = 0; i < java_sources_count; i++)
+    *argp++ = (char *) java_sources[i];
+  *argp = NULL;
+  /* Ensure argv length was correctly calculated.  */
+  if (argp - argv != argc)
+    abort ();
+
+  if (verbose)
+    {
+      char *command = shell_quote_argv (argv);
+      printf ("%s\n", command);
+      free (command);
+    }
+
+  exitstatus = execute ("jikes", "jikes", argv, false, false, false,
+			null_stderr, true, true);
+  err = (exitstatus != 0);
+
+  freesa (argv);
+
+  return err;
+}
+
+/* ====================== Usability test subroutines ====================== */
+
+/* Write a given contents to a temporary file.
+   FILE_NAME is the name of a file inside TMPDIR that is known not to exist
+   yet.
+   Return a failure indicator (true upon error).  */
+static bool
+write_temp_file (struct temp_dir *tmpdir, const char *file_name,
+		 const char *contents)
+{
+  FILE *fp;
+
+  register_temp_file (tmpdir, file_name);
+  fp = fopen (file_name, "w");
+  if (fp == NULL)
+    {
+      error (0, errno, _("failed to create \"%s\""), file_name);
+      unregister_temp_file (tmpdir, file_name);
+      return true;
+    }
+  fputs (contents, fp);
+  if (fwriteerror (fp))
+    {
+      error (0, errno, _("error while writing \"%s\" file"), file_name);
+      return true;
+    }
+  return false;
+}
+
+/* Return the class file version number of a class file on disk.  */
+static int
+get_classfile_version (const char *compiled_file_name)
+{
+  unsigned char header[8];
+  int fd;
+
+  /* Open the class file.  */
+  fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0);
+  if (fd >= 0)
+    {
+      /* Read its first 8 bytes.  */
+      if (safe_read (fd, header, 8) == 8)
+	{
+	  /* Verify the class file signature.  */
+	  if (header[0] == 0xCA && header[1] == 0xFE
+	      && header[2] == 0xBA && header[3] == 0xBE)
+	    return header[7];
+	}
+      close (fd);
+    }
+
+  /* Could not get the class file version.  Return a very large one.  */
+  return INT_MAX;
+}
+
+/* Return true if $JAVAC is a version of gcj.  */
+static bool
+is_envjavac_gcj (const char *javac)
+{
+  static bool envjavac_tested;
+  static bool envjavac_gcj;
+
+  if (!envjavac_tested)
+    {
+      /* Test whether $JAVAC is gcj:
+	 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /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 *) xallocsa (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;
+	}
+      envjavac_gcj = (strstr (line, "gcj") != NULL);
+
+      fclose (fp);
+
+      /* Remove zombie process from process list, and retrieve exit status.  */
+      exitstatus = wait_subprocess (child, javac, true, true, true, false);
+      if (exitstatus != 0)
+	envjavac_gcj = false;
+
+     failed:
+      freesa (command);
+
+      envjavac_tested = true;
+    }
+
+  return envjavac_gcj;
+}
+
+/* Test whether $JAVAC, known to be a version of gcj, can be used for
+   compiling with target_version = 1.4 and source_version = 1.4.
+   Return a failure indicator (true upon error).  */
+static bool
+is_envjavac_gcj_14_14_usable (const char *javac, bool *usablep)
+{
+  static bool envjavac_tested;
+  static bool envjavac_usable;
+
+  if (!envjavac_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 =
+	concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL);
+      if (write_temp_file (tmpdir, conftest_file_name,
+			   get_goodcode_snippet ("1.4")))
+	{
+	  free (conftest_file_name);
+	  cleanup_temp_dir (tmpdir);
+	  return true;
+	}
+
+      compiled_file_name =
+	concatenated_pathname (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)
+	/* Compilation succeeded.  */
+	envjavac_usable = true;
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      cleanup_temp_dir (tmpdir);
+
+      envjavac_tested = true;
+    }
+
+  *usablep = envjavac_usable;
+  return false;
+}
+
+/* Test whether $JAVAC, known to be a version of gcj, can be used for
+   compiling with target_version = 1.4 and source_version = 1.3.
+   Return a failure indicator (true upon error).  */
+static bool
+is_envjavac_gcj_14_13_usable (const char *javac,
+			      bool *usablep, bool *need_no_assert_option_p)
+{
+  static bool envjavac_tested;
+  static bool envjavac_usable;
+  static bool envjavac_need_no_assert_option;
+
+  if (!envjavac_tested)
+    {
+      /* Try $JAVAC and "$JAVAC -fno-assert".  But add -fno-assert only if
+	 it makes a difference.  (It could already be part of $JAVAC.)  */
+      struct temp_dir *tmpdir;
+      char *conftest_file_name;
+      char *compiled_file_name;
+      const char *java_sources[1];
+      struct stat statbuf;
+      bool javac_works;
+      char *javac_noassert;
+      bool javac_noassert_works;
+
+      tmpdir = create_temp_dir ("java", NULL, false);
+      if (tmpdir == NULL)
+	return true;
+
+      conftest_file_name =
+	concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL);
+      if (write_temp_file (tmpdir, conftest_file_name,
+			   get_goodcode_snippet ("1.3")))
+	{
+	  free (conftest_file_name);
+	  cleanup_temp_dir (tmpdir);
+	  return true;
+	}
+
+      compiled_file_name =
+	concatenated_pathname (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)
+	/* Compilation succeeded.  */
+	javac_works = true;
+      else
+	javac_works = false;
+
+      unlink (compiled_file_name);
+
+      javac_noassert = xasprintf ("%s -fno-assert", javac);
+
+      java_sources[0] = conftest_file_name;
+      if (!compile_using_envjavac (javac_noassert,
+				   java_sources, 1, tmpdir->dir_name,
+				   false, false, false, true)
+	  && stat (compiled_file_name, &statbuf) >= 0)
+	/* Compilation succeeded.  */
+	javac_noassert_works = true;
+      else
+	javac_noassert_works = false;
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      if (javac_works && javac_noassert_works)
+	{
+	  conftest_file_name =
+	    concatenated_pathname (tmpdir->dir_name, "conftestfail.java",
+				   NULL);
+	  if (write_temp_file (tmpdir, conftest_file_name,
+			       get_failcode_snippet ("1.3")))
+	    {
+	      free (conftest_file_name);
+	      free (javac_noassert);
+	      cleanup_temp_dir (tmpdir);
+	      return true;
+	    }
+
+	  compiled_file_name =
+	    concatenated_pathname (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)
+	    {
+	      /* Compilation succeeded.  */
+	      unlink (compiled_file_name);
+
+	      java_sources[0] = conftest_file_name;
+	      if (!(!compile_using_envjavac (javac_noassert,
+					     java_sources, 1, tmpdir->dir_name,
+					     false, false, false, true)
+		    && stat (compiled_file_name, &statbuf) >= 0))
+		/* Compilation failed.  */
+		/* "$JAVAC -fno-assert" works better than $JAVAC.  */
+		javac_works = true;
+	    }
+
+	  free (compiled_file_name);
+	  free (conftest_file_name);
+	}
+
+      cleanup_temp_dir (tmpdir);
+
+      if (javac_works)
+	{
+	  envjavac_usable = true;
+	  envjavac_need_no_assert_option = false;
+	}
+      else if (javac_noassert_works)
+	{
+	  envjavac_usable = true;
+	  envjavac_need_no_assert_option = true;
+	}
+
+      envjavac_tested = true;
+    }
+
+  *usablep = envjavac_usable;
+  *need_no_assert_option_p = envjavac_need_no_assert_option;
+  return false;
+}
+
+/* Test whether $JAVAC, known to be not a version of gcj, can be used, and
+   whether it needs a -source and/or -target option.
+   Return a failure indicator (true upon error).  */
+static bool
+is_envjavac_nongcj_usable (const char *javac,
+			   const char *source_version,
+			   const char *target_version,
+			   bool *usablep,
+			   bool *source_option_p, bool *target_option_p)
+{
+  /* The cache depends on the source_version and target_version.  */
+  struct result_t
+  {
+    bool tested;
+    bool usable;
+    bool source_option;
+    bool target_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 =
+	concatenated_pathname (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 =
+	concatenated_pathname (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 -source option if it is useful.  */
+	  char *javac_source =
+	    xasprintf ("%s -source %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 =
+		    concatenated_pathname (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 =
+		    concatenated_pathname (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 -source $source_version" rejects it.  So the
+			   -source option is useful.  */
+			resultp->source_option = true;
+		    }
+		}
+	    }
+
+	  free (javac_source);
+
+	  resultp->usable = true;
+	}
+      else
+	{
+	  /* Try with -target option alone. (Sun javac 1.3.1 has the -target
+	     option but no -source option.)  */
+	  char *javac_target =
+	    xasprintf ("%s -target %s", javac, 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 -target $target_version" compiled conftest.java
+		 successfully.  */
+	      /* Try adding -source option if it is useful.  */
+	      char *javac_target_source =
+		xasprintf ("%s -source %s", javac_target, source_version);
+
+	      unlink (compiled_file_name);
+
+	      java_sources[0] = conftest_file_name;
+	      if (!compile_using_envjavac (javac_target_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 =
+			concatenated_pathname (tmpdir->dir_name,
+					       "conftestfail.java",
+					       NULL);
+		      if (write_temp_file (tmpdir, conftest_file_name,
+					   failcode))
+			{
+			  free (conftest_file_name);
+			  free (javac_target_source);
+			  free (javac_target);
+			  cleanup_temp_dir (tmpdir);
+			  return true;
+			}
+
+		      compiled_file_name =
+			concatenated_pathname (tmpdir->dir_name,
+					       "conftestfail.class",
+					       NULL);
+		      register_temp_file (tmpdir, 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)
+			{
+			  unlink (compiled_file_name);
+
+			  java_sources[0] = conftest_file_name;
+			  if (compile_using_envjavac (javac_target_source,
+						      java_sources, 1,
+						      tmpdir->dir_name,
+						      false, false, false,
+						      true))
+			    /* "$JAVAC -target $target_version" compiled
+			       conftestfail.java successfully, and
+			       "$JAVAC -target $target_version -source $source_version"
+			       rejects it.  So the -source option is useful.  */
+			    resultp->source_option = true;
+			}
+		    }
+		}
+
+	      free (javac_target_source);
+
+	      resultp->target_option = true;
+	      resultp->usable = true;
+	    }
+	  else
+	    {
+	      /* Maybe this -target option requires a -source option? Try with
+		 -target and -source options. (Supported by Sun javac 1.4 and
+		 higher.)  */
+	      char *javac_target_source =
+		xasprintf ("%s -source %s", javac_target, source_version);
+
+	      unlink (compiled_file_name);
+
+	      java_sources[0] = conftest_file_name;
+	      if (!compile_using_envjavac (javac_target_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))
+		{
+		  /* "$JAVAC -target $target_version -source $source_version"
+		     compiled conftest.java successfully.  */
+		  resultp->source_option = true;
+		  resultp->target_option = true;
+		  resultp->usable = true;
+		}
+
+	      free (javac_target_source);
+	    }
+
+	  free (javac_target);
+	}
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      resultp->tested = true;
+    }
+
+  *usablep = resultp->usable;
+  *source_option_p = resultp->source_option;
+  *target_option_p = resultp->target_option;
+  return false;
+}
+
+static bool
+is_gcj_present (void)
+{
+  static bool gcj_tested;
+  static bool gcj_present;
+
+  if (!gcj_tested)
+    {
+      /* Test for presence of gcj:
+	 "gcj --version 2> /dev/null | \
+	  sed -e 's,^[^0-9]*,,' -e 1q | \
+	  sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null"  */
+      char *argv[3];
+      pid_t child;
+      int fd[1];
+      int exitstatus;
+
+      argv[0] = "gcj";
+      argv[1] = "--version";
+      argv[2] = NULL;
+      child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
+			      false, fd);
+      gcj_present = false;
+      if (child != -1)
+	{
+	  /* Read the subprocess output, drop all lines except the first,
+	     drop all characters before the first digit, and test whether
+	     the remaining string starts with a digit >= 3, but not with
+	     "3.0" or "3.1".  */
+	  char c[3];
+	  size_t count = 0;
+
+	  while (safe_read (fd[0], &c[count], 1) > 0)
+	    {
+	      if (c[count] == '\n')
+		break;
+	      if (count == 0)
+		{
+		  if (!(c[0] >= '0' && c[0] <= '9'))
+		    continue;
+		  gcj_present = (c[0] >= '3');
+		}
+	      count++;
+	      if (count == 3)
+		{
+		  if (c[0] == '3' && c[1] == '.'
+		      && (c[2] == '0' || c[2] == '1'))
+		    gcj_present = false;
+		  break;
+		}
+	    }
+	  while (safe_read (fd[0], &c[0], 1) > 0)
+	    ;
+
+	  close (fd[0]);
+
+	  /* Remove zombie process from process list, and retrieve exit
+	     status.  */
+	  exitstatus =
+	    wait_subprocess (child, "gcj", false, true, true, false);
+	  if (exitstatus != 0)
+	    gcj_present = false;
+	}
+
+      if (gcj_present)
+	{
+	  /* See if libgcj.jar is well installed.  */
+	  struct temp_dir *tmpdir;
+
+	  tmpdir = create_temp_dir ("java", NULL, false);
+	  if (tmpdir == NULL)
+	    gcj_present = false;
+	  else
+	    {
+	      char *conftest_file_name;
+
+	      conftest_file_name =
+		concatenated_pathname (tmpdir->dir_name, "conftestlib.java",
+				       NULL);
+	      if (write_temp_file (tmpdir, conftest_file_name,
+"public class conftestlib {\n"
+"  public static void main (String[] args) {\n"
+"  }\n"
+"}\n"))
+		gcj_present = false;
+	      else
+		{
+		  char *compiled_file_name;
+		  const char *java_sources[1];
+
+		  compiled_file_name =
+		    concatenated_pathname (tmpdir->dir_name,
+					   "conftestlib.class",
+					   NULL);
+		  register_temp_file (tmpdir, compiled_file_name);
+
+		  java_sources[0] = conftest_file_name;
+		  if (compile_using_gcj (java_sources, 1, false,
+					 tmpdir->dir_name,
+					 false, false, false, true))
+		    gcj_present = false;
+
+		  free (compiled_file_name);
+		}
+	      free (conftest_file_name);
+	    }
+	  cleanup_temp_dir (tmpdir);
+	}
+
+      gcj_tested = true;
+    }
+
+  return gcj_present;
+}
+
+/* Test gcj can be used for compiling with target_version = 1.4 and
+   source_version = 1.4.
+   Return a failure indicator (true upon error).  */
+static bool
+is_gcj_14_14_usable (bool *usablep)
+{
+  static bool gcj_tested;
+  static bool gcj_usable;
+
+  if (!gcj_tested)
+    {
+      /* Try gcj.  */
+      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 =
+	concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL);
+      if (write_temp_file (tmpdir, conftest_file_name,
+			   get_goodcode_snippet ("1.4")))
+	{
+	  free (conftest_file_name);
+	  cleanup_temp_dir (tmpdir);
+	  return true;
+	}
+
+      compiled_file_name =
+	concatenated_pathname (tmpdir->dir_name, "conftest.class", NULL);
+      register_temp_file (tmpdir, compiled_file_name);
+
+      java_sources[0] = conftest_file_name;
+      if (!compile_using_gcj (java_sources, 1, false, tmpdir->dir_name,
+			      false, false, false, true)
+	  && stat (compiled_file_name, &statbuf) >= 0)
+	/* Compilation succeeded.  */
+	gcj_usable = true;
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      cleanup_temp_dir (tmpdir);
+
+      gcj_tested = true;
+    }
+
+  *usablep = gcj_usable;
+  return false;
+}
+
+/* Test whether gcj can be used for compiling with target_version = 1.4 and
+   source_version = 1.3.
+   Return a failure indicator (true upon error).  */
+static bool
+is_gcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
+{
+  static bool gcj_tested;
+  static bool gcj_usable;
+  static bool gcj_need_no_assert_option;
+
+  if (!gcj_tested)
+    {
+      /* Try gcj and "gcj -fno-assert".  But add -fno-assert only if
+	 it works (not gcj < 3.3).  */
+      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 =
+	concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL);
+      if (write_temp_file (tmpdir, conftest_file_name,
+			   get_goodcode_snippet ("1.3")))
+	{
+	  free (conftest_file_name);
+	  cleanup_temp_dir (tmpdir);
+	  return true;
+	}
+
+      compiled_file_name =
+	concatenated_pathname (tmpdir->dir_name, "conftest.class", NULL);
+      register_temp_file (tmpdir, compiled_file_name);
+
+      java_sources[0] = conftest_file_name;
+      if (!compile_using_gcj (java_sources, 1, true, tmpdir->dir_name,
+			      false, false, false, true)
+	  && stat (compiled_file_name, &statbuf) >= 0)
+	/* Compilation succeeded.  */
+	{
+	  gcj_usable = true;
+	  gcj_need_no_assert_option = true;
+	}
+      else
+	{
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_gcj (java_sources, 1, false, tmpdir->dir_name,
+				  false, false, false, true)
+	      && stat (compiled_file_name, &statbuf) >= 0)
+	    /* Compilation succeeded.  */
+	    {
+	      gcj_usable = true;
+	      gcj_need_no_assert_option = false;
+	    }
+	}
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      cleanup_temp_dir (tmpdir);
+
+      gcj_tested = true;
+    }
+
+  *usablep = gcj_usable;
+  *need_no_assert_option_p = gcj_need_no_assert_option;
+  return false;
+}
+
+static bool
+is_javac_present (void)
+{
+  static bool javac_tested;
+  static bool javac_present;
+
+  if (!javac_tested)
+    {
+      /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2"  */
+      char *argv[2];
+      int exitstatus;
+
+      argv[0] = "javac";
+      argv[1] = NULL;
+      exitstatus = execute ("javac", "javac", argv, false, false, true, true,
+			    true, false);
+      javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
+      javac_tested = true;
+    }
+
+  return javac_present;
+}
+
+/* Test whether javac can be used and whether it needs a -source and/or
+   -target option.
+   Return a failure indicator (true upon error).  */
+static bool
+is_javac_usable (const char *source_version, const char *target_version,
+		 bool *usablep, bool *source_option_p, bool *target_option_p)
+{
+  /* The cache depends on the source_version and target_version.  */
+  struct result_t
+  {
+    bool tested;
+    bool usable;
+    bool source_option;
+    bool target_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 =
+	concatenated_pathname (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 =
+	concatenated_pathname (tmpdir->dir_name, "conftest.class", NULL);
+      register_temp_file (tmpdir, compiled_file_name);
+
+      java_sources[0] = conftest_file_name;
+      if (!compile_using_javac (java_sources, 1,
+				false, source_version,
+				false, target_version,
+				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 -source option if it is useful.  */
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_javac (java_sources, 1,
+				    true, source_version,
+				    false, target_version,
+				    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 =
+		    concatenated_pathname (tmpdir->dir_name,
+					   "conftestfail.java",
+					   NULL);
+		  if (write_temp_file (tmpdir, conftest_file_name, failcode))
+		    {
+		      free (conftest_file_name);
+		      cleanup_temp_dir (tmpdir);
+		      return true;
+		    }
+
+		  compiled_file_name =
+		    concatenated_pathname (tmpdir->dir_name,
+					   "conftestfail.class",
+					   NULL);
+		  register_temp_file (tmpdir, compiled_file_name);
+
+		  java_sources[0] = conftest_file_name;
+		  if (!compile_using_javac (java_sources, 1,
+					    false, source_version,
+					    false, target_version,
+					    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_javac (java_sources, 1,
+					       true, source_version,
+					       false, target_version,
+					       tmpdir->dir_name,
+					       false, false, false, true))
+			/* javac compiled conftestfail.java successfully, and
+			   "javac -source $source_version" rejects it.  So the
+			   -source option is useful.  */
+			resultp->source_option = true;
+		    }
+		}
+	    }
+
+	  resultp->usable = true;
+	}
+      else
+	{
+	  /* Try with -target option alone. (Sun javac 1.3.1 has the -target
+	     option but no -source option.)  */
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_javac (java_sources, 1,
+				    false, source_version,
+				    true, target_version,
+				    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 -target $target_version" compiled conftest.java
+		 successfully.  */
+	      /* Try adding -source option if it is useful.  */
+	      unlink (compiled_file_name);
+
+	      java_sources[0] = conftest_file_name;
+	      if (!compile_using_javac (java_sources, 1,
+					true, source_version,
+					true, target_version,
+					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 =
+			concatenated_pathname (tmpdir->dir_name,
+					       "conftestfail.java",
+					       NULL);
+		      if (write_temp_file (tmpdir, conftest_file_name,
+					   failcode))
+			{
+			  free (conftest_file_name);
+			  cleanup_temp_dir (tmpdir);
+			  return true;
+			}
+
+		      compiled_file_name =
+			concatenated_pathname (tmpdir->dir_name,
+					       "conftestfail.class",
+					       NULL);
+		      register_temp_file (tmpdir, compiled_file_name);
+
+		      java_sources[0] = conftest_file_name;
+		      if (!compile_using_javac (java_sources, 1,
+						false, source_version,
+						true, target_version,
+						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_javac (java_sources, 1,
+						   true, source_version,
+						   true, target_version,
+						   tmpdir->dir_name,
+						   false, false, false, true))
+			    /* "javac -target $target_version" compiled
+			       conftestfail.java successfully, and
+			       "javac -target $target_version -source $source_version"
+			       rejects it.  So the -source option is useful.  */
+			    resultp->source_option = true;
+			}
+		    }
+		}
+
+	      resultp->target_option = true;
+	      resultp->usable = true;
+	    }
+	  else
+	    {
+	      /* Maybe this -target option requires a -source option? Try with
+		 -target and -source options. (Supported by Sun javac 1.4 and
+		 higher.)  */
+	      unlink (compiled_file_name);
+
+	      java_sources[0] = conftest_file_name;
+	      if (!compile_using_javac (java_sources, 1,
+					true, source_version,
+					true, target_version,
+					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 -target $target_version -source $source_version"
+		     compiled conftest.java successfully.  */
+		  resultp->source_option = true;
+		  resultp->target_option = true;
+		  resultp->usable = true;
+		}
+	    }
+	}
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      resultp->tested = true;
+    }
+
+  *usablep = resultp->usable;
+  *source_option_p = resultp->source_option;
+  *target_option_p = resultp->target_option;
+  return false;
+}
+
+static bool
+is_jikes_present (void)
+{
+  static bool jikes_tested;
+  static bool jikes_present;
+
+  if (!jikes_tested)
+    {
+      /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1"  */
+      char *argv[2];
+      int exitstatus;
+
+      argv[0] = "jikes";
+      argv[1] = NULL;
+      exitstatus = execute ("jikes", "jikes", argv, false, false, true, true,
+			    true, false);
+      jikes_present = (exitstatus == 0 || exitstatus == 1);
+      jikes_tested = true;
+    }
+
+  return jikes_present;
+}
+
+/* ============================= Main function ============================= */
+
 bool
 compile_java_class (const char * const *java_sources,
 		    unsigned int java_sources_count,
 		    const char * const *classpaths,
 		    unsigned int classpaths_count,
+		    const char *source_version,
+		    const char *target_version,
 		    const char *directory,
 		    bool optimize, bool debug,
 		    bool use_minimal_classpath,
@@ -95,83 +1584,82 @@
     const char *javac = getenv ("JAVAC");
     if (javac != NULL && javac[0] != '\0')
       {
-	/* Because $JAVAC may consist of a command and options, we use the
-	   shell.  Because $JAVAC has been set by the user, we leave all
-	   environment variables in place, including JAVA_HOME, and
-	   we don't erase the user's CLASSPATH.  */
-	char *old_classpath;
-	unsigned int command_length;
-	char *command;
-	char *argv[4];
-	int exitstatus;
-	unsigned int i;
-	char *p;
+	bool usable = false;
+	bool no_assert_option = false;
+	bool source_option = false;
+	bool target_option = false;
 
-	/* Set CLASSPATH.  */
-	old_classpath =
-	  set_classpath (classpaths, classpaths_count, false,
-			 verbose);
+	if (target_version == NULL)
+	  target_version = default_target_version ();
 
-	command_length = strlen (javac);
-	if (optimize)
-	  command_length += 3;
-	if (debug)
-	  command_length += 3;
-	if (directory != NULL)
-	  command_length += 4 + shell_quote_length (directory);
-	for (i = 0; i < java_sources_count; i++)
-	  command_length += 1 + shell_quote_length (java_sources[i]);
-	command_length += 1;
-
-	command = (char *) xallocsa (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);
-	if (optimize)
+	if (is_envjavac_gcj (javac))
 	  {
-	    memcpy (p, " -O", 3);
-	    p += 3;
+	    /* It's a version of gcj.  Ignore the version of the class files
+	       that it creates.  */
+	    if (strcmp (target_version, "1.4") == 0
+		&& strcmp (source_version, "1.4") == 0)
+	      {
+		if (is_envjavac_gcj_14_14_usable (javac, &usable))
+		  {
+		    err = true;
+		    goto done1;
+		  }
+	      }
+	    else if (strcmp (target_version, "1.4") == 0
+		     && strcmp (source_version, "1.3") == 0)
+	      {
+		if (is_envjavac_gcj_14_13_usable (javac,
+						  &usable, &no_assert_option))
+		  {
+		    err = true;
+		    goto done1;
+		  }
+	      }
 	  }
-	if (debug)
-	  {
-	    memcpy (p, " -g", 3);
-	    p += 3;
-	  }
-	if (directory != NULL)
+	else
 	  {
-	    memcpy (p, " -d ", 4);
-	    p += 4;
-	    p = shell_quote_copy (p, directory);
-	  }
-	for (i = 0; i < java_sources_count; i++)
-	  {
-	    *p++ = ' ';
-	    p = shell_quote_copy (p, java_sources[i]);
+	    /* It's not gcj.  Assume the classfile versions are correct.  */
+	    if (is_envjavac_nongcj_usable (javac,
+					   source_version, target_version,
+					   &usable,
+					   &source_option, &target_option))
+	      {
+		err = true;
+		goto done1;
+	      }
 	  }
-	*p++ = '\0';
-	/* Ensure command_length was correctly calculated.  */
-	if (p - command > command_length)
-	  abort ();
 
-	if (verbose)
-	  printf ("%s\n", command);
+	if (usable)
+	  {
+	    char *old_classpath;
+	    char *javac_with_options;
+
+	    /* Set CLASSPATH.  */
+	    old_classpath =
+	      set_classpath (classpaths, classpaths_count, false, verbose);
 
-	argv[0] = "/bin/sh";
-	argv[1] = "-c";
-	argv[2] = command;
-	argv[3] = NULL;
-	exitstatus = execute (javac, "/bin/sh", argv, false, false, false,
-			      false, true, true);
-	err = (exitstatus != 0);
+	    javac_with_options =
+	      (no_assert_option
+	       ? xasprintf ("%s -fno-assert", javac)
+	       : xasprintf ("%s%s%s%s%s",
+			    javac,
+			    source_option ? " -source " : "",
+			    source_option ? source_version : "",
+			    target_option ? " -target " : "",
+			    target_option ? target_version : ""));
 
-	freesa (command);
+	    err = compile_using_envjavac (javac_with_options,
+					  java_sources, java_sources_count,
+					  directory, optimize, debug, verbose,
+					  false);
 
-	/* Reset CLASSPATH.  */
-	reset_classpath (old_classpath);
+	    free (javac_with_options);
 
-	goto done1;
+	    /* Reset CLASSPATH.  */
+	    reset_classpath (old_classpath);
+
+	    goto done1;
+	  }
       }
   }
 
@@ -183,286 +1671,128 @@
       unsetenv ("JAVA_HOME");
     }
 
-  {
-    static bool gcj_tested;
-    static bool gcj_present;
-
-    if (!gcj_tested)
-      {
-	/* Test for presence of gcj:
-	   "gcj --version 2> /dev/null | \
-	    sed -e 's,^[^0-9]*,,' -e 1q | \
-	    sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null"  */
-	char *argv[3];
-	pid_t child;
-	int fd[1];
-	int exitstatus;
-
-	argv[0] = "gcj";
-	argv[1] = "--version";
-	argv[2] = NULL;
-	child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
-				false, fd);
-	gcj_present = false;
-	if (child != -1)
-	  {
-	    /* Read the subprocess output, drop all lines except the first,
-	       drop all characters before the first digit, and test whether
-	       the remaining string starts with a digit >= 3, but not with
-	       "3.0" or "3.1".  */
-	    char c[3];
-	    size_t count = 0;
+  if (is_gcj_present ())
+    {
+      /* Test whether it supports the desired target-version and
+	 source-version.  But ignore the version of the class files that
+	 it creates.  */
+      bool usable = false;
+      bool no_assert_option = false;
 
-	    while (safe_read (fd[0], &c[count], 1) > 0)
-	      {
-		if (c[count] == '\n')
-		  break;
-		if (count == 0)
-		  {
-		    if (!(c[0] >= '0' && c[0] <= '9'))
-		      continue;
-		    gcj_present = (c[0] >= '3');
-		  }
-		count++;
-		if (count == 3)
-		  {
-		    if (c[0] == '3' && c[1] == '.'
-			&& (c[2] == '0' || c[2] == '1'))
-		      gcj_present = false;
-		    break;
-		  }
-	      }
-	    while (safe_read (fd[0], &c[0], 1) > 0)
-	      ;
-
-	    close (fd[0]);
-
-	    /* Remove zombie process from process list, and retrieve exit
-	       status.  */
-	    exitstatus =
-	      wait_subprocess (child, "gcj", false, true, true, false);
-	    if (exitstatus != 0)
-	      gcj_present = false;
-	  }
-	gcj_tested = true;
-      }
+      if (target_version == NULL)
+	target_version = default_target_version ();
 
-    if (gcj_present)
-      {
-	char *old_classpath;
-	unsigned int argc;
-	char **argv;
-	char **argp;
-	int exitstatus;
-	unsigned int i;
+      if (strcmp (target_version, "1.4") == 0
+	  && strcmp (source_version, "1.4") == 0)
+	{
+	  if (is_gcj_14_14_usable (&usable))
+	    {
+	      err = true;
+	      goto done1;
+	    }
+	}
+      else if (strcmp (target_version, "1.4") == 0
+	       && strcmp (source_version, "1.3") == 0)
+	{
+	  if (is_gcj_14_13_usable (&usable, &no_assert_option))
+	    {
+	      err = true;
+	      goto done1;
+	    }
+	}
 
-	/* Set CLASSPATH.  We could also use the --CLASSPATH=... option
-	   of gcj.  Note that --classpath=... option is different: its
-	   argument should also contain gcj's libgcj.jar, but we don't
-	   know its location.  */
-	old_classpath =
-	  set_classpath (classpaths, classpaths_count, use_minimal_classpath,
-			 verbose);
-
-	argc =
-	  2 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
-	  + java_sources_count;
-	argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
+      if (usable)
+	{
+	  char *old_classpath;
 
-	argp = argv;
-	*argp++ = "gcj";
-	*argp++ = "-C";
-	if (optimize)
-	  *argp++ = "-O";
-	if (debug)
-	  *argp++ = "-g";
-	if (directory != NULL)
-	  {
-	    *argp++ = "-d";
-	    *argp++ = (char *) directory;
-	  }
-	for (i = 0; i < java_sources_count; i++)
-	  *argp++ = (char *) java_sources[i];
-	*argp = NULL;
-	/* Ensure argv length was correctly calculated.  */
-	if (argp - argv != argc)
-	  abort ();
+	  /* Set CLASSPATH.  We could also use the --CLASSPATH=... option
+	     of gcj.  Note that --classpath=... option is different: its
+	     argument should also contain gcj's libgcj.jar, but we don't
+	     know its location.  */
+	  old_classpath =
+	    set_classpath (classpaths, classpaths_count, use_minimal_classpath,
+			   verbose);
+
+	  err = compile_using_gcj (java_sources, java_sources_count,
+				   no_assert_option,
+				   directory, optimize, debug, verbose, false);
 
-	if (verbose)
-	  {
-	    char *command = shell_quote_argv (argv);
-	    printf ("%s\n", command);
-	    free (command);
-	  }
-
-	exitstatus = execute ("gcj", "gcj", argv, false, false, false, false,
-			      true, true);
-	err = (exitstatus != 0);
-
-	freesa (argv);
+	  /* Reset CLASSPATH.  */
+	  reset_classpath (old_classpath);
 
-	/* Reset CLASSPATH.  */
-	reset_classpath (old_classpath);
-
-	goto done2;
-      }
-  }
+	  goto done2;
+	}
+    }
 
-  {
-    static bool javac_tested;
-    static bool javac_present;
-
-    if (!javac_tested)
-      {
-	/* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2"  */
-	char *argv[2];
-	int exitstatus;
+  if (is_javac_present ())
+    {
+      bool usable = false;
+      bool source_option = false;
+      bool target_option = false;
 
-	argv[0] = "javac";
-	argv[1] = NULL;
-	exitstatus = execute ("javac", "javac", argv, false, false, true, true,
-			      true, false);
-	javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
-	javac_tested = true;
-      }
+      if (target_version == NULL)
+	target_version = default_target_version ();
 
-    if (javac_present)
-      {
-	char *old_classpath;
-	unsigned int argc;
-	char **argv;
-	char **argp;
-	int exitstatus;
-	unsigned int i;
+      if (is_javac_usable (source_version, target_version,
+			   &usable, &source_option, &target_option))
+	{
+	  err = true;
+	  goto done1;
+	}
 
-	/* Set CLASSPATH.  We don't use the "-classpath ..." option because
-	   in JDK 1.1.x its argument should also contain the JDK's classes.zip,
-	   but we don't know its location.  (In JDK 1.3.0 it would work.)  */
-	old_classpath =
-	  set_classpath (classpaths, classpaths_count, use_minimal_classpath,
-			 verbose);
-
-	argc =
-	  1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
-	  + java_sources_count;
-	argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
+      if (usable)
+	{
+	  char *old_classpath;
 
-	argp = argv;
-	*argp++ = "javac";
-	if (optimize)
-	  *argp++ = "-O";
-	if (debug)
-	  *argp++ = "-g";
-	if (directory != NULL)
-	  {
-	    *argp++ = "-d";
-	    *argp++ = (char *) directory;
-	  }
-	for (i = 0; i < java_sources_count; i++)
-	  *argp++ = (char *) java_sources[i];
-	*argp = NULL;
-	/* Ensure argv length was correctly calculated.  */
-	if (argp - argv != argc)
-	  abort ();
+	  /* Set CLASSPATH.  We don't use the "-classpath ..." option because
+	     in JDK 1.1.x its argument should also contain the JDK's
+	     classes.zip, but we don't know its location.  (In JDK 1.3.0 it
+	     would work.)  */
+	  old_classpath =
+	    set_classpath (classpaths, classpaths_count, use_minimal_classpath,
+			   verbose);
 
-	if (verbose)
-	  {
-	    char *command = shell_quote_argv (argv);
-	    printf ("%s\n", command);
-	    free (command);
-	  }
-
-	exitstatus = execute ("javac", "javac", argv, false, false, false,
-			      false, true, true);
-	err = (exitstatus != 0);
+	  err = compile_using_javac (java_sources, java_sources_count,
+				     source_option, source_version,
+				     target_option, target_version,
+				     directory, optimize, debug, verbose,
+				     false);
 
-	freesa (argv);
-
-	/* Reset CLASSPATH.  */
-	reset_classpath (old_classpath);
-
-	goto done2;
-      }
-  }
-
-  {
-    static bool jikes_tested;
-    static bool jikes_present;
+	  /* Reset CLASSPATH.  */
+	  reset_classpath (old_classpath);
 
-    if (!jikes_tested)
-      {
-	/* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1"  */
-	char *argv[2];
-	int exitstatus;
-
-	argv[0] = "jikes";
-	argv[1] = NULL;
-	exitstatus = execute ("jikes", "jikes", argv, false, false, true, true,
-			      true, false);
-	jikes_present = (exitstatus == 0 || exitstatus == 1);
-	jikes_tested = true;
-      }
+	  goto done2;
+	}
+    }
 
-    if (jikes_present)
-      {
-	char *old_classpath;
-	unsigned int argc;
-	char **argv;
-	char **argp;
-	int exitstatus;
-	unsigned int i;
+  if (is_jikes_present ())
+    {
+      /* Test whether it supports the desired target-version and
+	 source-version.  */
+      bool usable = (strcmp (source_version, "1.3") == 0);
 
-	/* Set CLASSPATH.  We could also use the "-classpath ..." option.
-	   Since jikes doesn't come with its own standard library, it
-	   needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
-	   To increase the chance of success, we reuse the current CLASSPATH
-	   if the user has set it.  */
-	old_classpath =
-	  set_classpath (classpaths, classpaths_count, false,
-			 verbose);
-
-	argc =
-	  1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
-	  + java_sources_count;
-	argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
+      if (usable)
+	{
+	  char *old_classpath;
 
-	argp = argv;
-	*argp++ = "jikes";
-	if (optimize)
-	  *argp++ = "-O";
-	if (debug)
-	  *argp++ = "-g";
-	if (directory != NULL)
-	  {
-	    *argp++ = "-d";
-	    *argp++ = (char *) directory;
-	  }
-	for (i = 0; i < java_sources_count; i++)
-	  *argp++ = (char *) java_sources[i];
-	*argp = NULL;
-	/* Ensure argv length was correctly calculated.  */
-	if (argp - argv != argc)
-	  abort ();
+	  /* Set CLASSPATH.  We could also use the "-classpath ..." option.
+	     Since jikes doesn't come with its own standard library, it
+	     needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
+	     To increase the chance of success, we reuse the current CLASSPATH
+	     if the user has set it.  */
+	  old_classpath =
+	    set_classpath (classpaths, classpaths_count, false, verbose);
 
-	if (verbose)
-	  {
-	    char *command = shell_quote_argv (argv);
-	    printf ("%s\n", command);
-	    free (command);
-	  }
+	  err = compile_using_jikes (java_sources, java_sources_count,
+				     directory, optimize, debug, verbose,
+				     false);
 
-	exitstatus = execute ("jikes", "jikes", argv, false, false, false,
-			      false, true, true);
-	err = (exitstatus != 0);
-
-	freesa (argv);
+	  /* Reset CLASSPATH.  */
+	  reset_classpath (old_classpath);
 
-	/* Reset CLASSPATH.  */
-	reset_classpath (old_classpath);
-
-	goto done2;
-      }
-  }
+	  goto done2;
+	}
+    }
 
   error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
   err = true;
--- a/lib/javacomp.h
+++ b/lib/javacomp.h
@@ -1,5 +1,5 @@
 /* Compile a Java program.
-   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+   Copyright (C) 2001-2002, 2006 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
 
    This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,35 @@
 /* Compile a Java source file to bytecode.
    java_sources is an array of source file names.
    classpaths is a list of pathnames to be prepended to the CLASSPATH.
+
+   source_version can be:    support for
+             1.3             inner classes
+             1.4             assert keyword
+             1.5             generic classes and methods
+             1.6             (not yet supported)
+   target_version can be:  classfile version:
+             1.1                 45.3
+             1.2                 46.0
+             1.3                 47.0
+             1.4                 48.0
+             1.5                 49.0
+             1.6                 50.0
+   target_version can also be given as NULL. In this case, the required 
+   target_version is determined from the found JVM (see javaversion.h).
+   Specifying target_version is useful when building a library (.jar) that is
+   useful outside the given package. Passing target_version = NULL is useful
+   when building an application.
+   It is unreasonable to ask for:
+     - target_version < 1.4 with source_version >= 1.4, or
+     - target_version < 1.5 with source_version >= 1.5, or
+     - target_version < 1.6 with source_version >= 1.6,
+   because even Sun's javac doesn't support these combinations.
+   It is redundant to ask for a target_version > source_version, since the
+   smaller target_version = source_version will also always work and newer JVMs
+   support the older target_versions too. Except for the case
+   target_version = 1.4, source_version = 1.3, which allows gcj versions 3.0
+   to 3.2 to be used.
+
    directory is the target directory. The .class file for class X.Y.Z is
    written at directory/X/Y/Z.class. If directory is NULL, the .class
    file is written in the source's directory.
@@ -37,6 +66,8 @@
 				unsigned int java_sources_count,
 				const char * const *classpaths,
 				unsigned int classpaths_count,
+				const char *source_version,
+				const char *target_version,
 				const char *directory,
 				bool optimize, bool debug,
 				bool use_minimal_classpath,
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -1,3 +1,26 @@
+2006-07-21  Bruno Haible  <bruno@clisp.org>
+
+	* javacomp.m4 (gt_JAVACOMP): Convert target_version "null" to "1.1".
+
+2006-05-09  Bruno Haible  <bruno@clisp.org>
+
+	* javacomp.m4 (gt_JAVACOMP): On Cygwin, set CLASSPATH_SEPARATOR to
+	a semicolon. Use CLASSPATH_SEPARATOR for the conftestver execution.
+
+2006-05-01  Bruno Haible  <bruno@clisp.org>
+
+	* javacomp.m4 (gt_JAVACOMP): Accept a source-version and an optional
+	target-version argument. Verify that the compiler groks source of the
+	specified source-version, or add -source option as necessary. Verify
+	that the compiler produces bytecode in the specified target-version,
+	or add -target and -source options as necessary. Make the result of
+	the test available as variable CONF_JAVAC. Also log error output in
+	config.log.
+
+2006-03-11  Bruno Haible  <bruno@clisp.org>
+
+	* javacomp.m4 (gt_JAVACOMP): Treat gcj-4.x like gcj-3.x.
+
 2006-05-09  Bruno Haible  <bruno@clisp.org>
 
 	* javaexec.m4 (gt_JAVAEXEC): On Cygwin, set CLASSPATH_SEPARATOR to a
--- a/m4/javacomp.m4
+++ b/m4/javacomp.m4
@@ -1,24 +1,352 @@
-# javacomp.m4 serial 6 (gettext-0.13)
-dnl Copyright (C) 2001-2003 Free Software Foundation, Inc.
+# javacomp.m4 serial 8 (gettext-0.15)
+dnl Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
 # Prerequisites of javacomp.sh.
-# Sets HAVE_JAVACOMP to nonempty if javacomp.sh will work.
+# gt_JAVACOMP([source-version], [target-version])
+# Sets HAVE_JAVACOMP to nonempty if javacomp.sh will allow Java source code
+# according to source-version to be compiled to Java bytecode classes in the
+# target-version format.
+#
+# source-version can be:    support for
+#           1.3             inner classes
+#           1.4             assert keyword
+#           1.5             generic classes and methods
+#           1.6             (not yet supported)
+#
+# target-version can be:  classfile version:
+#           1.1                 45.3
+#           1.2                 46.0
+#           1.3                 47.0
+#           1.4                 48.0
+#           1.5                 49.0
+#           1.6                 50.0
+# The classfile version of a .class file can be determined through the "file"
+# command. More portably, the classfile major version can be determined through
+# "od -A n -t d1 -j 7 -N 1 classfile".
+# target-version can also be omitted. In this case, the required target-version
+# is determined from the found JVM (see macro gt_JAVAEXEC):
+#      target-version   for JVM
+#           1.1         JDK 1.1, jview
+#           1.2         JDK/JRE 1.2
+#           1.3         JDK/JRE 1.3, gij 3.3, 3.4
+#           1.4         JDK/JRE 1.4, gij 4.0, 4.1
+#           1.5         JDK/JRE 1.5
+#           1.6         JDK/JRE 1.6
+# Note: gij >= 3.3 can in some cases handle classes compiled with -target 1.4,
+# and gij >= 4.1 can in some cases partially handle classes compiled with
+# -target 1.5, but I have no idea how complete this support is.
+#
+# Specifying target-version is useful when building a library (.jar) that is
+# useful outside the given package. Omitting target-version is useful when
+# building an application.
+#
+# It is unreasonable to ask for:
+#   - target-version < 1.4 with source-version >= 1.4, or
+#   - target-version < 1.5 with source-version >= 1.5, or
+#   - target-version < 1.6 with source-version >= 1.6,
+# because even Sun's javac doesn't support these combinations.
+#
+# It is redundant to ask for a target-version > source-version, since the
+# smaller target-version = source-version will also always work and newer JVMs
+# support the older target-versions too. Except for the case
+# target-version = 1.4, source-version = 1.3, which allows gcj versions 3.0
+# to 3.2 to be used.
 
 AC_DEFUN([gt_JAVACOMP],
 [
-  AC_MSG_CHECKING([for Java compiler])
+  ifelse([$2], [], [AC_REQUIRE([gt_JAVAEXEC])], [])
   AC_EGREP_CPP(yes, [
-#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
   yes
 #endif
 ], CLASSPATH_SEPARATOR=';', CLASSPATH_SEPARATOR=':')
-  HAVE_JAVACOMP=1
+  source_version=$1
+  test -n "$source_version" || {
+    AC_MSG_ERROR([missing source-version argument to gt_@&t@JAVACOMP])
+  }
+  ifelse([$2], [],
+    [if test -n "$HAVE_JAVAEXEC"; then
+       dnl Use $CONF_JAVA to determine the JVM's version.
+changequote(,)dnl
+       cat > conftestver.java <<EOF
+public class conftestver {
+  public static void main (String[] args) {
+    System.out.println(System.getProperty("java.specification.version"));
+  }
+}
+EOF
+changequote([,])dnl
+       dnl A precompiled version of conftestver.java, compiled with
+       dnl "javac -target 1.1". This avoids having to compile conftestver.java
+       dnl during each test for a suitable Java compiler.
+       dnl For the conversion from binary to this ASCII encapsulation, avoiding
+       dnl to assume the presence of uudecode, use the command
+       dnl   $ od -A n -t o1 < conftestver.class | tr ' ' '\012'| sort | uniq | sed -e '/^$/d' -e 's,^,\\,' | tr -d '\012'
+       dnl and the long tr command in opposite direction.
+       echo 'xyvw!$!H!C,!)!2+!3!4*!5,!3!6,!7!8)!9)!:"!(LdhdmM"!$EFV"!%Ni_a"!1PdhaQngYakUXYfa"!%gXdh"!8EWPeXoXJfXhcJTmkdhcKFV"!,TinkZaOdfa"!2ZihbmalmoakIeXoX.!*!+)!;.!<!="!<eXoXIljaZdbdZXmdihIoakldih.!>!?)!@.!A!B"!-Zihbmalmoak"!2eXoXJfXhcJRYeaZm"!2eXoXJfXhcJTplmag"!$inm"!7PeXoXJdiJSkdhmTmkaXgK"!-camSkijakmp"!DEPeXoXJfXhcJTmkdhcKFPeXoXJfXhcJTmkdhcK"!5eXoXJdiJSkdhmTmkaXg"!)jkdhmfh"!7EPeXoXJfXhcJTmkdhcKFV!C!(!)!!!!!#!"!*!+!"!,!!!?!"!"!!!&Gt!"q!!!"!-!!!(!"!!!"!+!.!/!"!,!!!E!#!"!!!.r!#4$u!%s!&q!!!"!-!!!,!#!!!$!-!%!"!0!!!#!1' \
+         | tr -d '\012\015' \
+         | tr '!"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz' '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\046\050\051\052\055\056\057\073\074\076\103\106\114\116\117\120\123\124\126\133\141\142\143\144\145\146\147\151\152\154\155\156\157\160\162\163\164\165\166\171\261\262\266\267\270\272\276\312\376' \
+         > conftestver.class
+       target_version=`{
+         unset JAVA_HOME
+         echo "$as_me:__oline__: CLASSPATH=.${CLASSPATH:+$CLASSPATH_SEPARATOR$CLASSPATH} $CONF_JAVA conftestver" >&AS_MESSAGE_LOG_FD
+         CLASSPATH=.${CLASSPATH:+$CLASSPATH_SEPARATOR$CLASSPATH} $CONF_JAVA conftestver 2>&AS_MESSAGE_LOG_FD
+       }`
+       case "$target_version" in
+         1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6) ;;
+         null)
+           dnl JDK 1.1.X returns null.
+           target_version=1.1 ;;
+         *) AC_MSG_WARN([unknown target-version $target_version, please update gt_@&t@JAVACOMP macro])
+            target_version=1.1 ;;
+       esac
+     else
+       target_version="1.1"
+     fi
+    ],
+    [target_version=$2])
+  case "$source_version" in
+    1.3) goodcode='class conftest {}'
+         failcode='class conftestfail { static { assert(true); } }' ;;
+    1.4) goodcode='class conftest     { static { assert(true); } }'
+         failcode='class conftestfail<T> { T foo() { return null; } }' ;;
+    1.5) goodcode='class conftest<T>     { T foo() { return null; } }'
+         failcode='class conftestfail syntax error' ;;
+    *) AC_MSG_ERROR([invalid source-version argument to gt_@&t@JAVACOMP: $source_version]) ;;
+  esac
+  case "$target_version" in
+    1.1) cfversion=45 ;;
+    1.2) cfversion=46 ;;
+    1.3) cfversion=47 ;;
+    1.4) cfversion=48 ;;
+    1.5) cfversion=49 ;;
+    1.6) cfversion=50 ;;
+    *) AC_MSG_ERROR([invalid target-version argument to gt_@&t@JAVACOMP: $target_version]) ;;
+  esac
+  # Function to output the classfile version of a file (8th byte) in decimal.
+  if od -A x < /dev/null >/dev/null 2>/dev/null; then
+    # Use POSIX od.
+    func_classfile_version ()
+    {
+      od -A n -t d1 -j 7 -N 1 "[$]1"
+    }
+  else
+    # Use BSD hexdump.
+    func_classfile_version ()
+    {
+      dd if="[$]1" bs=1 count=1 skip=7 2>/dev/null | hexdump -e '1/1 "%3d "'
+      echo
+    }
+  fi
+  AC_MSG_CHECKING([for Java compiler])
+  dnl
+  dnl The support of GNU gcj for target-version and source-version:
+  dnl
+  dnl   gcj 3.0.4 to 4.1 does not have a way to specify the target-version.
+  dnl   It always assumes target-version=1.4 but labels the class files as 1.1.
+  dnl   One consequence of this is that gcj compiles GetURL.java to invalid
+  dnl   bytecode, which crashes with a VerifyError when executed by Sun Java
+  dnl   1.3.1. The bug is registered as java/7066, see
+  dnl   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7066
+  dnl   FIXME: Check new versions of gcj as they come out.
+  dnl
+  dnl   For gcj < 3.3, the source-version always is 1.3.
+  dnl   For gcj >= 3.3, the source-version defaults to 1.4; option
+  dnl   "-fno-assert" switches to source-version 1.3.
+  dnl
+  dnl The support of Sun javac for target-version and source-version:
+  dnl
+  dnl   javac 1.3:   -target 1.1 1.2 1.3               default: 1.1
+  dnl                                                  source always: 1.3
+  dnl
+  dnl   javac 1.4:   -target 1.1 1.2 1.3 1.4           default: 1.2
+  dnl                -source 1.3 1.4                   default: 1.3
+  dnl                -target 1.1/1.2/1.3 only possible with -source 1.3 or no -source
+  dnl
+  dnl   javac 1.5:   -target 1.1 1.2 1.3 1.4 1.5       default: 1.5
+  dnl                -source 1.3 1.4 1.5               default: 1.5
+  dnl                -target 1.1/1.2/1.3 only possible with -source 1.3
+  dnl                -target 1.4 only possible with -source 1.3/1.4
+  dnl
+  dnl   javac 1.6:   -target 1.1 1.2 1.3 1.4 1.5 1.6   default: 1.6
+  dnl                -source 1.3 1.4 1.5 1.6           default: 1.5
+  dnl                -target 1.1/1.2/1.3 only possible with -source 1.3
+  dnl                -target 1.4 only possible with -source 1.3/1.4
+  dnl                -target 1.5 only possible with -source 1.3/1.4/1.5 or no -source
+  dnl
+  dnl The support of jikes for target-version and source-version:
+  dnl
+  dnl   jikes 1.14 does not have a way to specify the target-version. It
+  dnl   always assumes target-version=1.1.
+  dnl
+  dnl   For jikes 1.14, the source-version always is 1.3.
+  dnl
+  CONF_JAVAC=
+  HAVE_JAVAC_ENVVAR=
+  HAVE_GCJ_C=
+  HAVE_JAVAC=
+  HAVE_JIKES=
+  HAVE_JAVACOMP=
+changequote(,)dnl
+  cat > conftestlib.java <<EOF
+public class conftestlib {
+  public static void main (String[] args) {
+  }
+}
+EOF
+changequote([,])dnl
+  echo "$goodcode" > conftest.java
+  echo "$failcode" > conftestfail.java
+  dnl If the user has set the JAVAC environment variable, use that, if it
+  dnl satisfies the constraints (possibly after adding -target and -source
+  dnl options).
   if test -n "$JAVAC"; then
-    ac_result="$JAVAC"
-  else
+    dnl Try the original $JAVAC.
+    if $JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null; then
+      dnl It's a version of gcj. Ignore the version of conftest.class.
+      if test "$target_version" = 1.4 && test "$source_version" = 1.4; then
+        dnl Try $JAVAC.
+        rm -f conftest.class
+        if { echo "$as_me:__oline__: $JAVAC -d . conftest.java" >&AS_MESSAGE_LOG_FD
+             $JAVAC -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+           } \
+           && test -f conftest.class; then
+          CONF_JAVAC="$JAVAC"
+          HAVE_JAVAC_ENVVAR=1
+          HAVE_JAVACOMP=1
+        fi
+      else
+        if test "$target_version" = 1.4 && test "$source_version" = 1.3; then
+          dnl Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
+          dnl it makes a difference. (It could already be part of $JAVAC.)
+          javac_works=
+          rm -f conftest.class
+          if { echo "$as_me:__oline__: $JAVAC -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               $JAVAC -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+             } \
+             && test -f conftest.class; then
+            javac_works=1
+          fi
+          javac_noassert_works=
+          rm -f conftest.class
+          if { echo "$as_me:__oline__: $JAVAC -fno-assert -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               $JAVAC -fno-assert -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+             } \
+             && test -f conftest.class; then
+            javac_noassert_works=1
+          fi
+          if test -n "$javac_works" && test -n "$javac_noassert_works"; then
+            rm -f conftestfail.class
+            if { echo "$as_me:__oline__: $JAVAC -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                 $JAVAC -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+               } \
+               && test -f conftestfail.class \
+               && ! { echo "$as_me:__oline__: $JAVAC -fno-assert -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                      $JAVAC -fno-assert -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                    }; then
+              dnl "$JAVAC -fno-assert" works better than $JAVAC.
+              javac_works=
+            fi
+          fi
+          if test -n "$javac_works"; then
+            CONF_JAVAC="$JAVAC"
+            HAVE_JAVAC_ENVVAR=1
+            HAVE_JAVACOMP=1
+          else
+            if test -n "$javac_noassert_works"; then
+              CONF_JAVAC="$JAVAC -fno-assert"
+              HAVE_JAVAC_ENVVAR=1
+              HAVE_JAVACOMP=1
+            fi
+          fi
+        fi
+      fi
+    else
+      dnl It's not gcj. Assume the classfile versions are correct.
+      dnl Try $JAVAC.
+      rm -f conftest.class
+      if { echo "$as_me:__oline__: $JAVAC -d . conftest.java" >&AS_MESSAGE_LOG_FD
+           $JAVAC -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+         } \
+         && test -f conftest.class \
+         && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+        dnl Try adding -source option if it is useful.
+        rm -f conftest.class
+        rm -f conftestfail.class
+        if { echo "$as_me:__oline__: $JAVAC -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+             $JAVAC -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+           } \
+           && test -f conftest.class \
+           && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \
+           && { echo "$as_me:__oline__: $JAVAC -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                $JAVAC -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+              } \
+           && test -f conftestfail.class \
+           && ! { echo "$as_me:__oline__: $JAVAC -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                  $JAVAC -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                }; then
+          CONF_JAVAC="$JAVAC -source $source_version"
+          HAVE_JAVAC_ENVVAR=1
+          HAVE_JAVACOMP=1
+        else
+          CONF_JAVAC="$JAVAC"
+          HAVE_JAVAC_ENVVAR=1
+          HAVE_JAVACOMP=1
+        fi
+      else
+        dnl Try with -target option alone. (Sun javac 1.3.1 has the -target
+        dnl option but no -source option.)
+        rm -f conftest.class
+        if { echo "$as_me:__oline__: $JAVAC -target $target_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+             $JAVAC -target "$target_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+           } \
+           && test -f conftest.class \
+           && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+          dnl Try adding -source option if it is useful.
+          rm -f conftest.class
+          rm -f conftestfail.class
+          if { echo "$as_me:__oline__: $JAVAC -target $target_version -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               $JAVAC -target "$target_version" -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+             } \
+             && test -f conftest.class \
+             && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \
+             && { echo "$as_me:__oline__: $JAVAC -target $target_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                  $JAVAC -target "$target_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                } \
+             && test -f conftestfail.class \
+             && ! { echo "$as_me:__oline__: $JAVAC -target $target_version -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                    $JAVAC -target "$target_version" -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                  }; then
+            CONF_JAVAC="$JAVAC -target $target_version -source $source_version"
+            HAVE_JAVAC_ENVVAR=1
+            HAVE_JAVACOMP=1
+          else
+            CONF_JAVAC="$JAVAC -target $target_version"
+            HAVE_JAVAC_ENVVAR=1
+            HAVE_JAVACOMP=1
+          fi
+        else
+          dnl Maybe this -target option requires a -source option? Try with
+          dnl -target and -source options. (Supported by Sun javac 1.4 and
+          dnl higher.)
+          rm -f conftest.class
+          if { echo "$as_me:__oline__: $JAVAC -target $target_version -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               $JAVAC -target "$target_version" -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+             } \
+             && test -f conftest.class \
+             && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+            CONF_JAVAC="$JAVAC -target $target_version -source $source_version"
+            HAVE_JAVAC_ENVVAR=1
+            HAVE_JAVACOMP=1
+          fi
+        fi
+      fi
+    fi
+  fi
+  if test -z "$HAVE_JAVACOMP"; then
     pushdef([AC_MSG_CHECKING],[:])dnl
     pushdef([AC_CHECKING],[:])dnl
     pushdef([AC_MSG_RESULT],[:])dnl
@@ -28,70 +356,175 @@
     popdef([AC_MSG_RESULT])dnl
     popdef([AC_CHECKING])dnl
     popdef([AC_MSG_CHECKING])dnl
+    if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_GCJ_IN_PATH"; then
+      dnl Test for a good gcj version (>= 3.0).
 changequote(,)dnl
-    # Test for a good gcj version (>= 3.0).
-    # Exclude some versions of gcj: gcj 3.0.4 compiles GetURL.java to invalid
-    # bytecode, that crashes with an IllegalAccessError when executed by
-    # gij 3.0.4 or with a VerifyError when executed by Sun Java. Likewise for
-    # gcj 3.1.
-    # I also exclude gcj 3.2, 3.3 etc. because I have no idea when this bug
-    # will be fixed. The bug is registered as java/7066, see
-    # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7066
-    # FIXME: Check new versions of gcj as they come out.
-    if test -n "$HAVE_GCJ_IN_PATH" \
-       && gcj --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[0123456789]/d' | grep '^[3-9]' >/dev/null \
-       && (
-        # See if libgcj.jar is well installed.
-        cat > conftest.java <<EOF
-public class conftest {
-  public static void main (String[] args) {
-  }
-}
-EOF
-        gcj -C -d . conftest.java 2>/dev/null
-        error=$?
-        rm -f conftest.java conftest.class
-        exit $error
-       ); then
-      HAVE_GCJ_C=1
-      ac_result="gcj -C"
-    else
-      if test -n "$HAVE_JAVAC_IN_PATH" \
-         && (javac -version >/dev/null 2>/dev/null || test $? -le 2) \
-         && (if javac -help 2>&1 >/dev/null | grep at.dms.kjc.Main >/dev/null && javac -help 2>/dev/null | grep 'released.*2000' >/dev/null ; then exit 1; else exit 0; fi); then
-        HAVE_JAVAC=1
-        ac_result="javac"
-      else
-        if test -n "$HAVE_JIKES_IN_PATH" \
-           && (jikes >/dev/null 2>/dev/null || test $? = 1) \
-           && (
-            # See if the existing CLASSPATH is sufficient to make jikes work.
-            cat > conftest.java <<EOF
-public class conftest {
-  public static void main (String[] args) {
-  }
-}
-EOF
-            unset JAVA_HOME
-            jikes conftest.java 2>/dev/null
-            error=$?
-            rm -f conftest.java conftest.class
-            exit $error
-           ); then
-          HAVE_JIKES=1
-          ac_result="jikes"
-        else
-          HAVE_JAVACOMP=
-          ac_result="no"
+      if gcj --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null; then
+changequote([,])dnl
+        dnl See if libgcj.jar is well installed.
+        if { echo "$as_me:__oline__: gcj -C -d . conftestlib.java" >&AS_MESSAGE_LOG_FD
+             gcj -C -d . conftestlib.java >&AS_MESSAGE_LOG_FD 2>&1
+           }; then
+          dnl OK, gcj works.
+          dnl Now test whether it supports the desired target-version and
+          dnl source-version. But ignore the version of conftest.class.
+          if test "$target_version" = 1.4 && test "$source_version" = 1.4; then
+            rm -f conftest.class
+            if { echo "$as_me:__oline__: gcj -C -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                 gcj -C -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+               } \
+               && test -f conftest.class; then
+              CONF_JAVAC="gcj -C"
+              HAVE_GCJ_C=1
+              HAVE_JAVACOMP=1
+            fi
+          else
+            if test "$target_version" = 1.4 && test "$source_version" = 1.3; then
+              dnl Try gcj and "gcj -fno-assert". But add -fno-assert only if
+              dnl it works (not gcj < 3.3).
+              rm -f conftest.class
+              if { echo "$as_me:__oline__: gcj -C -fno-assert -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                   gcj -C -fno-assert -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+                 } \
+                 && test -f conftest.class; then
+                CONF_JAVAC="gcj -C -fno-assert"
+                HAVE_GCJ_C=1
+                HAVE_JAVACOMP=1
+              else
+                rm -f conftest.class
+                if { echo "$as_me:__oline__: gcj -C -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                     gcj -C -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+                   } \
+                   && test -f conftest.class; then
+                  CONF_JAVAC="gcj -C"
+                  HAVE_GCJ_C=1
+                  HAVE_JAVACOMP=1
+                fi
+              fi
+            fi
+          fi
         fi
       fi
     fi
-changequote([,])dnl
+    if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_JAVAC_IN_PATH"; then
+      dnl Test whether javac is usable.
+      if { javac -version >/dev/null 2>/dev/null || test $? -le 2; } \
+         && ( if javac -help 2>&1 >/dev/null | grep at.dms.kjc.Main >/dev/null && javac -help 2>/dev/null | grep 'released.*2000' >/dev/null ; then exit 1; else exit 0; fi ); then
+        dnl OK, javac works.
+        dnl Now test whether it supports the desired target-version and
+        dnl source-version.
+        rm -f conftest.class
+        if { echo "$as_me:__oline__: javac -d . conftest.java" >&AS_MESSAGE_LOG_FD
+             javac -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+           } \
+           && test -f conftest.class \
+           && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+          dnl Try adding -source option if it is useful.
+          rm -f conftest.class
+          rm -f conftestfail.class
+          if { echo "$as_me:__oline__: javac -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               javac -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+             } \
+             && test -f conftest.class \
+             && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \
+             && { echo "$as_me:__oline__: javac -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                  javac -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                } \
+             && test -f conftestfail.class \
+             && ! { echo "$as_me:__oline__: javac -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                    javac -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                  }; then
+            CONF_JAVAC="javac -source $source_version"
+            HAVE_JAVAC=1
+            HAVE_JAVACOMP=1
+          else
+            CONF_JAVAC="javac"
+            HAVE_JAVAC=1
+            HAVE_JAVACOMP=1
+          fi
+        else
+          dnl Try with -target option alone. (Sun javac 1.3.1 has the -target
+          dnl option but no -source option.)
+          rm -f conftest.class
+          if { echo "$as_me:__oline__: javac -target $target_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               javac -target "$target_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+             } \
+             && test -f conftest.class \
+             && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+            dnl Try adding -source option if it is useful.
+            rm -f conftest.class
+            rm -f conftestfail.class
+            if { echo "$as_me:__oline__: javac -target $target_version -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                 javac -target "$target_version" -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+               } \
+               && test -f conftest.class \
+               && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \
+               && { echo "$as_me:__oline__: javac -target $target_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                    javac -target "$target_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                  } \
+               && test -f conftestfail.class \
+               && ! { echo "$as_me:__oline__: javac -target $target_version -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                      javac -target "$target_version" -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                    }; then
+              CONF_JAVAC="javac -target $target_version -source $source_version"
+              HAVE_JAVAC=1
+              HAVE_JAVACOMP=1
+            else
+              CONF_JAVAC="javac -target $target_version"
+              HAVE_JAVAC=1
+              HAVE_JAVACOMP=1
+            fi
+          else
+            dnl Maybe this -target option requires a -source option? Try with
+            dnl -target and -source options. (Supported by Sun javac 1.4 and
+            dnl higher.)
+            rm -f conftest.class
+            if { echo "$as_me:__oline__: javac -target $target_version -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                 javac -target "$target_version" -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+               } \
+               && test -f conftest.class \
+               && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+              CONF_JAVAC="javac -target $target_version -source $source_version"
+              HAVE_JAVAC=1
+              HAVE_JAVACOMP=1
+            fi
+          fi
+        fi
+      fi
+    fi
+    if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_JIKES_IN_PATH"; then
+      dnl Test whether jikes is usable.
+      if { jikes >/dev/null 2>/dev/null || test $? = 1; } \
+         && (
+              # See if the existing CLASSPATH is sufficient to make jikes work.
+              unset JAVA_HOME
+              jikes conftestlib.java >&AS_MESSAGE_LOG_FD 2>&1
+              error=$?
+              rm -f conftestlib.class
+              exit $error
+            ); then
+        dnl OK, jikes works.
+        dnl Now test whether it supports the desired target-version and
+        dnl source-version.
+        if test "$source_version" = 1.3; then
+          CONF_JAVAC="jikes"
+          HAVE_JIKES=1
+          HAVE_JAVACOMP=1
+        fi
+      fi
+    fi
+  fi
+  rm -f conftest*.java conftest*.class
+  if test -n "$HAVE_JAVACOMP"; then
+    ac_result="$CONF_JAVAC"
+  else
+    ac_result="no"
   fi
   AC_MSG_RESULT([$ac_result])
-  AC_SUBST(JAVAC)
+  AC_SUBST(CONF_JAVAC)
   AC_SUBST(CLASSPATH)
   AC_SUBST(CLASSPATH_SEPARATOR)
+  AC_SUBST(HAVE_JAVAC_ENVVAR)
   AC_SUBST(HAVE_GCJ_C)
   AC_SUBST(HAVE_JAVAC)
   AC_SUBST(HAVE_JIKES)