changeset 8078:0a080a2d054b

Make use of gcj-4.3's -fsource and -ftarget option.
author Bruno Haible <bruno@clisp.org>
date Sun, 04 Feb 2007 16:28:01 +0000
parents 9cd2d21f40cc
children 0951beec5b89
files ChangeLog lib/javacomp.c m4/javacomp.m4
diffstat 3 files changed, 763 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-02-04  Bruno Haible  <bruno@clisp.org>
+
+	Make use of gcj-4.3's -fsource and -ftarget option.
+	* m4/javacomp.m4 (gt_JAVACOMP): Test whether gcj is in version >= 4.3,
+	and if so try the options -fsource and -ftarget.
+	* lib/javacomp.c (compile_using_gcj): Add fsource_option,
+	source_version, ftarget_option, target_version arguments.
+	(is_envjavac_gcj43, is_envjavac_gcj43_usable): New functions.
+	(is_envjavac_oldgcj_14_14_usable): Renamed from
+	is_envjavac_gcj_14_14_usable.
+	(is_envjavac_oldgcj_14_13_usable): Renamed from
+	is_envjavac_gcj_14_13_usable.
+	(is_gcj_present): Update.
+	(is_gcj_43, is_gcj43_usable): New functions.
+	(is_oldgcj_14_14_usable): Renamed from is_gcj_14_14_usable. Update.
+	(is_oldgcj_14_13_usable): Renamed from is_gcj_14_13_usable. Update.
+	(compile_java_class): Test whether gcj is in version >= 4.3, and if so
+	try the options -fsource and -ftarget.
+
 2007-02-03  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* lib/xalloc.h (x2nrealloc): Fix an unlikely bug in the overflow
--- a/lib/javacomp.c
+++ b/lib/javacomp.c
@@ -284,6 +284,8 @@
 compile_using_gcj (const char * const *java_sources,
 		   unsigned int java_sources_count,
 		   bool no_assert_option,
+		   bool fsource_option, const char *source_version,
+		   bool ftarget_option, const char *target_version,
 		   const char *directory,
 		   bool optimize, bool debug,
 		   bool verbose, bool null_stderr)
@@ -292,11 +294,14 @@
   unsigned int argc;
   char **argv;
   char **argp;
+  char *fsource_arg;
+  char *ftarget_arg;
   int exitstatus;
   unsigned int i;
 
   argc =
-    2 + (no_assert_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
+    2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0)
+    + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
     + (directory != NULL ? 2 : 0) + java_sources_count;
   argv = (char **) xallocsa ((argc + 1) * sizeof (char *));
 
@@ -305,6 +310,24 @@
   *argp++ = "-C";
   if (no_assert_option)
     *argp++ = "-fno-assert";
+  if (fsource_option)
+    {
+      fsource_arg = (char *) xallocsa (9 + strlen (source_version) + 1);
+      memcpy (fsource_arg, "-fsource=", 9);
+      strcpy (fsource_arg + 9, source_version);
+      *argp++ = fsource_arg;
+    }
+  else
+    fsource_arg = NULL;
+  if (ftarget_option)
+    {
+      ftarget_arg = (char *) xallocsa (9 + strlen (target_version) + 1);
+      memcpy (ftarget_arg, "-ftarget=", 9);
+      strcpy (ftarget_arg + 9, target_version);
+      *argp++ = ftarget_arg;
+    }
+  else
+    ftarget_arg = NULL;
   if (optimize)
     *argp++ = "-O";
   if (debug)
@@ -332,6 +355,10 @@
 			true, true);
   err = (exitstatus != 0);
 
+  if (ftarget_arg != NULL)
+    freesa (ftarget_arg);
+  if (fsource_arg != NULL)
+    freesa (fsource_arg);
   freesa (argv);
 
   return err;
@@ -593,11 +620,258 @@
   return envjavac_gcj;
 }
 
-/* Test whether $JAVAC, known to be a version of gcj, can be used for
+/* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
+   of gcj.  */
+static bool
+is_envjavac_gcj43 (const char *javac)
+{
+  static bool envjavac_tested;
+  static bool envjavac_gcj43;
+
+  if (!envjavac_tested)
+    {
+      /* Test whether $JAVAC is gcj:
+	 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
+	  | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null"  */
+      unsigned int command_length;
+      char *command;
+      char *argv[4];
+      pid_t child;
+      int fd[1];
+      FILE *fp;
+      char *line;
+      size_t linesize;
+      size_t linelen;
+      int exitstatus;
+      char *p;
+
+      /* Setup the command "$JAVAC --version".  */
+      command_length = strlen (javac) + 1 + 9 + 1;
+      command = (char *) 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;
+	}
+      p = line;
+      while (*p != '\0' && !(*p >= '0' && *p <= '9'))
+	p++;
+      envjavac_gcj43 =
+        !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2')
+	&& (*p >= '4' && *p <= '9');
+
+      fclose (fp);
+
+      /* Remove zombie process from process list, and retrieve exit status.  */
+      exitstatus = wait_subprocess (child, javac, true, true, true, false);
+      if (exitstatus != 0)
+	envjavac_gcj43 = false;
+
+     failed:
+      freesa (command);
+
+      envjavac_tested = true;
+    }
+
+  return envjavac_gcj43;
+}
+
+/* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
+   whether it needs a -fsource and/or -ftarget option.
+   Return a failure indicator (true upon error).  */
+static bool
+is_envjavac_gcj43_usable (const char *javac,
+			  const char *source_version,
+			  const char *target_version,
+			  bool *usablep,
+			  bool *fsource_option_p, bool *ftarget_option_p)
+{
+  /* The cache depends on the source_version and target_version.  */
+  struct result_t
+  {
+    bool tested;
+    bool usable;
+    bool fsource_option;
+    bool ftarget_option;
+  };
+  static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
+  struct result_t *resultp;
+
+  resultp = &result_cache[source_version_index (source_version)]
+			 [target_version_index (target_version)];
+  if (!resultp->tested)
+    {
+      /* Try $JAVAC.  */
+      struct temp_dir *tmpdir;
+      char *conftest_file_name;
+      char *compiled_file_name;
+      const char *java_sources[1];
+      struct stat statbuf;
+
+      tmpdir = create_temp_dir ("java", NULL, false);
+      if (tmpdir == NULL)
+	return true;
+
+      conftest_file_name =
+	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 -fsource option if it is useful.  */
+	  char *javac_source =
+	    xasprintf ("%s -fsource=%s", javac, source_version);
+
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_envjavac (javac_source,
+				       java_sources, 1, tmpdir->dir_name,
+				       false, false, false, true)
+	      && stat (compiled_file_name, &statbuf) >= 0
+	      && get_classfile_version (compiled_file_name)
+		 <= corresponding_classfile_version (target_version))
+	    {
+	      const char *failcode = get_failcode_snippet (source_version);
+
+	      if (failcode != NULL)
+		{
+		  free (compiled_file_name);
+		  free (conftest_file_name);
+
+		  conftest_file_name =
+		    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 -fsource=$source_version" rejects it.  So
+			   the -fsource option is useful.  */
+			resultp->fsource_option = true;
+		    }
+		}
+	    }
+
+	  free (javac_source);
+
+	  resultp->usable = true;
+	}
+      else
+	{
+	  /* Try with -fsource and -ftarget options.  */
+	  char *javac_target =
+	    xasprintf ("%s -fsource=%s -ftarget=%s",
+		       javac, source_version, target_version);
+
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_envjavac (javac_target,
+				       java_sources, 1, tmpdir->dir_name,
+				       false, false, false, true)
+	      && stat (compiled_file_name, &statbuf) >= 0
+	      && get_classfile_version (compiled_file_name)
+		 <= corresponding_classfile_version (target_version))
+	    {
+	      /* "$JAVAC -fsource $source_version -ftarget $target_version"
+		 compiled conftest.java successfully.  */
+	      resultp->fsource_option = true;
+	      resultp->ftarget_option = true;
+	      resultp->usable = true;
+	    }
+
+	  free (javac_target);
+	}
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      resultp->tested = true;
+    }
+
+  *usablep = resultp->usable;
+  *fsource_option_p = resultp->fsource_option;
+  *ftarget_option_p = resultp->ftarget_option;
+  return false;
+}
+
+/* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
    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)
+is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
 {
   static bool envjavac_tested;
   static bool envjavac_usable;
@@ -648,11 +922,11 @@
   return false;
 }
 
-/* Test whether $JAVAC, known to be a version of gcj, can be used for
+/* Test whether $JAVAC, known to be a version of gcj < 4.3, 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,
+is_envjavac_oldgcj_14_13_usable (const char *javac,
 			      bool *usablep, bool *need_no_assert_option_p)
 {
   static bool envjavac_tested;
@@ -1134,6 +1408,7 @@
 
 		  java_sources[0] = conftest_file_name;
 		  if (compile_using_gcj (java_sources, 1, false,
+					 false, NULL, false, NULL,
 					 tmpdir->dir_name,
 					 false, false, false, true))
 		    gcj_present = false;
@@ -1151,11 +1426,232 @@
   return gcj_present;
 }
 
-/* Test gcj can be used for compiling with target_version = 1.4 and
-   source_version = 1.4.
+static bool
+is_gcj_43 (void)
+{
+  static bool gcj_tested;
+  static bool gcj_43;
+
+  if (!gcj_tested)
+    {
+      /* Test for presence of gcj:
+	 "gcj --version 2> /dev/null | \
+	  sed -e 's,^[^0-9]*,,' -e 1q | \
+	  sed -e '/^4\.[012]/d' | grep '^[4-9]'"  */
+      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_43 = 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 >= 4, but not with
+	     "4.0" or "4.1" or "4.2".  */
+	  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_43 = (c[0] >= '4');
+		}
+	      count++;
+	      if (count == 3)
+		{
+		  if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
+		    gcj_43 = 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_43 = false;
+	}
+
+      gcj_tested = true;
+    }
+
+  return gcj_43;
+}
+
+/* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
+   -ftarget option.
    Return a failure indicator (true upon error).  */
 static bool
-is_gcj_14_14_usable (bool *usablep)
+is_gcj43_usable (const char *source_version,
+		 const char *target_version,
+		 bool *usablep,
+		 bool *fsource_option_p, bool *ftarget_option_p)
+{
+  /* The cache depends on the source_version and target_version.  */
+  struct result_t
+  {
+    bool tested;
+    bool usable;
+    bool fsource_option;
+    bool ftarget_option;
+  };
+  static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
+  struct result_t *resultp;
+
+  resultp = &result_cache[source_version_index (source_version)]
+			 [target_version_index (target_version)];
+  if (!resultp->tested)
+    {
+      /* Try 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 (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_gcj (java_sources, 1, false, false, NULL, false, NULL,
+			      tmpdir->dir_name, false, false, false, true)
+	  && stat (compiled_file_name, &statbuf) >= 0
+	  && get_classfile_version (compiled_file_name)
+	     <= corresponding_classfile_version (target_version))
+	{
+	  /* gcj compiled conftest.java successfully.  */
+	  /* Try adding -fsource option if it is useful.  */
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_gcj (java_sources, 1,
+				  false, true, source_version, false, NULL,
+				  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_gcj (java_sources, 1,
+					  false, false, NULL, false, NULL,
+					  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_gcj (java_sources, 1,
+					     false, true, source_version,
+					     false, NULL,
+					     tmpdir->dir_name,
+					     false, false, false, true))
+			/* gcj compiled conftestfail.java successfully, and
+			   "gcj -fsource=$source_version" rejects it.  So
+			   the -fsource option is useful.  */
+			resultp->fsource_option = true;
+		    }
+		}
+	    }
+
+	  resultp->usable = true;
+	}
+      else
+	{
+	  /* Try with -fsource and -ftarget options.  */
+	  unlink (compiled_file_name);
+
+	  java_sources[0] = conftest_file_name;
+	  if (!compile_using_gcj (java_sources, 1,
+				  false, 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))
+	    {
+	      /* "gcj -fsource $source_version -ftarget $target_version"
+		 compiled conftest.java successfully.  */
+	      resultp->fsource_option = true;
+	      resultp->ftarget_option = true;
+	      resultp->usable = true;
+	    }
+	}
+
+      free (compiled_file_name);
+      free (conftest_file_name);
+
+      resultp->tested = true;
+    }
+
+  *usablep = resultp->usable;
+  *fsource_option_p = resultp->fsource_option;
+  *ftarget_option_p = resultp->ftarget_option;
+  return false;
+}
+
+/* Test whether gcj < 4.3 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_oldgcj_14_14_usable (bool *usablep)
 {
   static bool gcj_tested;
   static bool gcj_usable;
@@ -1188,8 +1684,8 @@
       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)
+      if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
+			      tmpdir->dir_name, false, false, false, true)
 	  && stat (compiled_file_name, &statbuf) >= 0)
 	/* Compilation succeeded.  */
 	gcj_usable = true;
@@ -1206,11 +1702,11 @@
   return false;
 }
 
-/* Test whether gcj can be used for compiling with target_version = 1.4 and
-   source_version = 1.3.
+/* Test whether gcj < 4.3 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)
+is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
 {
   static bool gcj_tested;
   static bool gcj_usable;
@@ -1245,8 +1741,8 @@
       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)
+      if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL,
+			      tmpdir->dir_name, false, false, false, true)
 	  && stat (compiled_file_name, &statbuf) >= 0)
 	/* Compilation succeeded.  */
 	{
@@ -1258,8 +1754,9 @@
 	  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)
+	  if (!compile_using_gcj (java_sources, 1, false,
+				  false, NULL, false, NULL,
+				  tmpdir->dir_name, false, false, false, true)
 	      && stat (compiled_file_name, &statbuf) >= 0)
 	    /* Compilation succeeded.  */
 	    {
@@ -1593,31 +2090,51 @@
 	bool no_assert_option = false;
 	bool source_option = false;
 	bool target_option = false;
+	bool fsource_option = false;
+	bool ftarget_option = false;
 
 	if (target_version == NULL)
 	  target_version = default_target_version ();
 
 	if (is_envjavac_gcj (javac))
 	  {
-	    /* 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)
+	    /* It's a version of gcj.  */
+	    if (is_envjavac_gcj43 (javac))
 	      {
-		if (is_envjavac_gcj_14_14_usable (javac, &usable))
+		/* It's a version of gcj >= 4.3.  Assume the classfile versions
+		   are correct.  */
+		if (is_envjavac_gcj43_usable (javac,
+					      source_version, target_version,
+					      &usable,
+					      &fsource_option, &ftarget_option))
 		  {
 		    err = true;
 		    goto done1;
 		  }
 	      }
-	    else if (strcmp (target_version, "1.4") == 0
-		     && strcmp (source_version, "1.3") == 0)
+	    else
 	      {
-		if (is_envjavac_gcj_14_13_usable (javac,
-						  &usable, &no_assert_option))
+		/* It's a version of gcj < 4.3.  Ignore the version of the
+		   class files that it creates.  */
+		if (strcmp (target_version, "1.4") == 0
+		    && strcmp (source_version, "1.4") == 0)
 		  {
-		    err = true;
-		    goto done1;
+		    if (is_envjavac_oldgcj_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_oldgcj_14_13_usable (javac,
+							 &usable,
+							 &no_assert_option))
+		      {
+			err = true;
+			goto done1;
+		      }
 		  }
 	      }
 	  }
@@ -1646,12 +2163,16 @@
 	    javac_with_options =
 	      (no_assert_option
 	       ? xasprintf ("%s -fno-assert", javac)
-	       : xasprintf ("%s%s%s%s%s",
+	       : xasprintf ("%s%s%s%s%s%s%s%s%s",
 			    javac,
 			    source_option ? " -source " : "",
 			    source_option ? source_version : "",
 			    target_option ? " -target " : "",
-			    target_option ? target_version : ""));
+			    target_option ? target_version : "",
+			    fsource_option ? " -fsource=" : "",
+			    fsource_option ? source_version : "",
+			    ftarget_option ? " -ftarget=" : "",
+			    ftarget_option ? target_version : ""));
 
 	    err = compile_using_envjavac (javac_with_options,
 					  java_sources, java_sources_count,
@@ -1678,31 +2199,49 @@
 
   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.  */
+      /* It's a version of gcj.  */
       bool usable = false;
       bool no_assert_option = false;
+      bool fsource_option = false;
+      bool ftarget_option = false;
 
       if (target_version == NULL)
 	target_version = default_target_version ();
 
-      if (strcmp (target_version, "1.4") == 0
-	  && strcmp (source_version, "1.4") == 0)
+      if (is_gcj_43 ())
 	{
-	  if (is_gcj_14_14_usable (&usable))
+	  /* It's a version of gcj >= 4.3.  Assume the classfile versions
+	     are correct.  */
+	  if (is_gcj43_usable (source_version, target_version,
+			       &usable, &fsource_option, &ftarget_option))
 	    {
 	      err = true;
 	      goto done1;
 	    }
 	}
-      else if (strcmp (target_version, "1.4") == 0
-	       && strcmp (source_version, "1.3") == 0)
+      else
 	{
-	  if (is_gcj_14_13_usable (&usable, &no_assert_option))
+	  /* It's a version of gcj < 4.3.  Ignore the version of the class
+	     files that it creates.
+	     Test whether it supports the desired target-version and
+	     source-version.  */
+	  if (strcmp (target_version, "1.4") == 0
+	      && strcmp (source_version, "1.4") == 0)
 	    {
-	      err = true;
-	      goto done1;
+	      if (is_oldgcj_14_14_usable (&usable))
+		{
+		  err = true;
+		  goto done1;
+		}
+	    }
+	  else if (strcmp (target_version, "1.4") == 0
+		   && strcmp (source_version, "1.3") == 0)
+	    {
+	      if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
+		{
+		  err = true;
+		  goto done1;
+		}
 	    }
 	}
 
@@ -1720,6 +2259,8 @@
 
 	  err = compile_using_gcj (java_sources, java_sources_count,
 				   no_assert_option,
+				   fsource_option, source_version,
+				   ftarget_option, target_version,
 				   directory, optimize, debug, verbose, false);
 
 	  /* Reset CLASSPATH.  */
--- a/m4/javacomp.m4
+++ b/m4/javacomp.m4
@@ -1,5 +1,5 @@
-# javacomp.m4 serial 8 (gettext-0.15)
-dnl Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+# javacomp.m4 serial 9 (gettext-0.16.2)
+dnl Copyright (C) 2001-2003, 2006-2007 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.
@@ -145,17 +145,18 @@
   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   gcj 3.0.4 to 4.2 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   gcj 4.3 and newer has an option -ftarget=1.X.
   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   For 3.3 <= gcj < 4.3, the source-version defaults to 1.4; option
   dnl   "-fno-assert" switches to source-version 1.3.
+  dnl   gcj >= 4.3 has an option -fsource=1.X.
   dnl
   dnl The support of Sun javac for target-version and source-version:
   dnl
@@ -206,60 +207,111 @@
   if test -n "$JAVAC"; then
     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 It's a version of gcj.
+changequote(,)dnl
+      if $JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null; then
+changequote([,])dnl
+        dnl It's a version of gcj >= 4.3. 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; then
-          CONF_JAVAC="$JAVAC"
-          HAVE_JAVAC_ENVVAR=1
-          HAVE_JAVACOMP=1
+           && test -f conftest.class \
+           && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+          dnl Try adding -fsource option if it is useful.
+          rm -f conftest.class
+          rm -f conftestfail.class
+          if { echo "$as_me:__oline__: $JAVAC -fsource=$source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               $JAVAC -fsource="$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 -fsource=$source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                    $JAVAC -fsource="$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                  }; then
+            CONF_JAVAC="$JAVAC -fsource=$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 -fsource and -ftarget options.
+          rm -f conftest.class
+          rm -f conftestfail.class
+          if { echo "$as_me:__oline__: $JAVAC -fsource=$source_version -ftarget=$target_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+               $JAVAC -fsource="$source_version" -ftarget="$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
+            CONF_JAVAC="$JAVAC -fsource=$source_version -ftarget=$target_version"
+            HAVE_JAVAC_ENVVAR=1
+            HAVE_JAVACOMP=1
+          fi
         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=
+        dnl It's a version of gcj < 4.3. 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
-            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"
+          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
@@ -366,39 +418,90 @@
              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
+changequote(,)dnl
+          if gcj --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null; then
+changequote([,])dnl
+            dnl It's a version of gcj >= 4.3. Assume the classfile versions are correct.
+            dnl Try gcj.
             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
+               && test -f conftest.class \
+               && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+              dnl Try adding -fsource option if it is useful.
+              rm -f conftest.class
+              rm -f conftestfail.class
+              if { echo "$as_me:__oline__: gcj -C -fsource=$source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                   gcj -C -fsource="$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__: gcj -C -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                      gcj -C -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                    } \
+                 && test -f conftestfail.class \
+                 && ! { echo "$as_me:__oline__: gcj -C -fsource=$source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
+                        gcj -C -fsource="$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
+                      }; then
+                CONF_JAVAC="gcj -C -fsource=$source_version"
+                HAVE_JAVAC_ENVVAR=1
+                HAVE_JAVACOMP=1
+              else
+                CONF_JAVAC="gcj -C"
+                HAVE_JAVAC_ENVVAR=1
+                HAVE_JAVACOMP=1
+              fi
+            else
+              dnl Try with -fsource and -ftarget options.
+              rm -f conftest.class
+              rm -f conftestfail.class
+              if { echo "$as_me:__oline__: gcj -C -fsource=$source_version -ftarget=$target_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
+                   gcj -C -fsource="$source_version" -ftarget="$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
+                CONF_JAVAC="gcj -C -fsource=$source_version -ftarget=$target_version"
+                HAVE_JAVAC_ENVVAR=1
+                HAVE_JAVACOMP=1
+              fi
             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).
+            dnl It's a version of gcj < 4.3. Ignore the version of conftest.class.
+            dnl Now test whether it supports the desired target-version and
+            dnl source-version.
+            if test "$target_version" = 1.4 && test "$source_version" = 1.4; then
               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
+              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 -fno-assert"
+                CONF_JAVAC="gcj -C"
                 HAVE_GCJ_C=1
                 HAVE_JAVACOMP=1
-              else
+              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 -d . conftest.java" >&AS_MESSAGE_LOG_FD
-                     gcj -C -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+                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"
+                  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