OSDN Git Service

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