aboutsummaryrefslogtreecommitdiff
path: root/gcc/java
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2002-05-08 01:41:41 +0000
committerTom Tromey <tromey@gcc.gnu.org>2002-05-08 01:41:41 +0000
commit6b9b5de22a60008f1139279ad1bf7141aeab1341 (patch)
tree4acb29adf6d91fc12701fb2159f77e7e32d489c3 /gcc/java
parentdb84f1bded499cdcc8a8eb7e81383ac8d86f2a44 (diff)
downloadgcc-6b9b5de22a60008f1139279ad1bf7141aeab1341.zip
gcc-6b9b5de22a60008f1139279ad1bf7141aeab1341.tar.gz
gcc-6b9b5de22a60008f1139279ad1bf7141aeab1341.tar.bz2
re PR java/1200 (gcjh -jni doesn't respect class hierarchy)
Fix for PR java/1200: * gjavah.c (throwable_p): New function. (decode_signature_piece): Use it. A `WeakReference' isn't the same as a `jweak'. Include hashtab.h. (gcjh_streq): New function. From-SVN: r53275
Diffstat (limited to 'gcc/java')
-rw-r--r--gcc/java/ChangeLog9
-rw-r--r--gcc/java/gjavah.c121
2 files changed, 119 insertions, 11 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 07b89d6..a8f7f20 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,12 @@
+2002-05-07 Tom Tromey <tromey@redhat.com>
+
+ Fix for PR java/1200:
+ * gjavah.c (throwable_p): New function.
+ (decode_signature_piece): Use it. A `WeakReference' isn't the
+ same as a `jweak'.
+ Include hashtab.h.
+ (gcjh_streq): New function.
+
2002-05-07 Andreas Jaeger <aj@suse.de>
* parse.y (finish_for_loop): Fix if statement.
diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c
index 4daaa2b..d152b37 100644
--- a/gcc/java/gjavah.c
+++ b/gcc/java/gjavah.c
@@ -33,6 +33,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "javaop.h"
#include "java-tree.h"
#include "java-opcodes.h"
+#include "hashtab.h"
#include <getopt.h>
@@ -142,6 +143,8 @@ static char *get_field_name PARAMS ((JCF *, int, JCF_u2));
static void print_field_name PARAMS ((FILE *, JCF *, int, JCF_u2));
static const unsigned char *super_class_name PARAMS ((JCF *, int *));
static void print_include PARAMS ((FILE *, const unsigned char *, int));
+static int gcjh_streq PARAMS ((const void *p1, const void *p2));
+static int throwable_p PARAMS ((const unsigned char *signature));
static const unsigned char *decode_signature_piece
PARAMS ((FILE *, const unsigned char *, const unsigned char *, int *));
static void print_class_decls PARAMS ((FILE *, JCF *, int));
@@ -1091,6 +1094,111 @@ decompile_method (out, jcf, code_len)
}
}
+/* Like strcmp, but invert the return result for the hash table. This
+ should probably be in hashtab.c to complement the existing string
+ hash function. */
+static int
+gcjh_streq (p1, p2)
+ const void *p1, *p2;
+{
+ return ! strcmp ((char *) p1, (char *) p2);
+}
+
+/* Return 1 if the initial (L<classname>;) part of SIGNATURE names a
+ subclass of throwable, or 0 if not. */
+static int
+throwable_p (signature)
+ const unsigned char *signature;
+{
+ int length;
+ unsigned char *current;
+ int i;
+ int result = 0;
+
+ /* We keep two hash tables of class names. In one we list all the
+ classes which are subclasses of Throwable. In the other we will
+ all other classes. We keep two tables to make the code a bit
+ simpler; we don't have to have a structure mapping class name to
+ a `throwable?' bit. */
+ static htab_t throw_hash;
+ static htab_t non_throw_hash;
+ static int init_done = 0;
+
+ if (! init_done)
+ {
+ PTR *slot;
+ const unsigned char *str;
+
+ /* Self-initializing. The cost of this really doesn't matter.
+ We also don't care about freeing these, either. */
+ throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
+ (htab_del) free);
+ non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
+ (htab_del) free);
+
+ /* Make sure the root classes show up in the tables. */
+ str = strdup ("java.lang.Throwable");
+ slot = htab_find_slot (throw_hash, str, INSERT);
+ *slot = (PTR) str;
+
+ str = strdup ("java.lang.Object");
+ slot = htab_find_slot (non_throw_hash, str, INSERT);
+ *slot = (PTR) str;
+
+ init_done = 1;
+ }
+
+ for (length = 0; signature[length] != ';'; ++length)
+ ;
+ current = (unsigned char *) ALLOC (length);
+ for (i = 1; signature[i] != ';'; ++i)
+ current[i - 1] = signature[i] == '/' ? '.' : signature[i];
+ current[i - 1] = '\0';
+
+ /* We don't compute the hash slot here because the table might be
+ modified by the recursion. In that case the slot could be
+ invalidated. */
+ if (htab_find (throw_hash, current))
+ result = 1;
+ else if (htab_find (non_throw_hash, current))
+ result = 0;
+ else
+ {
+ JCF jcf;
+ PTR *slot;
+ const char *classfile_name = find_class (current, strlen (current),
+ &jcf, 0);
+
+ if (! classfile_name)
+ {
+ fprintf (stderr, "couldn't find class %s\n", current);
+ found_error = 1;
+ return 0;
+ }
+ if (jcf_parse_preamble (&jcf) != 0
+ || jcf_parse_constant_pool (&jcf) != 0
+ || verify_constant_pool (&jcf) > 0)
+ {
+ fprintf (stderr, "parse error while reading %s\n", classfile_name);
+ found_error = 1;
+ return 0;
+ }
+ jcf_parse_class (&jcf);
+
+ result = throwable_p (super_class_name (&jcf, NULL));
+ slot = htab_find_slot (result ? throw_hash : non_throw_hash,
+ current, INSERT);
+ *slot = current;
+ current = NULL;
+
+ JCF_FINISH (&jcf);
+ }
+
+ if (current)
+ free (current);
+ return result;
+}
+
/* Print one piece of a signature. Returns pointer to next parseable
character on success, NULL on error. */
static const unsigned char *
@@ -1204,24 +1312,15 @@ decode_signature_piece (stream, signature, limit, need_space)
case 'L':
if (flag_jni)
{
- /* We know about certain types and special-case their
- names.
- FIXME: something like java.lang.Exception should be
- printed as `jthrowable', because it is a subclass. This
- means that gcjh must read the entire hierarchy and
- comprehend it. */
+ /* We know about certain types and special-case their names. */
if (! strncmp (signature, "Ljava/lang/String;",
sizeof ("Ljava/lang/String;") -1))
ctype = "jstring";
else if (! strncmp (signature, "Ljava/lang/Class;",
sizeof ("Ljava/lang/Class;") - 1))
ctype = "jclass";
- else if (! strncmp (signature, "Ljava/lang/Throwable;",
- sizeof ("Ljava/lang/Throwable;") - 1))
+ else if (throwable_p (signature))
ctype = "jthrowable";
- else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;",
- sizeof ("Ljava/lang/ref/WeakReference;") - 1))
- ctype = "jweak";
else
ctype = "jobject";