OSDN Git Service

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