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
This commit is contained in:
Tom Tromey 2002-05-08 01:41:41 +00:00 committed by Tom Tromey
parent db84f1bded
commit 6b9b5de22a
2 changed files with 119 additions and 11 deletions

View File

@ -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.

View File

@ -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";