OSDN Git Service

* update_web_docs, doc_exclude: Check out files that may be in the
[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 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 > 1 ? "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 > 1 ? "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 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 (%s)\n\n", version_string);
826   printf ("Copyright (C) 2001 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           break;
893
894         default:
895           usage ();
896         }
897     }
898
899   if (optind == argc)
900     {
901       fprintf (stderr, "jcf-dump: no classes specified\n");
902       usage ();
903     }
904
905   jcf_path_seal ();
906
907   if (flag_print_main)
908     {
909       flag_print_fields = 0;
910       flag_print_methods = 0;
911       flag_print_constant_pool = 0;
912       flag_print_attributes = 0;
913       flag_print_class_info = 0;
914     }
915
916   if (output_file)
917     {
918       out = fopen (output_file, "w");
919       if (! out)
920         {
921           fprintf (stderr, "Cannot open '%s' for output.\n", output_file);
922           return FATAL_EXIT_CODE;
923         }
924     }
925   else
926     out = stdout;
927
928   if (optind >= argc)
929     {
930       fprintf (out, "Reading .class from <standard input>.\n");
931 #if JCF_USE_STDIO
932       open_class ("<stdio>", jcf, stdin, NULL);
933 #else
934       open_class ("<stdio>", jcf, 0, NULL);
935 #endif
936       process_class (jcf);
937     }
938   else
939     {
940       for (argi = optind; argi < argc; argi++)
941         {
942           char *arg = argv[argi];
943           const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
944           if (class_filename == NULL)
945             class_filename = find_classfile (arg, jcf, NULL);
946           if (class_filename == NULL)
947             {
948               perror ("Could not find class");
949               return FATAL_EXIT_CODE;
950             }
951           JCF_FILL (jcf, 4);
952           if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
953             {
954               long compressed_size, member_size;
955               int compression_method, filename_length, extra_length;
956               int general_purpose_bits;
957               const char *filename;
958               int total_length;
959               if (flag_print_class_info)
960                 fprintf (out, "Reading classes from archive %s.\n",
961                          class_filename);
962               for (;;)
963                 {
964                   int skip = 0;
965                   jcf_filbuf_t save_filbuf = jcf->filbuf;
966                   long magic = JCF_readu4_le (jcf);
967                   if (magic == 0x02014b50 || magic == 0x06054b50)
968                     break;  /* got to central directory */
969                   if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
970                     {
971                       fprintf (stderr, "bad format of .zip/.jar archive\n");
972                       return FATAL_EXIT_CODE;
973                     }
974                   JCF_FILL (jcf, 26);
975                   JCF_SKIP (jcf, 2);
976                   general_purpose_bits = JCF_readu2_le (jcf);
977                   compression_method = JCF_readu2_le (jcf);
978                   JCF_SKIP (jcf, 8);
979                   compressed_size = JCF_readu4_le (jcf);
980                   member_size = JCF_readu4_le (jcf);
981                   filename_length = JCF_readu2_le (jcf);
982                   extra_length = JCF_readu2_le (jcf);
983                   total_length = filename_length + extra_length
984                     + compressed_size;
985                   if (jcf->read_end - jcf->read_ptr < total_length)
986                     jcf_trim_old_input (jcf);
987                   JCF_FILL (jcf, total_length);
988                   filename = jcf->read_ptr;
989                   JCF_SKIP (jcf, filename_length);
990                   JCF_SKIP (jcf, extra_length);
991                   if (filename_length > 0
992                       && filename[filename_length-1] == '/')
993                     {
994                       if (flag_print_class_info)
995                         fprintf (out, "[Skipping directory %.*s]\n",
996                                  filename_length, filename);
997                       skip = 1;
998                     }
999                   else if (compression_method != 0)
1000                     {
1001                       if (flag_print_class_info)
1002                         fprintf (out, "[Skipping compressed file %.*s]\n",
1003                                  filename_length, filename);
1004                       skip = 1;
1005                     }
1006                   else if (member_size < 4
1007                            || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1008                     {
1009                       if (flag_print_class_info)
1010                         fprintf (out, "[Skipping non-.class member %.*s]\n",
1011                                  filename_length, filename);
1012                       skip = 1;
1013                     }
1014                   else
1015                     {
1016                       if (flag_print_class_info)
1017                         fprintf (out, "Reading class member: %.*s.\n",
1018                                  filename_length, filename);
1019                     }
1020                   if (skip)
1021                     {
1022                       JCF_SKIP (jcf, compressed_size);
1023                     }
1024                   else
1025                     {
1026                       unsigned char *save_end;
1027                       jcf->filbuf = jcf_unexpected_eof;
1028                       save_end = jcf->read_end;
1029                       jcf->read_end = jcf->read_ptr + compressed_size;
1030                       process_class (jcf);
1031                       jcf->filbuf = save_filbuf;
1032                       jcf->read_end = save_end;
1033                     }
1034                 }
1035             }
1036           else
1037             {
1038               if (flag_print_class_info)
1039                 fprintf (out, "Reading .class from %s.\n", class_filename);
1040               process_class (jcf);
1041             }
1042           JCF_FINISH(jcf);
1043         }
1044     }
1045
1046   return SUCCESS_EXIT_CODE;
1047 }
1048
1049 \f
1050
1051 static void
1052 DEFUN(disassemble_method, (jcf, byte_ops, len),
1053       JCF* jcf AND const unsigned char *byte_ops AND int len)
1054 {
1055 #undef AND /* Causes problems with opcodes for iand and land. */
1056 #undef PTR
1057   int PC;
1058   int i;
1059   int saw_wide = 0;
1060   if (flag_disassemble_methods == 0)
1061     return;
1062 #define BCODE byte_ops
1063   for (PC = 0; PC < len;)
1064     {
1065       int oldpc = PC;
1066       int saw_index;
1067       jint INT_temp;
1068       switch (byte_ops[PC++])
1069         {
1070
1071 /* This is the actual code emitted for each of opcodes in javaops.def.
1072    The actual opcode-specific stuff is handled by the OPKIND macro.
1073    I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1074    Those macros are defiend below.  The OPKINDs that do not have any
1075    inline parameters (such as BINOP) and therefore do mot need anything
1076    else to me printed out just use an empty body. */
1077
1078 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1079         case OPCODE: \
1080           fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1081           OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1082           fputc ('\n', out); \
1083           break;
1084
1085 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1086 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1087 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1088 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1089
1090 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1091   (fprintf(stderr, "Bad byte codes.\n"), exit(-1)) : 1)
1092
1093 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1094    These all push a constant onto the opcode stack. */
1095 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1096   saw_index = 0, i = (OPERAND_VALUE); \
1097   if (oldpc+1 == PC) /* nothing */; \
1098   else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1099   else fprintf (out, " %d", i);
1100
1101 /* Print out operand (a local variable index) for LOAD opcodes.
1102    These all push local variable onto the opcode stack. */
1103 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1104   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1105
1106 /* Handle STORE opcodes same as LOAD opcodes.
1107    These all store a value from the opcode stack in a local variable. */
1108 #define STORE LOAD
1109
1110 /* Handle more kind of opcodes. */
1111 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1112 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1113 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1114 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1115 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1116 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1117 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1118
1119 /* Handle putfield and getfield opcodes, with static versions. */
1120 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1121   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1122
1123 /* Print operand for invoke opcodes. */
1124 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1125   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1126   if (OPERAND_VALUE) /* for invokeinterface */ \
1127   { int nargs = IMMEDIATE_u1;  PC++; \
1128     fprintf (out, " nargs:%d", nargs); }
1129
1130 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1131   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1132
1133 #define ARRAY(OPERAND_TYPE, SUBOP) \
1134   ARRAY_##SUBOP(OPERAND_TYPE)
1135 /* Handle sub-categories of ARRAY opcodes. */
1136 #define ARRAY_LOAD(TYPE) /* nothing */
1137 #define ARRAY_STORE(TYPE) /* nothing */
1138 #define ARRAY_LENGTH(TYPE) /* nothing */
1139 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1140 #define ARRAY_NEW_NUM \
1141  INT_temp = IMMEDIATE_u1; \
1142  { switch ((int) INT_temp) {  \
1143     case  4: fputs (" boolean", out); break; \
1144     case  5: fputs (" char", out); break; \
1145     case  6: fputs (" float", out); break; \
1146     case  7: fputs (" double", out); break; \
1147     case  8: fputs (" byte", out); break; \
1148     case  9: fputs (" short", out); break; \
1149     case 10: fputs (" int", out); break; \
1150     case 11: fputs (" long", out); break; \
1151     default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1152   } }
1153
1154 #define ARRAY_NEW_PTR  \
1155   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1156
1157 #define ARRAY_NEW_MULTI \
1158   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1159   fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1160
1161 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1162   fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1163
1164 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1165   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1166   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1167
1168 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1169   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1170   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1171
1172 #undef RET /* Defined by config/i386/i386.h */
1173 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1174   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1175   saw_wide = 0; \
1176   fprintf (out, " %ld", (long) INT_temp);
1177
1178 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1179   PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1180
1181 #define LOOKUP_SWITCH \
1182   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1183     fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1184     while (--npairs >= 0) { \
1185      jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1186      fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1187   }
1188
1189 #define TABLE_SWITCH \
1190   { jint default_offset = IMMEDIATE_s4; \
1191     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1192     fprintf (out, " low=%ld, high=%ld, default=%ld", \
1193       (long) low, (long) high, (long) default_offset+oldpc); \
1194     for (; low <= high; low++) { \
1195      jint offset = IMMEDIATE_s4; \
1196      fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1197   }
1198
1199 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1200   SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1201
1202 #define SPECIAL_IINC(OPERAND_TYPE) \
1203   i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1204   fprintf (out, " %ld", (long) i); \
1205   INT_temp = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1206   saw_wide = 0; \
1207   fprintf (out, " %ld", (long) INT_temp)
1208
1209 #define SPECIAL_WIDE(OPERAND_TYPE) \
1210   saw_wide = 1;
1211
1212 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1213 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1214 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1215 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1216
1217 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1218   fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1219
1220 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1221    TEST(OPERAND_TYPE, OPERAND_VALUE)
1222
1223 #include "javaop.def"
1224
1225         load_store:
1226           if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1227           else
1228             {
1229               saw_wide = 0;
1230               fprintf (out, " %ld", (long) INT_temp);
1231             }
1232           fputc ('\n', out);
1233           break;
1234
1235         default:
1236           fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1237         }
1238     }
1239 }