OSDN Git Service

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