OSDN Git Service

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