OSDN Git Service

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