OSDN Git Service

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