OSDN Git Service

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