* gcc.dg/20061124-1.c: Add exit() function prototype.
[official-gcc.git] / gcc / java / jcf-dump.c
bloba5e3444cb87af6cf98b2b91112fbcbcf3ba1e80e
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)
399 fprintf (stream, context == 'm' ? " varargs" : " transient");
400 if (flags & ACC_VOLATILE)
401 fprintf (stream, context == 'm' ? " bridge" : " volatile");
402 if (flags & ACC_NATIVE) fprintf (stream, " native");
403 if (flags & ACC_SYNCHRONIZED)
405 if (context == 'c')
406 fprintf (stream, " super");
407 else
408 fprintf (stream, " synchronized");
410 if (flags & ACC_INTERFACE)
411 fprintf (stream, (flags & ACC_ANNOTATION) ? " @interface" : " interface");
412 if (flags & ACC_ENUM) fprintf (stream, " enum");
413 if (flags & ACC_STRICT) fprintf (stream, " strictfp");
414 if (flags & ACC_SYNTHETIC) fprintf (stream, " synthetic");
418 static void
419 print_name (FILE* stream, JCF* jcf, int name_index)
421 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
422 fprintf (stream, "<not a UTF8 constant>");
423 else
424 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
425 JPOOL_UTF_LENGTH (jcf, name_index));
428 /* If the type of the constant at INDEX matches EXPECTED,
429 print it tersely, otherwise more verbosely. */
431 static void
432 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
434 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
435 fprintf (out, "<constant pool index %d not in range>", index);
436 else if (JPOOL_TAG (jcf, index) != expected)
438 fprintf (out, "<Unexpected constant type ");
439 print_constant (out, jcf, index, 1);
440 fprintf (out, ">");
442 else
443 print_constant (out, jcf, index, 0);
446 static void
447 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
449 if (flag_print_constant_pool)
450 fprintf (out, "%d=", index);
451 print_constant_terse (out, jcf, index, expected);
454 /* Print the constant at INDEX in JCF's constant pool.
455 If verbosity==0, print very tersely (no extraneous text).
456 If verbosity==1, prefix the type of the constant.
457 If verbosity==2, add more descriptive text. */
459 static void
460 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
462 int j, n;
463 jlong num;
464 const char *str;
465 int kind = JPOOL_TAG (jcf, index);
466 switch (kind)
468 case CONSTANT_Class:
469 n = JPOOL_USHORT1 (jcf, index);
470 if (verbosity > 0)
472 if (verbosity > 1)
473 fprintf (out, "Class name: %d=", n);
474 else
475 fprintf (out, "Class ");
477 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
478 fprintf (out, "<out of range>");
479 else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
481 int len = JPOOL_UTF_LENGTH (jcf, n);
482 jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
484 else
485 print_constant_terse (out, jcf, n, CONSTANT_Utf8);
486 break;
487 case CONSTANT_Fieldref:
488 str = "Field"; goto field_or_method;
489 case CONSTANT_Methodref:
490 str = "Method"; goto field_or_method;
491 case CONSTANT_InterfaceMethodref:
492 str = "InterfaceMethod"; goto field_or_method;
493 field_or_method:
495 uint16 tclass = JPOOL_USHORT1 (jcf, index);
496 uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
497 if (verbosity == 2)
498 fprintf (out, "%sref class: %d=", str, tclass);
499 else if (verbosity > 0)
500 fprintf (out, "%s ", str);
501 print_constant_terse (out, jcf, tclass, CONSTANT_Class);
502 if (verbosity < 2)
503 fprintf (out, ".");
504 else
505 fprintf (out, " name_and_type: %d=<", name_and_type);
506 print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
507 if (verbosity == 2)
508 fputc ('>', out);
510 break;
511 case CONSTANT_String:
512 j = JPOOL_USHORT1 (jcf, index);
513 if (verbosity > 0)
515 if (verbosity > 1)
516 fprintf (out, "String %d=", j);
517 else
518 fprintf (out, "String ");
520 print_constant_terse (out, jcf, j, CONSTANT_Utf8);
521 break;
522 case CONSTANT_Integer:
523 if (verbosity > 0)
524 fprintf (out, "Integer ");
525 num = JPOOL_INT (jcf, index);
526 goto integer;
527 case CONSTANT_Long:
528 if (verbosity > 0)
529 fprintf (out, "Long ");
530 num = JPOOL_LONG (jcf, index);
531 goto integer;
532 integer:
534 char buffer[25];
535 format_int (buffer, num, 10);
536 fprintf (out, "%s", buffer);
537 if (verbosity > 1)
539 format_uint (buffer, (uint64)num, 16);
540 fprintf (out, "=0x%s", buffer);
543 break;
544 case CONSTANT_Float:
546 jfloat fnum = JPOOL_FLOAT (jcf, index);
548 if (verbosity > 0)
549 fputs ("Float ", out);
551 if (fnum.negative)
552 putc ('-', out);
554 if (JFLOAT_FINITE (fnum))
556 int dummy;
557 int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
558 double f;
559 uint32 mantissa = fnum.mantissa;
560 if (fnum.exponent == 0)
561 /* Denormal. */
562 exponent++;
563 else
564 /* Normal; add the implicit bit. */
565 mantissa |= ((uint32)1 << 23);
567 f = frexp (mantissa, &dummy);
568 f = ldexp (f, exponent + 1);
569 fprintf (out, "%.10g", f);
571 else
573 if (fnum.mantissa == 0)
574 fputs ("Inf", out);
575 else if (fnum.mantissa & JFLOAT_QNAN_MASK)
576 fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
577 else
578 fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
581 if (verbosity > 1)
582 fprintf (out, ", bits = 0x%08lx", (long) JPOOL_UINT (jcf, index));
584 break;
586 case CONSTANT_Double:
588 jdouble dnum = JPOOL_DOUBLE (jcf, index);
590 if (verbosity > 0)
591 fputs ("Double ", out);
593 if (dnum.negative)
594 putc ('-', out);
596 if (JDOUBLE_FINITE (dnum))
598 int dummy;
599 int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
600 double d;
601 uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
602 + dnum.mantissa1);
603 if (dnum.exponent == 0)
604 /* Denormal. */
605 exponent++;
606 else
607 /* Normal; add the implicit bit. */
608 mantissa |= ((uint64)1 << 52);
610 d = frexp (mantissa, &dummy);
611 d = ldexp (d, exponent + 1);
612 fprintf (out, "%.20g", d);
614 else
616 uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
617 mantissa = (mantissa << 32) + dnum.mantissa1;
619 if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
620 fputs ("Inf", out);
621 else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
622 fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
623 else
624 fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
626 if (verbosity > 1)
628 int32 hi, lo;
629 hi = JPOOL_UINT (jcf, index);
630 lo = JPOOL_UINT (jcf, index + 1);
631 fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
633 break;
635 case CONSTANT_NameAndType:
637 uint16 name = JPOOL_USHORT1 (jcf, index);
638 uint16 sig = JPOOL_USHORT2 (jcf, index);
639 if (verbosity > 0)
641 if (verbosity > 1)
642 fprintf (out, "NameAndType name: %d=", name);
643 else
644 fprintf (out, "NameAndType ");
646 print_name (out, jcf, name);
647 if (verbosity <= 1)
648 fputc (' ', out);
649 else
650 fprintf (out, ", signature: %d=", sig);
651 print_signature (out, jcf, sig, 0);
653 break;
654 case CONSTANT_Utf8:
656 const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
657 int length = JPOOL_UTF_LENGTH (jcf, index);
658 if (verbosity > 0)
659 { /* Print as 8-bit bytes. */
660 fputs ("Utf8: \"", out);
661 while (--length >= 0)
662 jcf_print_char (out, *str++);
664 else
665 { /* Print as Unicode. */
666 fputc ('\"', out);
667 jcf_print_utf8 (out, str, length);
669 fputc ('\"', out);
671 break;
672 default:
673 fprintf (out, "(Unknown constant type %d)", kind);
677 static void
678 print_constant_pool (JCF *jcf)
680 int i;
681 for (i = 1; i < JPOOL_SIZE(jcf); i++)
683 int kind = JPOOL_TAG (jcf, i);
684 fprintf (out, "#%d: ", i);
685 print_constant (out, jcf, i, 2);
686 fprintf (out, "\n");
687 if (kind == CONSTANT_Double || kind == CONSTANT_Long)
688 i++; /* These take up two slots in the constant table */
692 static void
693 print_signature_type (FILE* stream, const unsigned char **ptr,
694 const unsigned char *limit)
696 int array_size;
697 if ((*ptr) >= limit)
698 return;
699 switch (*(*ptr))
701 case '[':
702 array_size = -1;
703 for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
705 array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
707 print_signature_type (stream, ptr, limit);
708 if (array_size == -1)
709 fprintf (stream, "[]");
710 else
711 fprintf (stream, "[%d]", array_size);
712 break;
713 case '(':
715 int nargs = 0;
716 fputc (*(*ptr)++, stream);
717 for (; **ptr != ')' && *ptr < limit; nargs++)
719 if (nargs > 0)
720 fputc (',', stream);
721 print_signature_type (stream, ptr, limit);
723 if (*ptr < limit)
725 fputc (*(*ptr)++, stream);
726 print_signature_type (stream, ptr, limit);
728 else
729 fprintf (stream, "???");
731 break;
733 case 'B': fprintf (stream, "byte"); (*ptr)++; break;
734 case 'C': fprintf (stream, "char"); (*ptr)++; break;
735 case 'D': fprintf (stream, "double"); (*ptr)++; break;
736 case 'F': fprintf (stream, "float"); (*ptr)++; break;
737 case 'S': fprintf (stream, "short"); (*ptr)++; break;
738 case 'I': fprintf (stream, "int"); (*ptr)++; break;
739 case 'J': fprintf (stream, "long"); (*ptr)++; break;
740 case 'Z': fprintf (stream, "boolean"); (*ptr)++; break;
741 case 'V': fprintf (stream, "void"); (*ptr)++; break;
743 case 'L':
744 for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
745 jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
746 if (*(*ptr) == ';')
747 (*ptr)++;
748 break;
749 default:
750 jcf_print_char (stream, *(*ptr)++);
754 static void
755 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
757 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
758 print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
759 else
761 const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
762 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
763 const unsigned char *limit;
764 limit = str + length;
765 if (str >= limit)
766 fprintf (stream, "<empty signature string>");
767 else
769 if (options & PRINT_SIGNATURE_RESULT_ONLY)
771 while (str < limit && *str++ != ')') ;
773 if (options & PRINT_SIGNATURE_ARGS_ONLY)
775 str++;
776 fputc ('(', stream);
777 while (str < limit && *str != ')')
779 print_signature_type (stream, &str, limit);
780 if (*str != ')')
781 fputs (", ", stream);
783 fputc (')', stream);
785 else
787 print_signature_type (stream, &str, limit);
788 if (str < limit)
790 fprintf (stream, "<junk:");
791 jcf_print_utf8 (stream, str, limit - str);
792 fputc ('>', stream);
800 static void
801 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
803 /* Print exception table. */
804 int i = count;
805 if (i > 0)
807 const unsigned char *ptr = entries;
808 fprintf (out, "Exceptions (count: %d):\n", i);
809 for (; --i >= 0; ptr+= 8)
811 int start_pc = GET_u2 (ptr);
812 int end_pc = GET_u2 (ptr+2);
813 int handler_pc = GET_u2 (ptr+4);
814 int catch_type = GET_u2 (ptr+6);
815 fprintf (out, " start: %d, end: %d, handler: %d, type: ",
816 start_pc, end_pc, handler_pc);
817 if (catch_type == 0)
818 fputs ("0 /* finally */", out);
819 else
820 print_constant_terse_with_index (out, jcf,
821 catch_type, CONSTANT_Class);
822 fputc ('\n', out);
827 #include "jcf-reader.c"
829 static void
830 process_class (JCF *jcf)
832 int code;
833 if (jcf_parse_preamble (jcf) != 0)
834 fprintf (stderr, _("Not a valid Java .class file.\n"));
836 /* Parse and possibly print constant pool */
837 code = jcf_parse_constant_pool (jcf);
838 if (code != 0)
840 fprintf (stderr, _("error while parsing constant pool\n"));
841 exit (FATAL_EXIT_CODE);
843 code = verify_constant_pool (jcf);
844 if (code > 0)
846 fprintf (stderr, _("error in constant pool entry #%d\n"), code);
847 exit (FATAL_EXIT_CODE);
849 if (flag_print_constant_pool)
850 print_constant_pool (jcf);
852 jcf_parse_class (jcf);
853 code = jcf_parse_fields (jcf);
854 if (code != 0)
856 fprintf (stderr, _("error while parsing fields\n"));
857 exit (FATAL_EXIT_CODE);
859 code = jcf_parse_methods (jcf);
860 if (code != 0)
862 fprintf (stderr, _("error while parsing methods\n"));
863 exit (FATAL_EXIT_CODE);
865 code = jcf_parse_final_attributes (jcf);
866 if (code != 0)
868 fprintf (stderr, _("error while parsing final attributes\n"));
869 exit (FATAL_EXIT_CODE);
871 jcf->filename = NULL;
876 /* This is used to mark options with no short value. */
877 #define LONG_OPT(Num) ((Num) + 128)
879 #define OPT_classpath LONG_OPT (0)
880 #define OPT_CLASSPATH OPT_classpath
881 #define OPT_bootclasspath LONG_OPT (1)
882 #define OPT_extdirs LONG_OPT (2)
883 #define OPT_HELP LONG_OPT (3)
884 #define OPT_VERSION LONG_OPT (4)
885 #define OPT_JAVAP LONG_OPT (5)
887 static const struct option options[] =
889 { "classpath", required_argument, NULL, OPT_classpath },
890 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
891 { "extdirs", required_argument, NULL, OPT_extdirs },
892 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
893 { "help", no_argument, NULL, OPT_HELP },
894 { "verbose", no_argument, NULL, 'v' },
895 { "version", no_argument, NULL, OPT_VERSION },
896 { "javap", no_argument, NULL, OPT_JAVAP },
897 { "print-main", no_argument, &flag_print_main, 1 },
898 { "print-constants", no_argument, &flag_print_constant_pool, 1 },
899 { NULL, no_argument, NULL, 0 }
902 static void
903 usage (void)
905 fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
906 exit (1);
909 static void
910 help (void)
912 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
913 printf (_("Display contents of a class file in readable form.\n\n"));
914 printf (_(" -c Disassemble method bodies\n"));
915 printf (_(" --javap Generate output in 'javap' format\n"));
916 printf ("\n");
917 printf (_(" --classpath PATH Set path to find .class files\n"));
918 printf (_(" -IDIR Append directory to class path\n"));
919 printf (_(" --bootclasspath PATH Override built-in class path\n"));
920 printf (_(" --extdirs PATH Set extensions directory path\n"));
921 printf (_(" -o FILE Set output file name\n"));
922 printf ("\n");
923 printf (_(" --help Print this help, then exit\n"));
924 printf (_(" --version Print version number, then exit\n"));
925 printf (_(" -v, --verbose Print extra information while running\n"));
926 printf ("\n");
927 printf (_("For bug reporting instructions, please see:\n"
928 "%s.\n"), bug_report_url);
929 exit (0);
932 static void
933 version (void)
935 printf ("jcf-dump (GCC) %s\n\n", version_string);
936 printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
937 printf (_("This is free software; see the source for copying conditions. There is NO\n"
938 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
939 exit (0);
943 main (int argc, char** argv)
945 JCF jcf[1];
946 int argi, opt;
948 /* Unlock the stdio streams. */
949 unlock_std_streams ();
951 gcc_init_libintl ();
953 if (argc <= 1)
955 fprintf (stderr, _("jcf-dump: no classes specified\n"));
956 usage ();
959 jcf_path_init ();
961 /* We use getopt_long_only to allow single `-' long options. For
962 some of our options this is more natural. */
963 while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
965 switch (opt)
967 case 0:
968 /* Already handled. */
969 break;
971 case 'o':
972 output_file = optarg;
973 break;
975 case 'I':
976 jcf_path_include_arg (optarg);
977 break;
979 case 'v':
980 verbose++;
981 break;
983 case 'c':
984 flag_disassemble_methods = 1;
985 break;
987 case OPT_classpath:
988 jcf_path_classpath_arg (optarg);
989 break;
991 case OPT_bootclasspath:
992 jcf_path_bootclasspath_arg (optarg);
993 break;
995 case OPT_extdirs:
996 jcf_path_extdirs_arg (optarg);
997 break;
999 case OPT_HELP:
1000 help ();
1001 break;
1003 case OPT_VERSION:
1004 version ();
1005 break;
1007 case OPT_JAVAP:
1008 flag_javap_compatible++;
1009 flag_print_constant_pool = 0;
1010 flag_print_attributes = 0;
1011 break;
1013 default:
1014 usage ();
1018 if (verbose && ! flag_javap_compatible)
1019 flag_print_constant_pool = 1;
1021 if (optind == argc)
1023 fprintf (stderr, _("jcf-dump: no classes specified\n"));
1024 usage ();
1027 jcf_path_seal (verbose);
1029 if (flag_print_main)
1031 flag_print_fields = 0;
1032 flag_print_methods = 0;
1033 flag_print_constant_pool = 0;
1034 flag_print_attributes = 0;
1035 flag_print_class_info = 0;
1038 if (output_file)
1040 out = fopen (output_file, "w");
1041 if (! out)
1043 fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1044 return FATAL_EXIT_CODE;
1047 else
1048 out = stdout;
1050 if (optind >= argc)
1052 fprintf (out, "Reading .class from <standard input>.\n");
1053 open_class ("<stdio>", jcf, 0, NULL);
1054 process_class (jcf);
1056 else
1058 for (argi = optind; argi < argc; argi++)
1060 char *arg = argv[argi];
1061 const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1062 if (class_filename == NULL)
1063 class_filename = find_classfile (arg, jcf, NULL);
1064 if (class_filename == NULL)
1066 perror ("Could not find class");
1067 return FATAL_EXIT_CODE;
1069 JCF_FILL (jcf, 4);
1070 if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1072 long compressed_size, member_size;
1073 int compression_method, filename_length, extra_length;
1074 int general_purpose_bits;
1075 const char *filename;
1076 int total_length;
1077 if (flag_print_class_info)
1078 fprintf (out, "Reading classes from archive %s.\n",
1079 class_filename);
1080 for (;;)
1082 int skip = 0;
1083 jcf_filbuf_t save_filbuf = jcf->filbuf;
1084 long magic = JCF_readu4_le (jcf);
1085 if (magic == 0x02014b50 || magic == 0x06054b50)
1086 break; /* got to central directory */
1087 if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1089 fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1090 return FATAL_EXIT_CODE;
1092 JCF_FILL (jcf, 26);
1093 JCF_SKIP (jcf, 2);
1094 general_purpose_bits = JCF_readu2_le (jcf);
1095 compression_method = JCF_readu2_le (jcf);
1096 JCF_SKIP (jcf, 8);
1097 compressed_size = JCF_readu4_le (jcf);
1098 member_size = JCF_readu4_le (jcf);
1099 filename_length = JCF_readu2_le (jcf);
1100 extra_length = JCF_readu2_le (jcf);
1101 total_length = filename_length + extra_length
1102 + compressed_size;
1103 if (jcf->read_end - jcf->read_ptr < total_length)
1104 jcf_trim_old_input (jcf);
1105 JCF_FILL (jcf, total_length);
1106 filename = (const char *) jcf->read_ptr;
1107 JCF_SKIP (jcf, filename_length);
1108 JCF_SKIP (jcf, extra_length);
1109 if (filename_length > 0
1110 && filename[filename_length-1] == '/')
1112 if (flag_print_class_info)
1113 fprintf (out, "[Skipping directory %.*s]\n",
1114 filename_length, filename);
1115 skip = 1;
1117 else if (compression_method != 0)
1119 if (flag_print_class_info)
1120 fprintf (out, "[Skipping compressed file %.*s]\n",
1121 filename_length, filename);
1122 skip = 1;
1124 else if (member_size < 4
1125 || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1127 if (flag_print_class_info)
1128 fprintf (out, "[Skipping non-.class member %.*s]\n",
1129 filename_length, filename);
1130 skip = 1;
1132 else
1134 if (flag_print_class_info)
1135 fprintf (out, "Reading class member: %.*s.\n",
1136 filename_length, filename);
1138 if (skip)
1140 JCF_SKIP (jcf, compressed_size);
1142 else
1144 unsigned char *save_end;
1145 jcf->filbuf = jcf_unexpected_eof;
1146 save_end = jcf->read_end;
1147 jcf->read_end = jcf->read_ptr + compressed_size;
1148 process_class (jcf);
1149 jcf->filbuf = save_filbuf;
1150 jcf->read_end = save_end;
1154 else
1156 if (flag_print_class_info)
1157 fprintf (out, "Reading .class from %s.\n", class_filename);
1158 process_class (jcf);
1160 JCF_FINISH(jcf);
1164 return SUCCESS_EXIT_CODE;
1169 static void
1170 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1172 #undef PTR
1173 int PC;
1174 int i;
1175 int saw_wide = 0;
1176 if (flag_disassemble_methods == 0)
1177 return;
1178 #define BCODE byte_ops
1179 for (PC = 0; PC < len;)
1181 int oldpc = PC;
1182 int saw_index;
1183 jint INT_temp;
1184 switch (byte_ops[PC++])
1187 /* This is the actual code emitted for each of opcodes in javaops.def.
1188 The actual opcode-specific stuff is handled by the OPKIND macro.
1189 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1190 Those macros are defined below. The OPKINDs that do not have any
1191 inline parameters (such as BINOP) and therefore do mot need anything
1192 else to me printed out just use an empty body. */
1194 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1195 case OPCODE: \
1196 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1197 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1198 fputc ('\n', out); \
1199 break;
1201 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1202 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1203 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1204 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1206 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1207 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1209 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1210 These all push a constant onto the opcode stack. */
1211 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1212 saw_index = 0, i = (OPERAND_VALUE); \
1213 if (oldpc+1 == PC) /* nothing */; \
1214 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1215 else fprintf (out, " %d", i);
1217 /* Print out operand (a local variable index) for LOAD opcodes.
1218 These all push local variable onto the opcode stack. */
1219 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1220 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1222 /* Handle STORE opcodes same as LOAD opcodes.
1223 These all store a value from the opcode stack in a local variable. */
1224 #define STORE LOAD
1226 /* Handle more kind of opcodes. */
1227 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1228 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1229 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1230 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1231 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1232 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1233 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1235 /* Handle putfield and getfield opcodes, with static versions. */
1236 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1237 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1239 /* Print operand for invoke opcodes. */
1240 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1241 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1242 if (OPERAND_VALUE) /* for invokeinterface */ \
1243 { int nargs = IMMEDIATE_u1; PC++; \
1244 fprintf (out, " nargs:%d", nargs); }
1246 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1247 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1249 #define ARRAY(OPERAND_TYPE, SUBOP) \
1250 ARRAY_##SUBOP(OPERAND_TYPE)
1251 /* Handle sub-categories of ARRAY opcodes. */
1252 #define ARRAY_LOAD(TYPE) /* nothing */
1253 #define ARRAY_STORE(TYPE) /* nothing */
1254 #define ARRAY_LENGTH(TYPE) /* nothing */
1255 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1256 #define ARRAY_NEW_NUM \
1257 INT_temp = IMMEDIATE_u1; \
1258 { switch ((int) INT_temp) { \
1259 case 4: fputs (" boolean", out); break; \
1260 case 5: fputs (" char", out); break; \
1261 case 6: fputs (" float", out); break; \
1262 case 7: fputs (" double", out); break; \
1263 case 8: fputs (" byte", out); break; \
1264 case 9: fputs (" short", out); break; \
1265 case 10: fputs (" int", out); break; \
1266 case 11: fputs (" long", out); break; \
1267 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1270 #define ARRAY_NEW_PTR \
1271 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1273 #define ARRAY_NEW_MULTI \
1274 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1275 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1277 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1278 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1280 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1281 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1282 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1284 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1285 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1286 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1288 #undef RET /* Defined by config/i386/i386.h */
1289 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1290 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1291 saw_wide = 0; \
1292 fprintf (out, " %ld", (long) INT_temp);
1294 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1295 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1297 #define LOOKUP_SWITCH \
1298 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1299 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1300 while (--npairs >= 0) { \
1301 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1302 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1305 #define TABLE_SWITCH \
1306 { jint default_offset = IMMEDIATE_s4; \
1307 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1308 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1309 (long) low, (long) high, (long) default_offset+oldpc); \
1310 for (; low <= high; low++) { \
1311 jint offset = IMMEDIATE_s4; \
1312 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1315 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1316 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1318 #define SPECIAL_IINC(OPERAND_TYPE) \
1319 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1320 fprintf (out, " %d", i); \
1321 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1322 saw_wide = 0; \
1323 fprintf (out, " %d", i)
1325 #define SPECIAL_WIDE(OPERAND_TYPE) \
1326 saw_wide = 1;
1328 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1329 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1330 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1331 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1333 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1334 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1336 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1337 TEST(OPERAND_TYPE, OPERAND_VALUE)
1339 #include "javaop.def"
1341 load_store:
1342 if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1343 else
1345 saw_wide = 0;
1346 fprintf (out, " %ld", (long) INT_temp);
1348 fputc ('\n', out);
1349 break;
1351 default:
1352 fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);