OSDN Git Service

Fix for PR java/1200:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 8 May 2002 01:41:41 +0000 (01:41 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 8 May 2002 01:41:41 +0000 (01:41 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53275 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/java/ChangeLog
gcc/java/gjavah.c

index 07b89d6..a8f7f20 100644 (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.
index 4daaa2b..d152b37 100644 (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";