Mark ChangeLog
[official-gcc.git] / gcc / java / jcf-dump.c
blobee6e38fa51cda744754f66167f675662af9dfbf4
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, 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 PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
346 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
347 fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
349 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
350 if (flag_print_attributes > 0) \
351 fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
353 #include "javaop.h"
355 static void
356 print_constant_ref (FILE *stream, JCF *jcf, int index)
358 if (index <= 0 || index >= JPOOL_SIZE(jcf))
359 fprintf (stream, "<out of range>");
360 else
362 if (flag_print_constant_pool)
363 fprintf (stream, "#%d=", index);
364 fputc ('<', stream);
365 print_constant (stream, jcf, index, 1);
366 fputc ('>', stream);
370 /* Print the access flags given by FLAGS.
371 The CONTEXT is one of 'c' (class flags), 'f' (field flags),
372 or 'm' (method flags). */
374 static void
375 print_access_flags (FILE *stream, uint16 flags, char context)
377 if (flags & ACC_PUBLIC) fprintf (stream, " public");
378 if (flags & ACC_PRIVATE) fprintf (stream, " private");
379 if (flags & ACC_PROTECTED) fprintf (stream, " protected");
380 if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
381 if (flags & ACC_STATIC) fprintf (stream, " static");
382 if (flags & ACC_FINAL) fprintf (stream, " final");
383 if (flags & ACC_TRANSIENT) fprintf (stream, " transient");
384 if (flags & ACC_VOLATILE) fprintf (stream, " volatile");
385 if (flags & ACC_NATIVE) fprintf (stream, " native");
386 if (flags & ACC_SYNCHRONIZED)
388 if (context == 'c')
389 fprintf (stream, " super");
390 else
391 fprintf (stream, " synchronized");
393 if (flags & ACC_INTERFACE) fprintf (stream, " interface");
394 if (flags & ACC_STRICT) fprintf (stream, " strictfp");
398 static void
399 print_name (FILE* stream, JCF* jcf, int name_index)
401 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
402 fprintf (stream, "<not a UTF8 constant>");
403 else
404 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
405 JPOOL_UTF_LENGTH (jcf, name_index));
408 /* If the type of the constant at INDEX matches EXPECTED,
409 print it tersely, otherwise more verbosely. */
411 static void
412 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
414 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
415 fprintf (out, "<constant pool index %d not in range>", index);
416 else if (JPOOL_TAG (jcf, index) != expected)
418 fprintf (out, "<Unexpected constant type ");
419 print_constant (out, jcf, index, 1);
420 fprintf (out, ">");
422 else
423 print_constant (out, jcf, index, 0);
426 static void
427 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
429 if (flag_print_constant_pool)
430 fprintf (out, "%d=", index);
431 print_constant_terse (out, jcf, index, expected);
434 /* Print the constant at INDEX in JCF's constant pool.
435 If verbosity==0, print very tersely (no extraneous text).
436 If verbosity==1, prefix the type of the constant.
437 If verbosity==2, add more descriptive text. */
439 static void
440 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
442 int j, n;
443 jlong num;
444 const char *str;
445 int kind = JPOOL_TAG (jcf, index);
446 switch (kind)
448 case CONSTANT_Class:
449 n = JPOOL_USHORT1 (jcf, index);
450 if (verbosity > 0)
452 if (verbosity > 1)
453 fprintf (out, "Class name: %d=", n);
454 else
455 fprintf (out, "Class ");
457 if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
458 fprintf (out, "<out of range>");
459 else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
461 int len = JPOOL_UTF_LENGTH (jcf, n);
462 jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
464 else
465 print_constant_terse (out, jcf, n, CONSTANT_Utf8);
466 break;
467 case CONSTANT_Fieldref:
468 str = "Field"; goto field_or_method;
469 case CONSTANT_Methodref:
470 str = "Method"; goto field_or_method;
471 case CONSTANT_InterfaceMethodref:
472 str = "InterfaceMethod"; goto field_or_method;
473 field_or_method:
475 uint16 tclass = JPOOL_USHORT1 (jcf, index);
476 uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
477 if (verbosity == 2)
478 fprintf (out, "%sref class: %d=", str, tclass);
479 else if (verbosity > 0)
480 fprintf (out, "%s ", str);
481 print_constant_terse (out, jcf, tclass, CONSTANT_Class);
482 if (verbosity < 2)
483 fprintf (out, ".");
484 else
485 fprintf (out, " name_and_type: %d=<", name_and_type);
486 print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
487 if (verbosity == 2)
488 fputc ('>', out);
490 break;
491 case CONSTANT_String:
492 j = JPOOL_USHORT1 (jcf, index);
493 if (verbosity > 0)
495 if (verbosity > 1)
496 fprintf (out, "String %d=", j);
497 else
498 fprintf (out, "String ");
500 print_constant_terse (out, jcf, j, CONSTANT_Utf8);
501 break;
502 case CONSTANT_Integer:
503 if (verbosity > 0)
504 fprintf (out, "Integer ");
505 num = JPOOL_INT (jcf, index);
506 goto integer;
507 case CONSTANT_Long:
508 if (verbosity > 0)
509 fprintf (out, "Long ");
510 num = JPOOL_LONG (jcf, index);
511 goto integer;
512 integer:
514 char buffer[25];
515 format_int (buffer, num, 10);
516 fprintf (out, "%s", buffer);
517 if (verbosity > 1)
519 format_uint (buffer, (uint64)num, 16);
520 fprintf (out, "=0x%s", buffer);
523 break;
524 case CONSTANT_Float:
526 jfloat fnum = JPOOL_FLOAT (jcf, index);
528 if (verbosity > 0)
529 fputs ("Float ", out);
531 if (fnum.negative)
532 putc ('-', out);
534 if (JFLOAT_FINITE (fnum))
536 int dummy;
537 int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
538 double f;
539 uint32 mantissa = fnum.mantissa;
540 if (fnum.exponent == 0)
541 /* Denormal. */
542 exponent++;
543 else
544 /* Normal; add the implicit bit. */
545 mantissa |= ((uint32)1 << 23);
547 f = frexp (mantissa, &dummy);
548 f = ldexp (f, exponent + 1);
549 fprintf (out, "%.10g", f);
551 else
553 if (fnum.mantissa == 0)
554 fputs ("Inf", out);
555 else if (fnum.mantissa & JFLOAT_QNAN_MASK)
556 fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
557 else
558 fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
561 if (verbosity > 1)
562 fprintf (out, ", bits = 0x%08lx", JPOOL_UINT (jcf, index));
564 break;
566 case CONSTANT_Double:
568 jdouble dnum = JPOOL_DOUBLE (jcf, index);
570 if (verbosity > 0)
571 fputs ("Double ", out);
573 if (dnum.negative)
574 putc ('-', out);
576 if (JDOUBLE_FINITE (dnum))
578 int dummy;
579 int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
580 double d;
581 uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
582 + dnum.mantissa1);
583 if (dnum.exponent == 0)
584 /* Denormal. */
585 exponent++;
586 else
587 /* Normal; add the implicit bit. */
588 mantissa |= ((uint64)1 << 52);
590 d = frexp (mantissa, &dummy);
591 d = ldexp (d, exponent + 1);
592 fprintf (out, "%.20g", d);
594 else
596 uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
597 mantissa = (mantissa << 32) + dnum.mantissa1;
599 if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
600 fputs ("Inf", out);
601 else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
602 fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
603 else
604 fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
606 if (verbosity > 1)
608 int32 hi, lo;
609 hi = JPOOL_UINT (jcf, index);
610 lo = JPOOL_UINT (jcf, index + 1);
611 fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo);
613 break;
615 case CONSTANT_NameAndType:
617 uint16 name = JPOOL_USHORT1 (jcf, index);
618 uint16 sig = JPOOL_USHORT2 (jcf, index);
619 if (verbosity > 0)
621 if (verbosity > 1)
622 fprintf (out, "NameAndType name: %d=", name);
623 else
624 fprintf (out, "NameAndType ");
626 print_name (out, jcf, name);
627 if (verbosity <= 1)
628 fputc (' ', out);
629 else
630 fprintf (out, ", signature: %d=", sig);
631 print_signature (out, jcf, sig, 0);
633 break;
634 case CONSTANT_Utf8:
636 const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
637 int length = JPOOL_UTF_LENGTH (jcf, index);
638 if (verbosity > 0)
639 { /* Print as 8-bit bytes. */
640 fputs ("Utf8: \"", out);
641 while (--length >= 0)
642 jcf_print_char (out, *str++);
644 else
645 { /* Print as Unicode. */
646 fputc ('\"', out);
647 jcf_print_utf8 (out, str, length);
649 fputc ('\"', out);
651 break;
652 default:
653 fprintf (out, "(Unknown constant type %d)", kind);
657 static void
658 print_constant_pool (JCF *jcf)
660 int i;
661 for (i = 1; i < JPOOL_SIZE(jcf); i++)
663 int kind = JPOOL_TAG (jcf, i);
664 fprintf (out, "#%d: ", i);
665 print_constant (out, jcf, i, 2);
666 fprintf (out, "\n");
667 if (kind == CONSTANT_Double || kind == CONSTANT_Long)
668 i++; /* These take up two slots in the constant table */
672 static void
673 print_signature_type (FILE* stream, const unsigned char **ptr,
674 const unsigned char *limit)
676 int array_size;
677 if ((*ptr) >= limit)
678 return;
679 switch (*(*ptr))
681 case '[':
682 array_size = -1;
683 for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
685 array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
687 print_signature_type (stream, ptr, limit);
688 if (array_size == -1)
689 fprintf (stream, "[]");
690 else
691 fprintf (stream, "[%d]", array_size);
692 break;
693 case '(':
695 int nargs = 0;
696 fputc (*(*ptr)++, stream);
697 for (; **ptr != ')' && *ptr < limit; nargs++)
699 if (nargs > 0)
700 fputc (',', stream);
701 print_signature_type (stream, ptr, limit);
703 if (*ptr < limit)
705 fputc (*(*ptr)++, stream);
706 print_signature_type (stream, ptr, limit);
708 else
709 fprintf (stream, "???");
711 break;
713 case 'B': fprintf (stream, "byte"); (*ptr)++; break;
714 case 'C': fprintf (stream, "char"); (*ptr)++; break;
715 case 'D': fprintf (stream, "double"); (*ptr)++; break;
716 case 'F': fprintf (stream, "float"); (*ptr)++; break;
717 case 'S': fprintf (stream, "short"); (*ptr)++; break;
718 case 'I': fprintf (stream, "int"); (*ptr)++; break;
719 case 'J': fprintf (stream, "long"); (*ptr)++; break;
720 case 'Z': fprintf (stream, "boolean"); (*ptr)++; break;
721 case 'V': fprintf (stream, "void"); (*ptr)++; break;
723 case 'L':
724 for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
725 jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
726 if (*(*ptr) == ';')
727 (*ptr)++;
728 break;
729 default:
730 jcf_print_char (stream, *(*ptr)++);
734 static void
735 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
737 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
738 print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
739 else
741 const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
742 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
743 const unsigned char *limit;
744 limit = str + length;
745 if (str >= limit)
746 fprintf (stream, "<empty signature string>");
747 else
749 if (options & PRINT_SIGNATURE_RESULT_ONLY)
751 while (str < limit && *str++ != ')') ;
753 if (options & PRINT_SIGNATURE_ARGS_ONLY)
755 str++;
756 fputc ('(', stream);
757 while (str < limit && *str != ')')
759 print_signature_type (stream, &str, limit);
760 if (*str != ')')
761 fputs (", ", stream);
763 fputc (')', stream);
765 else
767 print_signature_type (stream, &str, limit);
768 if (str < limit)
770 fprintf (stream, "<junk:");
771 jcf_print_utf8 (stream, str, limit - str);
772 fputc ('>', stream);
780 static void
781 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
783 /* Print exception table. */
784 int i = count;
785 if (i > 0)
787 const unsigned char *ptr = entries;
788 fprintf (out, "Exceptions (count: %d):\n", i);
789 for (; --i >= 0; ptr+= 8)
791 int start_pc = GET_u2 (ptr);
792 int end_pc = GET_u2 (ptr+2);
793 int handler_pc = GET_u2 (ptr+4);
794 int catch_type = GET_u2 (ptr+6);
795 fprintf (out, " start: %d, end: %d, handler: %d, type: ",
796 start_pc, end_pc, handler_pc);
797 if (catch_type == 0)
798 fputs ("0 /* finally */", out);
799 else
800 print_constant_terse_with_index (out, jcf,
801 catch_type, CONSTANT_Class);
802 fputc ('\n', out);
807 #include "jcf-reader.c"
809 static void
810 process_class (JCF *jcf)
812 int code;
813 if (jcf_parse_preamble (jcf) != 0)
814 fprintf (stderr, _("Not a valid Java .class file.\n"));
816 /* Parse and possibly print constant pool */
817 code = jcf_parse_constant_pool (jcf);
818 if (code != 0)
820 fprintf (stderr, _("error while parsing constant pool\n"));
821 exit (FATAL_EXIT_CODE);
823 code = verify_constant_pool (jcf);
824 if (code > 0)
826 fprintf (stderr, _("error in constant pool entry #%d\n"), code);
827 exit (FATAL_EXIT_CODE);
829 if (flag_print_constant_pool)
830 print_constant_pool (jcf);
832 jcf_parse_class (jcf);
833 code = jcf_parse_fields (jcf);
834 if (code != 0)
836 fprintf (stderr, _("error while parsing fields\n"));
837 exit (FATAL_EXIT_CODE);
839 code = jcf_parse_methods (jcf);
840 if (code != 0)
842 fprintf (stderr, _("error while parsing methods\n"));
843 exit (FATAL_EXIT_CODE);
845 code = jcf_parse_final_attributes (jcf);
846 if (code != 0)
848 fprintf (stderr, _("error while parsing final attributes\n"));
849 exit (FATAL_EXIT_CODE);
851 jcf->filename = NULL;
856 /* This is used to mark options with no short value. */
857 #define LONG_OPT(Num) ((Num) + 128)
859 #define OPT_classpath LONG_OPT (0)
860 #define OPT_CLASSPATH OPT_classpath
861 #define OPT_bootclasspath LONG_OPT (1)
862 #define OPT_extdirs LONG_OPT (2)
863 #define OPT_HELP LONG_OPT (3)
864 #define OPT_VERSION LONG_OPT (4)
865 #define OPT_JAVAP LONG_OPT (5)
867 static const struct option options[] =
869 { "classpath", required_argument, NULL, OPT_classpath },
870 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
871 { "extdirs", required_argument, NULL, OPT_extdirs },
872 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
873 { "help", no_argument, NULL, OPT_HELP },
874 { "verbose", no_argument, NULL, 'v' },
875 { "version", no_argument, NULL, OPT_VERSION },
876 { "javap", no_argument, NULL, OPT_JAVAP },
877 { "print-main", no_argument, &flag_print_main, 1 },
878 { "print-constants", no_argument, &flag_print_constant_pool, 1 },
879 { NULL, no_argument, NULL, 0 }
882 static void
883 usage (void)
885 fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
886 exit (1);
889 static void
890 help (void)
892 printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
893 printf (_("Display contents of a class file in readable form.\n\n"));
894 printf (_(" -c Disassemble method bodies\n"));
895 printf (_(" --javap Generate output in 'javap' format\n"));
896 printf ("\n");
897 printf (_(" --classpath PATH Set path to find .class files\n"));
898 printf (_(" -IDIR Append directory to class path\n"));
899 printf (_(" --bootclasspath PATH Override built-in class path\n"));
900 printf (_(" --extdirs PATH Set extensions directory path\n"));
901 printf (_(" -o FILE Set output file name\n"));
902 printf ("\n");
903 printf (_(" --help Print this help, then exit\n"));
904 printf (_(" --version Print version number, then exit\n"));
905 printf (_(" -v, --verbose Print extra information while running\n"));
906 printf ("\n");
907 printf (_("For bug reporting instructions, please see:\n"
908 "%s.\n"), bug_report_url);
909 exit (0);
912 static void
913 version (void)
915 printf ("jcf-dump (GCC) %s\n\n", version_string);
916 printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
917 printf (_("This is free software; see the source for copying conditions. There is NO\n"
918 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
919 exit (0);
923 main (int argc, char** argv)
925 JCF jcf[1];
926 int argi, opt;
928 /* Unlock the stdio streams. */
929 unlock_std_streams ();
931 gcc_init_libintl ();
933 if (argc <= 1)
935 fprintf (stderr, _("jcf-dump: no classes specified\n"));
936 usage ();
939 jcf_path_init ();
941 /* We use getopt_long_only to allow single `-' long options. For
942 some of our options this is more natural. */
943 while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
945 switch (opt)
947 case 0:
948 /* Already handled. */
949 break;
951 case 'o':
952 output_file = optarg;
953 break;
955 case 'I':
956 jcf_path_include_arg (optarg);
957 break;
959 case 'v':
960 verbose++;
961 break;
963 case 'c':
964 flag_disassemble_methods = 1;
965 break;
967 case OPT_classpath:
968 jcf_path_classpath_arg (optarg);
969 break;
971 case OPT_bootclasspath:
972 jcf_path_bootclasspath_arg (optarg);
973 break;
975 case OPT_extdirs:
976 jcf_path_extdirs_arg (optarg);
977 break;
979 case OPT_HELP:
980 help ();
981 break;
983 case OPT_VERSION:
984 version ();
985 break;
987 case OPT_JAVAP:
988 flag_javap_compatible++;
989 flag_print_constant_pool = 0;
990 flag_print_attributes = 0;
991 break;
993 default:
994 usage ();
998 if (verbose && ! flag_javap_compatible)
999 flag_print_constant_pool = 1;
1001 if (optind == argc)
1003 fprintf (stderr, _("jcf-dump: no classes specified\n"));
1004 usage ();
1007 jcf_path_seal (verbose);
1009 if (flag_print_main)
1011 flag_print_fields = 0;
1012 flag_print_methods = 0;
1013 flag_print_constant_pool = 0;
1014 flag_print_attributes = 0;
1015 flag_print_class_info = 0;
1018 if (output_file)
1020 out = fopen (output_file, "w");
1021 if (! out)
1023 fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1024 return FATAL_EXIT_CODE;
1027 else
1028 out = stdout;
1030 if (optind >= argc)
1032 fprintf (out, "Reading .class from <standard input>.\n");
1033 open_class ("<stdio>", jcf, 0, NULL);
1034 process_class (jcf);
1036 else
1038 for (argi = optind; argi < argc; argi++)
1040 char *arg = argv[argi];
1041 const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
1042 if (class_filename == NULL)
1043 class_filename = find_classfile (arg, jcf, NULL);
1044 if (class_filename == NULL)
1046 perror ("Could not find class");
1047 return FATAL_EXIT_CODE;
1049 JCF_FILL (jcf, 4);
1050 if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1052 long compressed_size, member_size;
1053 int compression_method, filename_length, extra_length;
1054 int general_purpose_bits;
1055 const char *filename;
1056 int total_length;
1057 if (flag_print_class_info)
1058 fprintf (out, "Reading classes from archive %s.\n",
1059 class_filename);
1060 for (;;)
1062 int skip = 0;
1063 jcf_filbuf_t save_filbuf = jcf->filbuf;
1064 long magic = JCF_readu4_le (jcf);
1065 if (magic == 0x02014b50 || magic == 0x06054b50)
1066 break; /* got to central directory */
1067 if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1069 fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1070 return FATAL_EXIT_CODE;
1072 JCF_FILL (jcf, 26);
1073 JCF_SKIP (jcf, 2);
1074 general_purpose_bits = JCF_readu2_le (jcf);
1075 compression_method = JCF_readu2_le (jcf);
1076 JCF_SKIP (jcf, 8);
1077 compressed_size = JCF_readu4_le (jcf);
1078 member_size = JCF_readu4_le (jcf);
1079 filename_length = JCF_readu2_le (jcf);
1080 extra_length = JCF_readu2_le (jcf);
1081 total_length = filename_length + extra_length
1082 + compressed_size;
1083 if (jcf->read_end - jcf->read_ptr < total_length)
1084 jcf_trim_old_input (jcf);
1085 JCF_FILL (jcf, total_length);
1086 filename = (const char *) jcf->read_ptr;
1087 JCF_SKIP (jcf, filename_length);
1088 JCF_SKIP (jcf, extra_length);
1089 if (filename_length > 0
1090 && filename[filename_length-1] == '/')
1092 if (flag_print_class_info)
1093 fprintf (out, "[Skipping directory %.*s]\n",
1094 filename_length, filename);
1095 skip = 1;
1097 else if (compression_method != 0)
1099 if (flag_print_class_info)
1100 fprintf (out, "[Skipping compressed file %.*s]\n",
1101 filename_length, filename);
1102 skip = 1;
1104 else if (member_size < 4
1105 || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1107 if (flag_print_class_info)
1108 fprintf (out, "[Skipping non-.class member %.*s]\n",
1109 filename_length, filename);
1110 skip = 1;
1112 else
1114 if (flag_print_class_info)
1115 fprintf (out, "Reading class member: %.*s.\n",
1116 filename_length, filename);
1118 if (skip)
1120 JCF_SKIP (jcf, compressed_size);
1122 else
1124 unsigned char *save_end;
1125 jcf->filbuf = jcf_unexpected_eof;
1126 save_end = jcf->read_end;
1127 jcf->read_end = jcf->read_ptr + compressed_size;
1128 process_class (jcf);
1129 jcf->filbuf = save_filbuf;
1130 jcf->read_end = save_end;
1134 else
1136 if (flag_print_class_info)
1137 fprintf (out, "Reading .class from %s.\n", class_filename);
1138 process_class (jcf);
1140 JCF_FINISH(jcf);
1144 return SUCCESS_EXIT_CODE;
1149 static void
1150 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1152 #undef PTR
1153 int PC;
1154 int i;
1155 int saw_wide = 0;
1156 if (flag_disassemble_methods == 0)
1157 return;
1158 #define BCODE byte_ops
1159 for (PC = 0; PC < len;)
1161 int oldpc = PC;
1162 int saw_index;
1163 jint INT_temp;
1164 switch (byte_ops[PC++])
1167 /* This is the actual code emitted for each of opcodes in javaops.def.
1168 The actual opcode-specific stuff is handled by the OPKIND macro.
1169 I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1170 Those macros are defined below. The OPKINDs that do not have any
1171 inline parameters (such as BINOP) and therefore do mot need anything
1172 else to me printed out just use an empty body. */
1174 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1175 case OPCODE: \
1176 fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1177 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1178 fputc ('\n', out); \
1179 break;
1181 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1182 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1183 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1184 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1186 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1187 (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1189 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1190 These all push a constant onto the opcode stack. */
1191 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1192 saw_index = 0, i = (OPERAND_VALUE); \
1193 if (oldpc+1 == PC) /* nothing */; \
1194 else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1195 else fprintf (out, " %d", i);
1197 /* Print out operand (a local variable index) for LOAD opcodes.
1198 These all push local variable onto the opcode stack. */
1199 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1200 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1202 /* Handle STORE opcodes same as LOAD opcodes.
1203 These all store a value from the opcode stack in a local variable. */
1204 #define STORE LOAD
1206 /* Handle more kind of opcodes. */
1207 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1208 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1209 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1210 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1211 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1212 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1213 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1215 /* Handle putfield and getfield opcodes, with static versions. */
1216 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1217 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1219 /* Print operand for invoke opcodes. */
1220 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1221 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1222 if (OPERAND_VALUE) /* for invokeinterface */ \
1223 { int nargs = IMMEDIATE_u1; PC++; \
1224 fprintf (out, " nargs:%d", nargs); }
1226 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1227 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1229 #define ARRAY(OPERAND_TYPE, SUBOP) \
1230 ARRAY_##SUBOP(OPERAND_TYPE)
1231 /* Handle sub-categories of ARRAY opcodes. */
1232 #define ARRAY_LOAD(TYPE) /* nothing */
1233 #define ARRAY_STORE(TYPE) /* nothing */
1234 #define ARRAY_LENGTH(TYPE) /* nothing */
1235 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1236 #define ARRAY_NEW_NUM \
1237 INT_temp = IMMEDIATE_u1; \
1238 { switch ((int) INT_temp) { \
1239 case 4: fputs (" boolean", out); break; \
1240 case 5: fputs (" char", out); break; \
1241 case 6: fputs (" float", out); break; \
1242 case 7: fputs (" double", out); break; \
1243 case 8: fputs (" byte", out); break; \
1244 case 9: fputs (" short", out); break; \
1245 case 10: fputs (" int", out); break; \
1246 case 11: fputs (" long", out); break; \
1247 default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1250 #define ARRAY_NEW_PTR \
1251 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1253 #define ARRAY_NEW_MULTI \
1254 fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1255 fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1257 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1258 fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1260 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1261 saw_index = 0, INT_temp = (OPERAND_VALUE); \
1262 fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1264 #define JSR(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 #undef RET /* Defined by config/i386/i386.h */
1269 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1270 INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1271 saw_wide = 0; \
1272 fprintf (out, " %ld", (long) INT_temp);
1274 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1275 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1277 #define LOOKUP_SWITCH \
1278 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1279 fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1280 while (--npairs >= 0) { \
1281 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1282 fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1285 #define TABLE_SWITCH \
1286 { jint default_offset = IMMEDIATE_s4; \
1287 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1288 fprintf (out, " low=%ld, high=%ld, default=%ld", \
1289 (long) low, (long) high, (long) default_offset+oldpc); \
1290 for (; low <= high; low++) { \
1291 jint offset = IMMEDIATE_s4; \
1292 fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1295 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1296 SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1298 #define SPECIAL_IINC(OPERAND_TYPE) \
1299 i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1300 fprintf (out, " %d", i); \
1301 i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1302 saw_wide = 0; \
1303 fprintf (out, " %d", i)
1305 #define SPECIAL_WIDE(OPERAND_TYPE) \
1306 saw_wide = 1;
1308 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1309 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1310 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1311 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1313 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1314 fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1316 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1317 TEST(OPERAND_TYPE, OPERAND_VALUE)
1319 #include "javaop.def"
1321 load_store:
1322 if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1323 else
1325 saw_wide = 0;
1326 fprintf (out, " %ld", (long) INT_temp);
1328 fputc ('\n', out);
1329 break;
1331 default:
1332 fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);