OSDN Git Service

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