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