* jcf-dump.c, jcf-io.c, jcf-reader.c, lang.c, parse.h,
[official-gcc.git] / gcc / java / jcf-dump.c
blobc3fd9f1bf4d3e329647228c3ed1fb7d87d4d28ec
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 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, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, 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 /* Outout 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 print_constant_terse_with_index (out, jcf, \
324 inner_class_info_index, CONSTANT_Class); \
325 if (inner_name_index == 0) \
326 fprintf (out, " (anonymous)"); \
327 else if (verbose || flag_print_constant_pool) \
329 fprintf (out, " ("); \
330 print_constant_terse_with_index (out, jcf, inner_name_index, \
331 CONSTANT_Utf8); \
332 fputc (')', out); \
334 fprintf (out, ", access flags: 0x%x", inner_class_access_flags); \
335 print_access_flags (out, inner_class_access_flags, 'c'); \
336 fprintf (out, ", outer class: "); \
337 print_constant_terse_with_index (out, jcf, \
338 outer_class_info_index, CONSTANT_Class); \
341 if (flag_print_class_info) \
342 fputc ('\n', out); \
345 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
346 { int i, n = (LENGTH), c = 0; \
347 COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
348 fputc ('\n', out); \
349 for (i = 0; i < n; i++) { c = JCF_readu(jcf); fputc(c, out); } \
350 if (c != '\r' && c != '\n') fputc('\n', out); }
352 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
353 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
354 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
356 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
357 if (flag_print_attributes > 0) \
358 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
360 #include "javaop.h"
362 static void
363 print_constant_ref (FILE *stream, JCF *jcf, int index)
365 if (index <= 0 || index >= JPOOL_SIZE(jcf))
366 fprintf (stream, "<out of range>");
367 else
369 if (flag_print_constant_pool)
370 fprintf (stream, "#%d=", index);
371 fputc ('<', stream);
372 print_constant (stream, jcf, index, 1);
373 fputc ('>', stream);
377 /* Print the access flags given by FLAGS.
378 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
379 or 'm' (method flags). */
381 static void
382 print_access_flags (FILE *stream, uint16 flags, char context)
384 if (flags & ACC_PUBLIC) fprintf (stream, " public");
385 if (flags & ACC_PRIVATE) fprintf (stream, " private");
386 if (flags & ACC_PROTECTED) fprintf (stream, " protected");
387 if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
388 if (flags & ACC_STATIC) fprintf (stream, " static");
389 if (flags & ACC_FINAL) fprintf (stream, " final");
390 if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
391 if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
392 if (flags & ACC_NATIVE) fprintf (stream, " native");
393 if (flags & ACC_SYNCHRONIZED)
395 if (context == 'c')
396 fprintf (stream, " super");
397 else
398 fprintf (stream, " synchronized");
400 if (flags & ACC_INTERFACE) fprintf (stream, " interface");
401 if (flags & ACC_STRICT) fprintf (stream, " strictfp");
405 static void
406 print_name (FILE* stream, JCF* jcf, int name_index)
408 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
409 fprintf (stream, "<not a UTF8 constant>");
410 else
411 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
412 JPOOL_UTF_LENGTH (jcf, name_index));
415 /* If the type of the constant at INDEX matches EXPECTED,
416 print it tersely, otherwise more verbosely. */
418 static void
419 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
421 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
422 fprintf (out, "<constant pool index %d not in range>", index);
423 else if (JPOOL_TAG (jcf, index) != expected)
425 fprintf (out, "<Unexpected constant type ");
426 print_constant (out, jcf, index, 1);
427 fprintf (out, ">");
429 else
430 print_constant (out, jcf, index, 0);
433 static void
434 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
436 if (flag_print_constant_pool)
437 fprintf (out, "%d=", index);
438 print_constant_terse (out, jcf, index, expected);
441 /* Print the constant at INDEX in JCF's constant pool.
442 If verbosity==0, print very tersely (no extraneous text).
443 If verbosity==1, prefix the type of the constant.
444 If verbosity==2, add more descriptive text. */
446 static void
447 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
449 int j, n;
450 jlong num;
451 const char *str;
452 int kind = JPOOL_TAG (jcf, index);
453 switch (kind)
455 case CONSTANT_Class:
456 n = JPOOL_USHORT1 (jcf, index);
457 if (verbosity > 0)
459 if (verbosity > 1)
460 fprintf (out, "Class name: %d=", n);
461 else
462 fprintf (out, "Class ");
464 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
465 fprintf (out, "<out of range>");
466 else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
468 int len = JPOOL_UTF_LENGTH (jcf, n);
469 jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
471 else
472 print_constant_terse (out, jcf, n, CONSTANT_Utf8);
473 break;
474 case CONSTANT_Fieldref:
475 str = "Field"; goto field_or_method;
476 case CONSTANT_Methodref:
477 str = "Method"; goto field_or_method;
478 case CONSTANT_InterfaceMethodref:
479 str = "InterfaceMethod"; goto field_or_method;
480 field_or_method:
482 uint16 tclass = JPOOL_USHORT1 (jcf, index);
483 uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
484 if (verbosity == 2)
485 fprintf (out, "%sref class: %d=", str, tclass);
486 else if (verbosity > 0)
487 fprintf (out, "%s ", str);
488 print_constant_terse (out, jcf, tclass, CONSTANT_Class);
489 if (verbosity < 2)
490 fprintf (out, ".");
491 else
492 fprintf (out, " name_and_type: %d=<", name_and_type);
493 print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
494 if (verbosity == 2)
495 fputc ('>', out);
497 break;
498 case CONSTANT_String:
499 j = JPOOL_USHORT1 (jcf, index);
500 if (verbosity > 0)
502 if (verbosity > 1)
503 fprintf (out, "String %d=", j);
504 else
505 fprintf (out, "String ");
507 print_constant_terse (out, jcf, j, CONSTANT_Utf8);
508 break;
509 case CONSTANT_Integer:
510 if (verbosity > 0)
511 fprintf (out, "Integer ");
512 num = JPOOL_INT (jcf, index);
513 goto integer;
514 case CONSTANT_Long:
515 if (verbosity > 0)
516 fprintf (out, "Long ");
517 num = JPOOL_LONG (jcf, index);
518 goto integer;
519 integer:
521 char buffer[25];
522 format_int (buffer, num, 10);
523 fprintf (out, "%s", buffer);
524 if (verbosity > 1)
526 format_uint (buffer, (uint64)num, 16);
527 fprintf (out, "=0x%s", buffer);
530 break;
531 case CONSTANT_Float:
533 jfloat fnum = JPOOL_FLOAT (jcf, index);
535 if (verbosity > 0)
536 fputs ("Float ", out);
538 if (fnum.negative)
539 putc ('-', out);
541 if (JFLOAT_FINITE (fnum))
543 int dummy;
544 int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
545 double f;
546 uint32 mantissa = fnum.mantissa;
547 if (fnum.exponent == 0)
548 /* Denormal. */
549 exponent++;
550 else
551 /* Normal; add the implicit bit. */
552 mantissa |= ((uint32)1 << 23);
554 f = frexp (mantissa, &dummy);
555 f = ldexp (f, exponent + 1);
556 fprintf (out, "%.10g", f);
558 else
560 if (fnum.mantissa == 0)
561 fputs ("Inf", out);
562 else if (fnum.mantissa & JFLOAT_QNAN_MASK)
563 fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
564 else
565 fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
568 if (verbosity > 1)
569 fprintf (out, ", bits = 0x%08lx", JPOOL_UINT (jcf, index));
571 break;
573 case CONSTANT_Double:
575 jdouble dnum = JPOOL_DOUBLE (jcf, index);
577 if (verbosity > 0)
578 fputs ("Double ", out);
580 if (dnum.negative)
581 putc ('-', out);
583 if (JDOUBLE_FINITE (dnum))
585 int dummy;
586 int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
587 double d;
588 uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
589 + dnum.mantissa1);
590 if (dnum.exponent == 0)
591 /* Denormal. */
592 exponent++;
593 else
594 /* Normal; add the implicit bit. */
595 mantissa |= ((uint64)1 << 52);
597 d = frexp (mantissa, &dummy);
598 d = ldexp (d, exponent + 1);
599 fprintf (out, "%.20g", d);
601 else
603 uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
604 mantissa = (mantissa << 32) + dnum.mantissa1;
606 if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
607 fputs ("Inf", out);
608 else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
609 fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
610 else
611 fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
613 if (verbosity > 1)
615 int32 hi, lo;
616 hi = JPOOL_UINT (jcf, index);
617 lo = JPOOL_UINT (jcf, index + 1);
618 fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
620 break;
622 case CONSTANT_NameAndType:
624 uint16 name = JPOOL_USHORT1 (jcf, index);
625 uint16 sig = JPOOL_USHORT2 (jcf, index);
626 if (verbosity > 0)
628 if (verbosity > 1)
629 fprintf (out, "NameAndType name: %d=", name);
630 else
631 fprintf (out, "NameAndType ");
633 print_name (out, jcf, name);
634 if (verbosity <= 1)
635 fputc (' ', out);
636 else
637 fprintf (out, ", signature: %d=", sig);
638 print_signature (out, jcf, sig, 0);
640 break;
641 case CONSTANT_Utf8:
643 const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
644 int length = JPOOL_UTF_LENGTH (jcf, index);
645 if (verbosity > 0)
646 { /* Print as 8-bit bytes. */
647 fputs ("Utf8: \"", out);
648 while (--length >= 0)
649 jcf_print_char (out, *str++);
651 else
652 { /* Print as Unicode. */
653 fputc ('\"', out);
654 jcf_print_utf8 (out, str, length);
656 fputc ('\"', out);
658 break;
659 default:
660 fprintf (out, "(Unknown constant type %d)", kind);
664 static void
665 print_constant_pool (JCF *jcf)
667 int i;
668 for (i = 1; i < JPOOL_SIZE(jcf); i++)
670 int kind = JPOOL_TAG (jcf, i);
671 fprintf (out, "#%d: ", i);
672 print_constant (out, jcf, i, 2);
673 fprintf (out, "\n");
674 if (kind == CONSTANT_Double || kind == CONSTANT_Long)
675 i++; /* These take up two slots in the constant table */
679 static void
680 print_signature_type (FILE* stream, const unsigned char **ptr,
681 const unsigned char *limit)
683 int array_size;
684 if ((*ptr) >= limit)
685 return;
686 switch (*(*ptr))
688 case '[':
689 array_size = -1;
690 for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
692 array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
694 print_signature_type (stream, ptr, limit);
695 if (array_size == -1)
696 fprintf (stream, "[]");
697 else
698 fprintf (stream, "[%d]", array_size);
699 break;
700 case '(':
702 int nargs = 0;
703 fputc (*(*ptr)++, stream);
704 for (; **ptr != ')' && *ptr < limit; nargs++)
706 if (nargs > 0)
707 fputc (',', stream);
708 print_signature_type (stream, ptr, limit);
710 if (*ptr < limit)
712 fputc (*(*ptr)++, stream);
713 print_signature_type (stream, ptr, limit);
715 else
716 fprintf (stream, "???");
718 break;
720 case 'B': fprintf (stream, "byte"); (*ptr)++; break;
721 case 'C': fprintf (stream, "char"); (*ptr)++; break;
722 case 'D': fprintf (stream, "double"); (*ptr)++; break;
723 case 'F': fprintf (stream, "float"); (*ptr)++; break;
724 case 'S': fprintf (stream, "short"); (*ptr)++; break;
725 case 'I': fprintf (stream, "int"); (*ptr)++; break;
726 case 'J': fprintf (stream, "long"); (*ptr)++; break;
727 case 'Z': fprintf (stream, "boolean"); (*ptr)++; break;
728 case 'V': fprintf (stream, "void"); (*ptr)++; break;
730 case 'L':
731 for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
732 jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
733 if (*(*ptr) == ';')
734 (*ptr)++;
735 break;
736 default:
737 jcf_print_char (stream, *(*ptr)++);
741 static void
742 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
744 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
745 print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
746 else
748 const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
749 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
750 const unsigned char *limit;
751 limit = str + length;
752 if (str >= limit)
753 fprintf (stream, "<empty signature string>");
754 else
756 if (options & PRINT_SIGNATURE_RESULT_ONLY)
758 while (str < limit && *str++ != ')') ;
760 if (options & PRINT_SIGNATURE_ARGS_ONLY)
762 str++;
763 fputc ('(', stream);
764 while (str < limit && *str != ')')
766 print_signature_type (stream, &str, limit);
767 if (*str != ')')
768 fputs (", ", stream);
770 fputc (')', stream);
772 else
774 print_signature_type (stream, &str, limit);
775 if (str < limit)
777 fprintf (stream, "<junk:");
778 jcf_print_utf8 (stream, str, limit - str);
779 fputc ('>', stream);
787 static void
788 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
790 /* Print exception table. */
791 int i = count;
792 if (i > 0)
794 const unsigned char *ptr = entries;
795 fprintf (out, "Exceptions (count: %d):\n", i);
796 for (; --i >= 0; ptr+= 8)
798 int start_pc = GET_u2 (ptr);
799 int end_pc = GET_u2 (ptr+2);
800 int handler_pc = GET_u2 (ptr+4);
801 int catch_type = GET_u2 (ptr+6);
802 fprintf (out, " start: %d, end: %d, handler: %d, type: ",
803 start_pc, end_pc, handler_pc);
804 if (catch_type == 0)
805 fputs ("0 /* finally */", out);
806 else
807 print_constant_terse_with_index (out, jcf,
808 catch_type, CONSTANT_Class);
809 fputc ('\n', out);
814 #include "jcf-reader.c"
816 static void
817 process_class (JCF *jcf)
819 int code;
820 if (jcf_parse_preamble (jcf) != 0)
821 fprintf (stderr, _("Not a valid Java .class file.\n"));
823 /* Parse and possibly print constant pool */
824 code = jcf_parse_constant_pool (jcf);
825 if (code != 0)
827 fprintf (stderr, _("error while parsing constant pool\n"));
828 exit (FATAL_EXIT_CODE);
830 code = verify_constant_pool (jcf);
831 if (code > 0)
833 fprintf (stderr, _("error in constant pool entry #%d\n"), code);
834 exit (FATAL_EXIT_CODE);
836 if (flag_print_constant_pool)
837 print_constant_pool (jcf);
839 jcf_parse_class (jcf);
840 code = jcf_parse_fields (jcf);
841 if (code != 0)
843 fprintf (stderr, _("error while parsing fields\n"));
844 exit (FATAL_EXIT_CODE);
846 code = jcf_parse_methods (jcf);
847 if (code != 0)
849 fprintf (stderr, _("error while parsing methods\n"));
850 exit (FATAL_EXIT_CODE);
852 code = jcf_parse_final_attributes (jcf);
853 if (code != 0)
855 fprintf (stderr, _("error while parsing final attributes\n"));
856 exit (FATAL_EXIT_CODE);
858 jcf->filename = NULL;
863 /* This is used to mark options with no short value. */
864 #define LONG_OPT(Num) ((Num) + 128)
866 #define OPT_classpath LONG_OPT (0)
867 #define OPT_CLASSPATH OPT_classpath
868 #define OPT_bootclasspath LONG_OPT (1)
869 #define OPT_extdirs LONG_OPT (2)
870 #define OPT_HELP LONG_OPT (3)
871 #define OPT_VERSION LONG_OPT (4)
872 #define OPT_JAVAP LONG_OPT (5)
874 static const struct option options[] =
876 { "classpath", required_argument, NULL, OPT_classpath },
877 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
878 { "extdirs", required_argument, NULL, OPT_extdirs },
879 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
880 { "help", no_argument, NULL, OPT_HELP },
881 { "verbose", no_argument, NULL, 'v' },
882 { "version", no_argument, NULL, OPT_VERSION },
883 { "javap", no_argument, NULL, OPT_JAVAP },
884 { "print-main", no_argument, &flag_print_main, 1 },
885 { "print-constants", no_argument, &flag_print_constant_pool, 1 },
886 { NULL, no_argument, NULL, 0 }
889 static void
890 usage (void)
892 fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
893 exit (1);
896 static void
897 help (void)
899 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
900 printf (_("Display contents of a class file in readable form.\n\n"));
901 printf (_(" -c Disassemble method bodies\n"));
902 printf (_(" --javap Generate output in 'javap' format\n"));
903 printf ("\n");
904 printf (_(" --classpath PATH Set path to find .class files\n"));
905 printf (_(" -IDIR Append directory to class path\n"));
906 printf (_(" --bootclasspath PATH Override built-in class path\n"));
907 printf (_(" --extdirs PATH Set extensions directory path\n"));
908 printf (_(" -o FILE Set output file name\n"));
909 printf ("\n");
910 printf (_(" --help Print this help, then exit\n"));
911 printf (_(" --version Print version number, then exit\n"));
912 printf (_(" -v, --verbose Print extra information while running\n"));
913 printf ("\n");
914 printf (_("For bug reporting instructions, please see:\n"
915 "%s.\n"), bug_report_url);
916 exit (0);
919 static void
920 version (void)
922 printf ("jcf-dump (GCC) %s\n\n", version_string);
923 printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
924 printf (_("This is free software; see the source for copying conditions. There is NO\n"
925 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
926 exit (0);
930 main (int argc, char** argv)
932 JCF jcf[1];
933 int argi, opt;
935 gcc_init_libintl ();
937 if (argc <= 1)
939 fprintf (stderr, _("jcf-dump: no classes specified\n"));
940 usage ();
943 jcf_path_init ();
945 /* We use getopt_long_only to allow single `-' long options. For
946 some of our options this is more natural. */
947 while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
949 switch (opt)
951 case 0:
952 /* Already handled. */
953 break;
955 case 'o':
956 output_file = optarg;
957 break;
959 case 'I':
960 jcf_path_include_arg (optarg);
961 break;
963 case 'v':
964 verbose++;
965 break;
967 case 'c':
968 flag_disassemble_methods = 1;
969 break;
971 case OPT_classpath:
972 jcf_path_classpath_arg (optarg);
973 break;
975 case OPT_bootclasspath:
976 jcf_path_bootclasspath_arg (optarg);
977 break;
979 case OPT_extdirs:
980 jcf_path_extdirs_arg (optarg);
981 break;
983 case OPT_HELP:
984 help ();
985 break;
987 case OPT_VERSION:
988 version ();
989 break;
991 case OPT_JAVAP:
992 flag_javap_compatible++;
993 flag_print_constant_pool = 0;
994 flag_print_attributes = 0;
995 break;
997 default:
998 usage ();
1002 if (verbose && ! flag_javap_compatible)
1003 flag_print_constant_pool = 1;
1005 if (optind == argc)
1007 fprintf (stderr, _("jcf-dump: no classes specified\n"));
1008 usage ();
1011 jcf_path_seal (verbose);
1013 if (flag_print_main)
1015 flag_print_fields = 0;
1016 flag_print_methods = 0;
1017 flag_print_constant_pool = 0;
1018 flag_print_attributes = 0;
1019 flag_print_class_info = 0;
1022 if (output_file)
1024 out = fopen (output_file, "w");
1025 if (! out)
1027 fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1028 return FATAL_EXIT_CODE;
1031 else
1032 out = stdout;
1034 if (optind >= argc)
1036 fprintf (out, "Reading .class from <standard input>.\n");
1037 open_class ("<stdio>", jcf, 0, NULL);
1038 process_class (jcf);
1040 else
1042 for (argi = optind; argi < argc; argi++)
1044 char *arg = argv[argi];
1045 const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1046 if (class_filename == NULL)
1047 class_filename = find_classfile (arg, jcf, NULL);
1048 if (class_filename == NULL)
1050 perror ("Could not find class");
1051 return FATAL_EXIT_CODE;
1053 JCF_FILL (jcf, 4);
1054 if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1056 long compressed_size, member_size;
1057 int compression_method, filename_length, extra_length;
1058 int general_purpose_bits;
1059 const char *filename;
1060 int total_length;
1061 if (flag_print_class_info)
1062 fprintf (out, "Reading classes from archive %s.\n",
1063 class_filename);
1064 for (;;)
1066 int skip = 0;
1067 jcf_filbuf_t save_filbuf = jcf->filbuf;
1068 long magic = JCF_readu4_le (jcf);
1069 if (magic == 0x02014b50 || magic == 0x06054b50)
1070 break; /* got to central directory */
1071 if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1073 fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1074 return FATAL_EXIT_CODE;
1076 JCF_FILL (jcf, 26);
1077 JCF_SKIP (jcf, 2);
1078 general_purpose_bits = JCF_readu2_le (jcf);
1079 compression_method = JCF_readu2_le (jcf);
1080 JCF_SKIP (jcf, 8);
1081 compressed_size = JCF_readu4_le (jcf);
1082 member_size = JCF_readu4_le (jcf);
1083 filename_length = JCF_readu2_le (jcf);
1084 extra_length = JCF_readu2_le (jcf);
1085 total_length = filename_length + extra_length
1086 + compressed_size;
1087 if (jcf->read_end - jcf->read_ptr < total_length)
1088 jcf_trim_old_input (jcf);
1089 JCF_FILL (jcf, total_length);
1090 filename = (const char *) jcf->read_ptr;
1091 JCF_SKIP (jcf, filename_length);
1092 JCF_SKIP (jcf, extra_length);
1093 if (filename_length > 0
1094 && filename[filename_length-1] == '/')
1096 if (flag_print_class_info)
1097 fprintf (out, "[Skipping directory %.*s]\n",
1098 filename_length, filename);
1099 skip = 1;
1101 else if (compression_method != 0)
1103 if (flag_print_class_info)
1104 fprintf (out, "[Skipping compressed file %.*s]\n",
1105 filename_length, filename);
1106 skip = 1;
1108 else if (member_size < 4
1109 || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1111 if (flag_print_class_info)
1112 fprintf (out, "[Skipping non-.class member %.*s]\n",
1113 filename_length, filename);
1114 skip = 1;
1116 else
1118 if (flag_print_class_info)
1119 fprintf (out, "Reading class member: %.*s.\n",
1120 filename_length, filename);
1122 if (skip)
1124 JCF_SKIP (jcf, compressed_size);
1126 else
1128 unsigned char *save_end;
1129 jcf->filbuf = jcf_unexpected_eof;
1130 save_end = jcf->read_end;
1131 jcf->read_end = jcf->read_ptr + compressed_size;
1132 process_class (jcf);
1133 jcf->filbuf = save_filbuf;
1134 jcf->read_end = save_end;
1138 else
1140 if (flag_print_class_info)
1141 fprintf (out, "Reading .class from %s.\n", class_filename);
1142 process_class (jcf);
1144 JCF_FINISH(jcf);
1148 return SUCCESS_EXIT_CODE;
1153 static void
1154 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1156 #undef PTR
1157 int PC;
1158 int i;
1159 int saw_wide = 0;
1160 if (flag_disassemble_methods == 0)
1161 return;
1162 #define BCODE byte_ops
1163 for (PC = 0; PC < len;)
1165 int oldpc = PC;
1166 int saw_index;
1167 jint INT_temp;
1168 switch (byte_ops[PC++])
1171 /* This is the actual code emitted for each of opcodes in javaops.def.
1172 The actual opcode-specific stuff is handled by the OPKIND macro.
1173 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1174 Those macros are defined below. The OPKINDs that do not have any
1175 inline parameters (such as BINOP) and therefore do mot need anything
1176 else to me printed out just use an empty body. */
1178 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1179 case OPCODE: \
1180 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1181 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1182 fputc ('\n', out); \
1183 break;
1185 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1186 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1187 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1188 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1190 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1191 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1193 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1194 These all push a constant onto the opcode stack. */
1195 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1196 saw_index = 0, i = (OPERAND_VALUE); \
1197 if (oldpc+1 == PC) /* nothing */; \
1198 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1199 else fprintf (out, " %d", i);
1201 /* Print out operand (a local variable index) for LOAD opcodes.
1202 These all push local variable onto the opcode stack. */
1203 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1204 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1206 /* Handle STORE opcodes same as LOAD opcodes.
1207 These all store a value from the opcode stack in a local variable. */
1208 #define STORE LOAD
1210 /* Handle more kind of opcodes. */
1211 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1212 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1213 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1214 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1215 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1216 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1217 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1219 /* Handle putfield and getfield opcodes, with static versions. */
1220 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1221 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1223 /* Print operand for invoke opcodes. */
1224 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1225 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1226 if (OPERAND_VALUE) /* for invokeinterface */ \
1227 { int nargs = IMMEDIATE_u1; PC++; \
1228 fprintf (out, " nargs:%d", nargs); }
1230 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1231 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1233 #define ARRAY(OPERAND_TYPE, SUBOP) \
1234 ARRAY_##SUBOP(OPERAND_TYPE)
1235 /* Handle sub-categories of ARRAY opcodes. */
1236 #define ARRAY_LOAD(TYPE) /* nothing */
1237 #define ARRAY_STORE(TYPE) /* nothing */
1238 #define ARRAY_LENGTH(TYPE) /* nothing */
1239 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1240 #define ARRAY_NEW_NUM \
1241 INT_temp = IMMEDIATE_u1; \
1242 { switch ((int) INT_temp) { \
1243 case 4: fputs (" boolean", out); break; \
1244 case 5: fputs (" char", out); break; \
1245 case 6: fputs (" float", out); break; \
1246 case 7: fputs (" double", out); break; \
1247 case 8: fputs (" byte", out); break; \
1248 case 9: fputs (" short", out); break; \
1249 case 10: fputs (" int", out); break; \
1250 case 11: fputs (" long", out); break; \
1251 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1254 #define ARRAY_NEW_PTR \
1255 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1257 #define ARRAY_NEW_MULTI \
1258 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1259 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1261 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1262 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1264 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1265 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1266 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1268 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1269 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1270 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1272 #undef RET /* Defined by config/i386/i386.h */
1273 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1274 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1275 saw_wide = 0; \
1276 fprintf (out, " %ld", (long) INT_temp);
1278 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1279 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1281 #define LOOKUP_SWITCH \
1282 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1283 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1284 while (--npairs >= 0) { \
1285 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1286 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1289 #define TABLE_SWITCH \
1290 { jint default_offset = IMMEDIATE_s4; \
1291 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1292 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1293 (long) low, (long) high, (long) default_offset+oldpc); \
1294 for (; low <= high; low++) { \
1295 jint offset = IMMEDIATE_s4; \
1296 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1299 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1300 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1302 #define SPECIAL_IINC(OPERAND_TYPE) \
1303 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1304 fprintf (out, " %d", i); \
1305 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1306 saw_wide = 0; \
1307 fprintf (out, " %d", i)
1309 #define SPECIAL_WIDE(OPERAND_TYPE) \
1310 saw_wide = 1;
1312 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1313 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1314 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1315 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1317 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1318 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1320 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1321 TEST(OPERAND_TYPE, OPERAND_VALUE)
1323 #include "javaop.def"
1325 load_store:
1326 if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1327 else
1329 saw_wide = 0;
1330 fprintf (out, " %ld", (long) INT_temp);
1332 fputc ('\n', out);
1333 break;
1335 default:
1336 fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);