OSDN Git Service

* jcf-dump.c (main): Updated call to find_class.
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-dump.c
index 6d976e5..0dfa4c2 100644 (file)
@@ -1,8 +1,8 @@
 /* Program to dump out a Java(TM) .class file.
    Functionally similar to Sun's javap.
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -18,8 +18,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -54,6 +54,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "coretypes.h"
 #include "tm.h"
 #include "ggc.h"
+#include "intl.h"
 
 #include "jcf.h"
 #include "tree.h"
@@ -62,8 +63,9 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "version.h"
 
 #include <getopt.h>
+#include <math.h>
 
-/* Outout file. */
+/* Output file. */
 FILE *out;
 /* Name of output file, if NULL if stdout. */
 char *output_file = NULL;
@@ -72,7 +74,7 @@ int verbose = 0;
 
 int flag_disassemble_methods = 0;
 int flag_print_class_info = 1;
-int flag_print_constant_pool = 1;
+int flag_print_constant_pool = 0;
 int flag_print_fields = 1;
 int flag_print_methods = 1;
 int flag_print_attributes = 1;
@@ -89,11 +91,12 @@ int this_class_index = 0;
 
 int class_access_flags = 0;
 
-/* Print in format similar to javap.  VERY IMCOMPLETE. */
+/* Print in format similar to javap.  VERY INCOMPLETE. */
 int flag_javap_compatible = 0;
 
 static void print_access_flags (FILE *, uint16, char);
 static void print_constant_terse (FILE*, JCF*, int, int);
+static void print_constant_terse_with_index (FILE *, JCF *, int, int);
 static void print_constant (FILE *, JCF *, int, int);
 static void print_constant_ref (FILE *, JCF *, int);
 static void disassemble_method (JCF*, const unsigned char *, int);
@@ -107,6 +110,11 @@ static void process_class (struct JCF *);
 static void print_constant_pool (struct JCF *);
 static void print_exception_table (struct JCF *, const unsigned char *entries,
                                   int);
+static void indent (FILE *, int);
+static void print_element_value (FILE *, JCF *, int);
+static void print_annotation (FILE *, JCF *, int);
+static void print_annotations (FILE *, JCF *, int);
+static void print_parameter_annotations (FILE *, JCF *, int);
 
 #define PRINT_SIGNATURE_RESULT_ONLY 1
 #define PRINT_SIGNATURE_ARGS_ONLY 2
@@ -150,9 +158,7 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
       print_access_flags (out, ACCESS_FLAGS, 'c'); \
       fputc ('\n', out); \
       fprintf (out, "This class: "); \
-      if (flag_print_constant_pool) \
-        fprintf (out, "%d=", THIS); \
-      print_constant_terse (out, jcf, THIS, CONSTANT_Class); \
+      print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
       if (flag_print_constant_pool || SUPER != 0) \
         fprintf (out, ", super: "); \
       if (flag_print_constant_pool) \
@@ -171,8 +177,8 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
 
 #define HANDLE_CLASS_INTERFACE(INDEX) \
   if (flag_print_class_info) \
-    { fprintf (out, "- Implements: %d=", INDEX); \
-      print_constant_terse (out, jcf, INDEX, CONSTANT_Class); \
+    { fprintf (out, "- Implements: "); \
+      print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
       fputc ('\n', out); }
 
 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
@@ -184,7 +190,7 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
     { fprintf (out, "Field name:"); \
       print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
       print_access_flags (out, ACCESS_FLAGS, 'f'); \
-      fprintf (out, " Signature: "); \
+      fprintf (out, " Descriptor: "); \
       if (flag_print_constant_pool) \
         fprintf (out, "%d=", SIGNATURE); \
       print_signature (out, jcf, SIGNATURE, 0); \
@@ -227,7 +233,7 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
          fprintf (out, "\nMethod name:"); \
          print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
          print_access_flags (out, ACCESS_FLAGS, 'm'); \
-         fprintf (out, " Signature: "); \
+         fprintf (out, " Descriptor: "); \
          if (flag_print_constant_pool) \
            fprintf (out, "%d=", SIGNATURE); \
          print_signature (out, jcf, SIGNATURE, 0); \
@@ -285,12 +291,36 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
     int name_index = JCF_readu2 (jcf); \
     int signature_index = JCF_readu2 (jcf); \
     int slot = JCF_readu2 (jcf); \
-    fprintf (out, "  slot#%d: name: %d=", slot, name_index); \
+    fprintf (out, "  slot#%d: name: ", slot); \
+    if (flag_print_constant_pool) \
+      fprintf (out, "%d=", name_index); \
     print_name (out, jcf, name_index); \
-    fprintf (out, ", type: %d=", signature_index); \
+    fprintf (out, ", type: "); \
+    if (flag_print_constant_pool) \
+      fprintf (out, "%d=", signature_index); \
     print_signature (out, jcf, signature_index, 0); \
     fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
 
+#define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT)                 \
+{ int n = (COUNT); int i;                                              \
+  COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length);      \
+  fprintf (out, ", count: %d\n", n);                                   \
+  for (i = 0; i < n; i++) {                                            \
+    int start_pc = JCF_readu2 (jcf);                                   \
+    int length = JCF_readu2 (jcf);                                     \
+    int name_index = JCF_readu2 (jcf);                                 \
+    int signature_index = JCF_readu2 (jcf);                            \
+    int slot = JCF_readu2 (jcf);                                       \
+    fprintf (out, "  slot#%d: name: ", slot);                          \
+    if (flag_print_constant_pool)                                      \
+      fprintf (out, "%d=", name_index);                                        \
+    print_name (out, jcf, name_index);                                 \
+    fprintf (out, ", type: ");                                         \
+    if (flag_print_constant_pool)                                      \
+      fprintf (out, "%d=", signature_index);                           \
+    print_signature (out, jcf, signature_index, 0);                    \
+    fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
+
 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
 { int n = (COUNT); int i; \
   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
@@ -315,26 +345,98 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
                                                                            \
       if (flag_print_class_info)                                           \
        {                                                                   \
-         fprintf (out, "\n  class: ");                                     \
-         if (flag_print_constant_pool)                                     \
-           fprintf (out, "%d=", inner_class_info_index);                   \
-         print_constant_terse (out, jcf,                                   \
-                               inner_class_info_index, CONSTANT_Class);    \
-         fprintf (out, " (%d=", inner_name_index);                         \
-         print_constant_terse (out, jcf, inner_name_index, CONSTANT_Utf8); \
-         fprintf (out, "), access flags: 0x%x", inner_class_access_flags); \
+         fprintf (out, "\n  inner: ");                                     \
+         if (inner_class_info_index == 0)                                  \
+           fprintf (out, " (no inner info index)");                        \
+         else                                                              \
+           print_constant_terse_with_index (out, jcf,                      \
+                                            inner_class_info_index,        \
+                                            CONSTANT_Class);               \
+         if (inner_name_index == 0)                                        \
+           fprintf (out, " (anonymous)");                                  \
+         else if (verbose || flag_print_constant_pool)                     \
+           {                                                               \
+             fprintf (out, " (");                                          \
+             print_constant_terse_with_index (out, jcf, inner_name_index,  \
+                                              CONSTANT_Utf8);              \
+             fputc (')', out);                                             \
+           }                                                               \
+         fprintf (out, ", access flags: 0x%x", inner_class_access_flags);  \
          print_access_flags (out, inner_class_access_flags, 'c');          \
          fprintf (out, ", outer class: ");                                 \
-         if (flag_print_constant_pool)                                     \
-           fprintf (out, "%d=", outer_class_info_index);                   \
-         print_constant_terse (out, jcf,                                   \
-                               outer_class_info_index, CONSTANT_Class);    \
+         if (outer_class_info_index == 0)                                  \
+           fprintf (out, "(not a member)");                                \
+         else                                                              \
+           print_constant_terse_with_index (out, jcf,                      \
+                                            outer_class_info_index,        \
+                                            CONSTANT_Class);               \
        }                                                                   \
     }                                                                      \
-      if (flag_print_class_info)                                           \
-       fputc ('\n', out);                                                  \
+  if (flag_print_class_info)                                               \
+    fputc ('\n', out);                                                     \
+}
+
+#define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
+{ int i, n = (LENGTH), c = 0;                                    \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
+  fputc ('\n', out); \
+  for (i = 0;  i < n;  i++) { c = JCF_readu(jcf); fputc(c, out); } \
+  if (c != '\r' && c != '\n') fputc('\n', out); }
+
+#define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE()                             \
+  { uint16 class_index, method_index;                                  \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  class_index = JCF_readu2 (jcf);                                      \
+  method_index = JCF_readu2 (jcf);                                     \
+  fprintf (out, "\n  Class: ");                                                \
+  print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
+  fprintf (out, "\n  Method: ");                                       \
+  print_constant_terse_with_index (out, jcf, method_index,             \
+                                  CONSTANT_NameAndType);               \
+  fputc ('\n', out);                                                   \
+}
+
+#define HANDLE_SIGNATURE_ATTRIBUTE()                                   \
+{                                                                      \
+  uint16 signature;                                                    \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  signature = JCF_readu2 (jcf);                                                \
+  fprintf (out, "\n  Value: ");                                                \
+  print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8);        \
+  fputc ('\n', out);                                                   \
+}
+
+#define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE()                   \
+{                                                                      \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  print_annotations (out, jcf, 1);                                     \
+}
+
+#define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE()                 \
+{                                                                      \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  print_annotations (out, jcf, 1);                                     \
+}
+
+#define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()          \
+{                                                                      \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  print_parameter_annotations (out, jcf, 1);                           \
 }
 
+#define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()                \
+{                                                                      \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  print_parameter_annotations (out, jcf, 1);                           \
+}
+
+#define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE()                           \
+{                                                                      \
+  COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);      \
+  print_element_value (out, jcf, 1);                                   \
+}
+
+
 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
   fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
@@ -345,15 +447,171 @@ utf8_equal_string (JCF *jcf, int index, const char * value)
 
 #include "javaop.h"
 
+\f
+
+static void
+indent (FILE *stream, int level)
+{
+  int i;
+  for (i = 0; i < level; ++i)
+    fprintf (stream, "  ");
+}
+
+static void
+print_element_value (FILE *stream, JCF *jcf, int level)
+{
+  uint8 tag = JCF_readu (jcf);
+  indent (stream, level);
+  switch (tag)
+    {
+    case 'B':
+    case 'C':
+    case 'S':
+    case 'Z':
+    case 'I':
+      {
+       uint16 cindex = JCF_readu2 (jcf);
+       print_constant_terse_with_index (stream, jcf, cindex,
+                                        CONSTANT_Integer);
+      }
+      break;
+    case 'D':
+      {
+       uint16 cindex = JCF_readu2 (jcf);
+       print_constant_terse_with_index (stream, jcf, cindex,
+                                        CONSTANT_Double);
+      }
+      break;
+    case 'F':
+      {
+       uint16 cindex = JCF_readu2 (jcf);
+       print_constant_terse_with_index (stream, jcf, cindex,
+                                        CONSTANT_Float);
+      }
+      break;
+    case 'J':
+      {
+       uint16 cindex = JCF_readu2 (jcf);
+       print_constant_terse_with_index (stream, jcf, cindex,
+                                        CONSTANT_Long);
+      }
+      break;
+    case 's':
+      {
+       uint16 cindex = JCF_readu2 (jcf);
+       /* Despite what the JVM spec says, compilers generate a Utf8
+          constant here, not a String.  */
+       print_constant_terse_with_index (stream, jcf, cindex,
+                                        CONSTANT_Utf8);
+      }
+      break;
+
+    case 'e':
+      {
+       uint16 type_name_index = JCF_readu2 (jcf);
+       uint16 const_name_index = JCF_readu2 (jcf);
+       fprintf (stream, "enum class: ");
+       print_constant_terse_with_index (stream, jcf, type_name_index,
+                                        CONSTANT_Utf8);
+       fprintf (stream, "\n");
+       indent (stream, level);
+       fprintf (stream, "Field: ");
+       print_constant_terse_with_index (stream, jcf, const_name_index,
+                                        CONSTANT_Utf8);
+      }
+      break;
+    case 'c':
+      {
+       uint16 class_info_index = JCF_readu2 (jcf);
+       print_constant_terse_with_index (stream, jcf, class_info_index,
+                                        CONSTANT_Utf8);
+      }
+      break;
+    case '@':
+      {
+       fprintf (stream, "Annotation:\n");
+       print_annotation (stream, jcf, level + 1);
+      }
+      break;
+    case '[':
+      {
+       uint16 n_array_elts = JCF_readu2 (jcf);
+       fprintf (stream, "array[%d]: [\n", (int) n_array_elts);
+       while (n_array_elts--)
+         print_element_value (stream, jcf, level + 1);
+       indent (stream, level);
+       fprintf (stream, "]");
+      }
+      break;
+    default:
+      fprintf (stream, "Unexpected tag value: %d", (int) tag);
+      break;
+    }
+  fputc ('\n', stream);
+}
+
+static void
+print_annotation (FILE *stream, JCF *jcf, int level)
+{
+  uint16 type_index = JCF_readu2 (jcf);
+  uint16 npairs = JCF_readu2 (jcf);
+  fprintf (stream, "\n");
+  indent (stream, level);
+  fprintf (stream, "Annotation name: ");
+  print_constant_terse_with_index (stream, jcf, type_index,
+                                  CONSTANT_Utf8);
+  if (npairs)
+    {
+      fprintf (stream, "\n");
+      while (npairs--)
+       {
+         uint16 name_index = JCF_readu2 (jcf);
+         indent (stream, level + 1);
+         fprintf (stream, "Name: ");
+         print_constant_terse_with_index (stream, jcf, name_index,
+                                          CONSTANT_Utf8);
+         fprintf (stream, "\n");
+         print_element_value (stream, jcf, level + 2);
+       }
+    }
+}
+
+static void
+print_annotations (FILE *stream, JCF *jcf, int level)
+{
+  uint16 num = JCF_readu2 (jcf);
+  while (num--)
+    print_annotation (stream, jcf, level);
+}
+
+static void
+print_parameter_annotations (FILE *stream, JCF *jcf, int level)
+{
+  uint8 nparams = JCF_readu (jcf);
+  uint8 i;
+  for (i = 0; i < nparams; ++i)
+    {
+      indent (stream, level);
+      fprintf (stream, "Parameter annotations (%d):\n", (int) i);
+      print_annotations (stream, jcf, level + 1);
+    }
+}
+
+\f
+
 static void
 print_constant_ref (FILE *stream, JCF *jcf, int index)
 {
-  fprintf (stream, "#%d=<", index);
   if (index <= 0 || index >= JPOOL_SIZE(jcf))
-    fprintf (stream, "out of range");
+    fprintf (stream, "<out of range>");
   else
-    print_constant (stream, jcf, index, 1);
-  fprintf (stream, ">");
+    {
+      if (flag_print_constant_pool)
+       fprintf (stream, "#%d=", index);
+      fputc ('<', stream);
+      print_constant (stream, jcf, index, 1);
+      fputc ('>', stream);
+    }
 }
 
 /* Print the access flags given by FLAGS.
@@ -369,8 +627,10 @@ print_access_flags (FILE *stream, uint16 flags, char context)
   if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
   if (flags & ACC_STATIC) fprintf (stream, " static");
   if (flags & ACC_FINAL) fprintf (stream, " final");
-  if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
-  if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
+  if (flags & ACC_TRANSIENT)
+    fprintf (stream, context == 'm' ? " varargs" : " transient");
+  if (flags & ACC_VOLATILE)
+    fprintf (stream, context == 'm' ? " bridge" : " volatile");
   if (flags & ACC_NATIVE) fprintf (stream, " native");
   if (flags & ACC_SYNCHRONIZED)
     {
@@ -379,8 +639,11 @@ print_access_flags (FILE *stream, uint16 flags, char context)
       else
        fprintf (stream, " synchronized");
     }
-  if (flags & ACC_INTERFACE) fprintf (stream, " interface");
+  if (flags & ACC_INTERFACE)
+    fprintf (stream, (flags & ACC_ANNOTATION) ? " @interface" : " interface");
+  if (flags & ACC_ENUM) fprintf (stream, " enum");
   if (flags & ACC_STRICT) fprintf (stream, " strictfp");
+  if (flags & ACC_SYNTHETIC) fprintf (stream, " synthetic");
 }
 
 
@@ -412,6 +675,14 @@ print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
     print_constant (out, jcf, index, 0);
 }
 
+static void
+print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
+{
+  if (flag_print_constant_pool)
+    fprintf (out, "%d=", index);
+  print_constant_terse (out, jcf, index, expected);
+}
+
 /* Print the constant at INDEX in JCF's constant pool.
    If verbosity==0, print very tersely (no extraneous text).
    If verbosity==1, prefix the type of the constant.
@@ -504,24 +775,86 @@ print_constant (FILE *out, JCF *jcf, int index, int verbosity)
       break;
     case CONSTANT_Float:
       {
-       union
-       {
-         jfloat f;
-         int32 i;
-       } pun;
-       
-       pun.f = JPOOL_FLOAT (jcf, index);
-       fprintf (out, "%s%.10g",
-                verbosity > 0 ? "Float " : "", (double) pun.f);
+       jfloat fnum = JPOOL_FLOAT (jcf, index);
+
+       if (verbosity > 0)
+         fputs ("Float ", out);
+
+       if (fnum.negative)
+         putc ('-', out);
+
+       if (JFLOAT_FINITE (fnum))
+         {
+           int dummy;
+           int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
+           double f;
+           uint32 mantissa = fnum.mantissa;
+           if (fnum.exponent == 0)
+             /* Denormal.  */
+             exponent++;
+           else
+             /* Normal; add the implicit bit.  */
+             mantissa |= ((uint32)1 << 23);
+           
+           f = frexp (mantissa, &dummy);
+           f = ldexp (f, exponent + 1);
+           fprintf (out, "%.10g", f);
+         }
+       else
+         {
+           if (fnum.mantissa == 0)
+             fputs ("Inf", out);
+           else if (fnum.mantissa & JFLOAT_QNAN_MASK)
+             fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
+           else
+             fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
+         }
+
        if (verbosity > 1)
-         fprintf (out, ", bits = 0x%08lx", (long) pun.i);
+         fprintf (out, ", bits = 0x%08lx", (long) JPOOL_UINT (jcf, index));
        
        break;
       }
     case CONSTANT_Double:
       {
        jdouble dnum = JPOOL_DOUBLE (jcf, index);
-       fprintf (out, "%s%.20g", verbosity > 0 ? "Double " : "", dnum);
+
+       if (verbosity > 0)
+         fputs ("Double ", out);
+
+       if (dnum.negative)
+         putc ('-', out);
+
+       if (JDOUBLE_FINITE (dnum))
+         {
+           int dummy;
+           int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
+           double d;
+           uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
+                              + dnum.mantissa1);
+           if (dnum.exponent == 0)
+             /* Denormal.  */
+             exponent++;
+           else
+             /* Normal; add the implicit bit.  */
+             mantissa |= ((uint64)1 << 52);
+
+           d = frexp (mantissa, &dummy);
+           d = ldexp (d, exponent + 1);
+           fprintf (out, "%.20g", d);
+         }
+       else
+         {
+           uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
+           mantissa = (mantissa << 32) + dnum.mantissa1;
+
+           if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
+             fputs ("Inf", out);
+           else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
+             fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
+           else
+             fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
+         }
        if (verbosity > 1)
          {
            int32 hi, lo;
@@ -552,7 +885,7 @@ print_constant (FILE *out, JCF *jcf, int index, int verbosity)
       break;
     case CONSTANT_Utf8:
       {
-       register const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
+       const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
        int length = JPOOL_UTF_LENGTH (jcf, index);
        if (verbosity > 0)
          { /* Print as 8-bit bytes. */
@@ -711,15 +1044,13 @@ print_exception_table (JCF *jcf, const unsigned char *entries, int count)
          int end_pc = GET_u2 (ptr+2);
          int handler_pc = GET_u2 (ptr+4);
          int catch_type = GET_u2 (ptr+6);
-         fprintf (out, "  start: %d, end: %d, handler: %d, type: %d",
-                  start_pc, end_pc, handler_pc, catch_type);
+         fprintf (out, "  start: %d, end: %d, handler: %d, type: ",
+                  start_pc, end_pc, handler_pc);
          if (catch_type == 0)
-           fputs (" /* finally */", out);
+           fputs ("0 /* finally */", out);
          else
-           {
-             fputc('=', out);
-             print_constant_terse (out, jcf, catch_type, CONSTANT_Class);
-           }
+           print_constant_terse_with_index (out, jcf,
+                                            catch_type, CONSTANT_Class);
          fputc ('\n', out);
        }
     }
@@ -732,19 +1063,19 @@ process_class (JCF *jcf)
 {
   int code;
   if (jcf_parse_preamble (jcf) != 0)
-    fprintf (stderr, "Not a valid Java .class file.\n");    
+    fprintf (stderr, _("Not a valid Java .class file.\n"));    
 
   /* Parse and possibly print constant pool */
   code = jcf_parse_constant_pool (jcf);
   if (code != 0)
     {
-      fprintf (stderr, "error while parsing constant pool\n");
+      fprintf (stderr, _("error while parsing constant pool\n"));
       exit (FATAL_EXIT_CODE);
     }
   code = verify_constant_pool (jcf);
   if (code > 0)
     {
-      fprintf (stderr, "error in constant pool entry #%d\n", code);
+      fprintf (stderr, _("error in constant pool entry #%d\n"), code);
       exit (FATAL_EXIT_CODE);
     }
   if (flag_print_constant_pool)
@@ -754,19 +1085,19 @@ process_class (JCF *jcf)
   code = jcf_parse_fields (jcf);
   if (code != 0)
     {
-      fprintf (stderr, "error while parsing fields\n");
+      fprintf (stderr, _("error while parsing fields\n"));
       exit (FATAL_EXIT_CODE);
     }
   code = jcf_parse_methods (jcf);
   if (code != 0)
     {
-      fprintf (stderr, "error while parsing methods\n");
+      fprintf (stderr, _("error while parsing methods\n"));
       exit (FATAL_EXIT_CODE);
     }
   code = jcf_parse_final_attributes (jcf);
   if (code != 0)
     {
-      fprintf (stderr, "error while parsing final attributes\n");
+      fprintf (stderr, _("error while parsing final attributes\n"));
       exit (FATAL_EXIT_CODE);
     }
   jcf->filename = NULL;
@@ -795,37 +1126,38 @@ static const struct option options[] =
   { "verbose",       no_argument,       NULL, 'v' },
   { "version",       no_argument,       NULL, OPT_VERSION },
   { "javap",         no_argument,       NULL, OPT_JAVAP },
-  { "print-main",    no_argument,      &flag_print_main, 1 },
+  { "print-main",    no_argument,       &flag_print_main, 1 },
+  { "print-constants", no_argument,     &flag_print_constant_pool, 1 },
   { NULL,            no_argument,       NULL, 0 }
 };
 
 static void
 usage (void)
 {
-  fprintf (stderr, "Try `jcf-dump --help' for more information.\n");
+  fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
   exit (1);
 }
 
 static void
 help (void)
 {
-  printf ("Usage: jcf-dump [OPTION]... CLASS...\n\n");
-  printf ("Display contents of a class file in readable form.\n\n");
-  printf ("  -c                      Disassemble method bodies\n");
-  printf ("  --javap                 Generate output in `javap' format\n");
+  printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
+  printf (_("Display contents of a class file in readable form.\n\n"));
+  printf (_("  -c                      Disassemble method bodies\n"));
+  printf (_("  --javap                 Generate output in 'javap' format\n"));
   printf ("\n");
-  printf ("  --classpath PATH        Set path to find .class files\n");
-  printf ("  -IDIR                   Append directory to class path\n");
-  printf ("  --bootclasspath PATH    Override built-in class path\n");
-  printf ("  --extdirs PATH          Set extensions directory path\n");
-  printf ("  -o FILE                 Set output file name\n");
+  printf (_("  --classpath PATH        Set path to find .class files\n"));
+  printf (_("  -IDIR                   Append directory to class path\n"));
+  printf (_("  --bootclasspath PATH    Override built-in class path\n"));
+  printf (_("  --extdirs PATH          Set extensions directory path\n"));
+  printf (_("  -o FILE                 Set output file name\n"));
   printf ("\n");
-  printf ("  --help                  Print this help, then exit\n");
-  printf ("  --version               Print version number, then exit\n");
-  printf ("  -v, --verbose           Print extra information while running\n");
+  printf (_("  --help                  Print this help, then exit\n"));
+  printf (_("  --version               Print version number, then exit\n"));
+  printf (_("  -v, --verbose           Print extra information while running\n"));
   printf ("\n");
-  printf ("For bug reporting instructions, please see:\n");
-  printf ("%s.\n", bug_report_url);
+  printf (_("For bug reporting instructions, please see:\n"
+           "%s.\n"), bug_report_url);
   exit (0);
 }
 
@@ -833,9 +1165,9 @@ static void
 version (void)
 {
   printf ("jcf-dump (GCC) %s\n\n", version_string);
-  printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
-  printf ("This is free software; see the source for copying conditions.  There is NO\n");
-  printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
+  printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
+  printf (_("This is free software; see the source for copying conditions.  There is NO\n"
+           "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
   exit (0);
 }
 
@@ -845,9 +1177,14 @@ main (int argc, char** argv)
   JCF jcf[1];
   int argi, opt;
 
+  /* Unlock the stdio streams.  */
+  unlock_std_streams ();
+
+  gcc_init_libintl ();
+
   if (argc <= 1)
     {
-      fprintf (stderr, "jcf-dump: no classes specified\n");
+      fprintf (stderr, _("jcf-dump: no classes specified\n"));
       usage ();
     }
 
@@ -910,9 +1247,12 @@ main (int argc, char** argv)
        }
     }
 
+  if (verbose && ! flag_javap_compatible)
+    flag_print_constant_pool = 1;
+
   if (optind == argc)
     {
-      fprintf (stderr, "jcf-dump: no classes specified\n");
+      fprintf (stderr, _("jcf-dump: no classes specified\n"));
       usage ();
     }
 
@@ -932,7 +1272,7 @@ main (int argc, char** argv)
       out = fopen (output_file, "w");
       if (! out)
        {
-         fprintf (stderr, "Cannot open '%s' for output.\n", output_file);
+         fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
          return FATAL_EXIT_CODE;
        }
     }
@@ -950,7 +1290,7 @@ main (int argc, char** argv)
       for (argi = optind; argi < argc; argi++)
        {
          char *arg = argv[argi];
-         const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
+         const char *class_filename = find_class (arg, strlen (arg), jcf);
          if (class_filename == NULL)
            class_filename = find_classfile (arg, jcf, NULL);
          if (class_filename == NULL)
@@ -978,7 +1318,7 @@ main (int argc, char** argv)
                    break;  /* got to central directory */
                  if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
                    {
-                     fprintf (stderr, "bad format of .zip/.jar archive\n");
+                     fprintf (stderr, _("bad format of .zip/.jar archive\n"));
                      return FATAL_EXIT_CODE;
                    }
                  JCF_FILL (jcf, 26);
@@ -995,7 +1335,7 @@ main (int argc, char** argv)
                  if (jcf->read_end - jcf->read_ptr < total_length)
                    jcf_trim_old_input (jcf);
                  JCF_FILL (jcf, total_length);
-                 filename = jcf->read_ptr;
+                 filename = (const char *) jcf->read_ptr;
                  JCF_SKIP (jcf, filename_length);
                  JCF_SKIP (jcf, extra_length);
                  if (filename_length > 0
@@ -1096,7 +1436,7 @@ disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
 
 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
-  (fprintf(stderr, "Bad byte codes.\n"), exit(-1)) : 1)
+  (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
 
 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
    These all push a constant onto the opcode stack. */