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