OSDN Git Service

2006-09-07 H.J. Lu <hongjiu.lu@intel.com>
[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    2006 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, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, 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)
399     fprintf (stream, context == 'm' ? " varargs" : " transient");
400   if (flags & ACC_VOLATILE)
401     fprintf (stream, context == 'm' ? " bridge" : " volatile");
402   if (flags & ACC_NATIVE) fprintf (stream, " native");
403   if (flags & ACC_SYNCHRONIZED)
404     {
405       if (context == 'c')
406         fprintf (stream, " super");
407       else
408         fprintf (stream, " synchronized");
409     }
410   if (flags & ACC_INTERFACE)
411     fprintf (stream, (flags & ACC_ANNOTATION) ? " @interface" : " interface");
412   if (flags & ACC_ENUM) fprintf (stream, " enum");
413   if (flags & ACC_STRICT) fprintf (stream, " strictfp");
414   if (flags & ACC_SYNTHETIC) fprintf (stream, " synthetic");
415 }
416
417
418 static void
419 print_name (FILE* stream, JCF* jcf, int name_index)
420 {
421   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
422     fprintf (stream, "<not a UTF8 constant>");
423   else
424     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
425                     JPOOL_UTF_LENGTH (jcf, name_index));
426 }
427
428 /* If the type of the constant at INDEX matches EXPECTED,
429    print it tersely, otherwise more verbosely. */
430
431 static void
432 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
433 {
434   if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
435     fprintf (out, "<constant pool index %d not in range>", index);
436   else if (JPOOL_TAG (jcf, index) != expected)
437     {
438       fprintf (out, "<Unexpected constant type ");
439       print_constant (out, jcf, index, 1);
440       fprintf (out, ">");
441     }
442   else
443     print_constant (out, jcf, index, 0);
444 }
445
446 static void
447 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
448 {
449   if (flag_print_constant_pool)
450     fprintf (out, "%d=", index);
451   print_constant_terse (out, jcf, index, expected);
452 }
453
454 /* Print the constant at INDEX in JCF's constant pool.
455    If verbosity==0, print very tersely (no extraneous text).
456    If verbosity==1, prefix the type of the constant.
457    If verbosity==2, add more descriptive text. */
458
459 static void
460 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
461 {
462   int j, n;
463   jlong num;
464   const char *str;
465   int kind = JPOOL_TAG (jcf, index);
466   switch (kind)
467     {
468     case CONSTANT_Class:
469       n = JPOOL_USHORT1 (jcf, index);
470       if (verbosity > 0)
471         {
472           if (verbosity > 1)
473             fprintf (out, "Class name: %d=", n);
474           else
475             fprintf (out, "Class ");
476         }
477       if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
478         fprintf (out, "<out of range>");
479       else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
480         {
481           int len = JPOOL_UTF_LENGTH (jcf, n);
482           jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
483         }
484       else
485         print_constant_terse (out, jcf, n, CONSTANT_Utf8);
486       break;
487     case CONSTANT_Fieldref:
488       str = "Field"; goto field_or_method;
489     case CONSTANT_Methodref:
490       str = "Method"; goto field_or_method;
491     case CONSTANT_InterfaceMethodref:
492       str = "InterfaceMethod"; goto field_or_method;
493     field_or_method:
494       {
495         uint16 tclass = JPOOL_USHORT1 (jcf, index);
496         uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
497         if (verbosity == 2)
498           fprintf (out, "%sref class: %d=", str, tclass);
499         else if (verbosity > 0)
500             fprintf (out, "%s ", str);
501         print_constant_terse (out, jcf, tclass, CONSTANT_Class);
502         if (verbosity < 2)
503           fprintf (out, ".");
504         else
505           fprintf (out, " name_and_type: %d=<", name_and_type);
506         print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
507         if (verbosity == 2)
508           fputc ('>', out);
509       }
510       break;
511     case CONSTANT_String:
512       j = JPOOL_USHORT1 (jcf, index);
513       if (verbosity > 0)
514         {
515           if (verbosity > 1)
516             fprintf (out, "String %d=", j);
517           else
518             fprintf (out, "String ");
519         }
520       print_constant_terse (out, jcf, j, CONSTANT_Utf8);
521       break;
522     case CONSTANT_Integer:
523       if (verbosity > 0)
524         fprintf (out, "Integer ");
525       num = JPOOL_INT (jcf, index);
526       goto integer;
527     case CONSTANT_Long:
528       if (verbosity > 0)
529         fprintf (out, "Long ");
530       num = JPOOL_LONG (jcf, index);
531       goto integer;
532     integer:
533       {
534         char buffer[25];
535         format_int (buffer, num, 10);
536         fprintf (out, "%s", buffer);
537         if (verbosity > 1)
538           {
539             format_uint (buffer, (uint64)num, 16);
540             fprintf (out, "=0x%s", buffer);
541           }
542       }
543       break;
544     case CONSTANT_Float:
545       {
546         jfloat fnum = JPOOL_FLOAT (jcf, index);
547
548         if (verbosity > 0)
549           fputs ("Float ", out);
550
551         if (fnum.negative)
552           putc ('-', out);
553
554         if (JFLOAT_FINITE (fnum))
555           {
556             int dummy;
557             int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
558             double f;
559             uint32 mantissa = fnum.mantissa;
560             if (fnum.exponent == 0)
561               /* Denormal.  */
562               exponent++;
563             else
564               /* Normal; add the implicit bit.  */
565               mantissa |= ((uint32)1 << 23);
566             
567             f = frexp (mantissa, &dummy);
568             f = ldexp (f, exponent + 1);
569             fprintf (out, "%.10g", f);
570           }
571         else
572           {
573             if (fnum.mantissa == 0)
574               fputs ("Inf", out);
575             else if (fnum.mantissa & JFLOAT_QNAN_MASK)
576               fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
577             else
578               fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
579           }
580
581         if (verbosity > 1)
582           fprintf (out, ", bits = 0x%08lx", (long) JPOOL_UINT (jcf, index));
583         
584         break;
585       }
586     case CONSTANT_Double:
587       {
588         jdouble dnum = JPOOL_DOUBLE (jcf, index);
589
590         if (verbosity > 0)
591           fputs ("Double ", out);
592
593         if (dnum.negative)
594           putc ('-', out);
595
596         if (JDOUBLE_FINITE (dnum))
597           {
598             int dummy;
599             int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
600             double d;
601             uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
602                                + dnum.mantissa1);
603             if (dnum.exponent == 0)
604               /* Denormal.  */
605               exponent++;
606             else
607               /* Normal; add the implicit bit.  */
608               mantissa |= ((uint64)1 << 52);
609
610             d = frexp (mantissa, &dummy);
611             d = ldexp (d, exponent + 1);
612             fprintf (out, "%.20g", d);
613           }
614         else
615           {
616             uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
617             mantissa = (mantissa << 32) + dnum.mantissa1;
618
619             if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
620               fputs ("Inf", out);
621             else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
622               fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
623             else
624               fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
625           }
626         if (verbosity > 1)
627           {
628             int32 hi, lo;
629             hi = JPOOL_UINT (jcf, index);
630             lo = JPOOL_UINT (jcf, index + 1);
631             fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
632           }
633         break;
634       }
635     case CONSTANT_NameAndType:
636       {
637         uint16 name = JPOOL_USHORT1 (jcf, index);
638         uint16 sig = JPOOL_USHORT2 (jcf, index);
639         if (verbosity > 0)
640           {
641             if (verbosity > 1)
642               fprintf (out, "NameAndType name: %d=", name);
643             else
644               fprintf (out, "NameAndType ");
645           }
646         print_name (out, jcf, name);
647         if (verbosity <= 1)
648           fputc (' ', out);
649         else
650           fprintf (out, ", signature: %d=", sig);
651         print_signature (out, jcf, sig, 0);
652       }
653       break;
654     case CONSTANT_Utf8:
655       {
656         const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
657         int length = JPOOL_UTF_LENGTH (jcf, index);
658         if (verbosity > 0)
659           { /* Print as 8-bit bytes. */
660             fputs ("Utf8: \"", out);
661             while (--length >= 0)
662               jcf_print_char (out, *str++);
663           }
664         else
665           { /* Print as Unicode. */
666             fputc ('\"', out);
667             jcf_print_utf8 (out, str, length);
668           }
669         fputc ('\"', out);
670       }
671       break;
672     default:
673       fprintf (out, "(Unknown constant type %d)", kind);
674     }
675 }
676
677 static void
678 print_constant_pool (JCF *jcf)
679 {
680   int i;
681   for (i = 1; i < JPOOL_SIZE(jcf); i++)
682     {
683       int kind = JPOOL_TAG (jcf, i);
684       fprintf (out, "#%d: ", i);
685       print_constant (out, jcf, i, 2);
686       fprintf (out, "\n");
687       if (kind == CONSTANT_Double || kind == CONSTANT_Long)
688         i++; /* These take up two slots in the constant table */
689     }
690 }
691
692 static void
693 print_signature_type (FILE* stream, const unsigned char **ptr,
694                       const unsigned char *limit)
695 {
696   int array_size;
697   if ((*ptr) >= limit)
698     return;
699   switch (*(*ptr))
700     {
701     case '[':
702       array_size = -1;
703       for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
704         {
705           array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
706         }
707       print_signature_type (stream, ptr, limit);
708       if (array_size == -1)
709         fprintf (stream, "[]");
710       else
711         fprintf (stream, "[%d]", array_size);
712       break;
713     case '(':
714       {
715         int nargs = 0;
716         fputc (*(*ptr)++, stream);
717         for (; **ptr != ')' && *ptr < limit; nargs++)
718           {
719             if (nargs > 0)
720               fputc (',', stream);
721             print_signature_type (stream, ptr, limit);
722           }
723         if (*ptr < limit)
724           {
725             fputc (*(*ptr)++, stream);
726             print_signature_type (stream, ptr, limit);
727           }
728         else
729           fprintf (stream, "???");
730       }
731     break;
732       
733     case 'B':  fprintf (stream, "byte");  (*ptr)++;  break;
734     case 'C':  fprintf (stream, "char");  (*ptr)++;  break;
735     case 'D':  fprintf (stream, "double");  (*ptr)++;  break;
736     case 'F':  fprintf (stream, "float");  (*ptr)++;  break;
737     case 'S':  fprintf (stream, "short");  (*ptr)++;  break;
738     case 'I':  fprintf (stream, "int");  (*ptr)++;  break;
739     case 'J':  fprintf (stream, "long");  (*ptr)++;  break;
740     case 'Z':  fprintf (stream, "boolean");  (*ptr)++;  break;
741     case 'V':  fprintf (stream, "void");  (*ptr)++;  break;
742
743     case 'L':
744       for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
745         jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
746       if (*(*ptr) == ';')
747         (*ptr)++;
748       break;
749     default:
750       jcf_print_char (stream, *(*ptr)++);
751     }
752 }
753
754 static void
755 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
756 {
757   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
758     print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
759   else
760     {
761       const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
762       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
763       const unsigned char *limit;
764       limit = str + length;
765       if (str >= limit)
766         fprintf (stream, "<empty signature string>");
767       else
768         {
769           if (options & PRINT_SIGNATURE_RESULT_ONLY)
770             {
771               while (str < limit && *str++ != ')') ;
772             }
773           if (options & PRINT_SIGNATURE_ARGS_ONLY)
774             {
775               str++;
776               fputc ('(', stream);
777               while (str < limit && *str != ')')
778                 {
779                   print_signature_type (stream, &str, limit);
780                   if (*str != ')')
781                     fputs (", ", stream);
782                 }
783               fputc (')', stream);
784             }
785           else
786             {
787               print_signature_type (stream, &str, limit);
788               if (str < limit)
789                 {
790                   fprintf (stream, "<junk:");
791                   jcf_print_utf8 (stream, str, limit - str);
792                   fputc ('>', stream);
793                 }
794             }
795         }
796     }
797 }
798
799
800 static void
801 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
802 {
803   /* Print exception table. */
804   int i = count;
805   if (i > 0)
806     {
807       const unsigned char *ptr = entries;
808       fprintf (out, "Exceptions (count: %d):\n", i);
809       for (; --i >= 0;  ptr+= 8)
810         {
811           int start_pc = GET_u2 (ptr);
812           int end_pc = GET_u2 (ptr+2);
813           int handler_pc = GET_u2 (ptr+4);
814           int catch_type = GET_u2 (ptr+6);
815           fprintf (out, "  start: %d, end: %d, handler: %d, type: ",
816                    start_pc, end_pc, handler_pc);
817           if (catch_type == 0)
818             fputs ("0 /* finally */", out);
819           else
820             print_constant_terse_with_index (out, jcf,
821                                              catch_type, CONSTANT_Class);
822           fputc ('\n', out);
823         }
824     }
825 }
826
827 #include "jcf-reader.c"
828
829 static void
830 process_class (JCF *jcf)
831 {
832   int code;
833   if (jcf_parse_preamble (jcf) != 0)
834     fprintf (stderr, _("Not a valid Java .class file.\n"));    
835
836   /* Parse and possibly print constant pool */
837   code = jcf_parse_constant_pool (jcf);
838   if (code != 0)
839     {
840       fprintf (stderr, _("error while parsing constant pool\n"));
841       exit (FATAL_EXIT_CODE);
842     }
843   code = verify_constant_pool (jcf);
844   if (code > 0)
845     {
846       fprintf (stderr, _("error in constant pool entry #%d\n"), code);
847       exit (FATAL_EXIT_CODE);
848     }
849   if (flag_print_constant_pool)
850     print_constant_pool (jcf);
851
852   jcf_parse_class (jcf);
853   code = jcf_parse_fields (jcf);
854   if (code != 0)
855     {
856       fprintf (stderr, _("error while parsing fields\n"));
857       exit (FATAL_EXIT_CODE);
858     }
859   code = jcf_parse_methods (jcf);
860   if (code != 0)
861     {
862       fprintf (stderr, _("error while parsing methods\n"));
863       exit (FATAL_EXIT_CODE);
864     }
865   code = jcf_parse_final_attributes (jcf);
866   if (code != 0)
867     {
868       fprintf (stderr, _("error while parsing final attributes\n"));
869       exit (FATAL_EXIT_CODE);
870     }
871   jcf->filename = NULL;
872 }
873
874 \f
875
876 /* This is used to mark options with no short value.  */
877 #define LONG_OPT(Num)  ((Num) + 128)
878
879 #define OPT_classpath     LONG_OPT (0)
880 #define OPT_CLASSPATH     OPT_classpath
881 #define OPT_bootclasspath LONG_OPT (1)
882 #define OPT_extdirs       LONG_OPT (2)
883 #define OPT_HELP          LONG_OPT (3)
884 #define OPT_VERSION       LONG_OPT (4)
885 #define OPT_JAVAP         LONG_OPT (5)
886
887 static const struct option options[] =
888 {
889   { "classpath",     required_argument, NULL, OPT_classpath },
890   { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
891   { "extdirs",       required_argument, NULL, OPT_extdirs },
892   { "CLASSPATH",     required_argument, NULL, OPT_CLASSPATH },
893   { "help",          no_argument,       NULL, OPT_HELP },
894   { "verbose",       no_argument,       NULL, 'v' },
895   { "version",       no_argument,       NULL, OPT_VERSION },
896   { "javap",         no_argument,       NULL, OPT_JAVAP },
897   { "print-main",    no_argument,       &flag_print_main, 1 },
898   { "print-constants", no_argument,     &flag_print_constant_pool, 1 },
899   { NULL,            no_argument,       NULL, 0 }
900 };
901
902 static void
903 usage (void)
904 {
905   fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
906   exit (1);
907 }
908
909 static void
910 help (void)
911 {
912   printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
913   printf (_("Display contents of a class file in readable form.\n\n"));
914   printf (_("  -c                      Disassemble method bodies\n"));
915   printf (_("  --javap                 Generate output in 'javap' format\n"));
916   printf ("\n");
917   printf (_("  --classpath PATH        Set path to find .class files\n"));
918   printf (_("  -IDIR                   Append directory to class path\n"));
919   printf (_("  --bootclasspath PATH    Override built-in class path\n"));
920   printf (_("  --extdirs PATH          Set extensions directory path\n"));
921   printf (_("  -o FILE                 Set output file name\n"));
922   printf ("\n");
923   printf (_("  --help                  Print this help, then exit\n"));
924   printf (_("  --version               Print version number, then exit\n"));
925   printf (_("  -v, --verbose           Print extra information while running\n"));
926   printf ("\n");
927   printf (_("For bug reporting instructions, please see:\n"
928             "%s.\n"), bug_report_url);
929   exit (0);
930 }
931
932 static void
933 version (void)
934 {
935   printf ("jcf-dump (GCC) %s\n\n", version_string);
936   printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
937   printf (_("This is free software; see the source for copying conditions.  There is NO\n"
938             "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
939   exit (0);
940 }
941
942 int
943 main (int argc, char** argv)
944 {
945   JCF jcf[1];
946   int argi, opt;
947
948   /* Unlock the stdio streams.  */
949   unlock_std_streams ();
950
951   gcc_init_libintl ();
952
953   if (argc <= 1)
954     {
955       fprintf (stderr, _("jcf-dump: no classes specified\n"));
956       usage ();
957     }
958
959   jcf_path_init ();
960
961   /* We use getopt_long_only to allow single `-' long options.  For
962      some of our options this is more natural.  */
963   while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
964     {
965       switch (opt)
966         {
967         case 0:
968           /* Already handled.  */
969           break;
970
971         case 'o':
972           output_file = optarg;
973           break;
974
975         case 'I':
976           jcf_path_include_arg (optarg);
977           break;
978
979         case 'v':
980           verbose++;
981           break;
982
983         case 'c':
984           flag_disassemble_methods = 1;
985           break;
986
987         case OPT_classpath:
988           jcf_path_classpath_arg (optarg);
989           break;
990
991         case OPT_bootclasspath:
992           jcf_path_bootclasspath_arg (optarg);
993           break;
994
995         case OPT_extdirs:
996           jcf_path_extdirs_arg (optarg);
997           break;
998
999         case OPT_HELP:
1000           help ();
1001           break;
1002
1003         case OPT_VERSION:
1004           version ();
1005           break;
1006
1007         case OPT_JAVAP:
1008           flag_javap_compatible++;
1009           flag_print_constant_pool = 0;
1010           flag_print_attributes = 0;
1011           break;
1012
1013         default:
1014           usage ();
1015         }
1016     }
1017
1018   if (verbose && ! flag_javap_compatible)
1019     flag_print_constant_pool = 1;
1020
1021   if (optind == argc)
1022     {
1023       fprintf (stderr, _("jcf-dump: no classes specified\n"));
1024       usage ();
1025     }
1026
1027   jcf_path_seal (verbose);
1028
1029   if (flag_print_main)
1030     {
1031       flag_print_fields = 0;
1032       flag_print_methods = 0;
1033       flag_print_constant_pool = 0;
1034       flag_print_attributes = 0;
1035       flag_print_class_info = 0;
1036     }
1037
1038   if (output_file)
1039     {
1040       out = fopen (output_file, "w");
1041       if (! out)
1042         {
1043           fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1044           return FATAL_EXIT_CODE;
1045         }
1046     }
1047   else
1048     out = stdout;
1049
1050   if (optind >= argc)
1051     {
1052       fprintf (out, "Reading .class from <standard input>.\n");
1053       open_class ("<stdio>", jcf, 0, NULL);
1054       process_class (jcf);
1055     }
1056   else
1057     {
1058       for (argi = optind; argi < argc; argi++)
1059         {
1060           char *arg = argv[argi];
1061           const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1062           if (class_filename == NULL)
1063             class_filename = find_classfile (arg, jcf, NULL);
1064           if (class_filename == NULL)
1065             {
1066               perror ("Could not find class");
1067               return FATAL_EXIT_CODE;
1068             }
1069           JCF_FILL (jcf, 4);
1070           if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1071             {
1072               long compressed_size, member_size;
1073               int compression_method, filename_length, extra_length;
1074               int general_purpose_bits;
1075               const char *filename;
1076               int total_length;
1077               if (flag_print_class_info)
1078                 fprintf (out, "Reading classes from archive %s.\n",
1079                          class_filename);
1080               for (;;)
1081                 {
1082                   int skip = 0;
1083                   jcf_filbuf_t save_filbuf = jcf->filbuf;
1084                   long magic = JCF_readu4_le (jcf);
1085                   if (magic == 0x02014b50 || magic == 0x06054b50)
1086                     break;  /* got to central directory */
1087                   if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1088                     {
1089                       fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1090                       return FATAL_EXIT_CODE;
1091                     }
1092                   JCF_FILL (jcf, 26);
1093                   JCF_SKIP (jcf, 2);
1094                   general_purpose_bits = JCF_readu2_le (jcf);
1095                   compression_method = JCF_readu2_le (jcf);
1096                   JCF_SKIP (jcf, 8);
1097                   compressed_size = JCF_readu4_le (jcf);
1098                   member_size = JCF_readu4_le (jcf);
1099                   filename_length = JCF_readu2_le (jcf);
1100                   extra_length = JCF_readu2_le (jcf);
1101                   total_length = filename_length + extra_length
1102                     + compressed_size;
1103                   if (jcf->read_end - jcf->read_ptr < total_length)
1104                     jcf_trim_old_input (jcf);
1105                   JCF_FILL (jcf, total_length);
1106                   filename = (const char *) jcf->read_ptr;
1107                   JCF_SKIP (jcf, filename_length);
1108                   JCF_SKIP (jcf, extra_length);
1109                   if (filename_length > 0
1110                       && filename[filename_length-1] == '/')
1111                     {
1112                       if (flag_print_class_info)
1113                         fprintf (out, "[Skipping directory %.*s]\n",
1114                                  filename_length, filename);
1115                       skip = 1;
1116                     }
1117                   else if (compression_method != 0)
1118                     {
1119                       if (flag_print_class_info)
1120                         fprintf (out, "[Skipping compressed file %.*s]\n",
1121                                  filename_length, filename);
1122                       skip = 1;
1123                     }
1124                   else if (member_size < 4
1125                            || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1126                     {
1127                       if (flag_print_class_info)
1128                         fprintf (out, "[Skipping non-.class member %.*s]\n",
1129                                  filename_length, filename);
1130                       skip = 1;
1131                     }
1132                   else
1133                     {
1134                       if (flag_print_class_info)
1135                         fprintf (out, "Reading class member: %.*s.\n",
1136                                  filename_length, filename);
1137                     }
1138                   if (skip)
1139                     {
1140                       JCF_SKIP (jcf, compressed_size);
1141                     }
1142                   else
1143                     {
1144                       unsigned char *save_end;
1145                       jcf->filbuf = jcf_unexpected_eof;
1146                       save_end = jcf->read_end;
1147                       jcf->read_end = jcf->read_ptr + compressed_size;
1148                       process_class (jcf);
1149                       jcf->filbuf = save_filbuf;
1150                       jcf->read_end = save_end;
1151                     }
1152                 }
1153             }
1154           else
1155             {
1156               if (flag_print_class_info)
1157                 fprintf (out, "Reading .class from %s.\n", class_filename);
1158               process_class (jcf);
1159             }
1160           JCF_FINISH(jcf);
1161         }
1162     }
1163
1164   return SUCCESS_EXIT_CODE;
1165 }
1166
1167 \f
1168
1169 static void
1170 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1171 {
1172 #undef PTR
1173   int PC;
1174   int i;
1175   int saw_wide = 0;
1176   if (flag_disassemble_methods == 0)
1177     return;
1178 #define BCODE byte_ops
1179   for (PC = 0; PC < len;)
1180     {
1181       int oldpc = PC;
1182       int saw_index;
1183       jint INT_temp;
1184       switch (byte_ops[PC++])
1185         {
1186
1187 /* This is the actual code emitted for each of opcodes in javaops.def.
1188    The actual opcode-specific stuff is handled by the OPKIND macro.
1189    I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1190    Those macros are defined below.  The OPKINDs that do not have any
1191    inline parameters (such as BINOP) and therefore do mot need anything
1192    else to me printed out just use an empty body. */
1193
1194 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1195         case OPCODE: \
1196           fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1197           OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1198           fputc ('\n', out); \
1199           break;
1200
1201 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1202 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1203 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1204 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1205
1206 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1207   (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1208
1209 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1210    These all push a constant onto the opcode stack. */
1211 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1212   saw_index = 0, i = (OPERAND_VALUE); \
1213   if (oldpc+1 == PC) /* nothing */; \
1214   else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1215   else fprintf (out, " %d", i);
1216
1217 /* Print out operand (a local variable index) for LOAD opcodes.
1218    These all push local variable onto the opcode stack. */
1219 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1220   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1221
1222 /* Handle STORE opcodes same as LOAD opcodes.
1223    These all store a value from the opcode stack in a local variable. */
1224 #define STORE LOAD
1225
1226 /* Handle more kind of opcodes. */
1227 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1228 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1229 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1230 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1231 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1232 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1233 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1234
1235 /* Handle putfield and getfield opcodes, with static versions. */
1236 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1237   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1238
1239 /* Print operand for invoke opcodes. */
1240 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1241   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1242   if (OPERAND_VALUE) /* for invokeinterface */ \
1243   { int nargs = IMMEDIATE_u1;  PC++; \
1244     fprintf (out, " nargs:%d", nargs); }
1245
1246 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1247   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1248
1249 #define ARRAY(OPERAND_TYPE, SUBOP) \
1250   ARRAY_##SUBOP(OPERAND_TYPE)
1251 /* Handle sub-categories of ARRAY opcodes. */
1252 #define ARRAY_LOAD(TYPE) /* nothing */
1253 #define ARRAY_STORE(TYPE) /* nothing */
1254 #define ARRAY_LENGTH(TYPE) /* nothing */
1255 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1256 #define ARRAY_NEW_NUM \
1257  INT_temp = IMMEDIATE_u1; \
1258  { switch ((int) INT_temp) {  \
1259     case  4: fputs (" boolean", out); break; \
1260     case  5: fputs (" char", out); break; \
1261     case  6: fputs (" float", out); break; \
1262     case  7: fputs (" double", out); break; \
1263     case  8: fputs (" byte", out); break; \
1264     case  9: fputs (" short", out); break; \
1265     case 10: fputs (" int", out); break; \
1266     case 11: fputs (" long", out); break; \
1267     default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1268   } }
1269
1270 #define ARRAY_NEW_PTR  \
1271   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1272
1273 #define ARRAY_NEW_MULTI \
1274   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1275   fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1276
1277 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1278   fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1279
1280 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1281   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1282   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1283
1284 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1285   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1286   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1287
1288 #undef RET /* Defined by config/i386/i386.h */
1289 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1290   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1291   saw_wide = 0; \
1292   fprintf (out, " %ld", (long) INT_temp);
1293
1294 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1295   PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1296
1297 #define LOOKUP_SWITCH \
1298   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1299     fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1300     while (--npairs >= 0) { \
1301      jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1302      fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1303   }
1304
1305 #define TABLE_SWITCH \
1306   { jint default_offset = IMMEDIATE_s4; \
1307     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1308     fprintf (out, " low=%ld, high=%ld, default=%ld", \
1309       (long) low, (long) high, (long) default_offset+oldpc); \
1310     for (; low <= high; low++) { \
1311      jint offset = IMMEDIATE_s4; \
1312      fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1313   }
1314
1315 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1316   SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1317
1318 #define SPECIAL_IINC(OPERAND_TYPE) \
1319   i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1320   fprintf (out, " %d", i); \
1321   i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1322   saw_wide = 0; \
1323   fprintf (out, " %d", i)
1324
1325 #define SPECIAL_WIDE(OPERAND_TYPE) \
1326   saw_wide = 1;
1327
1328 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1329 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1330 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1331 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1332
1333 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1334   fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1335
1336 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1337    TEST(OPERAND_TYPE, OPERAND_VALUE)
1338
1339 #include "javaop.def"
1340
1341         load_store:
1342           if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1343           else
1344             {
1345               saw_wide = 0;
1346               fprintf (out, " %ld", (long) INT_temp);
1347             }
1348           fputc ('\n', out);
1349           break;
1350
1351         default:
1352           fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1353         }
1354     }
1355 }