OSDN Git Service

* java-tree.h (TYPE_STRICTFP): New macro.
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-dump.c
1 /* Program to dump out a Java(TM) .class file.
2    Functionally similar to Sun's javap.
3
4    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 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 LONG_OPT (1)
778 #define OPT_HELP      LONG_OPT (2)
779 #define OPT_VERSION   LONG_OPT (3)
780 #define OPT_JAVAP     LONG_OPT (4)
781
782 static const struct option options[] =
783 {
784   { "classpath", required_argument, NULL, OPT_classpath },
785   { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
786   { "help",      no_argument,       NULL, OPT_HELP },
787   { "verbose",   no_argument,       NULL, 'v' },
788   { "version",   no_argument,       NULL, OPT_VERSION },
789   { "javap",     no_argument,       NULL, OPT_JAVAP },
790   { "print-main", no_argument,      &flag_print_main, 1 },
791   { NULL,        no_argument,       NULL, 0 }
792 };
793
794 static void
795 usage ()
796 {
797   fprintf (stderr, "Try `jcf-dump --help' for more information.\n");
798   exit (1);
799 }
800
801 static void
802 help ()
803 {
804   printf ("Usage: jcf-dump [OPTION]... CLASS...\n\n");
805   printf ("Display contents of a class file in readable form.\n\n");
806   printf ("  -c                      Disassemble method bodies\n");
807   printf ("  --javap                 Generate output in `javap' format\n");
808   printf ("\n");
809   printf ("  --classpath PATH        Set path to find .class files\n");
810   printf ("  --CLASSPATH PATH        Set path to find .class files\n");
811   printf ("  -IDIR                   Append directory to class path\n");
812   printf ("  -o FILE                 Set output file name\n");
813   printf ("\n");
814   printf ("  --help                  Print this help, then exit\n");
815   printf ("  --version               Print version number, then exit\n");
816   printf ("  -v, --verbose           Print extra information while running\n");
817   printf ("\n");
818   printf ("For bug reporting instructions, please see:\n");
819   printf ("%s.\n", GCCBUGURL);
820   exit (0);
821 }
822
823 static void
824 version ()
825 {
826   printf ("jcf-dump (GCC) %s\n\n", version_string);
827   printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
828   printf ("This is free software; see the source for copying conditions.  There is NO\n");
829   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
830   exit (0);
831 }
832
833 int
834 DEFUN(main, (argc, argv),
835       int argc AND char** argv)
836 {
837   JCF jcf[1];
838   int argi, opt;
839
840   if (argc <= 1)
841     {
842       fprintf (stderr, "jcf-dump: no classes specified\n");
843       usage ();
844     }
845
846   jcf_path_init ();
847
848   /* We use getopt_long_only to allow single `-' long options.  For
849      some of our options this is more natural.  */
850   while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
851     {
852       switch (opt)
853         {
854         case 0:
855           /* Already handled.  */
856           break;
857
858         case 'o':
859           output_file = optarg;
860           break;
861
862         case 'I':
863           jcf_path_include_arg (optarg);
864           break;
865
866         case 'v':
867           verbose++;
868           break;
869
870         case 'c':
871           flag_disassemble_methods = 1;
872           break;
873
874         case OPT_classpath:
875           jcf_path_classpath_arg (optarg);
876           break;
877
878         case OPT_CLASSPATH:
879           jcf_path_CLASSPATH_arg (optarg);
880           break;
881
882         case OPT_HELP:
883           help ();
884           break;
885
886         case OPT_VERSION:
887           version ();
888           break;
889
890         case OPT_JAVAP:
891           flag_javap_compatible++;
892           flag_print_constant_pool = 0;
893           flag_print_attributes = 0;
894           break;
895
896         default:
897           usage ();
898         }
899     }
900
901   if (optind == argc)
902     {
903       fprintf (stderr, "jcf-dump: no classes specified\n");
904       usage ();
905     }
906
907   jcf_path_seal (verbose);
908
909   if (flag_print_main)
910     {
911       flag_print_fields = 0;
912       flag_print_methods = 0;
913       flag_print_constant_pool = 0;
914       flag_print_attributes = 0;
915       flag_print_class_info = 0;
916     }
917
918   if (output_file)
919     {
920       out = fopen (output_file, "w");
921       if (! out)
922         {
923           fprintf (stderr, "Cannot open '%s' for output.\n", output_file);
924           return FATAL_EXIT_CODE;
925         }
926     }
927   else
928     out = stdout;
929
930   if (optind >= argc)
931     {
932       fprintf (out, "Reading .class from <standard input>.\n");
933 #if JCF_USE_STDIO
934       open_class ("<stdio>", jcf, stdin, NULL);
935 #else
936       open_class ("<stdio>", jcf, 0, NULL);
937 #endif
938       process_class (jcf);
939     }
940   else
941     {
942       for (argi = optind; argi < argc; argi++)
943         {
944           char *arg = argv[argi];
945           const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
946           if (class_filename == NULL)
947             class_filename = find_classfile (arg, jcf, NULL);
948           if (class_filename == NULL)
949             {
950               perror ("Could not find class");
951               return FATAL_EXIT_CODE;
952             }
953           JCF_FILL (jcf, 4);
954           if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
955             {
956               long compressed_size, member_size;
957               int compression_method, filename_length, extra_length;
958               int general_purpose_bits;
959               const char *filename;
960               int total_length;
961               if (flag_print_class_info)
962                 fprintf (out, "Reading classes from archive %s.\n",
963                          class_filename);
964               for (;;)
965                 {
966                   int skip = 0;
967                   jcf_filbuf_t save_filbuf = jcf->filbuf;
968                   long magic = JCF_readu4_le (jcf);
969                   if (magic == 0x02014b50 || magic == 0x06054b50)
970                     break;  /* got to central directory */
971                   if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
972                     {
973                       fprintf (stderr, "bad format of .zip/.jar archive\n");
974                       return FATAL_EXIT_CODE;
975                     }
976                   JCF_FILL (jcf, 26);
977                   JCF_SKIP (jcf, 2);
978                   general_purpose_bits = JCF_readu2_le (jcf);
979                   compression_method = JCF_readu2_le (jcf);
980                   JCF_SKIP (jcf, 8);
981                   compressed_size = JCF_readu4_le (jcf);
982                   member_size = JCF_readu4_le (jcf);
983                   filename_length = JCF_readu2_le (jcf);
984                   extra_length = JCF_readu2_le (jcf);
985                   total_length = filename_length + extra_length
986                     + compressed_size;
987                   if (jcf->read_end - jcf->read_ptr < total_length)
988                     jcf_trim_old_input (jcf);
989                   JCF_FILL (jcf, total_length);
990                   filename = jcf->read_ptr;
991                   JCF_SKIP (jcf, filename_length);
992                   JCF_SKIP (jcf, extra_length);
993                   if (filename_length > 0
994                       && filename[filename_length-1] == '/')
995                     {
996                       if (flag_print_class_info)
997                         fprintf (out, "[Skipping directory %.*s]\n",
998                                  filename_length, filename);
999                       skip = 1;
1000                     }
1001                   else if (compression_method != 0)
1002                     {
1003                       if (flag_print_class_info)
1004                         fprintf (out, "[Skipping compressed file %.*s]\n",
1005                                  filename_length, filename);
1006                       skip = 1;
1007                     }
1008                   else if (member_size < 4
1009                            || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1010                     {
1011                       if (flag_print_class_info)
1012                         fprintf (out, "[Skipping non-.class member %.*s]\n",
1013                                  filename_length, filename);
1014                       skip = 1;
1015                     }
1016                   else
1017                     {
1018                       if (flag_print_class_info)
1019                         fprintf (out, "Reading class member: %.*s.\n",
1020                                  filename_length, filename);
1021                     }
1022                   if (skip)
1023                     {
1024                       JCF_SKIP (jcf, compressed_size);
1025                     }
1026                   else
1027                     {
1028                       unsigned char *save_end;
1029                       jcf->filbuf = jcf_unexpected_eof;
1030                       save_end = jcf->read_end;
1031                       jcf->read_end = jcf->read_ptr + compressed_size;
1032                       process_class (jcf);
1033                       jcf->filbuf = save_filbuf;
1034                       jcf->read_end = save_end;
1035                     }
1036                 }
1037             }
1038           else
1039             {
1040               if (flag_print_class_info)
1041                 fprintf (out, "Reading .class from %s.\n", class_filename);
1042               process_class (jcf);
1043             }
1044           JCF_FINISH(jcf);
1045         }
1046     }
1047
1048   return SUCCESS_EXIT_CODE;
1049 }
1050
1051 \f
1052
1053 static void
1054 DEFUN(disassemble_method, (jcf, byte_ops, len),
1055       JCF* jcf AND const unsigned char *byte_ops AND int len)
1056 {
1057 #undef AND /* Causes problems with opcodes for iand and land. */
1058 #undef PTR
1059   int PC;
1060   int i;
1061   int saw_wide = 0;
1062   if (flag_disassemble_methods == 0)
1063     return;
1064 #define BCODE byte_ops
1065   for (PC = 0; PC < len;)
1066     {
1067       int oldpc = PC;
1068       int saw_index;
1069       jint INT_temp;
1070       switch (byte_ops[PC++])
1071         {
1072
1073 /* This is the actual code emitted for each of opcodes in javaops.def.
1074    The actual opcode-specific stuff is handled by the OPKIND macro.
1075    I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1076    Those macros are defiend below.  The OPKINDs that do not have any
1077    inline parameters (such as BINOP) and therefore do mot need anything
1078    else to me printed out just use an empty body. */
1079
1080 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1081         case OPCODE: \
1082           fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1083           OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1084           fputc ('\n', out); \
1085           break;
1086
1087 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1088 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1089 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1090 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1091
1092 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1093   (fprintf(stderr, "Bad byte codes.\n"), exit(-1)) : 1)
1094
1095 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1096    These all push a constant onto the opcode stack. */
1097 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1098   saw_index = 0, i = (OPERAND_VALUE); \
1099   if (oldpc+1 == PC) /* nothing */; \
1100   else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1101   else fprintf (out, " %d", i);
1102
1103 /* Print out operand (a local variable index) for LOAD opcodes.
1104    These all push local variable onto the opcode stack. */
1105 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1106   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1107
1108 /* Handle STORE opcodes same as LOAD opcodes.
1109    These all store a value from the opcode stack in a local variable. */
1110 #define STORE LOAD
1111
1112 /* Handle more kind of opcodes. */
1113 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1114 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1115 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1116 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1117 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1118 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1119 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1120
1121 /* Handle putfield and getfield opcodes, with static versions. */
1122 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1123   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1124
1125 /* Print operand for invoke opcodes. */
1126 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1127   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1128   if (OPERAND_VALUE) /* for invokeinterface */ \
1129   { int nargs = IMMEDIATE_u1;  PC++; \
1130     fprintf (out, " nargs:%d", nargs); }
1131
1132 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1133   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1134
1135 #define ARRAY(OPERAND_TYPE, SUBOP) \
1136   ARRAY_##SUBOP(OPERAND_TYPE)
1137 /* Handle sub-categories of ARRAY opcodes. */
1138 #define ARRAY_LOAD(TYPE) /* nothing */
1139 #define ARRAY_STORE(TYPE) /* nothing */
1140 #define ARRAY_LENGTH(TYPE) /* nothing */
1141 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1142 #define ARRAY_NEW_NUM \
1143  INT_temp = IMMEDIATE_u1; \
1144  { switch ((int) INT_temp) {  \
1145     case  4: fputs (" boolean", out); break; \
1146     case  5: fputs (" char", out); break; \
1147     case  6: fputs (" float", out); break; \
1148     case  7: fputs (" double", out); break; \
1149     case  8: fputs (" byte", out); break; \
1150     case  9: fputs (" short", out); break; \
1151     case 10: fputs (" int", out); break; \
1152     case 11: fputs (" long", out); break; \
1153     default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1154   } }
1155
1156 #define ARRAY_NEW_PTR  \
1157   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1158
1159 #define ARRAY_NEW_MULTI \
1160   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1161   fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1162
1163 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1164   fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1165
1166 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1167   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1168   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1169
1170 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1171   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1172   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1173
1174 #undef RET /* Defined by config/i386/i386.h */
1175 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1176   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1177   saw_wide = 0; \
1178   fprintf (out, " %ld", (long) INT_temp);
1179
1180 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1181   PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1182
1183 #define LOOKUP_SWITCH \
1184   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1185     fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1186     while (--npairs >= 0) { \
1187      jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1188      fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1189   }
1190
1191 #define TABLE_SWITCH \
1192   { jint default_offset = IMMEDIATE_s4; \
1193     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1194     fprintf (out, " low=%ld, high=%ld, default=%ld", \
1195       (long) low, (long) high, (long) default_offset+oldpc); \
1196     for (; low <= high; low++) { \
1197      jint offset = IMMEDIATE_s4; \
1198      fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1199   }
1200
1201 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1202   SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1203
1204 #define SPECIAL_IINC(OPERAND_TYPE) \
1205   i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1206   fprintf (out, " %d", i); \
1207   i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1208   saw_wide = 0; \
1209   fprintf (out, " %d", i)
1210
1211 #define SPECIAL_WIDE(OPERAND_TYPE) \
1212   saw_wide = 1;
1213
1214 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1215 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1216 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1217 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1218
1219 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1220   fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1221
1222 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1223    TEST(OPERAND_TYPE, OPERAND_VALUE)
1224
1225 #include "javaop.def"
1226
1227         load_store:
1228           if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1229           else
1230             {
1231               saw_wide = 0;
1232               fprintf (out, " %ld", (long) INT_temp);
1233             }
1234           fputc ('\n', out);
1235           break;
1236
1237         default:
1238           fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1239         }
1240     }
1241 }