gjavah.c (method_signature): New global.

* gjavah.c (method_signature): New global.
	(HANDLE_METHOD): Set it.
	(decompile_return_statement): New function.
	(decompile_method): Use it.
	(print_method_info): Removed `synth' argument.

From-SVN: r46999
This commit is contained in:
Tom Tromey 2001-11-14 01:43:56 +00:00 committed by Tom Tromey
parent 77bd67cbdd
commit 150f086dd5
2 changed files with 156 additions and 16 deletions

View file

@ -1,3 +1,11 @@
2001-11-13 Tom Tromey <tromey@redhat.com>
* gjavah.c (method_signature): New global.
(HANDLE_METHOD): Set it.
(decompile_return_statement): New function.
(decompile_method): Use it.
(print_method_info): Removed `synth' argument.
2001-11-09 Neil Booth <neil@daikokuya.demon.co.uk>
* java-tree.h (java_set_yydebug): New.

View file

@ -120,7 +120,7 @@ static struct method_name *method_name_list;
static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int));
static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int));
static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2, int));
static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *,
int));
static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int,
@ -151,6 +151,7 @@ static void version PARAMS ((void)) ATTRIBUTE_NORETURN;
static int overloaded_jni_method_exists_p PARAMS ((const unsigned char *, int,
const char *, int));
static void jni_print_char PARAMS ((FILE *, int));
static void decompile_return_statement PARAMS ((FILE *, JCF *, int, int, int));
JCF_u2 current_field_name;
JCF_u2 current_field_value;
@ -187,9 +188,12 @@ static int method_declared = 0;
static int method_access = 0;
static int method_printed = 0;
static int method_synthetic = 0;
static int method_signature = 0;
#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
{ \
method_synthetic = 0; \
method_signature = SIGNATURE; \
if (ATTRIBUTE_COUNT) \
method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
(const char *)"Synthetic", 9); \
@ -207,12 +211,12 @@ static int method_synthetic = 0;
decompiled = 0; method_printed = 0; \
if (out) \
print_method_info (out, jcf, NAME, SIGNATURE, \
ACCESS_FLAGS, method_synthetic); \
ACCESS_FLAGS); \
} \
else if (!method_synthetic) \
{ \
print_method_info (NULL, jcf, NAME, SIGNATURE, \
ACCESS_FLAGS, method_synthetic); \
ACCESS_FLAGS); \
if (! stubs && ! flag_jni) \
add_class_decl (out, jcf, SIGNATURE); \
} \
@ -784,9 +788,9 @@ DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
static void
DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth),
DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
FILE *stream AND JCF* jcf
AND int name_index AND int sig_index AND JCF_u2 flags AND int synth)
AND int name_index AND int sig_index AND JCF_u2 flags)
{
const unsigned char *str;
int length, is_init = 0;
@ -799,10 +803,6 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth),
str = JPOOL_UTF_DATA (jcf, name_index);
length = JPOOL_UTF_LENGTH (jcf, name_index);
/* Ignore synthetic methods. */
if (synth)
return;
if (str[0] == '<')
{
/* Ignore the internally generated method <clinit>. However,
@ -892,6 +892,133 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags, synth),
free (override);
}
/* A helper for the decompiler which prints a `return' statement where
the type is a reference type. If METHODTYPE and OBJECTTYPE are not
identical, we emit a cast. We do this because the C++ compiler
doesn't know that a reference can be cast to the type of an
interface it implements. METHODTYPE is the index of the method's
signature. NAMEINDEX is the index of the field name; -1 for
`this'. OBJECTTYPE is the index of the object's type. */
static void
decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
FILE *out;
JCF *jcf;
int methodtype, nameindex, objecttype;
{
int cast = 0;
int obj_name_len, method_name_len;
const unsigned char *obj_data, *method_data;
obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
obj_data = JPOOL_UTF_DATA (jcf, objecttype);
method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
method_data = JPOOL_UTF_DATA (jcf, methodtype);
/* Skip forward to return type part of method. */
while (*method_data != ')')
{
++method_data;
--method_name_len;
}
/* Skip past `)'. */
++method_data;
--method_name_len;
/* If we see an `L', skip it and the trailing `;'. */
if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
{
++method_data;
method_name_len -= 2;
}
if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
{
++obj_data;
obj_name_len -= 2;
}
/* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
need a cast. Right now there is no way to determine if this is
the case. */
if (method_name_len != obj_name_len)
cast = 1;
else
{
int i;
for (i = 0; i < method_name_len; ++i)
{
if (method_data[i] != obj_data[i])
{
cast = 1;
break;
}
}
}
fputs (" { return ", out);
if (cast)
{
int array_depth = 0;
const unsigned char *limit;
fputs ("reinterpret_cast<", out);
while (*method_data == '[')
{
++method_data;
++array_depth;
--method_name_len;
fputs ("JArray<", out);
}
/* Leading space to avoid C++ digraphs. */
fputs (" ::", out);
/* If we see an `L', skip it and the trailing `;'. Only do this
if we've seen an array specification. If we don't have an
array then the `L' was stripped earlier. */
if (array_depth && method_data[0] == 'L'
&& method_data[method_name_len - 1] == ';')
{
++method_data;
method_name_len -= 2;
}
limit = method_data + method_name_len;
while (method_data < limit)
{
int ch = UTF8_GET (method_data, limit);
if (ch == '/')
fputs ("::", out);
else
jcf_print_char (out, ch);
}
fputs (" *", out);
/* Close each array. */
while (array_depth > 0)
{
fputs ("> *", out);
--array_depth;
}
/* Close the cast. */
fputs ("> (", out);
}
if (nameindex == -1)
fputs ("this", out);
else
print_field_name (out, jcf, nameindex, 0);
if (cast)
fputs (")", out);
fputs ("; }", out);
}
/* Try to decompile a method body. Right now we just try to handle a
simple case that we can do. Expand as desired. */
static void
@ -918,24 +1045,29 @@ decompile_method (out, jcf, code_len)
|| codes[4] == OPCODE_lreturn))
{
/* Found code like `return FIELD'. */
fputs (" { return ", out);
index = (codes[2] << 8) | codes[3];
/* FIXME: ensure that tag is CONSTANT_Fieldref. */
/* FIXME: ensure that the field's class is this class. */
name_and_type = JPOOL_USHORT2 (jcf, index);
/* FIXME: ensure that tag is CONSTANT_NameAndType. */
name = JPOOL_USHORT1 (jcf, name_and_type);
/* FIXME: flags. */
print_field_name (out, jcf, name, 0);
fputs ("; }", out);
if (codes[4] == OPCODE_areturn)
decompile_return_statement (out, jcf, method_signature,
name, JPOOL_USHORT2 (jcf, name_and_type));
else
{
fputs (" { return ", out);
/* FIXME: flags. */
print_field_name (out, jcf, name, 0);
fputs ("; }", out);
}
decompiled = 1;
}
else if (code_len == 2
&& codes[0] == OPCODE_aload_0
&& codes[1] == OPCODE_areturn)
{
/* Found `return this'. */
fputs (" { return this; }", out);
decompile_return_statement (out, jcf, method_signature, -1,
JPOOL_USHORT1 (jcf, jcf->this_class));
decompiled = 1;
}
else if (code_len == 1 && codes[0] == OPCODE_return)