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