OSDN Git Service

Index: gcc/java/ChangeLog
[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    2006, 2007 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, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, 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 /* Output 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_terse_with_index (FILE *, JCF *, int, int);
100 static void print_constant (FILE *, JCF *, int, int);
101 static void print_constant_ref (FILE *, JCF *, int);
102 static void disassemble_method (JCF*, const unsigned char *, int);
103 static void print_name (FILE*, JCF*, int);
104 static void print_signature (FILE*, JCF*, int, int);
105 static int utf8_equal_string (struct JCF*, int, const char *);
106 static void usage (void) ATTRIBUTE_NORETURN;
107 static void help (void) ATTRIBUTE_NORETURN;
108 static void version (void) ATTRIBUTE_NORETURN;
109 static void process_class (struct JCF *);
110 static void print_constant_pool (struct JCF *);
111 static void print_exception_table (struct JCF *, const unsigned char *entries,
112                                    int);
113 static void indent (FILE *, int);
114 static void print_element_value (FILE *, JCF *, int);
115 static void print_annotation (FILE *, JCF *, int);
116 static void print_annotations (FILE *, JCF *, int);
117 static void print_parameter_annotations (FILE *, JCF *, int);
118
119 #define PRINT_SIGNATURE_RESULT_ONLY 1
120 #define PRINT_SIGNATURE_ARGS_ONLY 2
121
122 static int
123 utf8_equal_string (JCF *jcf, int index, const char * value)
124 {
125   if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index)
126       && JPOOL_TAG (jcf, index) == CONSTANT_Utf8)
127     {
128       int len = strlen (value);
129       if (JPOOL_UTF_LENGTH (jcf, index) == len
130           && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0)
131         return 1;
132     }
133   return 0;
134 }
135
136 #define HANDLE_MAGIC(MAGIC, MINOR, MAJOR) \
137   this_class_index = 0; \
138   if (flag_print_class_info) \
139     fprintf (out, \
140              "Magic number: 0x%0lx, minor_version: %ld, major_version: %ld.\n",\
141              (unsigned long) MAGIC, (long) MINOR, (long) MAJOR)
142
143 #define HANDLE_START_CONSTANT_POOL(COUNT) \
144   if (flag_print_constant_pool) \
145     fprintf (out, "\nConstant pool (count: %d):\n", COUNT)
146
147 #define HANDLE_SOURCEFILE(INDEX) \
148 { fprintf (out, "Attribute "); \
149   print_constant_terse (out, jcf, attribute_name, CONSTANT_Utf8); \
150   fprintf (out, ", length:%ld, #%d=", (long) attribute_length, INDEX); \
151   print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8); fputc ('\n', out); }
152
153 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
154   this_class_index = THIS; \
155   class_access_flags = ACCESS_FLAGS; \
156   if (flag_print_class_info) \
157     { fprintf (out, "\nAccess flags: 0x%x", ACCESS_FLAGS); \
158       print_access_flags (out, ACCESS_FLAGS, 'c'); \
159       fputc ('\n', out); \
160       fprintf (out, "This class: "); \
161       print_constant_terse_with_index (out, jcf, THIS, CONSTANT_Class); \
162       if (flag_print_constant_pool || SUPER != 0) \
163         fprintf (out, ", super: "); \
164       if (flag_print_constant_pool) \
165         { \
166           fprintf (out, "%d", SUPER); \
167           if (SUPER != 0) \
168             fputc ('=', out); \
169         } \
170       if (SUPER != 0) \
171         print_constant_terse (out, jcf, SUPER, CONSTANT_Class); \
172       fprintf (out, "\nInterfaces (count: %d):\n", INTERFACES_COUNT); \
173     }
174
175 #define IGNORE_ATTRIBUTE(JCF, NAME, NAME_LENGTH) \
176   (flag_print_attributes <= 0)
177
178 #define HANDLE_CLASS_INTERFACE(INDEX) \
179   if (flag_print_class_info) \
180     { fprintf (out, "- Implements: "); \
181       print_constant_terse_with_index (out, jcf, INDEX, CONSTANT_Class); \
182       fputc ('\n', out); }
183
184 #define HANDLE_START_FIELDS(FIELDS_COUNT) \
185   if (flag_print_fields) \
186     fprintf (out, "\nFields (count: %d):\n", FIELDS_COUNT)
187
188 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
189   if (flag_print_fields) \
190     { fprintf (out, "Field name:"); \
191       print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
192       print_access_flags (out, ACCESS_FLAGS, 'f'); \
193       fprintf (out, " Descriptor: "); \
194       if (flag_print_constant_pool) \
195         fprintf (out, "%d=", SIGNATURE); \
196       print_signature (out, jcf, SIGNATURE, 0); \
197       fputc ('\n', out); } \
198   else \
199     flag_print_attributes--;
200
201 #define HANDLE_END_FIELD() \
202   if (! flag_print_fields) \
203     flag_print_attributes++;
204
205 #define HANDLE_START_METHODS(METHODS_COUNT) \
206   if (flag_print_methods) \
207     fprintf (out, "\nMethods (count: %d):\n", METHODS_COUNT); \
208   else \
209     flag_print_attributes--;
210
211
212 #define HANDLE_END_METHODS() \
213   if (! flag_print_methods) \
214     flag_print_attributes++;
215
216 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
217 { \
218   if (flag_print_methods) \
219     { \
220       if (flag_javap_compatible) \
221         { \
222           fprintf (out, "    "); \
223           print_access_flags (out, ACCESS_FLAGS, 'm'); \
224           fputc (' ', out); \
225           print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_RESULT_ONLY); \
226           fputc (' ', out); \
227           print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
228           print_signature (out, jcf, SIGNATURE, PRINT_SIGNATURE_ARGS_ONLY); \
229           fputc ('\n', out); \
230         } \
231       else \
232         { \
233           fprintf (out, "\nMethod name:"); \
234           print_constant_terse (out, jcf, NAME, CONSTANT_Utf8); \
235           print_access_flags (out, ACCESS_FLAGS, 'm'); \
236           fprintf (out, " Descriptor: "); \
237           if (flag_print_constant_pool) \
238             fprintf (out, "%d=", SIGNATURE); \
239           print_signature (out, jcf, SIGNATURE, 0); \
240           fputc ('\n', out); \
241         } \
242     } \
243   if (flag_print_main && ACCESS_FLAGS == (ACC_STATIC|ACC_PUBLIC) \
244       && utf8_equal_string (jcf, NAME, "main") \
245       && utf8_equal_string (jcf, SIGNATURE, "([Ljava/lang/String;)V") \
246       && this_class_index > 0 \
247       && (class_access_flags & ACC_PUBLIC)) \
248     { \
249       print_constant_terse(out, jcf, this_class_index, CONSTANT_Class); \
250       fputc  ('\n', out); \
251    } \
252 }
253
254 #define COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH) \
255 ( fprintf (out, "Attribute "), \
256   print_constant_terse (out, jcf, INDEX, CONSTANT_Utf8), \
257   fprintf (out, ", length:%ld", (long) LENGTH) )
258
259 #define HANDLE_CONSTANTVALUE(VALUE_INDEX) \
260 ( COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length), \
261   fprintf (out, ", value: "), \
262   print_constant_ref (out, jcf, VALUE_INDEX), \
263   fprintf (out, "\n") )
264
265 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
266 { COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
267   fprintf (out, ", max_stack:%ld, max_locals:%ld, code_length:%ld\n", \
268     (long) MAX_STACK, (long) MAX_LOCALS, (long) CODE_LENGTH); \
269   disassemble_method (jcf, jcf->read_ptr, CODE_LENGTH); }
270
271 #define HANDLE_EXCEPTION_TABLE(ENTRIES, COUNT) \
272   print_exception_table (jcf, ENTRIES, COUNT)
273
274 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
275 { int n = (COUNT); int i; \
276   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
277   fprintf (out, ", count: %d\n", n); \
278   for (i = 0; i < n; i++) {\
279     int ex_index = JCF_readu2 (jcf); \
280     fprintf (out, "%3d: ", i); \
281     print_constant_ref (out, jcf, ex_index); \
282     fputc ('\n', out); } }
283
284 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
285 { int n = (COUNT); int i; \
286   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length); \
287   fprintf (out, ", count: %d\n", n); \
288   for (i = 0; i < n; i++) {\
289     int start_pc = JCF_readu2 (jcf); \
290     int length = JCF_readu2 (jcf); \
291     int name_index = JCF_readu2 (jcf); \
292     int signature_index = JCF_readu2 (jcf); \
293     int slot = JCF_readu2 (jcf); \
294     fprintf (out, "  slot#%d: name: ", slot); \
295     if (flag_print_constant_pool) \
296       fprintf (out, "%d=", name_index); \
297     print_name (out, jcf, name_index); \
298     fprintf (out, ", type: "); \
299     if (flag_print_constant_pool) \
300       fprintf (out, "%d=", signature_index); \
301     print_signature (out, jcf, signature_index, 0); \
302     fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
303
304 #define HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE(COUNT)                  \
305 { int n = (COUNT); int i;                                               \
306   COMMON_HANDLE_ATTRIBUTE(JCF, attribute_name, attribute_length);       \
307   fprintf (out, ", count: %d\n", n);                                    \
308   for (i = 0; i < n; i++) {                                             \
309     int start_pc = JCF_readu2 (jcf);                                    \
310     int length = JCF_readu2 (jcf);                                      \
311     int name_index = JCF_readu2 (jcf);                                  \
312     int signature_index = JCF_readu2 (jcf);                             \
313     int slot = JCF_readu2 (jcf);                                        \
314     fprintf (out, "  slot#%d: name: ", slot);                           \
315     if (flag_print_constant_pool)                                       \
316       fprintf (out, "%d=", name_index);                                 \
317     print_name (out, jcf, name_index);                                  \
318     fprintf (out, ", type: ");                                          \
319     if (flag_print_constant_pool)                                       \
320       fprintf (out, "%d=", signature_index);                            \
321     print_signature (out, jcf, signature_index, 0);                     \
322     fprintf (out, " (pc: %d length: %d)\n", start_pc, length); }}
323
324 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
325 { int n = (COUNT); int i; \
326   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
327   fprintf (out, ", count: %d\n", n); \
328   if (flag_disassemble_methods) \
329     for (i = 0; i < n; i++) {\
330       int start_pc = JCF_readu2 (jcf); \
331       int line_number = JCF_readu2 (jcf); \
332       fprintf (out, "  line: %d at pc: %d\n", line_number, start_pc); }\
333   else \
334     JCF_SKIP (jcf, 4 * n); }
335
336 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT)                                \
337 { int n = (COUNT);                                                          \
338   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);           \
339   while (n--)                                                               \
340     {                                                                       \
341       uint16 inner_class_info_index = JCF_readu2 (jcf);                     \
342       uint16 outer_class_info_index = JCF_readu2 (jcf);                     \
343       uint16 inner_name_index = JCF_readu2 (jcf);                           \
344       uint16 inner_class_access_flags = JCF_readu2 (jcf);                   \
345                                                                             \
346       if (flag_print_class_info)                                            \
347         {                                                                   \
348           fprintf (out, "\n  inner: ");                                     \
349           if (inner_class_info_index == 0)                                  \
350             fprintf (out, " (no inner info index)");                        \
351           else                                                              \
352             print_constant_terse_with_index (out, jcf,                      \
353                                              inner_class_info_index,        \
354                                              CONSTANT_Class);               \
355           if (inner_name_index == 0)                                        \
356             fprintf (out, " (anonymous)");                                  \
357           else if (verbose || flag_print_constant_pool)                     \
358             {                                                               \
359               fprintf (out, " (");                                          \
360               print_constant_terse_with_index (out, jcf, inner_name_index,  \
361                                                CONSTANT_Utf8);              \
362               fputc (')', out);                                             \
363             }                                                               \
364           fprintf (out, ", access flags: 0x%x", inner_class_access_flags);  \
365           print_access_flags (out, inner_class_access_flags, 'c');          \
366           fprintf (out, ", outer class: ");                                 \
367           if (outer_class_info_index == 0)                                  \
368             fprintf (out, "(not a member)");                                \
369           else                                                              \
370             print_constant_terse_with_index (out, jcf,                      \
371                                              outer_class_info_index,        \
372                                              CONSTANT_Class);               \
373         }                                                                   \
374     }                                                                       \
375   if (flag_print_class_info)                                                \
376     fputc ('\n', out);                                                      \
377 }
378
379 #define HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE(LENGTH) \
380 { int i, n = (LENGTH), c = 0;                                     \
381   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
382   fputc ('\n', out); \
383   for (i = 0;  i < n;  i++) { c = JCF_readu(jcf); fputc(c, out); } \
384   if (c != '\r' && c != '\n') fputc('\n', out); }
385
386 #define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE()                              \
387   { uint16 class_index, method_index;                                   \
388   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
389   class_index = JCF_readu2 (jcf);                                       \
390   method_index = JCF_readu2 (jcf);                                      \
391   fprintf (out, "\n  Class: ");                                         \
392   print_constant_terse_with_index (out, jcf, class_index, CONSTANT_Class); \
393   fprintf (out, "\n  Method: ");                                        \
394   print_constant_terse_with_index (out, jcf, method_index,              \
395                                    CONSTANT_NameAndType);               \
396   fputc ('\n', out);                                                    \
397 }
398
399 #define HANDLE_SIGNATURE_ATTRIBUTE()                                    \
400 {                                                                       \
401   uint16 signature;                                                     \
402   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
403   signature = JCF_readu2 (jcf);                                         \
404   fprintf (out, "\n  Value: ");                                         \
405   print_constant_terse_with_index (out, jcf, signature, CONSTANT_Utf8); \
406   fputc ('\n', out);                                                    \
407 }
408
409 #define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE()                    \
410 {                                                                       \
411   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
412   print_annotations (out, jcf, 1);                                      \
413 }
414
415 #define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE()                  \
416 {                                                                       \
417   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
418   print_annotations (out, jcf, 1);                                      \
419 }
420
421 #define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()           \
422 {                                                                       \
423   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
424   print_parameter_annotations (out, jcf, 1);                            \
425 }
426
427 #define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()         \
428 {                                                                       \
429   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
430   print_parameter_annotations (out, jcf, 1);                            \
431 }
432
433 #define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE()                            \
434 {                                                                       \
435   COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length);       \
436   print_element_value (out, jcf, 1);                                    \
437 }
438
439
440 #define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
441 { COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
442   fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
443
444 #define START_FINAL_ATTRIBUTES(ATTRIBUTES_COUNT) \
445   if (flag_print_attributes > 0) \
446     fprintf (out, "\nAttributes (count: %d):\n", attributes_count);
447
448 #include "javaop.h"
449
450 \f
451
452 static void
453 indent (FILE *stream, int level)
454 {
455   int i;
456   for (i = 0; i < level; ++i)
457     fprintf (stream, "  ");
458 }
459
460 static void
461 print_element_value (FILE *stream, JCF *jcf, int level)
462 {
463   uint8 tag = JCF_readu (jcf);
464   indent (stream, level);
465   switch (tag)
466     {
467     case 'B':
468     case 'C':
469     case 'S':
470     case 'Z':
471     case 'I':
472       {
473         uint16 cindex = JCF_readu2 (jcf);
474         print_constant_terse_with_index (stream, jcf, cindex,
475                                          CONSTANT_Integer);
476       }
477       break;
478     case 'D':
479       {
480         uint16 cindex = JCF_readu2 (jcf);
481         print_constant_terse_with_index (stream, jcf, cindex,
482                                          CONSTANT_Double);
483       }
484       break;
485     case 'F':
486       {
487         uint16 cindex = JCF_readu2 (jcf);
488         print_constant_terse_with_index (stream, jcf, cindex,
489                                          CONSTANT_Float);
490       }
491       break;
492     case 'J':
493       {
494         uint16 cindex = JCF_readu2 (jcf);
495         print_constant_terse_with_index (stream, jcf, cindex,
496                                          CONSTANT_Long);
497       }
498       break;
499     case 's':
500       {
501         uint16 cindex = JCF_readu2 (jcf);
502         /* Despite what the JVM spec says, compilers generate a Utf8
503            constant here, not a String.  */
504         print_constant_terse_with_index (stream, jcf, cindex,
505                                          CONSTANT_Utf8);
506       }
507       break;
508
509     case 'e':
510       {
511         uint16 type_name_index = JCF_readu2 (jcf);
512         uint16 const_name_index = JCF_readu2 (jcf);
513         fprintf (stream, "enum class: ");
514         print_constant_terse_with_index (stream, jcf, type_name_index,
515                                          CONSTANT_Utf8);
516         fprintf (stream, "\n");
517         indent (stream, level);
518         fprintf (stream, "Field: ");
519         print_constant_terse_with_index (stream, jcf, const_name_index,
520                                          CONSTANT_Utf8);
521       }
522       break;
523     case 'c':
524       {
525         uint16 class_info_index = JCF_readu2 (jcf);
526         print_constant_terse_with_index (stream, jcf, class_info_index,
527                                          CONSTANT_Utf8);
528       }
529       break;
530     case '@':
531       {
532         fprintf (stream, "Annotation:\n");
533         print_annotation (stream, jcf, level + 1);
534       }
535       break;
536     case '[':
537       {
538         uint16 n_array_elts = JCF_readu2 (jcf);
539         fprintf (stream, "array[%d]: [\n", (int) n_array_elts);
540         while (n_array_elts--)
541           print_element_value (stream, jcf, level + 1);
542         indent (stream, level);
543         fprintf (stream, "]");
544       }
545       break;
546     default:
547       fprintf (stream, "Unexpected tag value: %d", (int) tag);
548       break;
549     }
550   fputc ('\n', stream);
551 }
552
553 static void
554 print_annotation (FILE *stream, JCF *jcf, int level)
555 {
556   uint16 type_index = JCF_readu2 (jcf);
557   uint16 npairs = JCF_readu2 (jcf);
558   fprintf (stream, "\n");
559   indent (stream, level);
560   fprintf (stream, "Annotation name: ");
561   print_constant_terse_with_index (stream, jcf, type_index,
562                                    CONSTANT_Utf8);
563   if (npairs)
564     {
565       fprintf (stream, "\n");
566       while (npairs--)
567         {
568           uint16 name_index = JCF_readu2 (jcf);
569           indent (stream, level + 1);
570           fprintf (stream, "Name: ");
571           print_constant_terse_with_index (stream, jcf, name_index,
572                                            CONSTANT_Utf8);
573           fprintf (stream, "\n");
574           print_element_value (stream, jcf, level + 2);
575         }
576     }
577 }
578
579 static void
580 print_annotations (FILE *stream, JCF *jcf, int level)
581 {
582   uint16 num = JCF_readu2 (jcf);
583   while (num--)
584     print_annotation (stream, jcf, level);
585 }
586
587 static void
588 print_parameter_annotations (FILE *stream, JCF *jcf, int level)
589 {
590   uint8 nparams = JCF_readu (jcf);
591   uint8 i;
592   for (i = 0; i < nparams; ++i)
593     {
594       indent (stream, level);
595       fprintf (stream, "Parameter annotations (%d):\n", (int) i);
596       print_annotations (stream, jcf, level + 1);
597     }
598 }
599
600 \f
601
602 static void
603 print_constant_ref (FILE *stream, JCF *jcf, int index)
604 {
605   if (index <= 0 || index >= JPOOL_SIZE(jcf))
606     fprintf (stream, "<out of range>");
607   else
608     {
609       if (flag_print_constant_pool)
610         fprintf (stream, "#%d=", index);
611       fputc ('<', stream);
612       print_constant (stream, jcf, index, 1);
613       fputc ('>', stream);
614     }
615 }
616
617 /* Print the access flags given by FLAGS.
618    The CONTEXT is one of 'c' (class flags), 'f' (field flags),
619    or 'm' (method flags). */
620
621 static void
622 print_access_flags (FILE *stream, uint16 flags, char context)
623 {
624   if (flags & ACC_PUBLIC) fprintf (stream, " public");
625   if (flags & ACC_PRIVATE) fprintf (stream, " private");
626   if (flags & ACC_PROTECTED) fprintf (stream, " protected");
627   if (flags & ACC_ABSTRACT) fprintf (stream, " abstract");
628   if (flags & ACC_STATIC) fprintf (stream, " static");
629   if (flags & ACC_FINAL) fprintf (stream, " final");
630   if (flags & ACC_TRANSIENT)
631     fprintf (stream, context == 'm' ? " varargs" : " transient");
632   if (flags & ACC_VOLATILE)
633     fprintf (stream, context == 'm' ? " bridge" : " volatile");
634   if (flags & ACC_NATIVE) fprintf (stream, " native");
635   if (flags & ACC_SYNCHRONIZED)
636     {
637       if (context == 'c')
638         fprintf (stream, " super");
639       else
640         fprintf (stream, " synchronized");
641     }
642   if (flags & ACC_INTERFACE)
643     fprintf (stream, (flags & ACC_ANNOTATION) ? " @interface" : " interface");
644   if (flags & ACC_ENUM) fprintf (stream, " enum");
645   if (flags & ACC_STRICT) fprintf (stream, " strictfp");
646   if (flags & ACC_SYNTHETIC) fprintf (stream, " synthetic");
647 }
648
649
650 static void
651 print_name (FILE* stream, JCF* jcf, int name_index)
652 {
653   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
654     fprintf (stream, "<not a UTF8 constant>");
655   else
656     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index),
657                     JPOOL_UTF_LENGTH (jcf, name_index));
658 }
659
660 /* If the type of the constant at INDEX matches EXPECTED,
661    print it tersely, otherwise more verbosely. */
662
663 static void
664 print_constant_terse (FILE *out, JCF *jcf, int index, int expected)
665 {
666   if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
667     fprintf (out, "<constant pool index %d not in range>", index);
668   else if (JPOOL_TAG (jcf, index) != expected)
669     {
670       fprintf (out, "<Unexpected constant type ");
671       print_constant (out, jcf, index, 1);
672       fprintf (out, ">");
673     }
674   else
675     print_constant (out, jcf, index, 0);
676 }
677
678 static void
679 print_constant_terse_with_index (FILE *out, JCF *jcf, int index, int expected)
680 {
681   if (flag_print_constant_pool)
682     fprintf (out, "%d=", index);
683   print_constant_terse (out, jcf, index, expected);
684 }
685
686 /* Print the constant at INDEX in JCF's constant pool.
687    If verbosity==0, print very tersely (no extraneous text).
688    If verbosity==1, prefix the type of the constant.
689    If verbosity==2, add more descriptive text. */
690
691 static void
692 print_constant (FILE *out, JCF *jcf, int index, int verbosity)
693 {
694   int j, n;
695   jlong num;
696   const char *str;
697   int kind = JPOOL_TAG (jcf, index);
698   switch (kind)
699     {
700     case CONSTANT_Class:
701       n = JPOOL_USHORT1 (jcf, index);
702       if (verbosity > 0)
703         {
704           if (verbosity > 1)
705             fprintf (out, "Class name: %d=", n);
706           else
707             fprintf (out, "Class ");
708         }
709       if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n))
710         fprintf (out, "<out of range>");
711       else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8)
712         {
713           int len = JPOOL_UTF_LENGTH (jcf, n);
714           jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.');
715         }
716       else
717         print_constant_terse (out, jcf, n, CONSTANT_Utf8);
718       break;
719     case CONSTANT_Fieldref:
720       str = "Field"; goto field_or_method;
721     case CONSTANT_Methodref:
722       str = "Method"; goto field_or_method;
723     case CONSTANT_InterfaceMethodref:
724       str = "InterfaceMethod"; goto field_or_method;
725     field_or_method:
726       {
727         uint16 tclass = JPOOL_USHORT1 (jcf, index);
728         uint16 name_and_type = JPOOL_USHORT2 (jcf, index);
729         if (verbosity == 2)
730           fprintf (out, "%sref class: %d=", str, tclass);
731         else if (verbosity > 0)
732             fprintf (out, "%s ", str);
733         print_constant_terse (out, jcf, tclass, CONSTANT_Class);
734         if (verbosity < 2)
735           fprintf (out, ".");
736         else
737           fprintf (out, " name_and_type: %d=<", name_and_type);
738         print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType);
739         if (verbosity == 2)
740           fputc ('>', out);
741       }
742       break;
743     case CONSTANT_String:
744       j = JPOOL_USHORT1 (jcf, index);
745       if (verbosity > 0)
746         {
747           if (verbosity > 1)
748             fprintf (out, "String %d=", j);
749           else
750             fprintf (out, "String ");
751         }
752       print_constant_terse (out, jcf, j, CONSTANT_Utf8);
753       break;
754     case CONSTANT_Integer:
755       if (verbosity > 0)
756         fprintf (out, "Integer ");
757       num = JPOOL_INT (jcf, index);
758       goto integer;
759     case CONSTANT_Long:
760       if (verbosity > 0)
761         fprintf (out, "Long ");
762       num = JPOOL_LONG (jcf, index);
763       goto integer;
764     integer:
765       {
766         char buffer[25];
767         format_int (buffer, num, 10);
768         fprintf (out, "%s", buffer);
769         if (verbosity > 1)
770           {
771             format_uint (buffer, (uint64)num, 16);
772             fprintf (out, "=0x%s", buffer);
773           }
774       }
775       break;
776     case CONSTANT_Float:
777       {
778         jfloat fnum = JPOOL_FLOAT (jcf, index);
779
780         if (verbosity > 0)
781           fputs ("Float ", out);
782
783         if (fnum.negative)
784           putc ('-', out);
785
786         if (JFLOAT_FINITE (fnum))
787           {
788             int dummy;
789             int exponent = fnum.exponent - JFLOAT_EXP_BIAS;
790             double f;
791             uint32 mantissa = fnum.mantissa;
792             if (fnum.exponent == 0)
793               /* Denormal.  */
794               exponent++;
795             else
796               /* Normal; add the implicit bit.  */
797               mantissa |= ((uint32)1 << 23);
798             
799             f = frexp (mantissa, &dummy);
800             f = ldexp (f, exponent + 1);
801             fprintf (out, "%.10g", f);
802           }
803         else
804           {
805             if (fnum.mantissa == 0)
806               fputs ("Inf", out);
807             else if (fnum.mantissa & JFLOAT_QNAN_MASK)
808               fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
809             else
810               fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK));
811           }
812
813         if (verbosity > 1)
814           fprintf (out, ", bits = 0x%08lx", (unsigned long) JPOOL_UINT (jcf, index));
815         
816         break;
817       }
818     case CONSTANT_Double:
819       {
820         jdouble dnum = JPOOL_DOUBLE (jcf, index);
821
822         if (verbosity > 0)
823           fputs ("Double ", out);
824
825         if (dnum.negative)
826           putc ('-', out);
827
828         if (JDOUBLE_FINITE (dnum))
829           {
830             int dummy;
831             int exponent = dnum.exponent - JDOUBLE_EXP_BIAS;
832             double d;
833             uint64 mantissa = ((((uint64) dnum.mantissa0) << 32)
834                                + dnum.mantissa1);
835             if (dnum.exponent == 0)
836               /* Denormal.  */
837               exponent++;
838             else
839               /* Normal; add the implicit bit.  */
840               mantissa |= ((uint64)1 << 52);
841
842             d = frexp (mantissa, &dummy);
843             d = ldexp (d, exponent + 1);
844             fprintf (out, "%.20g", d);
845           }
846         else
847           {
848             uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK;
849             mantissa = (mantissa << 32) + dnum.mantissa1;
850
851             if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0)
852               fputs ("Inf", out);
853             else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK)
854               fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa);
855             else
856               fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa);
857           }
858         if (verbosity > 1)
859           {
860             int32 hi, lo;
861             hi = JPOOL_UINT (jcf, index);
862             lo = JPOOL_UINT (jcf, index + 1);
863             fprintf (out, ", bits = 0x%08lx%08lx", (unsigned long) hi,
864                      (unsigned long) lo);
865           }
866         break;
867       }
868     case CONSTANT_NameAndType:
869       {
870         uint16 name = JPOOL_USHORT1 (jcf, index);
871         uint16 sig = JPOOL_USHORT2 (jcf, index);
872         if (verbosity > 0)
873           {
874             if (verbosity > 1)
875               fprintf (out, "NameAndType name: %d=", name);
876             else
877               fprintf (out, "NameAndType ");
878           }
879         print_name (out, jcf, name);
880         if (verbosity <= 1)
881           fputc (' ', out);
882         else
883           fprintf (out, ", signature: %d=", sig);
884         print_signature (out, jcf, sig, 0);
885       }
886       break;
887     case CONSTANT_Utf8:
888       {
889         const unsigned char *str = JPOOL_UTF_DATA (jcf, index);
890         int length = JPOOL_UTF_LENGTH (jcf, index);
891         if (verbosity > 0)
892           { /* Print as 8-bit bytes. */
893             fputs ("Utf8: \"", out);
894             while (--length >= 0)
895               jcf_print_char (out, *str++);
896           }
897         else
898           { /* Print as Unicode. */
899             fputc ('\"', out);
900             jcf_print_utf8 (out, str, length);
901           }
902         fputc ('\"', out);
903       }
904       break;
905     default:
906       fprintf (out, "(Unknown constant type %d)", kind);
907     }
908 }
909
910 static void
911 print_constant_pool (JCF *jcf)
912 {
913   int i;
914   for (i = 1; i < JPOOL_SIZE(jcf); i++)
915     {
916       int kind = JPOOL_TAG (jcf, i);
917       fprintf (out, "#%d: ", i);
918       print_constant (out, jcf, i, 2);
919       fprintf (out, "\n");
920       if (kind == CONSTANT_Double || kind == CONSTANT_Long)
921         i++; /* These take up two slots in the constant table */
922     }
923 }
924
925 static void
926 print_signature_type (FILE* stream, const unsigned char **ptr,
927                       const unsigned char *limit)
928 {
929   int array_size;
930   if ((*ptr) >= limit)
931     return;
932   switch (*(*ptr))
933     {
934     case '[':
935       array_size = -1;
936       for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); (*ptr)++)
937         {
938           array_size = (array_size < 0 ? 0 : 10 * array_size) + *(*ptr) - '0';
939         }
940       print_signature_type (stream, ptr, limit);
941       if (array_size == -1)
942         fprintf (stream, "[]");
943       else
944         fprintf (stream, "[%d]", array_size);
945       break;
946     case '(':
947       {
948         int nargs = 0;
949         fputc (*(*ptr)++, stream);
950         for (; **ptr != ')' && *ptr < limit; nargs++)
951           {
952             if (nargs > 0)
953               fputc (',', stream);
954             print_signature_type (stream, ptr, limit);
955           }
956         if (*ptr < limit)
957           {
958             fputc (*(*ptr)++, stream);
959             print_signature_type (stream, ptr, limit);
960           }
961         else
962           fprintf (stream, "???");
963       }
964     break;
965       
966     case 'B':  fprintf (stream, "byte");  (*ptr)++;  break;
967     case 'C':  fprintf (stream, "char");  (*ptr)++;  break;
968     case 'D':  fprintf (stream, "double");  (*ptr)++;  break;
969     case 'F':  fprintf (stream, "float");  (*ptr)++;  break;
970     case 'S':  fprintf (stream, "short");  (*ptr)++;  break;
971     case 'I':  fprintf (stream, "int");  (*ptr)++;  break;
972     case 'J':  fprintf (stream, "long");  (*ptr)++;  break;
973     case 'Z':  fprintf (stream, "boolean");  (*ptr)++;  break;
974     case 'V':  fprintf (stream, "void");  (*ptr)++;  break;
975
976     case 'L':
977       for ((*ptr)++; (*ptr)<limit && *(*ptr) != ';'; (*ptr)++)
978         jcf_print_char (stream, *(*ptr) == '/' ? '.' : *(*ptr));
979       if (*(*ptr) == ';')
980         (*ptr)++;
981       break;
982     default:
983       jcf_print_char (stream, *(*ptr)++);
984     }
985 }
986
987 static void
988 print_signature (FILE* stream, JCF *jcf, int signature_index, int options)
989 {
990   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
991     print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8);
992   else
993     {
994       const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index);
995       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
996       const unsigned char *limit;
997       limit = str + length;
998       if (str >= limit)
999         fprintf (stream, "<empty signature string>");
1000       else
1001         {
1002           if (options & PRINT_SIGNATURE_RESULT_ONLY)
1003             {
1004               while (str < limit && *str++ != ')') ;
1005             }
1006           if (options & PRINT_SIGNATURE_ARGS_ONLY)
1007             {
1008               str++;
1009               fputc ('(', stream);
1010               while (str < limit && *str != ')')
1011                 {
1012                   print_signature_type (stream, &str, limit);
1013                   if (*str != ')')
1014                     fputs (", ", stream);
1015                 }
1016               fputc (')', stream);
1017             }
1018           else
1019             {
1020               print_signature_type (stream, &str, limit);
1021               if (str < limit)
1022                 {
1023                   fprintf (stream, "<junk:");
1024                   jcf_print_utf8 (stream, str, limit - str);
1025                   fputc ('>', stream);
1026                 }
1027             }
1028         }
1029     }
1030 }
1031
1032
1033 static void
1034 print_exception_table (JCF *jcf, const unsigned char *entries, int count)
1035 {
1036   /* Print exception table. */
1037   int i = count;
1038   if (i > 0)
1039     {
1040       const unsigned char *ptr = entries;
1041       fprintf (out, "Exceptions (count: %d):\n", i);
1042       for (; --i >= 0;  ptr+= 8)
1043         {
1044           int start_pc = GET_u2 (ptr);
1045           int end_pc = GET_u2 (ptr+2);
1046           int handler_pc = GET_u2 (ptr+4);
1047           int catch_type = GET_u2 (ptr+6);
1048           fprintf (out, "  start: %d, end: %d, handler: %d, type: ",
1049                    start_pc, end_pc, handler_pc);
1050           if (catch_type == 0)
1051             fputs ("0 /* finally */", out);
1052           else
1053             print_constant_terse_with_index (out, jcf,
1054                                              catch_type, CONSTANT_Class);
1055           fputc ('\n', out);
1056         }
1057     }
1058 }
1059
1060 #include "jcf-reader.c"
1061
1062 static void
1063 process_class (JCF *jcf)
1064 {
1065   int code;
1066   if (jcf_parse_preamble (jcf) != 0)
1067     fprintf (stderr, _("Not a valid Java .class file.\n"));    
1068
1069   /* Parse and possibly print constant pool */
1070   code = jcf_parse_constant_pool (jcf);
1071   if (code != 0)
1072     {
1073       fprintf (stderr, _("error while parsing constant pool\n"));
1074       exit (FATAL_EXIT_CODE);
1075     }
1076   code = verify_constant_pool (jcf);
1077   if (code > 0)
1078     {
1079       fprintf (stderr, _("error in constant pool entry #%d\n"), code);
1080       exit (FATAL_EXIT_CODE);
1081     }
1082   if (flag_print_constant_pool)
1083     print_constant_pool (jcf);
1084
1085   jcf_parse_class (jcf);
1086   code = jcf_parse_fields (jcf);
1087   if (code != 0)
1088     {
1089       fprintf (stderr, _("error while parsing fields\n"));
1090       exit (FATAL_EXIT_CODE);
1091     }
1092   code = jcf_parse_methods (jcf);
1093   if (code != 0)
1094     {
1095       fprintf (stderr, _("error while parsing methods\n"));
1096       exit (FATAL_EXIT_CODE);
1097     }
1098   code = jcf_parse_final_attributes (jcf);
1099   if (code != 0)
1100     {
1101       fprintf (stderr, _("error while parsing final attributes\n"));
1102       exit (FATAL_EXIT_CODE);
1103     }
1104   jcf->filename = NULL;
1105 }
1106
1107 \f
1108
1109 /* This is used to mark options with no short value.  */
1110 #define LONG_OPT(Num)  ((Num) + 128)
1111
1112 #define OPT_classpath     LONG_OPT (0)
1113 #define OPT_CLASSPATH     OPT_classpath
1114 #define OPT_bootclasspath LONG_OPT (1)
1115 #define OPT_extdirs       LONG_OPT (2)
1116 #define OPT_HELP          LONG_OPT (3)
1117 #define OPT_VERSION       LONG_OPT (4)
1118 #define OPT_JAVAP         LONG_OPT (5)
1119
1120 static const struct option options[] =
1121 {
1122   { "classpath",     required_argument, NULL, OPT_classpath },
1123   { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
1124   { "extdirs",       required_argument, NULL, OPT_extdirs },
1125   { "CLASSPATH",     required_argument, NULL, OPT_CLASSPATH },
1126   { "help",          no_argument,       NULL, OPT_HELP },
1127   { "verbose",       no_argument,       NULL, 'v' },
1128   { "version",       no_argument,       NULL, OPT_VERSION },
1129   { "javap",         no_argument,       NULL, OPT_JAVAP },
1130   { "print-main",    no_argument,       &flag_print_main, 1 },
1131   { "print-constants", no_argument,     &flag_print_constant_pool, 1 },
1132   { NULL,            no_argument,       NULL, 0 }
1133 };
1134
1135 static void
1136 usage (void)
1137 {
1138   fprintf (stderr, _("Try 'jcf-dump --help' for more information.\n"));
1139   exit (1);
1140 }
1141
1142 static void
1143 help (void)
1144 {
1145   printf (_("Usage: jcf-dump [OPTION]... CLASS...\n\n"));
1146   printf (_("Display contents of a class file in readable form.\n\n"));
1147   printf (_("  -c                      Disassemble method bodies\n"));
1148   printf (_("  --javap                 Generate output in 'javap' format\n"));
1149   printf ("\n");
1150   printf (_("  --classpath PATH        Set path to find .class files\n"));
1151   printf (_("  -IDIR                   Append directory to class path\n"));
1152   printf (_("  --bootclasspath PATH    Override built-in class path\n"));
1153   printf (_("  --extdirs PATH          Set extensions directory path\n"));
1154   printf (_("  -o FILE                 Set output file name\n"));
1155   printf ("\n");
1156   printf (_("  --help                  Print this help, then exit\n"));
1157   printf (_("  --version               Print version number, then exit\n"));
1158   printf (_("  -v, --verbose           Print extra information while running\n"));
1159   printf ("\n");
1160   printf (_("For bug reporting instructions, please see:\n"
1161             "%s.\n"), bug_report_url);
1162   exit (0);
1163 }
1164
1165 static void
1166 version (void)
1167 {
1168   printf ("jcf-dump (GCC) %s\n\n", version_string);
1169   printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
1170   printf (_("This is free software; see the source for copying conditions.  There is NO\n"
1171             "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
1172   exit (0);
1173 }
1174
1175 int
1176 main (int argc, char** argv)
1177 {
1178   JCF jcf[1];
1179   int argi, opt;
1180
1181   /* Unlock the stdio streams.  */
1182   unlock_std_streams ();
1183
1184   gcc_init_libintl ();
1185
1186   if (argc <= 1)
1187     {
1188       fprintf (stderr, _("jcf-dump: no classes specified\n"));
1189       usage ();
1190     }
1191
1192   jcf_path_init ();
1193
1194   /* We use getopt_long_only to allow single `-' long options.  For
1195      some of our options this is more natural.  */
1196   while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
1197     {
1198       switch (opt)
1199         {
1200         case 0:
1201           /* Already handled.  */
1202           break;
1203
1204         case 'o':
1205           output_file = optarg;
1206           break;
1207
1208         case 'I':
1209           jcf_path_include_arg (optarg);
1210           break;
1211
1212         case 'v':
1213           verbose++;
1214           break;
1215
1216         case 'c':
1217           flag_disassemble_methods = 1;
1218           break;
1219
1220         case OPT_classpath:
1221           jcf_path_classpath_arg (optarg);
1222           break;
1223
1224         case OPT_bootclasspath:
1225           jcf_path_bootclasspath_arg (optarg);
1226           break;
1227
1228         case OPT_extdirs:
1229           jcf_path_extdirs_arg (optarg);
1230           break;
1231
1232         case OPT_HELP:
1233           help ();
1234           break;
1235
1236         case OPT_VERSION:
1237           version ();
1238           break;
1239
1240         case OPT_JAVAP:
1241           flag_javap_compatible++;
1242           flag_print_constant_pool = 0;
1243           flag_print_attributes = 0;
1244           break;
1245
1246         default:
1247           usage ();
1248         }
1249     }
1250
1251   if (verbose && ! flag_javap_compatible)
1252     flag_print_constant_pool = 1;
1253
1254   if (optind == argc)
1255     {
1256       fprintf (stderr, _("jcf-dump: no classes specified\n"));
1257       usage ();
1258     }
1259
1260   jcf_path_seal (verbose);
1261
1262   if (flag_print_main)
1263     {
1264       flag_print_fields = 0;
1265       flag_print_methods = 0;
1266       flag_print_constant_pool = 0;
1267       flag_print_attributes = 0;
1268       flag_print_class_info = 0;
1269     }
1270
1271   if (output_file)
1272     {
1273       out = fopen (output_file, "w");
1274       if (! out)
1275         {
1276           fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
1277           return FATAL_EXIT_CODE;
1278         }
1279     }
1280   else
1281     out = stdout;
1282
1283   if (optind >= argc)
1284     {
1285       fprintf (out, "Reading .class from <standard input>.\n");
1286       open_class ("<stdio>", jcf, 0, NULL);
1287       process_class (jcf);
1288     }
1289   else
1290     {
1291       for (argi = optind; argi < argc; argi++)
1292         {
1293           char *arg = argv[argi];
1294           const char *class_filename = find_class (arg, strlen (arg), jcf);
1295           if (class_filename == NULL)
1296             class_filename = find_classfile (arg, jcf, NULL);
1297           if (class_filename == NULL)
1298             {
1299               perror ("Could not find class");
1300               return FATAL_EXIT_CODE;
1301             }
1302           JCF_FILL (jcf, 4);
1303           if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
1304             {
1305               long compressed_size, member_size;
1306               int compression_method, filename_length, extra_length;
1307               int general_purpose_bits;
1308               const char *filename;
1309               int total_length;
1310               if (flag_print_class_info)
1311                 fprintf (out, "Reading classes from archive %s.\n",
1312                          class_filename);
1313               for (;;)
1314                 {
1315                   int skip = 0;
1316                   jcf_filbuf_t save_filbuf = jcf->filbuf;
1317                   long magic = JCF_readu4_le (jcf);
1318                   if (magic == 0x02014b50 || magic == 0x06054b50)
1319                     break;  /* got to central directory */
1320                   if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
1321                     {
1322                       fprintf (stderr, _("bad format of .zip/.jar archive\n"));
1323                       return FATAL_EXIT_CODE;
1324                     }
1325                   JCF_FILL (jcf, 26);
1326                   JCF_SKIP (jcf, 2);
1327                   general_purpose_bits = JCF_readu2_le (jcf);
1328                   compression_method = JCF_readu2_le (jcf);
1329                   JCF_SKIP (jcf, 8);
1330                   compressed_size = JCF_readu4_le (jcf);
1331                   member_size = JCF_readu4_le (jcf);
1332                   filename_length = JCF_readu2_le (jcf);
1333                   extra_length = JCF_readu2_le (jcf);
1334                   total_length = filename_length + extra_length
1335                     + compressed_size;
1336                   if (jcf->read_end - jcf->read_ptr < total_length)
1337                     jcf_trim_old_input (jcf);
1338                   JCF_FILL (jcf, total_length);
1339                   filename = (const char *) jcf->read_ptr;
1340                   JCF_SKIP (jcf, filename_length);
1341                   JCF_SKIP (jcf, extra_length);
1342                   if (filename_length > 0
1343                       && filename[filename_length-1] == '/')
1344                     {
1345                       if (flag_print_class_info)
1346                         fprintf (out, "[Skipping directory %.*s]\n",
1347                                  filename_length, filename);
1348                       skip = 1;
1349                     }
1350                   else if (compression_method != 0)
1351                     {
1352                       if (flag_print_class_info)
1353                         fprintf (out, "[Skipping compressed file %.*s]\n",
1354                                  filename_length, filename);
1355                       skip = 1;
1356                     }
1357                   else if (member_size < 4
1358                            || GET_u4 (jcf->read_ptr) != 0xcafebabe)
1359                     {
1360                       if (flag_print_class_info)
1361                         fprintf (out, "[Skipping non-.class member %.*s]\n",
1362                                  filename_length, filename);
1363                       skip = 1;
1364                     }
1365                   else
1366                     {
1367                       if (flag_print_class_info)
1368                         fprintf (out, "Reading class member: %.*s.\n",
1369                                  filename_length, filename);
1370                     }
1371                   if (skip)
1372                     {
1373                       JCF_SKIP (jcf, compressed_size);
1374                     }
1375                   else
1376                     {
1377                       unsigned char *save_end;
1378                       jcf->filbuf = jcf_unexpected_eof;
1379                       save_end = jcf->read_end;
1380                       jcf->read_end = jcf->read_ptr + compressed_size;
1381                       process_class (jcf);
1382                       jcf->filbuf = save_filbuf;
1383                       jcf->read_end = save_end;
1384                     }
1385                 }
1386             }
1387           else
1388             {
1389               if (flag_print_class_info)
1390                 fprintf (out, "Reading .class from %s.\n", class_filename);
1391               process_class (jcf);
1392             }
1393           JCF_FINISH(jcf);
1394         }
1395     }
1396
1397   return SUCCESS_EXIT_CODE;
1398 }
1399
1400 \f
1401
1402 static void
1403 disassemble_method (JCF* jcf, const unsigned char *byte_ops, int len)
1404 {
1405 #undef PTR
1406   int PC;
1407   int i;
1408   int saw_wide = 0;
1409   if (flag_disassemble_methods == 0)
1410     return;
1411 #define BCODE byte_ops
1412   for (PC = 0; PC < len;)
1413     {
1414       int oldpc = PC;
1415       int saw_index;
1416       jint INT_temp;
1417       switch (byte_ops[PC++])
1418         {
1419
1420 /* This is the actual code emitted for each of opcodes in javaops.def.
1421    The actual opcode-specific stuff is handled by the OPKIND macro.
1422    I.e. for an opcode whose OPKIND is BINOP, the BINOP will be called.
1423    Those macros are defined below.  The OPKINDs that do not have any
1424    inline parameters (such as BINOP) and therefore do mot need anything
1425    else to me printed out just use an empty body. */
1426
1427 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1428         case OPCODE: \
1429           fprintf (out, "%3d: %s", oldpc, #OPNAME); \
1430           OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1431           fputc ('\n', out); \
1432           break;
1433
1434 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1435 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1436 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1437 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1438
1439 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > len ? \
1440   (fprintf(stderr, _("Bad byte codes.\n")), exit(-1), 0) : 1)
1441
1442 /* Print out operand (if not implied by the opcode) for PUSCH opcodes.
1443    These all push a constant onto the opcode stack. */
1444 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
1445   saw_index = 0, i = (OPERAND_VALUE); \
1446   if (oldpc+1 == PC) /* nothing */; \
1447   else if (saw_index) fprintf (out, " "), print_constant_ref (out, jcf, i); \
1448   else fprintf (out, " %d", i);
1449
1450 /* Print out operand (a local variable index) for LOAD opcodes.
1451    These all push local variable onto the opcode stack. */
1452 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
1453   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); goto load_store;
1454
1455 /* Handle STORE opcodes same as LOAD opcodes.
1456    These all store a value from the opcode stack in a local variable. */
1457 #define STORE LOAD
1458
1459 /* Handle more kind of opcodes. */
1460 #define STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1461 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1462 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1463 #define CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1464 #define CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1465 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1466 #define UNKNOWN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1467
1468 /* Handle putfield and getfield opcodes, with static versions. */
1469 #define FIELD(MAYBE_STATIC, PUT_OR_GET) \
1470   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2)
1471
1472 /* Print operand for invoke opcodes. */
1473 #define INVOKE(OPERAND_TYPE, OPERAND_VALUE) \
1474   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);\
1475   if (OPERAND_VALUE) /* for invokeinterface */ \
1476   { int nargs = IMMEDIATE_u1;  PC++; \
1477     fprintf (out, " nargs:%d", nargs); }
1478
1479 #define OBJECT(OPERAND_TYPE, OPERAND_VALUE) \
1480   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1481
1482 #define ARRAY(OPERAND_TYPE, SUBOP) \
1483   ARRAY_##SUBOP(OPERAND_TYPE)
1484 /* Handle sub-categories of ARRAY opcodes. */
1485 #define ARRAY_LOAD(TYPE) /* nothing */
1486 #define ARRAY_STORE(TYPE) /* nothing */
1487 #define ARRAY_LENGTH(TYPE) /* nothing */
1488 #define ARRAY_NEW(TYPE) ARRAY_NEW_##TYPE
1489 #define ARRAY_NEW_NUM \
1490  INT_temp = IMMEDIATE_u1; \
1491  { switch ((int) INT_temp) {  \
1492     case  4: fputs (" boolean", out); break; \
1493     case  5: fputs (" char", out); break; \
1494     case  6: fputs (" float", out); break; \
1495     case  7: fputs (" double", out); break; \
1496     case  8: fputs (" byte", out); break; \
1497     case  9: fputs (" short", out); break; \
1498     case 10: fputs (" int", out); break; \
1499     case 11: fputs (" long", out); break; \
1500     default: fprintf (out, " <unknown type code %ld>", (long)INT_temp); break;\
1501   } }
1502
1503 #define ARRAY_NEW_PTR  \
1504   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2);
1505
1506 #define ARRAY_NEW_MULTI \
1507   fputc (' ', out); print_constant_ref (out, jcf, IMMEDIATE_u2); \
1508   fprintf (out, " %d", IMMEDIATE_u1); /* number of dimensions */
1509
1510 #define TEST(OPERAND_TYPE, OPERAND_VALUE) \
1511   fprintf (out, " %d", oldpc + IMMEDIATE_s2)
1512
1513 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1514   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1515   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1516
1517 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
1518   saw_index = 0, INT_temp = (OPERAND_VALUE); \
1519   fprintf (out, " %ld", (long) (saw_index ? INT_temp : oldpc + INT_temp))
1520
1521 #undef RET /* Defined by config/i386/i386.h */
1522 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
1523   INT_temp = saw_wide ? IMMEDIATE_u2 : (OPERAND_VALUE); \
1524   saw_wide = 0; \
1525   fprintf (out, " %ld", (long) INT_temp);
1526
1527 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1528   PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
1529
1530 #define LOOKUP_SWITCH \
1531   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
1532     fprintf (out, " npairs=%ld, default=%ld", (long) npairs, (long) default_offset+oldpc); \
1533     while (--npairs >= 0) { \
1534      jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1535      fprintf (out, "\n%10ld: %ld", (long)match, (long)(offset+oldpc)); } \
1536   }
1537
1538 #define TABLE_SWITCH \
1539   { jint default_offset = IMMEDIATE_s4; \
1540     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1541     fprintf (out, " low=%ld, high=%ld, default=%ld", \
1542       (long) low, (long) high, (long) default_offset+oldpc); \
1543     for (; low <= high; low++) { \
1544      jint offset = IMMEDIATE_s4; \
1545      fprintf (out, "\n%10ld: %ld", (long)low, (long)(offset+oldpc)); } \
1546   }
1547
1548 #define SPECIAL(OPERAND_TYPE, OPERAND_VALUE) \
1549   SPECIAL_##OPERAND_VALUE(OPERAND_TYPE)
1550
1551 #define SPECIAL_IINC(OPERAND_TYPE) \
1552   i = saw_wide ? IMMEDIATE_u2 : IMMEDIATE_u1; \
1553   fprintf (out, " %d", i); \
1554   i = saw_wide ? IMMEDIATE_s2 : IMMEDIATE_s1; \
1555   saw_wide = 0; \
1556   fprintf (out, " %d", i)
1557
1558 #define SPECIAL_WIDE(OPERAND_TYPE) \
1559   saw_wide = 1;
1560
1561 #define SPECIAL_EXIT(OPERAND_TYPE) /* nothing */
1562 #define SPECIAL_ENTER(OPERAND_TYPE) /* nothing */
1563 #define SPECIAL_BREAK(OPERAND_TYPE) /* nothing */
1564 #define SPECIAL_THROW(OPERAND_TYPE) /* nothing */
1565
1566 #define IMPL(OPERAND_TYPE, OPERAND_VALUE) \
1567   fprintf (out, " %d", IMMEDIATE_u##OPERAND_VALUE)
1568
1569 #define COND(OPERAND_TYPE, OPERAND_VALUE) \
1570    TEST(OPERAND_TYPE, OPERAND_VALUE)
1571
1572 #include "javaop.def"
1573
1574         load_store:
1575           if (oldpc+1 == PC) /* nothing - local index implied by opcode */;
1576           else
1577             {
1578               saw_wide = 0;
1579               fprintf (out, " %ld", (long) INT_temp);
1580             }
1581           fputc ('\n', out);
1582           break;
1583
1584         default:
1585           fprintf (out, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
1586         }
1587     }
1588 }