* Mainline merge as of 2006-02-16 (@111136).
[official-gcc.git] / gcc / java / jcf-dump.c
blobb02dfceabe27c71cca363a6df48cb1351e812cbc
1 /* Program to dump out a Java(TM) .class file.
2 Functionally similar to Sun's javap.
4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2006 Free Software Foundation, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to
21 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.
24 Java and all Java-based marks are trademarks or registered trademarks
25 of Sun Microsystems, Inc. in the United States and other countries.
26 The Free Software Foundation is independent of Sun Microsystems, Inc. */
28 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
31 jcf-dump is a program to print out the contents of class files.
32 Usage: jcf-dump [FLAGS] CLASS
33 Each CLASS is either:
34 + the name of a class in the CLASSPATH (e.g "java.lang.String"), or
35 + the name of a class *file* (e.g. "/home/me/work/package/Foo.class").
36 + The name of a .zip or .jar file (which prints all the classes in the
37 archive).
39 OPTIONS:
41 Dis-assemble each method.
42 -classpath PATH
43 Overrides $CLASSPATH.
44 --print-main
45 Print nothing if there is no valid "main" method;
46 otherwise, print only the class name.
47 --javap
48 Print output in the style of Sun's javap program. VERY UNFINISHED.
52 #include "config.h"
53 #include "system.h"
54 #include "coretypes.h"
55 #include "tm.h"
56 #include "ggc.h"
57 #include "intl.h"
59 #include "jcf.h"
60 #include "tree.h"
61 #include "java-tree.h"
63 #include "version.h"
65 #include <getopt.h>
66 #include <math.h>
68 /* Output file. */
69 FILE *out;
70 /* Name of output file, if NULL if stdout. */
71 char *output_file = NULL;
73 int verbose = 0;
75 int flag_disassemble_methods = 0;
76 int flag_print_class_info = 1;
77 int flag_print_constant_pool = 0;
78 int flag_print_fields = 1;
79 int flag_print_methods = 1;
80 int flag_print_attributes = 1;
82 /* When nonzero, warn when source file is newer than matching class
83 file. */
84 int flag_newer = 1;
86 /* Print names of classes that have a "main" method. */
87 int flag_print_main = 0;
89 /* Index in constant pool of this class. */
90 int this_class_index = 0;
92 int class_access_flags = 0;
94 /* Print in format similar to javap. VERY INCOMPLETE. */
95 int flag_javap_compatible = 0;
97 static void print_access_flags (FILE *, uint16, char);
98 static void print_constant_terse (FILE*, JCF*, int, int);
99 static void print_constant (FILE *, JCF *, int, int);
100 static void print_constant_ref (FILE *, JCF *, int);
101 static void disassemble_method (JCF*, const unsigned char *, int);
102 static void print_name (FILE*, JCF*, int);
103 static void print_signature (FILE*, JCF*, int, int);
104 static int utf8_equal_string (struct JCF*, int, const char *);
105 static void usage (void) ATTRIBUTE_NORETURN;
106 static void help (void) ATTRIBUTE_NORETURN;
107 static void version (void) ATTRIBUTE_NORETURN;
108 static void process_class (struct JCF *);
109 static void print_constant_pool (struct JCF *);
110 static void print_exception_table (struct JCF *, const unsigned char *entries,
111 int);
113 #define PRINT_SIGNATURE_RESULT_ONLY 1
114 #define PRINT_SIGNATURE_ARGS_ONLY 2
116 static int
117 utf8_equal_string (JCF *jcf, int index, const char * value)
119 if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index)
120 && JPOOL_TAG (jcf, index) == CONSTANT_Utf8)
122 int len = strlen (value);
123 if (JPOOL_UTF_LENGTH (jcf, index) == len
124 && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0)
125 return 1;
127 return 0;
130 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
131 this_class_index = 0; \
132 if (flag_print_class_info) \
133 fprintf (out, \
134 "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
135 (long) MAGIC, (long) MINOR, (long) MAJOR)
137 #define HANDLE_START_CONSTANT_POOL(COUNT) \
138 if (flag_print_constant_pool) \
139 fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
141 #define HANDLE_SOURCEFILE(INDEX) \
142 { fprintf (out, "Attribute "); \
143 print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
144 fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
145 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
147 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
148 this_class_index = THIS; \
149 class_access_flags = ACCESS_FLAGS; \
150 if (flag_print_class_info) \
151 { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
152 print_access_flags (out, ACCESS_FLAGS, 'c'); \
153 fputc ('\n', out); \
154 fprintf (out, "This class: "); \
155 print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
156 if (flag_print_constant_pool || SUPER != 0) \
157 fprintf (out, ", super: "); \
158 if (flag_print_constant_pool) \
160 fprintf (out, "%d", SUPER); \
161 if (SUPER != 0) \
162 fputc ('=', out); \
164 if (SUPER != 0) \
165 print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
166 fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
169 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
170 (flag_print_attributes <= 0)
172 #define HANDLE_CLASS_INTERFACE(INDEX) \
173 if (flag_print_class_info) \
174 { fprintf (out, "- Implements: "); \
175 print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
176 fputc ('\n', out); }
178 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
179 if (flag_print_fields) \
180 fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
182 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
183 if (flag_print_fields) \
184 { fprintf (out, "Field name:"); \
185 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
186 print_access_flags (out, ACCESS_FLAGS, 'f'); \
187 fprintf (out, " Signature: "); \
188 if (flag_print_constant_pool) \
189 fprintf (out, "%d=", SIGNATURE); \
190 print_signature (out, jcf, SIGNATURE, 0); \
191 fputc ('\n', out); } \
192 else \
193 flag_print_attributes--;
195 #define HANDLE_END_FIELD() \
196 if (! flag_print_fields) \
197 flag_print_attributes++;
199 #define HANDLE_START_METHODS(METHODS_COUNT) \
200 if (flag_print_methods) \
201 fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
202 else \
203 flag_print_attributes--;
206 #define HANDLE_END_METHODS() \
207 if (! flag_print_methods) \
208 flag_print_attributes++;
210 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
212 if (flag_print_methods) \
214 if (flag_javap_compatible) \
216 fprintf (out, " "); \
217 print_access_flags (out, ACCESS_FLAGS, 'm'); \
218 fputc (' ', out); \
219 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
220 fputc (' ', out); \
221 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
222 print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
223 fputc ('\n', out); \
225 else \
227 fprintf (out, "\nMethod name:"); \
228 print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
229 print_access_flags (out, ACCESS_FLAGS, 'm'); \
230 fprintf (out, " Signature: "); \
231 if (flag_print_constant_pool) \
232 fprintf (out, "%d=", SIGNATURE); \
233 print_signature (out, jcf, SIGNATURE, 0); \
234 fputc ('\n', out); \
237 if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
238 && utf8_equal_string (jcf, NAME, "main") \
239 && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
240 && this_class_index > 0 \
241 && (class_access_flags & ACC_PUBLIC)) \
243 print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
244 fputc ('\n', out); \
248 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
249 ( fprintf (out, "Attribute "), \
250 print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
251 fprintf (out, ", length:%ld", (long) LENGTH) )
253 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
254 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
255 fprintf (out, ", value: "), \
256 print_constant_ref (out, jcf, VALUE_INDEX), \
257 fprintf (out, "\n") )
259 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
260 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
261 fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
262 (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
263 disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
265 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
266 print_exception_table (jcf, ENTRIES, COUNT)
268 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
269 { int n = (COUNT); int i; \
270 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
271 fprintf (out, ", count: %d\n", n); \
272 for (i = 0; i < n; i++) {\
273 int ex_index = JCF_readu2 (jcf); \
274 fprintf (out, "%3d: ", i); \
275 print_constant_ref (out, jcf, ex_index); \
276 fputc ('\n', out); } }
278 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
279 { int n = (COUNT); int i; \
280 COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
281 fprintf (out, ", count: %d\n", n); \
282 for (i = 0; i < n; i++) {\
283 int start_pc = JCF_readu2 (jcf); \
284 int length = JCF_readu2 (jcf); \
285 int name_index = JCF_readu2 (jcf); \
286 int signature_index = JCF_readu2 (jcf); \
287 int slot = JCF_readu2 (jcf); \
288 fprintf (out, " slot#%d: name: ", slot); \
289 if (flag_print_constant_pool) \
290 fprintf (out, "%d=", name_index); \
291 print_name (out, jcf, name_index); \
292 fprintf (out, ", type: "); \
293 if (flag_print_constant_pool) \
294 fprintf (out, "%d=", signature_index); \
295 print_signature (out, jcf, signature_index, 0); \
296 fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
298 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
299 { int n = (COUNT); int i; \
300 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
301 fprintf (out, ", count: %d\n", n); \
302 if (flag_disassemble_methods) \
303 for (i = 0; i < n; i++) {\
304 int start_pc = JCF_readu2 (jcf); \
305 int line_number = JCF_readu2 (jcf); \
306 fprintf (out, " line: %d at pc: %d\n", line_number, start_pc); }\
307 else \
308 JCF_SKIP (jcf, 4 * n); }
310 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
311 { int n = (COUNT); \
312 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
313 while (n--) \
315 uint16 inner_class_info_index = JCF_readu2 (jcf); \
316 uint16 outer_class_info_index = JCF_readu2 (jcf); \
317 uint16 inner_name_index = JCF_readu2 (jcf); \
318 uint16 inner_class_access_flags = JCF_readu2 (jcf); \
320 if (flag_print_class_info) \
322 fprintf (out, "\n inner: "); \
323 if (inner_class_info_index == 0) \
324 fprintf (out, " (no inner info index)"); \
325 else \
326 print_constant_terse_with_index (out, jcf, \
327 inner_class_info_index, \
328 CONSTANT_Class); \
329 if (inner_name_index == 0) \
330 fprintf (out, " (anonymous)"); \
331 else if (verbose || flag_print_constant_pool) \
333 fprintf (out, " ("); \
334 print_constant_terse_with_index (out, jcf, inner_name_index, \
335 CONSTANT_Utf8); \
336 fputc (')', out); \
338 fprintf (out, ", access flags: 0x%x", inner_class_access_flags); \
339 print_access_flags (out, inner_class_access_flags, 'c'); \
340 fprintf (out, ", outer class: "); \
341 if (outer_class_info_index == 0) \
342 fprintf (out, "(not a member)"); \
343 else \
344 print_constant_terse_with_index (out, jcf, \
345 outer_class_info_index, \
346 CONSTANT_Class); \
349 if (flag_print_class_info) \
350 fputc ('\n', out); \
353 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
354 { int i, n = (LENGTH), c = 0; \
355 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
356 fputc ('\n', out); \
357 for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
358 if (c != '\r' && c != '\n') fputc('\n', out); }
360 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
361 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
362 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
364 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
365 if (flag_print_attributes > 0) \
366 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
368 #include "javaop.h"
370 static void
371 print_constant_ref (FILE *stream, JCF *jcf, int index)
373 if (index <= 0 || index >= JPOOL_SIZE(jcf))
374 fprintf (stream, "<out of range>");
375 else
377 if (flag_print_constant_pool)
378 fprintf (stream, "#%d=", index);
379 fputc ('<', stream);
380 print_constant (stream, jcf, index, 1);
381 fputc ('>', stream);
385 /* Print the access flags given by FLAGS.
386 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
387 or 'm' (method flags). */
389 static void
390 print_access_flags (FILE *stream, uint16 flags, char context)
392 if (flags & ACC_PUBLIC) fprintf (stream, " public");
393 if (flags & ACC_PRIVATE) fprintf (stream, " private");
394 if (flags & ACC_PROTECTED) fprintf (stream, " protected");
395 if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
396 if (flags & ACC_STATIC) fprintf (stream, " static");
397 if (flags & ACC_FINAL) fprintf (stream, " final");
398 if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
399 if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
400 if (flags & ACC_NATIVE) fprintf (stream, " native");
401 if (flags & ACC_SYNCHRONIZED)
403 if (context == 'c')
404 fprintf (stream, " super");
405 else
406 fprintf (stream, " synchronized");
408 if (flags & ACC_INTERFACE) fprintf (stream, " interface");
409 if (flags & ACC_STRICT) fprintf (stream, " strictfp");
413 static void
414 print_name (FILE* stream, JCF* jcf, int name_index)
416 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
417 fprintf (stream, "<not a UTF8 constant>");
418 else
419 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
420 JPOOL_UTF_LENGTH (jcf, name_index));
423 /* If the type of the constant at INDEX matches EXPECTED,
424 print it tersely, otherwise more verbosely. */
426 static void
427 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
429 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
430 fprintf (out, "<constant pool index %d not in range>", index);
431 else if (JPOOL_TAG (jcf, index) != expected)
433 fprintf (out, "<Unexpected constant type ");
434 print_constant (out, jcf, index, 1);
435 fprintf (out, ">");
437 else
438 print_constant (out, jcf, index, 0);
441 static void
442 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
444 if (flag_print_constant_pool)
445 fprintf (out, "%d=", index);
446 print_constant_terse (out, jcf, index, expected);
449 /* Print the constant at INDEX in JCF's constant pool.
450 If verbosity==0, print very tersely (no extraneous text).
451 If verbosity==1, prefix the type of the constant.
452 If verbosity==2, add more descriptive text. */
454 static void
455 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
457 int j, n;
458 jlong num;
459 const char *str;
460 int kind = JPOOL_TAG (jcf, index);
461 switch (kind)
463 case CONSTANT_Class:
464 n = JPOOL_USHORT1 (jcf, index);
465 if (verbosity > 0)
467 if (verbosity > 1)
468 fprintf (out, "Class name: %d=", n);
469 else
470 fprintf (out, "Class ");
472 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
473 fprintf (out, "<out of range>");
474 else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
476 int len = JPOOL_UTF_LENGTH (jcf, n);
477 jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
479 else
480 print_constant_terse (out, jcf, n, CONSTANT_Utf8);
481 break;
482 case CONSTANT_Fieldref:
483 str = "Field"; goto field_or_method;
484 case CONSTANT_Methodref:
485 str = "Method"; goto field_or_method;
486 case CONSTANT_InterfaceMethodref:
487 str = "InterfaceMethod"; goto field_or_method;
488 field_or_method:
490 uint16 tclass = JPOOL_USHORT1 (jcf, index);
491 uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
492 if (verbosity == 2)
493 fprintf (out, "%sref class: %d=", str, tclass);
494 else if (verbosity > 0)
495 fprintf (out, "%s ", str);
496 print_constant_terse (out, jcf, tclass, CONSTANT_Class);
497 if (verbosity < 2)
498 fprintf (out, ".");
499 else
500 fprintf (out, " name_and_type: %d=<", name_and_type);
501 print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
502 if (verbosity == 2)
503 fputc ('>', out);
505 break;
506 case CONSTANT_String:
507 j = JPOOL_USHORT1 (jcf, index);
508 if (verbosity > 0)
510 if (verbosity > 1)
511 fprintf (out, "String %d=", j);
512 else
513 fprintf (out, "String ");
515 print_constant_terse (out, jcf, j, CONSTANT_Utf8);
516 break;
517 case CONSTANT_Integer:
518 if (verbosity > 0)
519 fprintf (out, "Integer ");
520 num = JPOOL_INT (jcf, index);
521 goto integer;
522 case CONSTANT_Long:
523 if (verbosity > 0)
524 fprintf (out, "Long ");
525 num = JPOOL_LONG (jcf, index);
526 goto integer;
527 integer:
529 char buffer[25];
530 format_int (buffer, num, 10);
531 fprintf (out, "%s", buffer);
532 if (verbosity > 1)
534 format_uint (buffer, (uint64)num, 16);
535 fprintf (out, "=0x%s", buffer);
538 break;
539 case CONSTANT_Float:
541 jfloat fnum = JPOOL_FLOAT (jcf, index);
543 if (verbosity > 0)
544 fputs ("Float ", out);
546 if (fnum.negative)
547 putc ('-', out);
549 if (JFLOAT_FINITE (fnum))
551 int dummy;
552 int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
553 double f;
554 uint32 mantissa = fnum.mantissa;
555 if (fnum.exponent == 0)
556 /* Denormal. */
557 exponent++;
558 else
559 /* Normal; add the implicit bit. */
560 mantissa |= ((uint32)1 << 23);
562 f = frexp (mantissa, &dummy);
563 f = ldexp (f, exponent + 1);
564 fprintf (out, "%.10g", f);
566 else
568 if (fnum.mantissa == 0)
569 fputs ("Inf", out);
570 else if (fnum.mantissa & JFLOAT_QNAN_MASK)
571 fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
572 else
573 fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
576 if (verbosity > 1)
577 fprintf (out, ", bits = 0x%08lx", JPOOL_UINT (jcf, index));
579 break;
581 case CONSTANT_Double:
583 jdouble dnum = JPOOL_DOUBLE (jcf, index);
585 if (verbosity > 0)
586 fputs ("Double ", out);
588 if (dnum.negative)
589 putc ('-', out);
591 if (JDOUBLE_FINITE (dnum))
593 int dummy;
594 int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
595 double d;
596 uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
597 + dnum.mantissa1);
598 if (dnum.exponent == 0)
599 /* Denormal. */
600 exponent++;
601 else
602 /* Normal; add the implicit bit. */
603 mantissa |= ((uint64)1 << 52);
605 d = frexp (mantissa, &dummy);
606 d = ldexp (d, exponent + 1);
607 fprintf (out, "%.20g", d);
609 else
611 uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
612 mantissa = (mantissa << 32) + dnum.mantissa1;
614 if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
615 fputs ("Inf", out);
616 else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
617 fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
618 else
619 fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
621 if (verbosity > 1)
623 int32 hi, lo;
624 hi = JPOOL_UINT (jcf, index);
625 lo = JPOOL_UINT (jcf, index + 1);
626 fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
628 break;
630 case CONSTANT_NameAndType:
632 uint16 name = JPOOL_USHORT1 (jcf, index);
633 uint16 sig = JPOOL_USHORT2 (jcf, index);
634 if (verbosity > 0)
636 if (verbosity > 1)
637 fprintf (out, "NameAndType name: %d=", name);
638 else
639 fprintf (out, "NameAndType ");
641 print_name (out, jcf, name);
642 if (verbosity <= 1)
643 fputc (' ', out);
644 else
645 fprintf (out, ", signature: %d=", sig);
646 print_signature (out, jcf, sig, 0);
648 break;
649 case CONSTANT_Utf8:
651 const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
652 int length = JPOOL_UTF_LENGTH (jcf, index);
653 if (verbosity > 0)
654 { /* Print as 8-bit bytes. */
655 fputs ("Utf8: \"", out);
656 while (--length >= 0)
657 jcf_print_char (out, *str++);
659 else
660 { /* Print as Unicode. */
661 fputc ('\"', out);
662 jcf_print_utf8 (out, str, length);
664 fputc ('\"', out);
666 break;
667 default:
668 fprintf (out, "(Unknown constant type %d)", kind);
672 static void
673 print_constant_pool (JCF *jcf)
675 int i;
676 for (i = 1; i < JPOOL_SIZE(jcf); i++)
678 int kind = JPOOL_TAG (jcf, i);
679 fprintf (out, "#%d: ", i);
680 print_constant (out, jcf, i, 2);
681 fprintf (out, "\n");
682 if (kind == CONSTANT_Double || kind == CONSTANT_Long)
683 i++; /* These take up two slots in the constant table */
687 static void
688 print_signature_type (FILE* stream, const unsigned char **ptr,
689 const unsigned char *limit)
691 int array_size;
692 if ((*ptr) >= limit)
693 return;
694 switch (*(*ptr))
696 case '[':
697 array_size = -1;
698 for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
700 array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
702 print_signature_type (stream, ptr, limit);
703 if (array_size == -1)
704 fprintf (stream, "[]");
705 else
706 fprintf (stream, "[%d]", array_size);
707 break;
708 case '(':
710 int nargs = 0;
711 fputc (*(*ptr)++, stream);
712 for (; **ptr != ')' && *ptr < limit; nargs++)
714 if (nargs > 0)
715 fputc (',', stream);
716 print_signature_type (stream, ptr, limit);
718 if (*ptr < limit)
720 fputc (*(*ptr)++, stream);
721 print_signature_type (stream, ptr, limit);
723 else
724 fprintf (stream, "???");
726 break;
728 case 'B': fprintf (stream, "byte"); (*ptr)++; break;
729 case 'C': fprintf (stream, "char"); (*ptr)++; break;
730 case 'D': fprintf (stream, "double"); (*ptr)++; break;
731 case 'F': fprintf (stream, "float"); (*ptr)++; break;
732 case 'S': fprintf (stream, "short"); (*ptr)++; break;
733 case 'I': fprintf (stream, "int"); (*ptr)++; break;
734 case 'J': fprintf (stream, "long"); (*ptr)++; break;
735 case 'Z': fprintf (stream, "boolean"); (*ptr)++; break;
736 case 'V': fprintf (stream, "void"); (*ptr)++; break;
738 case 'L':
739 for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
740 jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
741 if (*(*ptr) == ';')
742 (*ptr)++;
743 break;
744 default:
745 jcf_print_char (stream, *(*ptr)++);
749 static void
750 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
752 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
753 print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
754 else
756 const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
757 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
758 const unsigned char *limit;
759 limit = str + length;
760 if (str >= limit)
761 fprintf (stream, "<empty signature string>");
762 else
764 if (options & PRINT_SIGNATURE_RESULT_ONLY)
766 while (str < limit && *str++ != ')') ;
768 if (options & PRINT_SIGNATURE_ARGS_ONLY)
770 str++;
771 fputc ('(', stream);
772 while (str < limit && *str != ')')
774 print_signature_type (stream, &str, limit);
775 if (*str != ')')
776 fputs (", ", stream);
778 fputc (')', stream);
780 else
782 print_signature_type (stream, &str, limit);
783 if (str < limit)
785 fprintf (stream, "<junk:");
786 jcf_print_utf8 (stream, str, limit - str);
787 fputc ('>', stream);
795 static void
796 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
798 /* Print exception table. */
799 int i = count;
800 if (i > 0)
802 const unsigned char *ptr = entries;
803 fprintf (out, "Exceptions (count: %d):\n", i);
804 for (; --i >= 0; ptr+= 8)
806 int start_pc = GET_u2 (ptr);
807 int end_pc = GET_u2 (ptr+2);
808 int handler_pc = GET_u2 (ptr+4);
809 int catch_type = GET_u2 (ptr+6);
810 fprintf (out, " start: %d, end: %d, handler: %d, type: ",
811 start_pc, end_pc, handler_pc);
812 if (catch_type == 0)
813 fputs ("0 /* finally */", out);
814 else
815 print_constant_terse_with_index (out, jcf,
816 catch_type, CONSTANT_Class);
817 fputc ('\n', out);
822 #include "jcf-reader.c"
824 static void
825 process_class (JCF *jcf)
827 int code;
828 if (jcf_parse_preamble (jcf) != 0)
829 fprintf (stderr, _("Not a valid Java .class file.\n"));
831 /* Parse and possibly print constant pool */
832 code = jcf_parse_constant_pool (jcf);
833 if (code != 0)
835 fprintf (stderr, _("error while parsing constant pool\n"));
836 exit (FATAL_EXIT_CODE);
838 code = verify_constant_pool (jcf);
839 if (code > 0)
841 fprintf (stderr, _("error in constant pool entry #%d\n"), code);
842 exit (FATAL_EXIT_CODE);
844 if (flag_print_constant_pool)
845 print_constant_pool (jcf);
847 jcf_parse_class (jcf);
848 code = jcf_parse_fields (jcf);
849 if (code != 0)
851 fprintf (stderr, _("error while parsing fields\n"));
852 exit (FATAL_EXIT_CODE);
854 code = jcf_parse_methods (jcf);
855 if (code != 0)
857 fprintf (stderr, _("error while parsing methods\n"));
858 exit (FATAL_EXIT_CODE);
860 code = jcf_parse_final_attributes (jcf);
861 if (code != 0)
863 fprintf (stderr, _("error while parsing final attributes\n"));
864 exit (FATAL_EXIT_CODE);
866 jcf->filename = NULL;
871 /* This is used to mark options with no short value. */
872 #define LONG_OPT(Num) ((Num) + 128)
874 #define OPT_classpath LONG_OPT (0)
875 #define OPT_CLASSPATH OPT_classpath
876 #define OPT_bootclasspath LONG_OPT (1)
877 #define OPT_extdirs LONG_OPT (2)
878 #define OPT_HELP LONG_OPT (3)
879 #define OPT_VERSION LONG_OPT (4)
880 #define OPT_JAVAP LONG_OPT (5)
882 static const struct option options[] =
884 { "classpath", required_argument, NULL, OPT_classpath },
885 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
886 { "extdirs", required_argument, NULL, OPT_extdirs },
887 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
888 { "help", no_argument, NULL, OPT_HELP },
889 { "verbose", no_argument, NULL, 'v' },
890 { "version", no_argument, NULL, OPT_VERSION },
891 { "javap", no_argument, NULL, OPT_JAVAP },
892 { "print-main", no_argument, &flag_print_main, 1 },
893 { "print-constants", no_argument, &flag_print_constant_pool, 1 },
894 { NULL, no_argument, NULL, 0 }
897 static void
898 usage (void)
900 fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
901 exit (1);
904 static void
905 help (void)
907 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
908 printf (_("Display contents of a class file in readable form.\n\n"));
909 printf (_(" -c Disassemble method bodies\n"));
910 printf (_(" --javap Generate output in 'javap' format\n"));
911 printf ("\n");
912 printf (_(" --classpath PATH Set path to find .class files\n"));
913 printf (_(" -IDIR Append directory to class path\n"));
914 printf (_(" --bootclasspath PATH Override built-in class path\n"));
915 printf (_(" --extdirs PATH Set extensions directory path\n"));
916 printf (_(" -o FILE Set output file name\n"));
917 printf ("\n");
918 printf (_(" --help Print this help, then exit\n"));
919 printf (_(" --version Print version number, then exit\n"));
920 printf (_(" -v, --verbose Print extra information while running\n"));
921 printf ("\n");
922 printf (_("For bug reporting instructions, please see:\n"
923 "%s.\n"), bug_report_url);
924 exit (0);
927 static void
928 version (void)
930 printf ("jcf-dump (GCC) %s\n\n", version_string);
931 printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
932 printf (_("This is free software; see the source for copying conditions. There is NO\n"
933 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
934 exit (0);
938 main (int argc, char** argv)
940 JCF jcf[1];
941 int argi, opt;
943 /* Unlock the stdio streams. */
944 unlock_std_streams ();
946 gcc_init_libintl ();
948 if (argc <= 1)
950 fprintf (stderr, _("jcf-dump: no classes specified\n"));
951 usage ();
954 jcf_path_init ();
956 /* We use getopt_long_only to allow single `-' long options. For
957 some of our options this is more natural. */
958 while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
960 switch (opt)
962 case 0:
963 /* Already handled. */
964 break;
966 case 'o':
967 output_file = optarg;
968 break;
970 case 'I':
971 jcf_path_include_arg (optarg);
972 break;
974 case 'v':
975 verbose++;
976 break;
978 case 'c':
979 flag_disassemble_methods = 1;
980 break;
982 case OPT_classpath:
983 jcf_path_classpath_arg (optarg);
984 break;
986 case OPT_bootclasspath:
987 jcf_path_bootclasspath_arg (optarg);
988 break;
990 case OPT_extdirs:
991 jcf_path_extdirs_arg (optarg);
992 break;
994 case OPT_HELP:
995 help ();
996 break;
998 case OPT_VERSION:
999 version ();
1000 break;
1002 case OPT_JAVAP:
1003 flag_javap_compatible++;
1004 flag_print_constant_pool = 0;
1005 flag_print_attributes = 0;
1006 break;
1008 default:
1009 usage ();
1013 if (verbose && ! flag_javap_compatible)
1014 flag_print_constant_pool = 1;
1016 if (optind == argc)
1018 fprintf (stderr, _("jcf-dump: no classes specified\n"));
1019 usage ();
1022 jcf_path_seal (verbose);
1024 if (flag_print_main)
1026 flag_print_fields = 0;
1027 flag_print_methods = 0;
1028 flag_print_constant_pool = 0;
1029 flag_print_attributes = 0;
1030 flag_print_class_info = 0;
1033 if (output_file)
1035 out = fopen (output_file, "w");
1036 if (! out)
1038 fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1039 return FATAL_EXIT_CODE;
1042 else
1043 out = stdout;
1045 if (optind >= argc)
1047 fprintf (out, "Reading .class from <standard input>.\n");
1048 open_class ("<stdio>", jcf, 0, NULL);
1049 process_class (jcf);
1051 else
1053 for (argi = optind; argi < argc; argi++)
1055 char *arg = argv[argi];
1056 const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1057 if (class_filename == NULL)
1058 class_filename = find_classfile (arg, jcf, NULL);
1059 if (class_filename == NULL)
1061 perror ("Could not find class");
1062 return FATAL_EXIT_CODE;
1064 JCF_FILL (jcf, 4);
1065 if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1067 long compressed_size, member_size;
1068 int compression_method, filename_length, extra_length;
1069 int general_purpose_bits;
1070 const char *filename;
1071 int total_length;
1072 if (flag_print_class_info)
1073 fprintf (out, "Reading classes from archive %s.\n",
1074 class_filename);
1075 for (;;)
1077 int skip = 0;
1078 jcf_filbuf_t save_filbuf = jcf->filbuf;
1079 long magic = JCF_readu4_le (jcf);
1080 if (magic == 0x02014b50 || magic == 0x06054b50)
1081 break; /* got to central directory */
1082 if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1084 fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1085 return FATAL_EXIT_CODE;
1087 JCF_FILL (jcf, 26);
1088 JCF_SKIP (jcf, 2);
1089 general_purpose_bits = JCF_readu2_le (jcf);
1090 compression_method = JCF_readu2_le (jcf);
1091 JCF_SKIP (jcf, 8);
1092 compressed_size = JCF_readu4_le (jcf);
1093 member_size = JCF_readu4_le (jcf);
1094 filename_length = JCF_readu2_le (jcf);
1095 extra_length = JCF_readu2_le (jcf);
1096 total_length = filename_length + extra_length
1097 + compressed_size;
1098 if (jcf->read_end - jcf->read_ptr < total_length)
1099 jcf_trim_old_input (jcf);
1100 JCF_FILL (jcf, total_length);
1101 filename = (const char *) jcf->read_ptr;
1102 JCF_SKIP (jcf, filename_length);
1103 JCF_SKIP (jcf, extra_length);
1104 if (filename_length > 0
1105 && filename[filename_length-1] == '/')
1107 if (flag_print_class_info)
1108 fprintf (out, "[Skipping directory %.*s]\n",
1109 filename_length, filename);
1110 skip = 1;
1112 else if (compression_method != 0)
1114 if (flag_print_class_info)
1115 fprintf (out, "[Skipping compressed file %.*s]\n",
1116 filename_length, filename);
1117 skip = 1;
1119 else if (member_size < 4
1120 || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1122 if (flag_print_class_info)
1123 fprintf (out, "[Skipping non-.class member %.*s]\n",
1124 filename_length, filename);
1125 skip = 1;
1127 else
1129 if (flag_print_class_info)
1130 fprintf (out, "Reading class member: %.*s.\n",
1131 filename_length, filename);
1133 if (skip)
1135 JCF_SKIP (jcf, compressed_size);
1137 else
1139 unsigned char *save_end;
1140 jcf->filbuf = jcf_unexpected_eof;
1141 save_end = jcf->read_end;
1142 jcf->read_end = jcf->read_ptr + compressed_size;
1143 process_class (jcf);
1144 jcf->filbuf = save_filbuf;
1145 jcf->read_end = save_end;
1149 else
1151 if (flag_print_class_info)
1152 fprintf (out, "Reading .class from %s.\n", class_filename);
1153 process_class (jcf);
1155 JCF_FINISH(jcf);
1159 return SUCCESS_EXIT_CODE;
1164 static void
1165 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1167 #undef PTR
1168 int PC;
1169 int i;
1170 int saw_wide = 0;
1171 if (flag_disassemble_methods == 0)
1172 return;
1173 #define BCODE byte_ops
1174 for (PC = 0; PC < len;)
1176 int oldpc = PC;
1177 int saw_index;
1178 jint INT_temp;
1179 switch (byte_ops[PC++])
1182 /* This is the actual code emitted for each of opcodes in javaops.def.
1183 The actual opcode-specific stuff is handled by the OPKIND macro.
1184 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1185 Those macros are defined below. The OPKINDs that do not have any
1186 inline parameters (such as BINOP) and therefore do mot need anything
1187 else to me printed out just use an empty body. */
1189 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1190 case OPCODE: \
1191 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1192 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1193 fputc ('\n', out); \
1194 break;
1196 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1197 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1198 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1199 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1201 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1202 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1204 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1205 These all push a constant onto the opcode stack. */
1206 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1207 saw_index = 0, i = (OPERAND_VALUE); \
1208 if (oldpc+1 == PC) /* nothing */; \
1209 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1210 else fprintf (out, " %d", i);
1212 /* Print out operand (a local variable index) for LOAD opcodes.
1213 These all push local variable onto the opcode stack. */
1214 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1215 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1217 /* Handle STORE opcodes same as LOAD opcodes.
1218 These all store a value from the opcode stack in a local variable. */
1219 #define STORE LOAD
1221 /* Handle more kind of opcodes. */
1222 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1223 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1224 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1225 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1226 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1227 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1228 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1230 /* Handle putfield and getfield opcodes, with static versions. */
1231 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1232 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1234 /* Print operand for invoke opcodes. */
1235 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1236 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1237 if (OPERAND_VALUE) /* for invokeinterface */ \
1238 { int nargs = IMMEDIATE_u1; PC++; \
1239 fprintf (out, " nargs:%d", nargs); }
1241 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1242 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1244 #define ARRAY(OPERAND_TYPE, SUBOP) \
1245 ARRAY_##SUBOP(OPERAND_TYPE)
1246 /* Handle sub-categories of ARRAY opcodes. */
1247 #define ARRAY_LOAD(TYPE) /* nothing */
1248 #define ARRAY_STORE(TYPE) /* nothing */
1249 #define ARRAY_LENGTH(TYPE) /* nothing */
1250 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1251 #define ARRAY_NEW_NUM \
1252 INT_temp = IMMEDIATE_u1; \
1253 { switch ((int) INT_temp) { \
1254 case 4: fputs (" boolean", out); break; \
1255 case 5: fputs (" char", out); break; \
1256 case 6: fputs (" float", out); break; \
1257 case 7: fputs (" double", out); break; \
1258 case 8: fputs (" byte", out); break; \
1259 case 9: fputs (" short", out); break; \
1260 case 10: fputs (" int", out); break; \
1261 case 11: fputs (" long", out); break; \
1262 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1265 #define ARRAY_NEW_PTR \
1266 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1268 #define ARRAY_NEW_MULTI \
1269 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1270 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1272 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1273 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1275 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1276 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1277 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1279 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1280 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1281 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1283 #undef RET /* Defined by config/i386/i386.h */
1284 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1285 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1286 saw_wide = 0; \
1287 fprintf (out, " %ld", (long) INT_temp);
1289 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1290 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1292 #define LOOKUP_SWITCH \
1293 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1294 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1295 while (--npairs >= 0) { \
1296 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1297 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1300 #define TABLE_SWITCH \
1301 { jint default_offset = IMMEDIATE_s4; \
1302 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1303 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1304 (long) low, (long) high, (long) default_offset+oldpc); \
1305 for (; low <= high; low++) { \
1306 jint offset = IMMEDIATE_s4; \
1307 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1310 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1311 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1313 #define SPECIAL_IINC(OPERAND_TYPE) \
1314 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1315 fprintf (out, " %d", i); \
1316 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1317 saw_wide = 0; \
1318 fprintf (out, " %d", i)
1320 #define SPECIAL_WIDE(OPERAND_TYPE) \
1321 saw_wide = 1;
1323 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1324 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1325 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1326 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1328 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1329 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1331 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1332 TEST(OPERAND_TYPE, OPERAND_VALUE)
1334 #include "javaop.def"
1336 load_store:
1337 if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1338 else
1340 saw_wide = 0;
1341 fprintf (out, " %ld", (long) INT_temp);
1343 fputc ('\n', out);
1344 break;
1346 default:
1347 fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);