OSDN Git Service

* java-tree.h, class.c, expr.c, jcf-parse.c, parse.y,
[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 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  
20
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
24
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
26
27 /*
28   jcf-dump is a program to print out the contents of class files.
29   Usage:  jcf-dump [FLAGS] CLASS
30   Each CLASS is either:
31   + the name of a class in the CLASSPATH (e.g "java.lang.String"), or
32   + the name of a class *file* (e.g. "/home/me/work/package/Foo.class").
33   + The name of a .zip or .jar file (which prints all the classes in the
34   archive).
35
36   OPTIONS:
37   -c
38         Dis-assemble each method.
39   -classpath PATH
40         Overrides $CLASSPATH.
41   --print-main
42         Print nothing if there is no valid "main" method;
43         otherwise, print only the class name.
44   --javap
45         Print output in the style of Sun's javap program.  VERY UNFINISHED.
46  */
47     
48
49 #include "config.h"
50 #include "system.h"
51
52 #include "jcf.h"
53 #include "tree.h"
54 #include "java-tree.h"
55
56 #include "version.h"
57
58 #include <getopt.h>
59
60 /* Outout file. */
61 FILE *out;
62 /* Name of output file, if NULL if stdout. */
63 char *output_file = NULL;
64
65 int verbose = 0;
66
67 int flag_disassemble_methods = 0;
68 int flag_print_class_info = 1;
69 int flag_print_constant_pool = 1;
70 int flag_print_fields = 1;
71 int flag_print_methods = 1;
72 int flag_print_attributes = 1;
73
74 /* When non zero, warn when source file is newer than matching class
75    file.  */
76 int flag_newer = 1;
77
78 /* Print names of classes that have a "main" method. */
79 int flag_print_main = 0;
80
81 /* Index in constant pool of this class. */
82 int this_class_index = 0;
83
84 int class_access_flags = 0;
85
86 /* Print in format similar to javap.  VERY IMCOMPLETE. */
87 int flag_javap_compatible = 0;
88
89 static void print_access_flags PARAMS ((FILE *, uint16, char));
90 static void print_constant_terse PARAMS ((FILE*, JCF*, int, int));
91 static void print_constant PARAMS ((FILE *, JCF *, int, int));
92 static void print_constant_ref PARAMS ((FILE *, JCF *, int));
93 static void disassemble_method PARAMS ((JCF*, const unsigned char *, int));
94 static void print_name PARAMS ((FILE*, JCF*, int));
95 static void print_signature PARAMS ((FILE*, JCF*, int, int));
96 static int utf8_equal_string PARAMS ((struct JCF*, int, const char *));
97 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
98 static void help PARAMS ((void)) ATTRIBUTE_NORETURN;
99 static void version PARAMS ((void)) ATTRIBUTE_NORETURN;
100 static void process_class PARAMS ((struct JCF *));
101 static void print_constant_pool PARAMS ((struct JCF *));
102 static void print_exception_table PARAMS ((struct JCF *,
103                                           const unsigned char *entries, int));
104
105 #define PRINT_SIGNATURE_RESULT_ONLY 1
106 #define PRINT_SIGNATURE_ARGS_ONLY 2
107
108 static int
109 DEFUN(utf8_equal_string, (jcf, index, value),
110       JCF *jcf AND int index AND const char * value)
111 {
112   if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index)
113       && JPOOL_TAG (jcf, index) == CONSTANT_Utf8)
114     {
115       int len = strlen (value);
116       if (JPOOL_UTF_LENGTH (jcf, index) == len
117           && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0)
118         return 1;
119     }
120   return 0;
121 }
122
123 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
124   this_class_index = 0; \
125   if (flag_print_class_info) \
126     fprintf (out, \
127              "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
128              (long) MAGIC, (long) MINOR, (long) MAJOR)
129
130 #define HANDLE_START_CONSTANT_POOL(COUNT) \
131   if (flag_print_constant_pool) \
132     fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
133
134 #define HANDLE_SOURCEFILE(INDEX) \
135 { fprintf (out, "Attribute "); \
136   print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
137   fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
138   print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
139
140 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
141   this_class_index = THIS; \
142   class_access_flags = ACCESS_FLAGS; \
143   if (flag_print_class_info) \
144     { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
145       print_access_flags (out, ACCESS_FLAGS, 'c'); \
146       fputc ('\n', out); \
147       fprintf (out, "This class: "); \
148       if (flag_print_constant_pool) \
149         fprintf (out, "%d=", THIS); \
150       print_constant_terse (out, jcf, THIS, CONSTANT_Class); \
151       if (flag_print_constant_pool || SUPER != 0) \
152         fprintf (out, ", super: "); \
153       if (flag_print_constant_pool) \
154         { \
155           fprintf (out, "%d", SUPER); \
156           if (SUPER != 0) \
157             fputc ('=', out); \
158         } \
159       if (SUPER != 0) \
160         print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
161       fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
162     }
163
164 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
165   (flag_print_attributes <= 0)
166
167 #define HANDLE_CLASS_INTERFACE(INDEX) \
168   if (flag_print_class_info) \
169     { fprintf (out, "- Implements: %d=", INDEX); \
170       print_constant_terse (out, jcf, INDEX, CONSTANT_Class); \
171       fputc ('\n', out); }
172
173 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
174   if (flag_print_fields) \
175     fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
176
177 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
178   if (flag_print_fields) \
179     { fprintf (out, "Field name:"); \
180       print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
181       print_access_flags (out, ACCESS_FLAGS, 'f'); \
182       fprintf (out, " Signature: "); \
183       if (flag_print_constant_pool) \
184         fprintf (out, "%d=", SIGNATURE); \
185       print_signature (out, jcf, SIGNATURE, 0); \
186       fputc ('\n', out); } \
187   else \
188     flag_print_attributes--;
189
190 #define HANDLE_END_FIELD() \
191   if (! flag_print_fields) \
192     flag_print_attributes++;
193
194 #define HANDLE_START_METHODS(METHODS_COUNT) \
195   if (flag_print_methods) \
196     fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
197   else \
198     flag_print_attributes--;
199
200
201 #define HANDLE_END_METHODS() \
202   if (! flag_print_methods) \
203     flag_print_attributes++;
204
205 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
206 { \
207   if (flag_print_methods) \
208     { \
209       if (flag_javap_compatible) \
210         { \
211           fprintf (out, "    "); \
212           print_access_flags (out, ACCESS_FLAGS, 'm'); \
213           fputc (' ', out); \
214           print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
215           fputc (' ', out); \
216           print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
217           print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
218           fputc ('\n', out); \
219         } \
220       else \
221         { \
222           fprintf (out, "\nMethod name:"); \
223           print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
224           print_access_flags (out, ACCESS_FLAGS, 'm'); \
225           fprintf (out, " Signature: "); \
226           if (flag_print_constant_pool) \
227             fprintf (out, "%d=", SIGNATURE); \
228           print_signature (out, jcf, SIGNATURE, 0); \
229           fputc ('\n', out); \
230         } \
231     } \
232   if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
233       && utf8_equal_string (jcf, NAME, "main") \
234       && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
235       && this_class_index > 0 \
236       && (class_access_flags & ACC_PUBLIC)) \
237     { \
238       print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
239       fputc  ('\n', out); \
240    } \
241 }
242
243 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
244 ( fprintf (out, "Attribute "), \
245   print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
246   fprintf (out, ", length:%ld", (long) LENGTH) )
247
248 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
249 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
250   fprintf (out, ", value: "), \
251   print_constant_ref (out, jcf, VALUE_INDEX), \
252   fprintf (out, "\n") )
253
254 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
255 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
256   fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
257     (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
258   disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
259
260 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
261   print_exception_table (jcf, ENTRIES, COUNT)
262
263 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
264 { int n = (COUNT); int i; \
265   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
266   fprintf (out, ", count: %d\n", n); \
267   for (i = 0; i < n; i++) {\
268     int ex_index = JCF_readu2 (jcf); \
269     fprintf (out, "%3d: ", i); \
270     print_constant_ref (out, jcf, ex_index); \
271     fputc ('\n', out); } }
272
273 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
274 { int n = (COUNT); int i; \
275   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
276   fprintf (out, ", count: %d\n", n); \
277   for (i = 0; i < n; i++) {\
278     int start_pc = JCF_readu2 (jcf); \
279     int length = JCF_readu2 (jcf); \
280     int name_index = JCF_readu2 (jcf); \
281     int signature_index = JCF_readu2 (jcf); \
282     int slot = JCF_readu2 (jcf); \
283     fprintf (out, "  slot#%d: name: %d=", slot, name_index); \
284     print_name (out, jcf, name_index); \
285     fprintf (out, ", type: %d=", signature_index); \
286     print_signature (out, jcf, signature_index, 0); \
287     fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
288
289 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
290 { int n = (COUNT); int i; \
291   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
292   fprintf (out, ", count: %d\n", n); \
293   if (flag_disassemble_methods) \
294     for (i = 0; i < n; i++) {\
295       int start_pc = JCF_readu2 (jcf); \
296       int line_number = JCF_readu2 (jcf); \
297       fprintf (out, "  line: %d at pc: %d\n", line_number, start_pc); }\
298   else \
299     JCF_SKIP (jcf, 4 * n); }
300
301 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT)                                \
302 { int n = (COUNT);                                                          \
303   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);           \
304   while (n--)                                                               \
305     {                                                                       \
306       uint16 inner_class_info_index = JCF_readu2 (jcf);                     \
307       uint16 outer_class_info_index = JCF_readu2 (jcf);                     \
308       uint16 inner_name_index = JCF_readu2 (jcf);                           \
309       uint16 inner_class_access_flags = JCF_readu2 (jcf);                   \
310                                                                             \
311       if (flag_print_class_info)                                            \
312         {                                                                   \
313           fprintf (out, "\n  class: ");                                     \
314           if (flag_print_constant_pool)                                     \
315             fprintf (out, "%d=", inner_class_info_index);                   \
316           print_constant_terse (out, jcf,                                   \
317                                 inner_class_info_index, CONSTANT_Class);    \
318           fprintf (out, " (%d=", inner_name_index);                         \
319           print_constant_terse (out, jcf, inner_name_index, CONSTANT_Utf8); \
320           fprintf (out, "), access flags: 0x%x", inner_class_access_flags); \
321           print_access_flags (out, inner_class_access_flags, 'c');          \
322           fprintf (out, ", outer class: ");                                 \
323           if (flag_print_constant_pool)                                     \
324             fprintf (out, "%d=", outer_class_info_index);                   \
325           print_constant_terse (out, jcf,                                   \
326                                 outer_class_info_index, CONSTANT_Class);    \
327         }                                                                   \
328     }                                                                       \
329       if (flag_print_class_info)                                            \
330         fputc ('\n', out);                                                  \
331 }
332
333 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
334 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
335   fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
336
337 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
338   if (flag_print_attributes > 0) \
339     fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
340
341 #include "javaop.h"
342
343 static void
344 DEFUN(print_constant_ref, (stream, jcf, index),
345       FILE *stream AND JCF *jcf AND int index)
346 {
347   fprintf (stream, "#%d=<", index);
348   if (index <= 0 || index >= JPOOL_SIZE(jcf))
349     fprintf (stream, "out of range");
350   else
351     print_constant (stream, jcf, index, 1);
352   fprintf (stream, ">");
353 }
354
355 /* Print the access flags given by FLAGS.
356    The CONTEXT is one of 'c' (class flags), 'f' (field flags),
357    or 'm' (method flags). */
358
359 static void
360 DEFUN (print_access_flags, (stream, flags, context),
361        FILE *stream AND uint16 flags AND char context)
362 {
363   if (flags & ACC_PUBLIC) fprintf (stream, " public");
364   if (flags & ACC_PRIVATE) fprintf (stream, " private");
365   if (flags & ACC_PROTECTED) fprintf (stream, " protected");
366   if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
367   if (flags & ACC_STATIC) fprintf (stream, " static");
368   if (flags & ACC_FINAL) fprintf (stream, " final");
369   if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
370   if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
371   if (flags & ACC_NATIVE) fprintf (stream, " native");
372   if (flags & ACC_SYNCHRONIZED)
373     {
374       if (context == 'c')
375         fprintf (stream, " super");
376       else
377         fprintf (stream, " synchronized");
378     }
379   if (flags & ACC_INTERFACE) fprintf (stream, " interface");
380   if (flags & ACC_STRICT) fprintf (stream, " strictfp");
381 }
382
383
384 static void
385 DEFUN(print_name, (stream, jcf, name_index),
386       FILE* stream AND JCF* jcf AND int name_index)
387 {
388   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
389     fprintf (stream, "<not a UTF8 constant>");
390   else
391     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
392                     JPOOL_UTF_LENGTH (jcf, name_index));
393 }
394
395 /* If the type of the constant at INDEX matches EXPECTED,
396    print it tersely, otherwise more verbosely. */
397
398 static void
399 DEFUN(print_constant_terse, (out, jcf, index, expected),
400       FILE *out AND JCF *jcf AND int index AND 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 DEFUN(print_constant, (out, jcf, index, verbosity),
421       FILE *out AND JCF *jcf AND int index AND int verbosity)
422 {
423   int j, n;
424   jlong num;
425   const char *str;
426   int kind = JPOOL_TAG (jcf, index);
427   switch (kind)
428     {
429     case CONSTANT_Class:
430       n = JPOOL_USHORT1 (jcf, index);
431       if (verbosity > 0)
432         {
433           if (verbosity > 1)
434             fprintf (out, "Class name: %d=", n);
435           else
436             fprintf (out, "Class ");
437         }
438       if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
439         fprintf (out, "<out of range>");
440       else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
441         {
442           int len = JPOOL_UTF_LENGTH (jcf, n);
443           jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
444         }
445       else
446         print_constant_terse (out, jcf, n, CONSTANT_Utf8);
447       break;
448     case CONSTANT_Fieldref:
449       str = "Field"; goto field_or_method;
450     case CONSTANT_Methodref:
451       str = "Method"; goto field_or_method;
452     case CONSTANT_InterfaceMethodref:
453       str = "InterfaceMethod"; goto field_or_method;
454     field_or_method:
455       {
456         uint16 tclass = JPOOL_USHORT1 (jcf, index);
457         uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
458         if (verbosity == 2)
459           fprintf (out, "%sref class: %d=", str, tclass);
460         else if (verbosity > 0)
461             fprintf (out, "%s ", str);
462         print_constant_terse (out, jcf, tclass, CONSTANT_Class);
463         if (verbosity < 2)
464           fprintf (out, ".");
465         else
466           fprintf (out, " name_and_type: %d=<", name_and_type);
467         print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
468         if (verbosity == 2)
469           fputc ('>', out);
470       }
471       break;
472     case CONSTANT_String:
473       j = JPOOL_USHORT1 (jcf, index);
474       if (verbosity > 0)
475         {
476           if (verbosity > 1)
477             fprintf (out, "String %d=", j);
478           else
479             fprintf (out, "String ");
480         }
481       print_constant_terse (out, jcf, j, CONSTANT_Utf8);
482       break;
483     case CONSTANT_Integer:
484       if (verbosity > 0)
485         fprintf (out, "Integer ");
486       num = JPOOL_INT (jcf, index);
487       goto integer;
488     case CONSTANT_Long:
489       if (verbosity > 0)
490         fprintf (out, "Long ");
491       num = JPOOL_LONG (jcf, index);
492       goto integer;
493     integer:
494       {
495         char buffer[25];
496         format_int (buffer, num, 10);
497         fprintf (out, "%s", buffer);
498         if (verbosity > 1)
499           {
500             format_uint (buffer, (uint64)num, 16);
501             fprintf (out, "=0x%s", buffer);
502           }
503       }
504       break;
505     case CONSTANT_Float:
506       {
507         jfloat fnum = JPOOL_FLOAT (jcf, index);
508         fprintf (out, "%s%.10g", verbosity > 0 ? "Float " : "", (double) fnum);
509         if (verbosity > 1)
510           fprintf (out, ", bits = 0x%08lx", (long) (* (int32 *) &fnum));
511         break;
512       }
513     case CONSTANT_Double:
514       {
515         jdouble dnum = JPOOL_DOUBLE (jcf, index);
516         fprintf (out, "%s%.20g", verbosity > 0 ? "Double " : "", dnum);
517         if (verbosity > 1)
518           {
519             int32 hi, lo;
520             hi = JPOOL_UINT (jcf, index);
521             lo = JPOOL_UINT (jcf, index + 1);
522             fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
523           }
524         break;
525       }
526     case CONSTANT_NameAndType:
527       {
528         uint16 name = JPOOL_USHORT1 (jcf, index);
529         uint16 sig = JPOOL_USHORT2 (jcf, index);
530         if (verbosity > 0)
531           {
532             if (verbosity > 1)
533               fprintf (out, "NameAndType name: %d=", name);
534             else
535               fprintf (out, "NameAndType ");
536           }
537         print_name (out, jcf, name);
538         if (verbosity <= 1)
539           fputc (' ', out);
540         else
541           fprintf (out, ", signature: %d=", sig);
542         print_signature (out, jcf, sig, 0);
543       }
544       break;
545     case CONSTANT_Utf8:
546       {
547         register const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
548         int length = JPOOL_UTF_LENGTH (jcf, index);
549         if (verbosity > 0)
550           { /* Print as 8-bit bytes. */
551             fputs ("Utf8: \"", out);
552             while (--length >= 0)
553               jcf_print_char (out, *str++);
554           }
555         else
556           { /* Print as Unicode. */
557             fputc ('\"', out);
558             jcf_print_utf8 (out, str, length);
559           }
560         fputc ('\"', out);
561       }
562       break;
563     default:
564       fprintf (out, "(Unknown constant type %d)", kind);
565     }
566 }
567
568 static void
569 DEFUN(print_constant_pool, (jcf),
570       JCF *jcf)
571 {
572   int i;
573   for (i = 1; i < JPOOL_SIZE(jcf); i++)
574     {
575       int kind = JPOOL_TAG (jcf, i);
576       fprintf (out, "#%d: ", i);
577       print_constant (out, jcf, i, 2);
578       fprintf (out, "\n");
579       if (kind == CONSTANT_Double || kind == CONSTANT_Long)
580         i++; /* These take up two slots in the constant table */
581     }
582 }
583
584 static void
585 DEFUN(print_signature_type, (stream, ptr, limit),
586      FILE* stream AND const unsigned char **ptr AND const unsigned char *limit)
587 {
588   int array_size;
589   if ((*ptr) >= limit)
590     return;
591   switch (*(*ptr))
592     {
593     case '[':
594       array_size = -1;
595       for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
596         {
597           array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
598         }
599       print_signature_type (stream, ptr, limit);
600       if (array_size == -1)
601         fprintf (stream, "[]");
602       else
603         fprintf (stream, "[%d]", array_size);
604       break;
605     case '(':
606       {
607         int nargs = 0;
608         fputc (*(*ptr)++, stream);
609         for (; **ptr != ')' && *ptr < limit; nargs++)
610           {
611             if (nargs > 0)
612               fputc (',', stream);
613             print_signature_type (stream, ptr, limit);
614           }
615         if (*ptr < limit)
616           {
617             fputc (*(*ptr)++, stream);
618             print_signature_type (stream, ptr, limit);
619           }
620         else
621           fprintf (stream, "???");
622       }
623     break;
624       
625     case 'B':  fprintf (stream, "byte");  (*ptr)++;  break;
626     case 'C':  fprintf (stream, "char");  (*ptr)++;  break;
627     case 'D':  fprintf (stream, "double");  (*ptr)++;  break;
628     case 'F':  fprintf (stream, "float");  (*ptr)++;  break;
629     case 'S':  fprintf (stream, "short");  (*ptr)++;  break;
630     case 'I':  fprintf (stream, "int");  (*ptr)++;  break;
631     case 'J':  fprintf (stream, "long");  (*ptr)++;  break;
632     case 'Z':  fprintf (stream, "boolean");  (*ptr)++;  break;
633     case 'V':  fprintf (stream, "void");  (*ptr)++;  break;
634
635     case 'L':
636       for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
637         jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
638       if (*(*ptr) == ';')
639         (*ptr)++;
640       break;
641     default:
642       jcf_print_char (stream, *(*ptr)++);
643     }
644 }
645
646 static void
647 DEFUN(print_signature, (stream, jcf, signature_index, int options),
648       FILE* stream AND JCF *jcf AND int signature_index AND int options)
649 {
650   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
651     print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
652   else
653     {
654       const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
655       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
656       const unsigned char *limit;
657       limit = str + length;
658       if (str >= limit)
659         fprintf (stream, "<empty signature string>");
660       else
661         {
662           if (options & PRINT_SIGNATURE_RESULT_ONLY)
663             {
664               while (str < limit && *str++ != ')') ;
665             }
666           if (options & PRINT_SIGNATURE_ARGS_ONLY)
667             {
668               str++;
669               fputc ('(', stream);
670               while (str < limit && *str != ')')
671                 {
672                   print_signature_type (stream, &str, limit);
673                   if (*str != ')')
674                     fputs (", ", stream);
675                 }
676               fputc (')', stream);
677             }
678           else
679             {
680               print_signature_type (stream, &str, limit);
681               if (str < limit)
682                 {
683                   fprintf (stream, "<junk:");
684                   jcf_print_utf8 (stream, str, limit - str);
685                   fputc ('>', stream);
686                 }
687             }
688         }
689     }
690 }
691
692
693 static void
694 DEFUN(print_exception_table, (jcf, entries, count),
695       JCF *jcf AND const unsigned char *entries AND int count)
696 {
697   /* Print exception table. */
698   int i = count;
699   if (i > 0)
700     {
701       const unsigned char *ptr = entries;
702       fprintf (out, "Exceptions (count: %d):\n", i);
703       for (; --i >= 0;  ptr+= 8)
704         {
705           int start_pc = GET_u2 (ptr);
706           int end_pc = GET_u2 (ptr+2);
707           int handler_pc = GET_u2 (ptr+4);
708           int catch_type = GET_u2 (ptr+6);
709           fprintf (out, "  start: %d, end: %d, handler: %d, type: %d",
710                    start_pc, end_pc, handler_pc, catch_type);
711           if (catch_type == 0)
712             fputs (" /* finally */", out);
713           else
714             {
715               fputc('=', out);
716               print_constant_terse (out, jcf, catch_type, CONSTANT_Class);
717             }
718           fputc ('\n', out);
719         }
720     }
721 }
722
723 #include "jcf-reader.c"
724
725 static void
726 DEFUN(process_class, (jcf),
727       JCF *jcf)
728 {
729   int code;
730   if (jcf_parse_preamble (jcf) != 0)
731     fprintf (stderr, "Not a valid Java .class file.\n");    
732
733   /* Parse and possibly print constant pool */
734   code = jcf_parse_constant_pool (jcf);
735   if (code != 0)
736     {
737       fprintf (stderr, "error while parsing constant pool\n");
738       exit (FATAL_EXIT_CODE);
739     }
740   code = verify_constant_pool (jcf);
741   if (code > 0)
742     {
743       fprintf (stderr, "error in constant pool entry #%d\n", code);
744       exit (FATAL_EXIT_CODE);
745     }
746   if (flag_print_constant_pool)
747     print_constant_pool (jcf);
748
749   jcf_parse_class (jcf);
750   code = jcf_parse_fields (jcf);
751   if (code != 0)
752     {
753       fprintf (stderr, "error while parsing fields\n");
754       exit (FATAL_EXIT_CODE);
755     }
756   code = jcf_parse_methods (jcf);
757   if (code != 0)
758     {
759       fprintf (stderr, "error while parsing methods\n");
760       exit (FATAL_EXIT_CODE);
761     }
762   code = jcf_parse_final_attributes (jcf);
763   if (code != 0)
764     {
765       fprintf (stderr, "error while parsing final attributes\n");
766       exit (FATAL_EXIT_CODE);
767     }
768   jcf->filename = NULL;
769 }
770
771 \f
772
773 /* This is used to mark options with no short value.  */
774 #define LONG_OPT(Num)  ((Num) + 128)
775
776 #define OPT_classpath     LONG_OPT (0)
777 #define OPT_CLASSPATH     OPT_classpath
778 #define OPT_bootclasspath LONG_OPT (1)
779 #define OPT_extdirs       LONG_OPT (2)
780 #define OPT_HELP          LONG_OPT (3)
781 #define OPT_VERSION       LONG_OPT (4)
782 #define OPT_JAVAP         LONG_OPT (5)
783
784 static const struct option options[] =
785 {
786   { "classpath",     required_argument, NULL, OPT_classpath },
787   { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
788   { "extdirs",       required_argument, NULL, OPT_extdirs },
789   { "CLASSPATH",     required_argument, NULL, OPT_CLASSPATH },
790   { "help",          no_argument,       NULL, OPT_HELP },
791   { "verbose",       no_argument,       NULL, 'v' },
792   { "version",       no_argument,       NULL, OPT_VERSION },
793   { "javap",         no_argument,       NULL, OPT_JAVAP },
794   { "print-main",    no_argument,      &flag_print_main, 1 },
795   { NULL,            no_argument,       NULL, 0 }
796 };
797
798 static void
799 usage ()
800 {
801   fprintf (stderr, "Try `jcf-dump --help' for more information.\n");
802   exit (1);
803 }
804
805 static void
806 help ()
807 {
808   printf ("Usage: jcf-dump [OPTION]... CLASS...\n\n");
809   printf ("Display contents of a class file in readable form.\n\n");
810   printf ("  -c                      Disassemble method bodies\n");
811   printf ("  --javap                 Generate output in `javap' format\n");
812   printf ("\n");
813   printf ("  --classpath PATH        Set path to find .class files\n");
814   printf ("  -IDIR                   Append directory to class path\n");
815   printf ("  --bootclasspath PATH    Override built-in class path\n");
816   printf ("  --extdirs PATH          Set extensions directory path\n");
817   printf ("  -o FILE                 Set output file name\n");
818   printf ("\n");
819   printf ("  --help                  Print this help, then exit\n");
820   printf ("  --version               Print version number, then exit\n");
821   printf ("  -v, --verbose           Print extra information while running\n");
822   printf ("\n");
823   printf ("For bug reporting instructions, please see:\n");
824   printf ("%s.\n", GCCBUGURL);
825   exit (0);
826 }
827
828 static void
829 version ()
830 {
831   printf ("jcf-dump (GCC) %s\n\n", version_string);
832   printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
833   printf ("This is free software; see the source for copying conditions.  There is NO\n");
834   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
835   exit (0);
836 }
837
838 int
839 DEFUN(main, (argc, argv),
840       int argc AND char** argv)
841 {
842   JCF jcf[1];
843   int argi, opt;
844
845   if (argc <= 1)
846     {
847       fprintf (stderr, "jcf-dump: no classes specified\n");
848       usage ();
849     }
850
851   jcf_path_init ();
852
853   /* We use getopt_long_only to allow single `-' long options.  For
854      some of our options this is more natural.  */
855   while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
856     {
857       switch (opt)
858         {
859         case 0:
860           /* Already handled.  */
861           break;
862
863         case 'o':
864           output_file = optarg;
865           break;
866
867         case 'I':
868           jcf_path_include_arg (optarg);
869           break;
870
871         case 'v':
872           verbose++;
873           break;
874
875         case 'c':
876           flag_disassemble_methods = 1;
877           break;
878
879         case OPT_classpath:
880           jcf_path_classpath_arg (optarg);
881           break;
882
883         case OPT_bootclasspath:
884           jcf_path_bootclasspath_arg (optarg);
885           break;
886
887         case OPT_extdirs:
888           jcf_path_extdirs_arg (optarg);
889           break;
890
891         case OPT_HELP:
892           help ();
893           break;
894
895         case OPT_VERSION:
896           version ();
897           break;
898
899         case OPT_JAVAP:
900           flag_javap_compatible++;
901           flag_print_constant_pool = 0;
902           flag_print_attributes = 0;
903           break;
904
905         default:
906           usage ();
907         }
908     }
909
910   if (optind == argc)
911     {
912       fprintf (stderr, "jcf-dump: no classes specified\n");
913       usage ();
914     }
915
916   jcf_path_seal (verbose);
917
918   if (flag_print_main)
919     {
920       flag_print_fields = 0;
921       flag_print_methods = 0;
922       flag_print_constant_pool = 0;
923       flag_print_attributes = 0;
924       flag_print_class_info = 0;
925     }
926
927   if (output_file)
928     {
929       out = fopen (output_file, "w");
930       if (! out)
931         {
932           fprintf (stderr, "Cannot open '%s' for output.\n", output_file);
933           return FATAL_EXIT_CODE;
934         }
935     }
936   else
937     out = stdout;
938
939   if (optind >= argc)
940     {
941       fprintf (out, "Reading .class from <standard input>.\n");
942       open_class ("<stdio>", jcf, 0, NULL);
943       process_class (jcf);
944     }
945   else
946     {
947       for (argi = optind; argi < argc; argi++)
948         {
949           char *arg = argv[argi];
950           const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
951           if (class_filename == NULL)
952             class_filename = find_classfile (arg, jcf, NULL);
953           if (class_filename == NULL)
954             {
955               perror ("Could not find class");
956               return FATAL_EXIT_CODE;
957             }
958           JCF_FILL (jcf, 4);
959           if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
960             {
961               long compressed_size, member_size;
962               int compression_method, filename_length, extra_length;
963               int general_purpose_bits;
964               const char *filename;
965               int total_length;
966               if (flag_print_class_info)
967                 fprintf (out, "Reading classes from archive %s.\n",
968                          class_filename);
969               for (;;)
970                 {
971                   int skip = 0;
972                   jcf_filbuf_t save_filbuf = jcf->filbuf;
973                   long magic = JCF_readu4_le (jcf);
974                   if (magic == 0x02014b50 || magic == 0x06054b50)
975                     break;  /* got to central directory */
976                   if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
977                     {
978                       fprintf (stderr, "bad format of .zip/.jar archive\n");
979                       return FATAL_EXIT_CODE;
980                     }
981                   JCF_FILL (jcf, 26);
982                   JCF_SKIP (jcf, 2);
983                   general_purpose_bits = JCF_readu2_le (jcf);
984                   compression_method = JCF_readu2_le (jcf);
985                   JCF_SKIP (jcf, 8);
986                   compressed_size = JCF_readu4_le (jcf);
987                   member_size = JCF_readu4_le (jcf);
988                   filename_length = JCF_readu2_le (jcf);
989                   extra_length = JCF_readu2_le (jcf);
990                   total_length = filename_length + extra_length
991                     + compressed_size;
992                   if (jcf->read_end - jcf->read_ptr < total_length)
993                     jcf_trim_old_input (jcf);
994                   JCF_FILL (jcf, total_length);
995                   filename = jcf->read_ptr;
996                   JCF_SKIP (jcf, filename_length);
997                   JCF_SKIP (jcf, extra_length);
998                   if (filename_length > 0
999                       && filename[filename_length-1] == '/')
1000                     {
1001                       if (flag_print_class_info)
1002                         fprintf (out, "[Skipping directory %.*s]\n",
1003                                  filename_length, filename);
1004                       skip = 1;
1005                     }
1006                   else if (compression_method != 0)
1007                     {
1008                       if (flag_print_class_info)
1009                         fprintf (out, "[Skipping compressed file %.*s]\n",
1010                                  filename_length, filename);
1011                       skip = 1;
1012                     }
1013                   else if (member_size < 4
1014                            || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1015                     {
1016                       if (flag_print_class_info)
1017                         fprintf (out, "[Skipping non-.class member %.*s]\n",
1018                                  filename_length, filename);
1019                       skip = 1;
1020                     }
1021                   else
1022                     {
1023                       if (flag_print_class_info)
1024                         fprintf (out, "Reading class member: %.*s.\n",
1025                                  filename_length, filename);
1026                     }
1027                   if (skip)
1028                     {
1029                       JCF_SKIP (jcf, compressed_size);
1030                     }
1031                   else
1032                     {
1033                       unsigned char *save_end;
1034                       jcf->filbuf = jcf_unexpected_eof;
1035                       save_end = jcf->read_end;
1036                       jcf->read_end = jcf->read_ptr + compressed_size;
1037                       process_class (jcf);
1038                       jcf->filbuf = save_filbuf;
1039                       jcf->read_end = save_end;
1040                     }
1041                 }
1042             }
1043           else
1044             {
1045               if (flag_print_class_info)
1046                 fprintf (out, "Reading .class from %s.\n", class_filename);
1047               process_class (jcf);
1048             }
1049           JCF_FINISH(jcf);
1050         }
1051     }
1052
1053   return SUCCESS_EXIT_CODE;
1054 }
1055
1056 \f
1057
1058 static void
1059 DEFUN(disassemble_method, (jcf, byte_ops, len),
1060       JCF* jcf AND const unsigned char *byte_ops AND int len)
1061 {
1062 #undef AND /* Causes problems with opcodes for iand and land. */
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 }