OSDN Git Service

* jcf-dump.c (HANDLE_INNERCLASSES_ATTRIBUTE): Handle cases where
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-dump.c
1 /* Program to dump out a Java(TM) .class file.
2    Functionally similar to Sun's javap.
3
4    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
5    Free Software Foundation, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  
23
24 Java and all Java-based marks are trademarks or registered trademarks
25 of Sun Microsystems, Inc. in the United States and other countries.
26 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
27
28 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
29
30 /*
31   jcf-dump is a program to print out the contents of class files.
32   Usage:  jcf-dump [FLAGS] CLASS
33   Each CLASS is either:
34   + the name of a class in the CLASSPATH (e.g "java.lang.String"), or
35   + the name of a class *file* (e.g. "/home/me/work/package/Foo.class").
36   + The name of a .zip or .jar file (which prints all the classes in the
37   archive).
38
39   OPTIONS:
40   -c
41         Dis-assemble each method.
42   -classpath PATH
43         Overrides $CLASSPATH.
44   --print-main
45         Print nothing if there is no valid "main" method;
46         otherwise, print only the class name.
47   --javap
48         Print output in the style of Sun's javap program.  VERY UNFINISHED.
49  */
50     
51
52 #include "config.h"
53 #include "system.h"
54 #include "coretypes.h"
55 #include "tm.h"
56 #include "ggc.h"
57 #include "intl.h"
58
59 #include "jcf.h"
60 #include "tree.h"
61 #include "java-tree.h"
62
63 #include "version.h"
64
65 #include <getopt.h>
66 #include <math.h>
67
68 /* Output file. */
69 FILE *out;
70 /* Name of output file, if NULL if stdout. */
71 char *output_file = NULL;
72
73 int verbose = 0;
74
75 int flag_disassemble_methods = 0;
76 int flag_print_class_info = 1;
77 int flag_print_constant_pool = 0;
78 int flag_print_fields = 1;
79 int flag_print_methods = 1;
80 int flag_print_attributes = 1;
81
82 /* When nonzero, warn when source file is newer than matching class
83    file.  */
84 int flag_newer = 1;
85
86 /* Print names of classes that have a "main" method. */
87 int flag_print_main = 0;
88
89 /* Index in constant pool of this class. */
90 int this_class_index = 0;
91
92 int class_access_flags = 0;
93
94 /* Print in format similar to javap.  VERY INCOMPLETE. */
95 int flag_javap_compatible = 0;
96
97 static void print_access_flags (FILE *, uint16, char);
98 static void print_constant_terse (FILE*, JCF*, int, int);
99 static void print_constant (FILE *, JCF *, int, int);
100 static void print_constant_ref (FILE *, JCF *, int);
101 static void disassemble_method (JCF*, const unsigned char *, int);
102 static void print_name (FILE*, JCF*, int);
103 static void print_signature (FILE*, JCF*, int, int);
104 static int utf8_equal_string (struct JCF*, int, const char *);
105 static void usage (void) ATTRIBUTE_NORETURN;
106 static void help (void) ATTRIBUTE_NORETURN;
107 static void version (void) ATTRIBUTE_NORETURN;
108 static void process_class (struct JCF *);
109 static void print_constant_pool (struct JCF *);
110 static void print_exception_table (struct JCF *, const unsigned char *entries,
111                                    int);
112
113 #define PRINT_SIGNATURE_RESULT_ONLY 1
114 #define PRINT_SIGNATURE_ARGS_ONLY 2
115
116 static int
117 utf8_equal_string (JCF *jcf, int index, const char * value)
118 {
119   if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index)
120       && JPOOL_TAG (jcf, index) == CONSTANT_Utf8)
121     {
122       int len = strlen (value);
123       if (JPOOL_UTF_LENGTH (jcf, index) == len
124           && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0)
125         return 1;
126     }
127   return 0;
128 }
129
130 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
131   this_class_index = 0; \
132   if (flag_print_class_info) \
133     fprintf (out, \
134              "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
135              (long) MAGIC, (long) MINOR, (long) MAJOR)
136
137 #define HANDLE_START_CONSTANT_POOL(COUNT) \
138   if (flag_print_constant_pool) \
139     fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
140
141 #define HANDLE_SOURCEFILE(INDEX) \
142 { fprintf (out, "Attribute "); \
143   print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
144   fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
145   print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
146
147 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
148   this_class_index = THIS; \
149   class_access_flags = ACCESS_FLAGS; \
150   if (flag_print_class_info) \
151     { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
152       print_access_flags (out, ACCESS_FLAGS, 'c'); \
153       fputc ('\n', out); \
154       fprintf (out, "This class: "); \
155       print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
156       if (flag_print_constant_pool || SUPER != 0) \
157         fprintf (out, ", super: "); \
158       if (flag_print_constant_pool) \
159         { \
160           fprintf (out, "%d", SUPER); \
161           if (SUPER != 0) \
162             fputc ('=', out); \
163         } \
164       if (SUPER != 0) \
165         print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
166       fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
167     }
168
169 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
170   (flag_print_attributes <= 0)
171
172 #define HANDLE_CLASS_INTERFACE(INDEX) \
173   if (flag_print_class_info) \
174     { fprintf (out, "- Implements: "); \
175       print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
176       fputc ('\n', out); }
177
178 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
179   if (flag_print_fields) \
180     fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
181
182 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
183   if (flag_print_fields) \
184     { fprintf (out, "Field name:"); \
185       print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
186       print_access_flags (out, ACCESS_FLAGS, 'f'); \
187       fprintf (out, " Signature: "); \
188       if (flag_print_constant_pool) \
189         fprintf (out, "%d=", SIGNATURE); \
190       print_signature (out, jcf, SIGNATURE, 0); \
191       fputc ('\n', out); } \
192   else \
193     flag_print_attributes--;
194
195 #define HANDLE_END_FIELD() \
196   if (! flag_print_fields) \
197     flag_print_attributes++;
198
199 #define HANDLE_START_METHODS(METHODS_COUNT) \
200   if (flag_print_methods) \
201     fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
202   else \
203     flag_print_attributes--;
204
205
206 #define HANDLE_END_METHODS() \
207   if (! flag_print_methods) \
208     flag_print_attributes++;
209
210 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
211 { \
212   if (flag_print_methods) \
213     { \
214       if (flag_javap_compatible) \
215         { \
216           fprintf (out, "    "); \
217           print_access_flags (out, ACCESS_FLAGS, 'm'); \
218           fputc (' ', out); \
219           print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
220           fputc (' ', out); \
221           print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
222           print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
223           fputc ('\n', out); \
224         } \
225       else \
226         { \
227           fprintf (out, "\nMethod name:"); \
228           print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
229           print_access_flags (out, ACCESS_FLAGS, 'm'); \
230           fprintf (out, " Signature: "); \
231           if (flag_print_constant_pool) \
232             fprintf (out, "%d=", SIGNATURE); \
233           print_signature (out, jcf, SIGNATURE, 0); \
234           fputc ('\n', out); \
235         } \
236     } \
237   if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
238       && utf8_equal_string (jcf, NAME, "main") \
239       && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
240       && this_class_index > 0 \
241       && (class_access_flags & ACC_PUBLIC)) \
242     { \
243       print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
244       fputc  ('\n', out); \
245    } \
246 }
247
248 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
249 ( fprintf (out, "Attribute "), \
250   print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
251   fprintf (out, ", length:%ld", (long) LENGTH) )
252
253 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
254 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
255   fprintf (out, ", value: "), \
256   print_constant_ref (out, jcf, VALUE_INDEX), \
257   fprintf (out, "\n") )
258
259 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
260 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
261   fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
262     (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
263   disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
264
265 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
266   print_exception_table (jcf, ENTRIES, COUNT)
267
268 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
269 { int n = (COUNT); int i; \
270   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
271   fprintf (out, ", count: %d\n", n); \
272   for (i = 0; i < n; i++) {\
273     int ex_index = JCF_readu2 (jcf); \
274     fprintf (out, "%3d: ", i); \
275     print_constant_ref (out, jcf, ex_index); \
276     fputc ('\n', out); } }
277
278 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
279 { int n = (COUNT); int i; \
280   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
281   fprintf (out, ", count: %d\n", n); \
282   for (i = 0; i < n; i++) {\
283     int start_pc = JCF_readu2 (jcf); \
284     int length = JCF_readu2 (jcf); \
285     int name_index = JCF_readu2 (jcf); \
286     int signature_index = JCF_readu2 (jcf); \
287     int slot = JCF_readu2 (jcf); \
288     fprintf (out, "  slot#%d: name: ", slot); \
289     if (flag_print_constant_pool) \
290       fprintf (out, "%d=", name_index); \
291     print_name (out, jcf, name_index); \
292     fprintf (out, ", type: "); \
293     if (flag_print_constant_pool) \
294       fprintf (out, "%d=", signature_index); \
295     print_signature (out, jcf, signature_index, 0); \
296     fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
297
298 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
299 { int n = (COUNT); int i; \
300   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
301   fprintf (out, ", count: %d\n", n); \
302   if (flag_disassemble_methods) \
303     for (i = 0; i < n; i++) {\
304       int start_pc = JCF_readu2 (jcf); \
305       int line_number = JCF_readu2 (jcf); \
306       fprintf (out, "  line: %d at pc: %d\n", line_number, start_pc); }\
307   else \
308     JCF_SKIP (jcf, 4 * n); }
309
310 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT)                                \
311 { int n = (COUNT);                                                          \
312   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);           \
313   while (n--)                                                               \
314     {                                                                       \
315       uint16 inner_class_info_index = JCF_readu2 (jcf);                     \
316       uint16 outer_class_info_index = JCF_readu2 (jcf);                     \
317       uint16 inner_name_index = JCF_readu2 (jcf);                           \
318       uint16 inner_class_access_flags = JCF_readu2 (jcf);                   \
319                                                                             \
320       if (flag_print_class_info)                                            \
321         {                                                                   \
322           fprintf (out, "\n  inner: ");                                     \
323           if (inner_class_info_index == 0)                                  \
324             fprintf (out, " (no inner info index)");                        \
325           else                                                              \
326             print_constant_terse_with_index (out, jcf,                      \
327                                              inner_class_info_index,        \
328                                              CONSTANT_Class);               \
329           if (inner_name_index == 0)                                        \
330             fprintf (out, " (anonymous)");                                  \
331           else if (verbose || flag_print_constant_pool)                     \
332             {                                                               \
333               fprintf (out, " (");                                          \
334               print_constant_terse_with_index (out, jcf, inner_name_index,  \
335                                                CONSTANT_Utf8);              \
336               fputc (')', out);                                             \
337             }                                                               \
338           fprintf (out, ", access flags: 0x%x", inner_class_access_flags);  \
339           print_access_flags (out, inner_class_access_flags, 'c');          \
340           fprintf (out, ", outer class: ");                                 \
341           if (outer_class_info_index == 0)                                  \
342             fprintf (out, "(not a member)");                                \
343           else                                                              \
344             print_constant_terse_with_index (out, jcf,                      \
345                                              outer_class_info_index,        \
346                                              CONSTANT_Class);               \
347         }                                                                   \
348     }                                                                       \
349   if (flag_print_class_info)                                                \
350     fputc ('\n', out);                                                      \
351 }
352
353 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
354 { int i, n = (LENGTH), c = 0;                                     \
355   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
356   fputc ('\n', out); \
357   for (i = 0;  i < n;  i++) { c = JCF_readu(jcf); fputc(c, out); } \
358   if (c != '\r' && c != '\n') fputc('\n', out); }
359
360 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
361 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
362   fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
363
364 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
365   if (flag_print_attributes > 0) \
366     fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
367
368 #include "javaop.h"
369
370 static void
371 print_constant_ref (FILE *stream, JCF *jcf, int index)
372 {
373   if (index <= 0 || index >= JPOOL_SIZE(jcf))
374     fprintf (stream, "<out of range>");
375   else
376     {
377       if (flag_print_constant_pool)
378         fprintf (stream, "#%d=", index);
379       fputc ('<', stream);
380       print_constant (stream, jcf, index, 1);
381       fputc ('>', stream);
382     }
383 }
384
385 /* Print the access flags given by FLAGS.
386    The CONTEXT is one of 'c' (class flags), 'f' (field flags),
387    or 'm' (method flags). */
388
389 static void
390 print_access_flags (FILE *stream, uint16 flags, char context)
391 {
392   if (flags & ACC_PUBLIC) fprintf (stream, " public");
393   if (flags & ACC_PRIVATE) fprintf (stream, " private");
394   if (flags & ACC_PROTECTED) fprintf (stream, " protected");
395   if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
396   if (flags & ACC_STATIC) fprintf (stream, " static");
397   if (flags & ACC_FINAL) fprintf (stream, " final");
398   if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
399   if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
400   if (flags & ACC_NATIVE) fprintf (stream, " native");
401   if (flags & ACC_SYNCHRONIZED)
402     {
403       if (context == 'c')
404         fprintf (stream, " super");
405       else
406         fprintf (stream, " synchronized");
407     }
408   if (flags & ACC_INTERFACE) fprintf (stream, " interface");
409   if (flags & ACC_STRICT) fprintf (stream, " strictfp");
410 }
411
412
413 static void
414 print_name (FILE* stream, JCF* jcf, int name_index)
415 {
416   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
417     fprintf (stream, "<not a UTF8 constant>");
418   else
419     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
420                     JPOOL_UTF_LENGTH (jcf, name_index));
421 }
422
423 /* If the type of the constant at INDEX matches EXPECTED,
424    print it tersely, otherwise more verbosely. */
425
426 static void
427 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
428 {
429   if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
430     fprintf (out, "<constant pool index %d not in range>", index);
431   else if (JPOOL_TAG (jcf, index) != expected)
432     {
433       fprintf (out, "<Unexpected constant type ");
434       print_constant (out, jcf, index, 1);
435       fprintf (out, ">");
436     }
437   else
438     print_constant (out, jcf, index, 0);
439 }
440
441 static void
442 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
443 {
444   if (flag_print_constant_pool)
445     fprintf (out, "%d=", index);
446   print_constant_terse (out, jcf, index, expected);
447 }
448
449 /* Print the constant at INDEX in JCF's constant pool.
450    If verbosity==0, print very tersely (no extraneous text).
451    If verbosity==1, prefix the type of the constant.
452    If verbosity==2, add more descriptive text. */
453
454 static void
455 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
456 {
457   int j, n;
458   jlong num;
459   const char *str;
460   int kind = JPOOL_TAG (jcf, index);
461   switch (kind)
462     {
463     case CONSTANT_Class:
464       n = JPOOL_USHORT1 (jcf, index);
465       if (verbosity > 0)
466         {
467           if (verbosity > 1)
468             fprintf (out, "Class name: %d=", n);
469           else
470             fprintf (out, "Class ");
471         }
472       if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
473         fprintf (out, "<out of range>");
474       else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
475         {
476           int len = JPOOL_UTF_LENGTH (jcf, n);
477           jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
478         }
479       else
480         print_constant_terse (out, jcf, n, CONSTANT_Utf8);
481       break;
482     case CONSTANT_Fieldref:
483       str = "Field"; goto field_or_method;
484     case CONSTANT_Methodref:
485       str = "Method"; goto field_or_method;
486     case CONSTANT_InterfaceMethodref:
487       str = "InterfaceMethod"; goto field_or_method;
488     field_or_method:
489       {
490         uint16 tclass = JPOOL_USHORT1 (jcf, index);
491         uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
492         if (verbosity == 2)
493           fprintf (out, "%sref class: %d=", str, tclass);
494         else if (verbosity > 0)
495             fprintf (out, "%s ", str);
496         print_constant_terse (out, jcf, tclass, CONSTANT_Class);
497         if (verbosity < 2)
498           fprintf (out, ".");
499         else
500           fprintf (out, " name_and_type: %d=<", name_and_type);
501         print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
502         if (verbosity == 2)
503           fputc ('>', out);
504       }
505       break;
506     case CONSTANT_String:
507       j = JPOOL_USHORT1 (jcf, index);
508       if (verbosity > 0)
509         {
510           if (verbosity > 1)
511             fprintf (out, "String %d=", j);
512           else
513             fprintf (out, "String ");
514         }
515       print_constant_terse (out, jcf, j, CONSTANT_Utf8);
516       break;
517     case CONSTANT_Integer:
518       if (verbosity > 0)
519         fprintf (out, "Integer ");
520       num = JPOOL_INT (jcf, index);
521       goto integer;
522     case CONSTANT_Long:
523       if (verbosity > 0)
524         fprintf (out, "Long ");
525       num = JPOOL_LONG (jcf, index);
526       goto integer;
527     integer:
528       {
529         char buffer[25];
530         format_int (buffer, num, 10);
531         fprintf (out, "%s", buffer);
532         if (verbosity > 1)
533           {
534             format_uint (buffer, (uint64)num, 16);
535             fprintf (out, "=0x%s", buffer);
536           }
537       }
538       break;
539     case CONSTANT_Float:
540       {
541         jfloat fnum = JPOOL_FLOAT (jcf, index);
542
543         if (verbosity > 0)
544           fputs ("Float ", out);
545
546         if (fnum.negative)
547           putc ('-', out);
548
549         if (JFLOAT_FINITE (fnum))
550           {
551             int dummy;
552             int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
553             double f;
554             uint32 mantissa = fnum.mantissa;
555             if (fnum.exponent == 0)
556               /* Denormal.  */
557               exponent++;
558             else
559               /* Normal; add the implicit bit.  */
560               mantissa |= ((uint32)1 << 23);
561             
562             f = frexp (mantissa, &dummy);
563             f = ldexp (f, exponent + 1);
564             fprintf (out, "%.10g", f);
565           }
566         else
567           {
568             if (fnum.mantissa == 0)
569               fputs ("Inf", out);
570             else if (fnum.mantissa & JFLOAT_QNAN_MASK)
571               fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
572             else
573               fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
574           }
575
576         if (verbosity > 1)
577           fprintf (out, ", bits = 0x%08lx", JPOOL_UINT (jcf, index));
578         
579         break;
580       }
581     case CONSTANT_Double:
582       {
583         jdouble dnum = JPOOL_DOUBLE (jcf, index);
584
585         if (verbosity > 0)
586           fputs ("Double ", out);
587
588         if (dnum.negative)
589           putc ('-', out);
590
591         if (JDOUBLE_FINITE (dnum))
592           {
593             int dummy;
594             int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
595             double d;
596             uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
597                                + dnum.mantissa1);
598             if (dnum.exponent == 0)
599               /* Denormal.  */
600               exponent++;
601             else
602               /* Normal; add the implicit bit.  */
603               mantissa |= ((uint64)1 << 52);
604
605             d = frexp (mantissa, &dummy);
606             d = ldexp (d, exponent + 1);
607             fprintf (out, "%.20g", d);
608           }
609         else
610           {
611             uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
612             mantissa = (mantissa << 32) + dnum.mantissa1;
613
614             if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
615               fputs ("Inf", out);
616             else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
617               fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
618             else
619               fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
620           }
621         if (verbosity > 1)
622           {
623             int32 hi, lo;
624             hi = JPOOL_UINT (jcf, index);
625             lo = JPOOL_UINT (jcf, index + 1);
626             fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
627           }
628         break;
629       }
630     case CONSTANT_NameAndType:
631       {
632         uint16 name = JPOOL_USHORT1 (jcf, index);
633         uint16 sig = JPOOL_USHORT2 (jcf, index);
634         if (verbosity > 0)
635           {
636             if (verbosity > 1)
637               fprintf (out, "NameAndType name: %d=", name);
638             else
639               fprintf (out, "NameAndType ");
640           }
641         print_name (out, jcf, name);
642         if (verbosity <= 1)
643           fputc (' ', out);
644         else
645           fprintf (out, ", signature: %d=", sig);
646         print_signature (out, jcf, sig, 0);
647       }
648       break;
649     case CONSTANT_Utf8:
650       {
651         const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
652         int length = JPOOL_UTF_LENGTH (jcf, index);
653         if (verbosity > 0)
654           { /* Print as 8-bit bytes. */
655             fputs ("Utf8: \"", out);
656             while (--length >= 0)
657               jcf_print_char (out, *str++);
658           }
659         else
660           { /* Print as Unicode. */
661             fputc ('\"', out);
662             jcf_print_utf8 (out, str, length);
663           }
664         fputc ('\"', out);
665       }
666       break;
667     default:
668       fprintf (out, "(Unknown constant type %d)", kind);
669     }
670 }
671
672 static void
673 print_constant_pool (JCF *jcf)
674 {
675   int i;
676   for (i = 1; i < JPOOL_SIZE(jcf); i++)
677     {
678       int kind = JPOOL_TAG (jcf, i);
679       fprintf (out, "#%d: ", i);
680       print_constant (out, jcf, i, 2);
681       fprintf (out, "\n");
682       if (kind == CONSTANT_Double || kind == CONSTANT_Long)
683         i++; /* These take up two slots in the constant table */
684     }
685 }
686
687 static void
688 print_signature_type (FILE* stream, const unsigned char **ptr,
689                       const unsigned char *limit)
690 {
691   int array_size;
692   if ((*ptr) >= limit)
693     return;
694   switch (*(*ptr))
695     {
696     case '[':
697       array_size = -1;
698       for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
699         {
700           array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
701         }
702       print_signature_type (stream, ptr, limit);
703       if (array_size == -1)
704         fprintf (stream, "[]");
705       else
706         fprintf (stream, "[%d]", array_size);
707       break;
708     case '(':
709       {
710         int nargs = 0;
711         fputc (*(*ptr)++, stream);
712         for (; **ptr != ')' && *ptr < limit; nargs++)
713           {
714             if (nargs > 0)
715               fputc (',', stream);
716             print_signature_type (stream, ptr, limit);
717           }
718         if (*ptr < limit)
719           {
720             fputc (*(*ptr)++, stream);
721             print_signature_type (stream, ptr, limit);
722           }
723         else
724           fprintf (stream, "???");
725       }
726     break;
727       
728     case 'B':  fprintf (stream, "byte");  (*ptr)++;  break;
729     case 'C':  fprintf (stream, "char");  (*ptr)++;  break;
730     case 'D':  fprintf (stream, "double");  (*ptr)++;  break;
731     case 'F':  fprintf (stream, "float");  (*ptr)++;  break;
732     case 'S':  fprintf (stream, "short");  (*ptr)++;  break;
733     case 'I':  fprintf (stream, "int");  (*ptr)++;  break;
734     case 'J':  fprintf (stream, "long");  (*ptr)++;  break;
735     case 'Z':  fprintf (stream, "boolean");  (*ptr)++;  break;
736     case 'V':  fprintf (stream, "void");  (*ptr)++;  break;
737
738     case 'L':
739       for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
740         jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
741       if (*(*ptr) == ';')
742         (*ptr)++;
743       break;
744     default:
745       jcf_print_char (stream, *(*ptr)++);
746     }
747 }
748
749 static void
750 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
751 {
752   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
753     print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
754   else
755     {
756       const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
757       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
758       const unsigned char *limit;
759       limit = str + length;
760       if (str >= limit)
761         fprintf (stream, "<empty signature string>");
762       else
763         {
764           if (options & PRINT_SIGNATURE_RESULT_ONLY)
765             {
766               while (str < limit && *str++ != ')') ;
767             }
768           if (options & PRINT_SIGNATURE_ARGS_ONLY)
769             {
770               str++;
771               fputc ('(', stream);
772               while (str < limit && *str != ')')
773                 {
774                   print_signature_type (stream, &str, limit);
775                   if (*str != ')')
776                     fputs (", ", stream);
777                 }
778               fputc (')', stream);
779             }
780           else
781             {
782               print_signature_type (stream, &str, limit);
783               if (str < limit)
784                 {
785                   fprintf (stream, "<junk:");
786                   jcf_print_utf8 (stream, str, limit - str);
787                   fputc ('>', stream);
788                 }
789             }
790         }
791     }
792 }
793
794
795 static void
796 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
797 {
798   /* Print exception table. */
799   int i = count;
800   if (i > 0)
801     {
802       const unsigned char *ptr = entries;
803       fprintf (out, "Exceptions (count: %d):\n", i);
804       for (; --i >= 0;  ptr+= 8)
805         {
806           int start_pc = GET_u2 (ptr);
807           int end_pc = GET_u2 (ptr+2);
808           int handler_pc = GET_u2 (ptr+4);
809           int catch_type = GET_u2 (ptr+6);
810           fprintf (out, "  start: %d, end: %d, handler: %d, type: ",
811                    start_pc, end_pc, handler_pc);
812           if (catch_type == 0)
813             fputs ("0 /* finally */", out);
814           else
815             print_constant_terse_with_index (out, jcf,
816                                              catch_type, CONSTANT_Class);
817           fputc ('\n', out);
818         }
819     }
820 }
821
822 #include "jcf-reader.c"
823
824 static void
825 process_class (JCF *jcf)
826 {
827   int code;
828   if (jcf_parse_preamble (jcf) != 0)
829     fprintf (stderr, _("Not a valid Java .class file.\n"));    
830
831   /* Parse and possibly print constant pool */
832   code = jcf_parse_constant_pool (jcf);
833   if (code != 0)
834     {
835       fprintf (stderr, _("error while parsing constant pool\n"));
836       exit (FATAL_EXIT_CODE);
837     }
838   code = verify_constant_pool (jcf);
839   if (code > 0)
840     {
841       fprintf (stderr, _("error in constant pool entry #%d\n"), code);
842       exit (FATAL_EXIT_CODE);
843     }
844   if (flag_print_constant_pool)
845     print_constant_pool (jcf);
846
847   jcf_parse_class (jcf);
848   code = jcf_parse_fields (jcf);
849   if (code != 0)
850     {
851       fprintf (stderr, _("error while parsing fields\n"));
852       exit (FATAL_EXIT_CODE);
853     }
854   code = jcf_parse_methods (jcf);
855   if (code != 0)
856     {
857       fprintf (stderr, _("error while parsing methods\n"));
858       exit (FATAL_EXIT_CODE);
859     }
860   code = jcf_parse_final_attributes (jcf);
861   if (code != 0)
862     {
863       fprintf (stderr, _("error while parsing final attributes\n"));
864       exit (FATAL_EXIT_CODE);
865     }
866   jcf->filename = NULL;
867 }
868
869 \f
870
871 /* This is used to mark options with no short value.  */
872 #define LONG_OPT(Num)  ((Num) + 128)
873
874 #define OPT_classpath     LONG_OPT (0)
875 #define OPT_CLASSPATH     OPT_classpath
876 #define OPT_bootclasspath LONG_OPT (1)
877 #define OPT_extdirs       LONG_OPT (2)
878 #define OPT_HELP          LONG_OPT (3)
879 #define OPT_VERSION       LONG_OPT (4)
880 #define OPT_JAVAP         LONG_OPT (5)
881
882 static const struct option options[] =
883 {
884   { "classpath",     required_argument, NULL, OPT_classpath },
885   { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
886   { "extdirs",       required_argument, NULL, OPT_extdirs },
887   { "CLASSPATH",     required_argument, NULL, OPT_CLASSPATH },
888   { "help",          no_argument,       NULL, OPT_HELP },
889   { "verbose",       no_argument,       NULL, 'v' },
890   { "version",       no_argument,       NULL, OPT_VERSION },
891   { "javap",         no_argument,       NULL, OPT_JAVAP },
892   { "print-main",    no_argument,       &flag_print_main, 1 },
893   { "print-constants", no_argument,     &flag_print_constant_pool, 1 },
894   { NULL,            no_argument,       NULL, 0 }
895 };
896
897 static void
898 usage (void)
899 {
900   fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
901   exit (1);
902 }
903
904 static void
905 help (void)
906 {
907   printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
908   printf (_("Display contents of a class file in readable form.\n\n"));
909   printf (_("  -c                      Disassemble method bodies\n"));
910   printf (_("  --javap                 Generate output in 'javap' format\n"));
911   printf ("\n");
912   printf (_("  --classpath PATH        Set path to find .class files\n"));
913   printf (_("  -IDIR                   Append directory to class path\n"));
914   printf (_("  --bootclasspath PATH    Override built-in class path\n"));
915   printf (_("  --extdirs PATH          Set extensions directory path\n"));
916   printf (_("  -o FILE                 Set output file name\n"));
917   printf ("\n");
918   printf (_("  --help                  Print this help, then exit\n"));
919   printf (_("  --version               Print version number, then exit\n"));
920   printf (_("  -v, --verbose           Print extra information while running\n"));
921   printf ("\n");
922   printf (_("For bug reporting instructions, please see:\n"
923             "%s.\n"), bug_report_url);
924   exit (0);
925 }
926
927 static void
928 version (void)
929 {
930   printf ("jcf-dump (GCC) %s\n\n", version_string);
931   printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
932   printf (_("This is free software; see the source for copying conditions.  There is NO\n"
933             "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
934   exit (0);
935 }
936
937 int
938 main (int argc, char** argv)
939 {
940   JCF jcf[1];
941   int argi, opt;
942
943   gcc_init_libintl ();
944
945   if (argc <= 1)
946     {
947       fprintf (stderr, _("jcf-dump: no classes specified\n"));
948       usage ();
949     }
950
951   jcf_path_init ();
952
953   /* We use getopt_long_only to allow single `-' long options.  For
954      some of our options this is more natural.  */
955   while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
956     {
957       switch (opt)
958         {
959         case 0:
960           /* Already handled.  */
961           break;
962
963         case 'o':
964           output_file = optarg;
965           break;
966
967         case 'I':
968           jcf_path_include_arg (optarg);
969           break;
970
971         case 'v':
972           verbose++;
973           break;
974
975         case 'c':
976           flag_disassemble_methods = 1;
977           break;
978
979         case OPT_classpath:
980           jcf_path_classpath_arg (optarg);
981           break;
982
983         case OPT_bootclasspath:
984           jcf_path_bootclasspath_arg (optarg);
985           break;
986
987         case OPT_extdirs:
988           jcf_path_extdirs_arg (optarg);
989           break;
990
991         case OPT_HELP:
992           help ();
993           break;
994
995         case OPT_VERSION:
996           version ();
997           break;
998
999         case OPT_JAVAP:
1000           flag_javap_compatible++;
1001           flag_print_constant_pool = 0;
1002           flag_print_attributes = 0;
1003           break;
1004
1005         default:
1006           usage ();
1007         }
1008     }
1009
1010   if (verbose && ! flag_javap_compatible)
1011     flag_print_constant_pool = 1;
1012
1013   if (optind == argc)
1014     {
1015       fprintf (stderr, _("jcf-dump: no classes specified\n"));
1016       usage ();
1017     }
1018
1019   jcf_path_seal (verbose);
1020
1021   if (flag_print_main)
1022     {
1023       flag_print_fields = 0;
1024       flag_print_methods = 0;
1025       flag_print_constant_pool = 0;
1026       flag_print_attributes = 0;
1027       flag_print_class_info = 0;
1028     }
1029
1030   if (output_file)
1031     {
1032       out = fopen (output_file, "w");
1033       if (! out)
1034         {
1035           fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1036           return FATAL_EXIT_CODE;
1037         }
1038     }
1039   else
1040     out = stdout;
1041
1042   if (optind >= argc)
1043     {
1044       fprintf (out, "Reading .class from <standard input>.\n");
1045       open_class ("<stdio>", jcf, 0, NULL);
1046       process_class (jcf);
1047     }
1048   else
1049     {
1050       for (argi = optind; argi < argc; argi++)
1051         {
1052           char *arg = argv[argi];
1053           const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1054           if (class_filename == NULL)
1055             class_filename = find_classfile (arg, jcf, NULL);
1056           if (class_filename == NULL)
1057             {
1058               perror ("Could not find class");
1059               return FATAL_EXIT_CODE;
1060             }
1061           JCF_FILL (jcf, 4);
1062           if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1063             {
1064               long compressed_size, member_size;
1065               int compression_method, filename_length, extra_length;
1066               int general_purpose_bits;
1067               const char *filename;
1068               int total_length;
1069               if (flag_print_class_info)
1070                 fprintf (out, "Reading classes from archive %s.\n",
1071                          class_filename);
1072               for (;;)
1073                 {
1074                   int skip = 0;
1075                   jcf_filbuf_t save_filbuf = jcf->filbuf;
1076                   long magic = JCF_readu4_le (jcf);
1077                   if (magic == 0x02014b50 || magic == 0x06054b50)
1078                     break;  /* got to central directory */
1079                   if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1080                     {
1081                       fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1082                       return FATAL_EXIT_CODE;
1083                     }
1084                   JCF_FILL (jcf, 26);
1085                   JCF_SKIP (jcf, 2);
1086                   general_purpose_bits = JCF_readu2_le (jcf);
1087                   compression_method = JCF_readu2_le (jcf);
1088                   JCF_SKIP (jcf, 8);
1089                   compressed_size = JCF_readu4_le (jcf);
1090                   member_size = JCF_readu4_le (jcf);
1091                   filename_length = JCF_readu2_le (jcf);
1092                   extra_length = JCF_readu2_le (jcf);
1093                   total_length = filename_length + extra_length
1094                     + compressed_size;
1095                   if (jcf->read_end - jcf->read_ptr < total_length)
1096                     jcf_trim_old_input (jcf);
1097                   JCF_FILL (jcf, total_length);
1098                   filename = (const char *) jcf->read_ptr;
1099                   JCF_SKIP (jcf, filename_length);
1100                   JCF_SKIP (jcf, extra_length);
1101                   if (filename_length > 0
1102                       && filename[filename_length-1] == '/')
1103                     {
1104                       if (flag_print_class_info)
1105                         fprintf (out, "[Skipping directory %.*s]\n",
1106                                  filename_length, filename);
1107                       skip = 1;
1108                     }
1109                   else if (compression_method != 0)
1110                     {
1111                       if (flag_print_class_info)
1112                         fprintf (out, "[Skipping compressed file %.*s]\n",
1113                                  filename_length, filename);
1114                       skip = 1;
1115                     }
1116                   else if (member_size < 4
1117                            || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1118                     {
1119                       if (flag_print_class_info)
1120                         fprintf (out, "[Skipping non-.class member %.*s]\n",
1121                                  filename_length, filename);
1122                       skip = 1;
1123                     }
1124                   else
1125                     {
1126                       if (flag_print_class_info)
1127                         fprintf (out, "Reading class member: %.*s.\n",
1128                                  filename_length, filename);
1129                     }
1130                   if (skip)
1131                     {
1132                       JCF_SKIP (jcf, compressed_size);
1133                     }
1134                   else
1135                     {
1136                       unsigned char *save_end;
1137                       jcf->filbuf = jcf_unexpected_eof;
1138                       save_end = jcf->read_end;
1139                       jcf->read_end = jcf->read_ptr + compressed_size;
1140                       process_class (jcf);
1141                       jcf->filbuf = save_filbuf;
1142                       jcf->read_end = save_end;
1143                     }
1144                 }
1145             }
1146           else
1147             {
1148               if (flag_print_class_info)
1149                 fprintf (out, "Reading .class from %s.\n", class_filename);
1150               process_class (jcf);
1151             }
1152           JCF_FINISH(jcf);
1153         }
1154     }
1155
1156   return SUCCESS_EXIT_CODE;
1157 }
1158
1159 \f
1160
1161 static void
1162 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1163 {
1164 #undef PTR
1165   int PC;
1166   int i;
1167   int saw_wide = 0;
1168   if (flag_disassemble_methods == 0)
1169     return;
1170 #define BCODE byte_ops
1171   for (PC = 0; PC < len;)
1172     {
1173       int oldpc = PC;
1174       int saw_index;
1175       jint INT_temp;
1176       switch (byte_ops[PC++])
1177         {
1178
1179 /* This is the actual code emitted for each of opcodes in javaops.def.
1180    The actual opcode-specific stuff is handled by the OPKIND macro.
1181    I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1182    Those macros are defined below.  The OPKINDs that do not have any
1183    inline parameters (such as BINOP) and therefore do mot need anything
1184    else to me printed out just use an empty body. */
1185
1186 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1187         case OPCODE: \
1188           fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1189           OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1190           fputc ('\n', out); \
1191           break;
1192
1193 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1194 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1195 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1196 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1197
1198 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1199   (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1200
1201 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1202    These all push a constant onto the opcode stack. */
1203 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1204   saw_index = 0, i = (OPERAND_VALUE); \
1205   if (oldpc+1 == PC) /* nothing */; \
1206   else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1207   else fprintf (out, " %d", i);
1208
1209 /* Print out operand (a local variable index) for LOAD opcodes.
1210    These all push local variable onto the opcode stack. */
1211 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1212   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1213
1214 /* Handle STORE opcodes same as LOAD opcodes.
1215    These all store a value from the opcode stack in a local variable. */
1216 #define STORE LOAD
1217
1218 /* Handle more kind of opcodes. */
1219 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1220 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1221 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1222 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1223 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1224 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1225 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1226
1227 /* Handle putfield and getfield opcodes, with static versions. */
1228 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1229   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1230
1231 /* Print operand for invoke opcodes. */
1232 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1233   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1234   if (OPERAND_VALUE) /* for invokeinterface */ \
1235   { int nargs = IMMEDIATE_u1;  PC++; \
1236     fprintf (out, " nargs:%d", nargs); }
1237
1238 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1239   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1240
1241 #define ARRAY(OPERAND_TYPE, SUBOP) \
1242   ARRAY_##SUBOP(OPERAND_TYPE)
1243 /* Handle sub-categories of ARRAY opcodes. */
1244 #define ARRAY_LOAD(TYPE) /* nothing */
1245 #define ARRAY_STORE(TYPE) /* nothing */
1246 #define ARRAY_LENGTH(TYPE) /* nothing */
1247 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1248 #define ARRAY_NEW_NUM \
1249  INT_temp = IMMEDIATE_u1; \
1250  { switch ((int) INT_temp) {  \
1251     case  4: fputs (" boolean", out); break; \
1252     case  5: fputs (" char", out); break; \
1253     case  6: fputs (" float", out); break; \
1254     case  7: fputs (" double", out); break; \
1255     case  8: fputs (" byte", out); break; \
1256     case  9: fputs (" short", out); break; \
1257     case 10: fputs (" int", out); break; \
1258     case 11: fputs (" long", out); break; \
1259     default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1260   } }
1261
1262 #define ARRAY_NEW_PTR  \
1263   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1264
1265 #define ARRAY_NEW_MULTI \
1266   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1267   fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1268
1269 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1270   fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1271
1272 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1273   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1274   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1275
1276 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1277   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1278   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1279
1280 #undef RET /* Defined by config/i386/i386.h */
1281 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1282   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1283   saw_wide = 0; \
1284   fprintf (out, " %ld", (long) INT_temp);
1285
1286 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1287   PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1288
1289 #define LOOKUP_SWITCH \
1290   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1291     fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1292     while (--npairs >= 0) { \
1293      jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1294      fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1295   }
1296
1297 #define TABLE_SWITCH \
1298   { jint default_offset = IMMEDIATE_s4; \
1299     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1300     fprintf (out, " low=%ld, high=%ld, default=%ld", \
1301       (long) low, (long) high, (long) default_offset+oldpc); \
1302     for (; low <= high; low++) { \
1303      jint offset = IMMEDIATE_s4; \
1304      fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1305   }
1306
1307 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1308   SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1309
1310 #define SPECIAL_IINC(OPERAND_TYPE) \
1311   i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1312   fprintf (out, " %d", i); \
1313   i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1314   saw_wide = 0; \
1315   fprintf (out, " %d", i)
1316
1317 #define SPECIAL_WIDE(OPERAND_TYPE) \
1318   saw_wide = 1;
1319
1320 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1321 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1322 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1323 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1324
1325 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1326   fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1327
1328 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1329    TEST(OPERAND_TYPE, OPERAND_VALUE)
1330
1331 #include "javaop.def"
1332
1333         load_store:
1334           if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1335           else
1336             {
1337               saw_wide = 0;
1338               fprintf (out, " %ld", (long) INT_temp);
1339             }
1340           fputc ('\n', out);
1341           break;
1342
1343         default:
1344           fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1345         }
1346     }
1347 }