OSDN Git Service

PR java/10491:
[pf3gnuchains/gcc-fork.git] / gcc / java / gjavah.c
1 /* Program to write C++-suitable header files from a Java(TM) .class
2    file.  This is similar to SUN's javah.
3
4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003
5 Free Software Foundation, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  
23
24 Java and all Java-based marks are trademarks or registered trademarks
25 of Sun Microsystems, Inc. in the United States and other countries.
26 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
27
28 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
29
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "tm.h"
34 #include <math.h>
35
36 #include "jcf.h"
37 #include "tree.h"
38 #include "javaop.h"
39 #include "java-tree.h"
40 #include "java-opcodes.h"
41 #include "ggc.h"
42 #include "hashtab.h"
43
44 #include <getopt.h>
45
46 \f
47
48 /* The output file.  */
49 FILE *out = NULL;
50
51 /* Nonzero on failure.  */
52 static int found_error = 0;
53
54 /* Nonzero if we're generating JNI output.  */
55 static int flag_jni = 0;
56
57 /* When nonzero, warn when source file is newer than matching class
58    file.  */
59 int flag_newer = 1;
60
61 /* Directory to place resulting files in. Set by -d option. */
62 const char *output_directory = "";
63
64 /* Directory to place temporary file.  Set by -td option.  Currently unused. */
65 const char *temp_directory = "/tmp";
66
67 /* Number of friend functions we have to declare.  */
68 static int friend_count;
69
70 /* A class can optionally have a `friend' function declared.  If
71    non-NULL, this is that function.  */
72 static char **friend_specs = NULL;
73
74 /* Number of lines we are prepending before the class.  */
75 static int prepend_count;
76
77 /* We can prepend extra lines before the class's start. */
78 static char **prepend_specs = NULL;
79
80 /* Number of lines we are appending at the end of the class.  */
81 static int add_count;
82
83 /* We can append extra lines just before the class's end. */
84 static char **add_specs = NULL;
85
86 /* Number of lines we are appending after the class.  */
87 static int append_count;
88
89 /* We can append extra lines after the class's end. */
90 static char **append_specs = NULL;
91
92 int verbose = 0;
93
94 int stubs = 0;
95
96 struct JCF *current_jcf;
97
98 /* This holds access information for the last field we examined.  They
99    let us generate "private:", "public:", and "protected:" properly.
100    If 0 then we haven't previously examined any field.  */
101 static JCF_u2 last_access;
102
103 /* Pass this macro the flags for a class and for a method.  It will
104    return true if the method should be considered `final'.  */
105 #define METHOD_IS_FINAL(Class, Method) \
106    (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
107
108 /* Pass this macro the flags for a method.  It will return true if the
109    method is native.  */
110 #define METHOD_IS_NATIVE(Method) \
111    ((Method) & ACC_NATIVE)
112
113 /* We keep a linked list of all method names we have seen.  This lets
114    us determine if a method name and a field name are in conflict.  */
115 struct method_name
116 {
117   unsigned char *name;
118   int length;
119   unsigned char *signature;
120   int sig_length;
121   struct method_name *next;
122 };
123
124 /* List of method names we've seen.  */
125 static struct method_name *method_name_list;
126
127 static void print_field_info (FILE*, JCF*, int, int, JCF_u2);
128 static void print_mangled_classname (FILE*, JCF*, const char*, int);
129 static int  print_cxx_classname (FILE*, const char*, JCF*, int, int);
130 static void print_method_info (FILE*, JCF*, int, int, JCF_u2);
131 static void print_c_decl (FILE*, JCF*, int, int, int, const char *, int);
132 static void print_stub_or_jni (FILE*, JCF*, int, int, int, const char *, int);
133 static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int);
134 static void decompile_method (FILE*, JCF*, int);
135 static void add_class_decl (FILE*, JCF*, JCF_u2);
136
137 static void print_name (FILE *, JCF *, int);
138 static void print_base_classname (FILE *, JCF *, int);
139 static int utf8_cmp (const unsigned char *, int, const char *);
140 static char *cxx_keyword_subst (const unsigned char *, int);
141 static void generate_access (FILE *, JCF_u2);
142 static int name_is_method_p (const unsigned char *, int);
143 static char *get_field_name (JCF *, int, JCF_u2);
144 static void print_field_name (FILE *, JCF *, int, JCF_u2);
145 static const unsigned char *super_class_name (JCF *, int *);
146 static void print_include (FILE *, const unsigned char *, int);
147 static int gcjh_streq (const void *p1, const void *p2);
148 static int throwable_p (const unsigned char *signature);
149 static const unsigned char *
150   decode_signature_piece (FILE *, const unsigned char *,
151                           const unsigned char *, int *);
152 static void print_class_decls (FILE *, JCF *, int);
153 static void usage (void) ATTRIBUTE_NORETURN;
154 static void help (void) ATTRIBUTE_NORETURN;
155 static void version (void) ATTRIBUTE_NORETURN;
156 static int overloaded_jni_method_exists_p (const unsigned char *, int,
157                                            const char *, int);
158 static void jni_print_char (FILE *, int);
159 static void jni_print_float (FILE *, jfloat);
160 static void jni_print_double (FILE *, jdouble);
161 static void decompile_return_statement (FILE *, JCF *, int, int, int);
162
163 static void handle_inner_classes (int);
164
165 JCF_u2 current_field_name;
166 JCF_u2 current_field_value;
167 JCF_u2 current_field_signature;
168 JCF_u2 current_field_flags;
169
170 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
171 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
172   current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
173
174 /* We pass over fields twice.  The first time we just note the types
175    of the fields and then the start of the methods.  Then we go back
176    and parse the fields for real.  This is ugly.  */
177 static int field_pass;
178 /* Likewise we pass over methods twice.  The first time we generate
179    class decl information; the second time we generate actual method
180    decls.  */
181 static int method_pass;
182
183 #define HANDLE_END_FIELD()                                                    \
184   if (field_pass)                                                             \
185     {                                                                         \
186       if (out && ! stubs && ! flag_jni)                                       \
187         print_field_info (out, jcf, current_field_name,                       \
188                           current_field_signature,                            \
189                           current_field_flags);                               \
190     }                                                                         \
191   else if (! stubs && ! flag_jni)                                             \
192     add_class_decl (out, jcf, current_field_signature);
193
194 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
195
196 static int method_declared = 0;
197 static int method_access = 0;
198 static int method_printed = 0;
199 static int method_synthetic = 0;
200 static int method_signature = 0;
201
202 /* Set to 1 while the very first data member of a class is being handled.  */
203 static int is_first_data_member = 0;
204
205 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT)   \
206   {                                                                     \
207     method_synthetic = 0;                                               \
208     method_printed = 0;                                                 \
209     decompiled = 0;                                                     \
210     method_signature = SIGNATURE;                                       \
211     if (ATTRIBUTE_COUNT)                                                \
212       method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT,          \
213                                   (const char *)"Synthetic", 9);        \
214     /* If a synthetic methods have been declared, its attribute aren't  \
215        worth reading (and triggering side-effects). We skip them an     \
216        set ATTRIBUTE_COUNT to zero so that they'll be skipped in        \
217        jcf_parse_one_method.  */                                        \
218     if (method_synthetic)                                               \
219       {                                                                 \
220         skip_attribute (jcf, ATTRIBUTE_COUNT);                          \
221         ATTRIBUTE_COUNT = 0;                                            \
222       }                                                                 \
223     if (method_pass && !method_synthetic)                               \
224       {                                                                 \
225         if (out)                                                        \
226           print_method_info (out, jcf, NAME, SIGNATURE,                 \
227                              ACCESS_FLAGS);                             \
228       }                                                                 \
229     else if (!method_synthetic)                                         \
230       {                                                                 \
231         print_method_info (NULL, jcf, NAME, SIGNATURE,                  \
232                            ACCESS_FLAGS);                               \
233         if (! stubs && ! flag_jni)                                      \
234           add_class_decl (out, jcf, SIGNATURE);                         \
235       }                                                                 \
236   }
237
238 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH)       \
239   if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
240
241 static int decompiled = 0;
242 #define HANDLE_END_METHOD()                             \
243   if (out && method_printed && !method_synthetic)       \
244     fputs (decompiled || stubs ? "\n" : ";\n", out);
245
246 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
247
248 /* We're going to need {peek,skip}_attribute, enable their definition.   */
249 #define NEED_PEEK_ATTRIBUTE
250 #define NEED_SKIP_ATTRIBUTE
251
252 #include "jcf-reader.c"
253
254 /* Print a single-precision float, suitable for parsing by g++.  */
255 static void
256 jni_print_float (FILE *stream, jfloat f)
257 {
258   /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
259      work in data initializers.  FIXME.  */
260   if (JFLOAT_FINITE (f))
261     {
262       fputs (" = ", stream);
263       if (f.negative)
264         putc ('-', stream);
265       if (f.exponent)
266         fprintf (stream, "0x1.%.6xp%+df",
267                  ((unsigned int)f.mantissa) << 1,
268                  f.exponent - JFLOAT_EXP_BIAS);
269       else
270         /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
271            because the implicit leading 1 bit is no longer present.  */
272         fprintf (stream, "0x0.%.6xp%+df",
273                  ((unsigned int)f.mantissa) << 1,
274                  f.exponent + 1 - JFLOAT_EXP_BIAS);
275     }
276   fputs (";\n", stream);
277 }
278
279 /* Print a double-precision float, suitable for parsing by g++.  */
280 static void
281 jni_print_double (FILE *stream, jdouble f)
282 {
283   /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
284      work in data initializers.  FIXME.  */
285   if (JDOUBLE_FINITE (f))
286     {
287       fputs (" = ", stream);
288       if (f.negative)
289         putc ('-', stream);
290       if (f.exponent)
291         fprintf (stream, "0x1.%.5x%.8xp%+d",
292                  f.mantissa0, f.mantissa1,
293                  f.exponent - JDOUBLE_EXP_BIAS);
294       else
295         /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
296            because the implicit leading 1 bit is no longer present.  */
297         fprintf (stream, "0x0.%.5x%.8xp%+d",
298                  f.mantissa0, f.mantissa1,
299                  f.exponent + 1 - JDOUBLE_EXP_BIAS);
300     }
301   fputs (";\n", stream);
302 }
303
304 /* Print a character, appropriately mangled for JNI.  */
305
306 static void
307 jni_print_char (FILE *stream, int ch)
308 {
309   if (! flag_jni)
310     jcf_print_char (stream, ch);
311   else if (ch == '(' || ch == ')')
312     {
313       /* Ignore.  */
314     }
315   else if (ch == '_')
316     fputs ("_1", stream);
317   else if (ch == ';')
318     fputs ("_2", stream);
319   else if (ch == '[')
320     fputs ("_3", stream);
321   else if (ch == '/')
322     fputs ("_", stream);
323   else if (ISALNUM (ch))
324     fputc (ch, stream);
325   else
326     {
327       /* "Unicode" character.  */
328       fprintf (stream, "_0%04x", ch);
329     }
330 }
331
332 /* Print a name from the class data.  If the index does not point to a
333    string, an error results.  */
334
335 static void
336 print_name (FILE* stream, JCF* jcf, int name_index)
337 {
338   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
339     {
340       fprintf (stream, "<not a UTF8 constant>");
341       found_error = 1;
342     }
343   else if (! flag_jni)
344     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
345                     JPOOL_UTF_LENGTH (jcf, name_index));
346   else
347     {
348       /* For JNI we must correctly quote each character.  */
349       const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
350       int length = JPOOL_UTF_LENGTH (jcf, name_index);
351       const unsigned char *limit = str + length;
352       while (str < limit)
353         {
354           int ch = UTF8_GET (str, limit);
355           if (ch < 0)
356             {
357               fprintf (stream, "\\<invalid>");
358               return;
359             }
360           jni_print_char (stream, ch);
361         }
362     }
363 }
364
365 /* Print base name of class.  The base name is everything after the
366    final separator.  */
367
368 static void
369 print_base_classname (FILE *stream, JCF *jcf, int index)
370 {
371   int name_index = JPOOL_USHORT1 (jcf, index);
372   int len;
373   const unsigned char *s, *p, *limit;
374
375   s = JPOOL_UTF_DATA (jcf, name_index);
376   len = JPOOL_UTF_LENGTH (jcf, name_index);
377   limit = s + len;
378   p = s;
379   while (s < limit)
380     {
381       int c = UTF8_GET (s, limit);
382       if (c == '/')
383         p = s;
384     }
385
386   while (p < limit)
387     {
388       int ch = UTF8_GET (p, limit);
389       if (ch == '/')
390         fputs ("::", stream);
391       else
392         jcf_print_char (stream, ch);
393     }
394 }
395
396 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
397    and 1 if STR is "greater" than NAME.  */
398
399 static int
400 utf8_cmp (const unsigned char *str, int length, const char *name)
401 {
402   const unsigned char *limit = str + length;
403   int i;
404
405   for (i = 0; name[i]; ++i)
406     {
407       int ch = UTF8_GET (str, limit);
408       if (ch != name[i])
409         return ch - name[i];
410     }
411
412   return str == limit ? 0 : 1;
413 }
414
415 /* This is a sorted list of all C++ keywords.  */
416
417 static const char *const cxx_keywords[] =
418 {
419   "_Complex",
420   "__alignof",
421   "__alignof__",
422   "__asm",
423   "__asm__",
424   "__attribute",
425   "__attribute__",
426   "__builtin_va_arg",
427   "__complex",
428   "__complex__",
429   "__const",
430   "__const__",
431   "__extension__",
432   "__imag",
433   "__imag__",
434   "__inline",
435   "__inline__",
436   "__label__",
437   "__null",
438   "__real",
439   "__real__",
440   "__restrict",
441   "__restrict__",
442   "__signed",
443   "__signed__",
444   "__typeof",
445   "__typeof__",
446   "__volatile",
447   "__volatile__",
448   "and",
449   "and_eq",
450   "asm",
451   "auto",
452   "bitand",
453   "bitor",
454   "bool",
455   "break",
456   "case",
457   "catch",
458   "char",
459   "class",
460   "compl",
461   "const",
462   "const_cast",
463   "continue",
464   "default",
465   "delete",
466   "do",
467   "double",
468   "dynamic_cast",
469   "else",
470   "enum",
471   "explicit",
472   "export",
473   "extern",
474   "false",
475   "float",
476   "for",
477   "friend",
478   "goto",
479   "if",
480   "inline",
481   "int",
482   "long",
483   "mutable",
484   "namespace",
485   "new",
486   "not",
487   "not_eq",
488   "operator",
489   "or",
490   "or_eq",
491   "private",
492   "protected",
493   "public",
494   "register",
495   "reinterpret_cast",
496   "return",
497   "short",
498   "signed",
499   "sizeof",
500   "static",
501   "static_cast",
502   "struct",
503   "switch",
504   "template",
505   "this",      
506   "throw",
507   "true",
508   "try",
509   "typedef",
510   "typeid",
511   "typename",
512   "typeof",
513   "union",
514   "unsigned",
515   "using",
516   "virtual",
517   "void",
518   "volatile",
519   "wchar_t",
520   "while",
521   "xor",
522   "xor_eq"
523 };
524
525
526 /* If NAME is the name of a C++ keyword, then return an override name.
527    This is a name that can be used in place of the keyword.
528    Otherwise, return NULL.  The return value is malloc()d.  */
529
530 static char *
531 cxx_keyword_subst (const unsigned char *str, int length)
532 {
533   int last = ARRAY_SIZE (cxx_keywords);
534   int first = 0;
535   int mid = (last + first) / 2;
536   int old = -1;
537
538   for (mid = (last + first) / 2;
539        mid != old;
540        old = mid, mid = (last + first) / 2)
541     {
542       int kwl = strlen (cxx_keywords[mid]);
543       int min_length = kwl > length ? length : kwl;
544       int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
545
546       if (r == 0)
547         {
548           int i;
549
550           /* Skip all trailing `$'.  */
551           for (i = min_length; i < length && str[i] == '$'; ++i)
552             ;
553           /* We've only found a match if all the remaining characters
554              are `$'.  */
555           if (i == length)
556             {
557               char *dup = xmalloc (2 + length - min_length + kwl);
558               strcpy (dup, cxx_keywords[mid]);
559               for (i = kwl; i < length + 1; ++i)
560                 dup[i] = '$';
561               dup[i] = '\0';
562               return dup;
563             }
564           r = 1;
565         }
566         
567       if (r < 0)
568         last = mid;
569       else
570         first = mid;
571     }
572   return NULL;
573 }
574
575 /* Generate an access control keyword based on FLAGS.  */
576
577 static void
578 generate_access (FILE *stream, JCF_u2 flags)
579 {
580   if ((flags & ACC_VISIBILITY) == last_access)
581     return;
582   last_access = (flags & ACC_VISIBILITY);
583
584   switch (last_access)
585     {
586     case 0:
587       fputs ("public: // actually package-private\n", stream);
588       break;
589     case ACC_PUBLIC:
590       fputs ("public:\n", stream);
591       break;
592     case ACC_PRIVATE:
593       fputs ("private:\n", stream);
594       break;
595     case ACC_PROTECTED:
596       fputs ("public:  // actually protected\n", stream);
597       break;
598     default:
599       found_error = 1;
600       fprintf (stream, "#error unrecognized visibility %d\n",
601                (flags & ACC_VISIBILITY));
602       break;
603     }
604 }
605
606 /* See if NAME is already the name of a method.  */
607 static int
608 name_is_method_p (const unsigned char *name, int length)
609 {
610   struct method_name *p;
611
612   for (p = method_name_list; p != NULL; p = p->next)
613     {
614       if (p->length == length && ! memcmp (p->name, name, length))
615         return 1;
616     }
617   return 0;
618 }
619
620 /* If there is already a method named NAME, whose signature is not
621    SIGNATURE, then return true.  Otherwise return false.  */
622 static int
623 overloaded_jni_method_exists_p (const unsigned char *name, int length,
624                                 const char *signature, int sig_length)
625 {
626   struct method_name *p;
627
628   for (p = method_name_list; p != NULL; p = p->next)
629     {
630       if (p->length == length
631           && ! memcmp (p->name, name, length)
632           && (p->sig_length != sig_length
633               || memcmp (p->signature, signature, sig_length)))
634         return 1;
635     }
636   return 0;
637 }
638
639 /* Get name of a field.  This handles renamings due to C++ clash.  */
640 static char *
641 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
642 {
643   unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
644   int length = JPOOL_UTF_LENGTH (jcf, name_index);
645   char *override;
646
647   if (name_is_method_p (name, length))
648     {
649       /* This field name matches a method.  So override the name with
650          a dummy name.  This is yucky, but it isn't clear what else to
651          do.  FIXME: if the field is static, then we'll be in real
652          trouble.  */
653       if ((flags & ACC_STATIC))
654         {
655           fprintf (stderr, "static field has same name as method\n");
656           found_error = 1;
657           return NULL;
658         }
659
660       override = xmalloc (length + 3);
661       memcpy (override, name, length);
662       strcpy (override + length, "__");
663     }
664   else
665     override = cxx_keyword_subst (name, length);
666
667   return override;
668 }
669
670 /* Print a field name.  Convenience function for use with
671    get_field_name.  */
672 static void
673 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
674 {
675   char *override = get_field_name (jcf, name_index, flags);
676
677   if (override)
678     {
679       fputs (override, stream);
680       free (override);
681     }
682   else
683     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
684                     JPOOL_UTF_LENGTH (jcf, name_index));
685 }
686
687 static void
688 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
689                   JCF_u2 flags)
690 {
691   char *override = NULL;
692
693   generate_access (stream, flags);
694   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
695     {
696       fprintf (stream, "<not a UTF8 constant>");
697       found_error = 1;
698       return;
699     }
700
701   fputs ("  ", out);
702   if ((flags & ACC_STATIC))
703     fputs ("static ", out);
704
705   if ((flags & ACC_FINAL))
706     {
707       if (current_field_value > 0)
708         {
709           char buffer[25];
710           int done = 1;
711
712           switch (JPOOL_TAG (jcf, current_field_value))
713             {
714             case CONSTANT_Integer:
715               {
716                 jint num;
717                 int most_negative = 0;
718                 fputs ("const jint ", out);
719                 print_field_name (out, jcf, name_index, 0);
720                 fputs (" = ", out);
721                 num = JPOOL_INT (jcf, current_field_value);
722                 /* We single out the most negative number to print
723                    specially.  This avoids later warnings from g++.  */
724                 if (num == (jint) 0x80000000)
725                   {
726                     most_negative = 1;
727                     ++num;
728                   }
729                 format_int (buffer, (jlong) num, 10);
730                 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
731               }
732               break;
733             case CONSTANT_Long:
734               {
735                 jlong num;
736                 int most_negative = 0;
737                 fputs ("const jlong ", out);
738                 print_field_name (out, jcf, name_index, 0);
739                 fputs (" = ", out);
740                 num = JPOOL_LONG (jcf, current_field_value);
741                 /* We single out the most negative number to print
742                    specially..  This avoids later warnings from g++.  */
743                 if (num == (jlong) 0x8000000000000000LL)
744                   {
745                     most_negative = 1;
746                     ++num;
747                   }
748                 format_int (buffer, num, 10);
749                 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
750               }
751               break;
752             case CONSTANT_Float:
753               {
754                 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
755                 fputs ("const jfloat ", out);
756                 print_field_name (out, jcf, name_index, 0);
757                 jni_print_float (out, fnum);
758               }
759               break;
760             case CONSTANT_Double:
761               {
762                 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
763                 fputs ("const jdouble ", out);
764                 print_field_name (out, jcf, name_index, 0);
765                 jni_print_double (out, dnum);
766               }
767               break;
768             default:
769               /* We can't print this as a constant, but we can still
770                  print something sensible.  */
771               done = 0;
772               break;
773             }
774
775           if (done)
776             return;
777         }
778     }
779
780   override = get_field_name (jcf, name_index, flags);
781   print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
782   fputs (";\n", out);
783
784   if (override)
785     free (override);
786 }
787
788
789 static void
790 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
791                    JCF_u2 flags)
792 {
793   const unsigned char *str;
794   int length, is_init = 0;
795   char *override = NULL;
796
797   method_declared = 0;
798   method_access = flags;
799   if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
800     fprintf (stream, "<not a UTF8 constant>");
801   str = JPOOL_UTF_DATA (jcf, name_index);
802   length = JPOOL_UTF_LENGTH (jcf, name_index);
803
804   if (str[0] == '<')
805     {
806       /* Ignore the internally generated method <clinit>. However,
807          treat <init> as a constructor.  */
808       if (! utf8_cmp (str, length, "<init>"))
809         is_init = 1;
810       else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
811                && ! (flags & ACC_STATIC))
812         {
813           /* FIXME: i18n bug here.  Order of prints should not be
814              fixed.  */
815           fprintf (stderr, "ignored method `");
816           jcf_print_utf8 (stderr, str, length);
817           fprintf (stderr, "' marked virtual\n");
818           found_error = 1;
819           return;
820         }
821       else
822         return;
823     }
824
825   /* During the first method pass, build a list of method names. This will
826   be used to determine if field names conflict with method names. */
827   if (! stream)
828     {
829       struct method_name *nn;
830
831       nn = xmalloc (sizeof (struct method_name));
832       nn->name = xmalloc (length);
833       memcpy (nn->name, str, length);
834       nn->length = length;
835       nn->next = method_name_list;
836       nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
837       nn->signature = xmalloc (nn->sig_length);
838       memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
839               nn->sig_length);
840       method_name_list = nn;
841       
842       /* The rest of this function doesn't matter. */
843       return;
844     }
845
846   /* We don't worry about overrides in JNI mode.  */
847   if (! flag_jni)
848     {
849       /* We can't generate a method whose name is a C++ reserved word.
850          We can't just ignore the function, because that will cause
851          incorrect code to be generated if the function is virtual
852          (not only for calls to this function for for other functions
853          after it in the vtbl).  So we give it a dummy name instead.  */
854       override = cxx_keyword_subst (str, length);
855     }
856
857   if (! stubs && ! flag_jni)
858     {
859       method_printed = 1;
860
861       generate_access (stream, flags);
862       
863       fputs ("  ", out);
864       if ((flags & ACC_STATIC))
865         fputs ("static ", out);
866       else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
867         {
868           /* Don't print `virtual' if we have a constructor.  */
869           if (! is_init)
870             fputs ("virtual ", out);
871         }
872       print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
873       
874       if ((flags & ACC_ABSTRACT))
875         fputs (" = 0", out);
876       else
877         method_declared = 1;
878     }
879   else
880     {
881       if (METHOD_IS_NATIVE (flags)) 
882         {
883           method_printed = 1;
884           print_stub_or_jni (out, jcf, name_index, sig_index,
885                              is_init, override, flags);
886         }
887     }
888
889   if (override)
890     free (override);
891 }
892
893 /* A helper for the decompiler which prints a `return' statement where
894    the type is a reference type.  If METHODTYPE and OBJECTTYPE are not
895    identical, we emit a cast.  We do this because the C++ compiler
896    doesn't know that a reference can be cast to the type of an
897    interface it implements.  METHODTYPE is the index of the method's
898    signature.  NAMEINDEX is the index of the field name; -1 for
899    `this'.  OBJECTTYPE is the index of the object's type.  */
900 static void
901 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
902                             int nameindex, int objecttype)
903 {
904   int cast = 0;
905   int obj_name_len, method_name_len;
906   const unsigned char *obj_data, *method_data;
907
908   obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
909   obj_data = JPOOL_UTF_DATA (jcf, objecttype);
910
911   method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
912   method_data = JPOOL_UTF_DATA (jcf, methodtype);
913
914   /* Skip forward to return type part of method.  */
915   while (*method_data != ')')
916     {
917       ++method_data;
918       --method_name_len;
919     }
920   /* Skip past `)'.  */
921   ++method_data;
922   --method_name_len;
923
924   /* If we see an `L', skip it and the trailing `;'.  */
925   if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
926     {
927       ++method_data;
928       method_name_len -= 2;
929     }
930   if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
931     {
932       ++obj_data;
933       obj_name_len -= 2;
934     }
935
936   /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
937      need a cast.  Right now there is no way to determine if this is
938      the case.  */
939   if (method_name_len != obj_name_len)
940     cast = 1;
941   else
942     {
943       int i;
944       for (i = 0; i < method_name_len; ++i)
945         {
946           if (method_data[i] != obj_data[i])
947             {
948               cast = 1;
949               break;
950             }
951         }
952     }
953
954   fputs (" { return ", out);
955
956   if (cast)
957     {
958       int array_depth = 0;
959       const unsigned char *limit;
960
961       fputs ("reinterpret_cast<", out);
962
963       while (*method_data == '[')
964         {
965           ++method_data;
966           ++array_depth;
967           --method_name_len;
968           fputs ("JArray<", out);
969         }
970
971       /* Leading space to avoid C++ digraphs.  */
972       fputs (" ::", out);
973
974       /* If we see an `L', skip it and the trailing `;'.  Only do this
975          if we've seen an array specification.  If we don't have an
976          array then the `L' was stripped earlier.  */
977       if (array_depth && method_data[0] == 'L'
978           && method_data[method_name_len - 1] == ';')
979         {
980           ++method_data;
981           method_name_len -= 2;
982         }
983
984       limit = method_data + method_name_len;
985       while (method_data < limit)
986         {
987           int ch = UTF8_GET (method_data, limit);
988           if (ch == '/')
989             fputs ("::", out);
990           else
991             jcf_print_char (out, ch);
992         }
993       fputs (" *", out);
994
995       /* Close each array.  */
996       while (array_depth > 0)
997         {
998           fputs ("> *", out);
999           --array_depth;
1000         }
1001
1002       /* Close the cast.  */
1003       fputs ("> (", out);
1004     }
1005
1006   if (nameindex == -1)
1007     fputs ("this", out);
1008   else
1009     print_field_name (out, jcf, nameindex, 0);
1010
1011   if (cast)
1012     fputs (")", out);
1013
1014   fputs ("; }", out);
1015 }
1016
1017
1018 /* Try to decompile a method body.  Right now we just try to handle a
1019    simple case that we can do.  Expand as desired.  */
1020 static void
1021 decompile_method (FILE *out, JCF *jcf, int code_len)
1022 {
1023   const unsigned char *codes = jcf->read_ptr;
1024   int index;
1025   uint16 name_and_type, name;
1026
1027   /* If the method is synchronized, don't touch it.  */
1028   if ((method_access & ACC_SYNCHRONIZED))
1029     return;
1030
1031   if (code_len == 5
1032       && codes[0] == OPCODE_aload_0
1033       && codes[1] == OPCODE_getfield
1034       && (codes[4] == OPCODE_areturn
1035           || codes[4] == OPCODE_dreturn
1036           || codes[4] == OPCODE_freturn
1037           || codes[4] == OPCODE_ireturn
1038           || codes[4] == OPCODE_lreturn))
1039     {
1040       /* Found code like `return FIELD'.  */
1041       index = (codes[2] << 8) | codes[3];
1042       /* FIXME: ensure that tag is CONSTANT_Fieldref.  */
1043       name_and_type = JPOOL_USHORT2 (jcf, index);
1044       /* FIXME: ensure that tag is CONSTANT_NameAndType.  */
1045       name = JPOOL_USHORT1 (jcf, name_and_type);
1046       if (codes[4] == OPCODE_areturn)
1047         decompile_return_statement (out, jcf, method_signature,
1048                                     name, JPOOL_USHORT2 (jcf, name_and_type));
1049       else
1050         {
1051           fputs (" { return ", out);
1052           /* FIXME: flags.  */
1053           print_field_name (out, jcf, name, 0);
1054           fputs ("; }", out);
1055         }
1056       decompiled = 1;
1057     }
1058   else if (code_len == 2
1059            && codes[0] == OPCODE_aload_0
1060            && codes[1] == OPCODE_areturn
1061            /* We're going to generate `return this'.  This only makes
1062               sense for non-static methods.  */
1063            && ! (method_access & ACC_STATIC))
1064     {
1065       decompile_return_statement (out, jcf, method_signature, -1,
1066                                   JPOOL_USHORT1 (jcf, jcf->this_class));
1067       decompiled = 1;
1068     }
1069   else if (code_len == 1 && codes[0] == OPCODE_return)
1070     {
1071       /* Found plain `return'.  */
1072       fputs (" { }", out);
1073       decompiled = 1;
1074     }
1075   else if (code_len == 2
1076            && codes[0] == OPCODE_aconst_null
1077            && codes[1] == OPCODE_areturn)
1078     {
1079       /* Found `return null'.  We don't want to depend on NULL being
1080          defined.  */
1081       fputs (" { return 0; }", out);
1082       decompiled = 1;
1083     }
1084 }
1085
1086 /* Like strcmp, but invert the return result for the hash table.  This
1087    should probably be in hashtab.c to complement the existing string
1088    hash function.  */
1089 static int
1090 gcjh_streq (const void *p1, const void *p2)
1091 {
1092   return ! strcmp ((char *) p1, (char *) p2);
1093 }
1094
1095 /* Return 1 if the initial part of CLNAME names a subclass of throwable, 
1096    or 0 if not.  CLNAME may be extracted from a signature, and can be 
1097    terminated with either `;' or NULL.  */
1098 static int
1099 throwable_p (const unsigned char *clname)
1100 {
1101   int length;
1102   unsigned char *current;
1103   int i;
1104   int result = 0;
1105
1106   /* We keep two hash tables of class names.  In one we list all the
1107      classes which are subclasses of Throwable.  In the other we will
1108      all other classes.  We keep two tables to make the code a bit
1109      simpler; we don't have to have a structure mapping class name to
1110      a `throwable?' bit.  */
1111   static htab_t throw_hash;
1112   static htab_t non_throw_hash;
1113   static int init_done = 0;
1114
1115   if (! init_done)
1116     {
1117       void **slot;
1118       unsigned char *str;
1119
1120       /* Self-initializing.  The cost of this really doesn't matter.
1121          We also don't care about freeing these, either.  */
1122       throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1123                                 (htab_del) free);
1124       non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1125                                     (htab_del) free);
1126
1127       /* Make sure the root classes show up in the tables.  */
1128       str = xstrdup ("java.lang.Throwable");
1129       slot = htab_find_slot (throw_hash, str, INSERT);
1130       *slot = str;
1131
1132       str = xstrdup ("java.lang.Object");
1133       slot = htab_find_slot (non_throw_hash, str, INSERT);
1134       *slot = str;
1135
1136       init_done = 1;
1137     }
1138
1139   for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1140     ;
1141   current = ALLOC (length + 1);
1142   for (i = 0; i < length; ++i)
1143     current[i] = clname[i] == '/' ? '.' : clname[i];
1144   current[length] = '\0';
1145
1146   /* We don't compute the hash slot here because the table might be
1147      modified by the recursion.  In that case the slot could be
1148      invalidated.  */
1149   if (htab_find (throw_hash, current))
1150     result = 1;
1151   else if (htab_find (non_throw_hash, current))
1152     result = 0;
1153   else
1154     {
1155       JCF jcf;
1156       void **slot;
1157       unsigned char *super, *tmp;
1158       int super_length = -1;
1159       const char *classfile_name = find_class (current, strlen (current),
1160                                                &jcf, 0);
1161
1162       if (! classfile_name)
1163         {
1164           fprintf (stderr, "couldn't find class %s\n", current);
1165           found_error = 1;
1166           return 0;
1167         }
1168       if (jcf_parse_preamble (&jcf) != 0
1169           || jcf_parse_constant_pool (&jcf) != 0
1170           || verify_constant_pool (&jcf) > 0)
1171         {
1172           fprintf (stderr, "parse error while reading %s\n", classfile_name);
1173           found_error = 1;
1174           return 0;
1175         }
1176       jcf_parse_class (&jcf);
1177
1178       tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1179       super = ALLOC (super_length + 1);
1180       memcpy (super, tmp, super_length);      
1181       super[super_length] = '\0';
1182
1183       result = throwable_p (super);
1184       slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1185                              current, INSERT);
1186       *slot = current;
1187       current = NULL;
1188
1189       JCF_FINISH (&jcf);
1190     }
1191
1192   return result;
1193 }
1194
1195 /* Print one piece of a signature.  Returns pointer to next parseable
1196    character on success, NULL on error.  */
1197 static const unsigned char *
1198 decode_signature_piece (FILE *stream, const unsigned char *signature,
1199                         const unsigned char *limit, int *need_space)
1200 {
1201   const char *ctype;
1202   int array_depth = 0;
1203
1204   switch (signature[0])
1205     {
1206     case '[':
1207       /* More spaghetti.  */
1208
1209     array_loop:
1210       for (signature++; (signature < limit
1211                          && ISDIGIT (*signature)); signature++)
1212         ;
1213       switch (*signature)
1214         {
1215         case 'B':
1216           ctype = "jbyteArray";
1217           break;
1218         case 'C':
1219           ctype = "jcharArray";
1220           break;
1221         case 'D':
1222           ctype = "jdoubleArray";
1223           break;
1224         case 'F':
1225           ctype = "jfloatArray";
1226           break;
1227         case 'I':
1228           ctype = "jintArray";
1229           break;
1230         case 'S':
1231           ctype = "jshortArray";
1232           break;
1233         case 'J':
1234           ctype = "jlongArray";
1235           break;
1236         case 'Z':
1237           ctype = "jbooleanArray";
1238           break;
1239         case '[':
1240           /* We have a nested array.  */
1241           ++array_depth;
1242           if (! flag_jni)
1243             fputs ("JArray<", stream);
1244           goto array_loop;
1245
1246         case 'L':
1247           /* We have to generate a reference to JArray here, so that
1248              our output matches what the compiler does.  */
1249           ++signature;
1250           /* Space between `<' and `:' to avoid C++ digraphs.  */
1251           if (! flag_jni)
1252             fputs ("JArray< ::", stream);
1253           while (signature < limit && *signature != ';')
1254             {
1255               int ch = UTF8_GET (signature, limit);
1256               if (! flag_jni)
1257                 {
1258                   if (ch == '/')
1259                     fputs ("::", stream);
1260                   else
1261                     jcf_print_char (stream, ch);
1262                 }
1263             }
1264           if (! flag_jni)
1265             fputs (" *> *", stream);
1266           *need_space = 0;
1267           ctype = NULL;
1268           break;
1269         default:
1270           /* Unparseable signature.  */
1271           return NULL;
1272         }
1273
1274       /* If the previous iterations left us with something to print,
1275          print it.  For JNI, we always print `jobjectArray' in the
1276          nested cases.  */
1277       if (flag_jni && (ctype == NULL || array_depth > 0))
1278         {
1279           ctype = "jobjectArray";
1280           *need_space = 1;
1281         }
1282       /* The `printit' case will advance SIGNATURE for us.  If we
1283          don't go there, we must advance past the `;' ourselves.  */
1284       if (ctype != NULL)
1285         goto printit;
1286       ++signature;
1287       break;
1288
1289     case '(':
1290     case ')':
1291       /* This shouldn't happen.  */
1292       return NULL;
1293
1294     case 'B': ctype = "jbyte";  goto printit;
1295     case 'C': ctype = "jchar";  goto printit;
1296     case 'D': ctype = "jdouble";  goto printit;
1297     case 'F': ctype = "jfloat";  goto printit;
1298     case 'I': ctype = "jint";  goto printit;
1299     case 'J': ctype = "jlong";  goto printit;
1300     case 'S': ctype = "jshort";  goto printit;
1301     case 'Z': ctype = "jboolean";  goto printit;
1302     case 'V': ctype = "void";  goto printit;
1303     case 'L':
1304       if (flag_jni)
1305         {
1306           /* We know about certain types and special-case their names.  */
1307           if (! strncmp (signature, "Ljava/lang/String;",
1308                          sizeof ("Ljava/lang/String;") -1))
1309             ctype = "jstring";
1310           else if (! strncmp (signature, "Ljava/lang/Class;",
1311                               sizeof ("Ljava/lang/Class;") - 1))
1312             ctype = "jclass";
1313           /* Skip leading 'L' for throwable_p call.  */
1314           else if (throwable_p (signature + 1))
1315             ctype = "jthrowable";
1316           else
1317             ctype = "jobject";
1318
1319           while (*signature && *signature != ';')
1320             ++signature;
1321
1322           goto printit;
1323         }
1324       /* Print a leading "::" so we look in the right namespace.  */
1325       fputs ("::", stream);
1326       ++signature;
1327       while (*signature && *signature != ';')
1328         {
1329           int ch = UTF8_GET (signature, limit);
1330           if (ch == '/')
1331             fputs ("::", stream);
1332           else
1333             jcf_print_char (stream, ch);
1334         }
1335       fputs (" *", stream);
1336       if (*signature == ';')
1337         signature++;
1338       *need_space = 0;
1339       break;
1340     default:
1341       *need_space = 1;
1342       jni_print_char (stream, *signature++);
1343       break;
1344     printit:
1345       signature++;
1346       *need_space = 1;
1347       fputs (ctype, stream);
1348       break;
1349     }
1350
1351   if (! flag_jni)
1352     {
1353       while (array_depth-- > 0)
1354         fputs ("> *", stream);
1355     }
1356
1357   return signature;
1358 }
1359
1360 static void
1361 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1362               int is_init, const char *name_override, int flags)
1363 {
1364   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1365     {
1366       fprintf (stream, "<not a UTF8 constant>");
1367       found_error = 1;
1368     }
1369   else
1370     {
1371       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1372       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1373       register const  unsigned char *str = str0;
1374       const unsigned char *limit = str + length;
1375       int need_space = 0;
1376       int is_method = str[0] == '(';
1377       const unsigned char *next;
1378
1379       /* If printing a method, skip to the return signature and print
1380          that first.  However, there is no return value if this is a
1381          constructor.  */
1382       if (is_method && ! is_init)
1383         {
1384           while (str < limit)
1385             {
1386               int ch = *str++;
1387               if (ch == ')')
1388                 break;
1389             }
1390         }
1391
1392       /* If printing a field or an ordinary method, then print the
1393          "return value" now.  */
1394       if (! is_method || ! is_init)
1395         {
1396           next = decode_signature_piece (stream, str, limit, &need_space);
1397           if (! next)
1398             {
1399               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1400               found_error = 1;
1401               return;
1402             }
1403         }
1404
1405       /* Force the alignment of the first data member.  This is
1406          because the "new" C++ ABI changed the alignemnt of non-POD
1407          classes.  gcj, however, still uses the "old" alignment.  */
1408       if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
1409         {
1410           is_first_data_member = 0;
1411           print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1412                                jcf, jcf->super_class, 1);
1413           fputs (" )))) ", stream);
1414         }
1415
1416       /* Now print the name of the thing.  */
1417       if (need_space)
1418         fputs (" ", stream);
1419       print_full_cxx_name (stream, jcf, name_index, 
1420                            signature_index, is_init, name_override,
1421                            flags);
1422     }
1423 }
1424
1425 /* Print the unqualified method name followed by the signature. */
1426 static void
1427 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1428                      int signature_index, int is_init,
1429                      const char *name_override, int flags)
1430 {
1431   int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1432   const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1433   register const unsigned char *str = str0;
1434   const unsigned char *limit = str + length;
1435   int need_space = 0;
1436   int is_method = str[0] == '(';
1437   const unsigned char *next;
1438
1439   if (name_override)
1440     fputs (name_override, stream);
1441   else if (name_index)
1442     {
1443       /* Declare constructors specially.  */
1444       if (is_init)
1445         print_base_classname (stream, jcf, jcf->this_class);
1446       else
1447         print_name (stream, jcf, name_index);
1448     }
1449
1450   if (flag_jni)
1451     {
1452       unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1453       int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1454       if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1455                                           JPOOL_UTF_LENGTH (jcf, name_index),
1456                                           signature, sig_len))
1457         {
1458           /* If this method is overloaded by another native method,
1459              then include the argument information in the mangled
1460              name.  */
1461           unsigned char *limit = signature + sig_len;
1462           fputs ("__", stream);
1463           while (signature < limit)
1464             {
1465               int ch = UTF8_GET (signature, limit);
1466               jni_print_char (stream, ch);
1467               if (ch == ')')
1468                 {
1469                   /* Done.  */
1470                   break;
1471                 }
1472             }
1473         }
1474     }
1475
1476   if (is_method)
1477     {
1478       /* Have a method or a constructor.  Print signature pieces
1479          until done.  */
1480       fputs (" (", stream);
1481
1482       str = str0 + 1;
1483
1484       /* In JNI mode, add extra arguments.  */
1485       if (flag_jni)
1486         {
1487           /* FIXME: it would be nice to know if we are printing a decl
1488              or a definition, and only print `env' for the latter.  */
1489           fputs ("JNIEnv *env", stream);
1490
1491           fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1492
1493           if (*str != ')')
1494             fputs (", ", stream);
1495         }
1496
1497       while (str < limit && *str != ')')
1498         {
1499           next = decode_signature_piece (stream, str, limit, &need_space);
1500           if (! next)
1501             {
1502               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1503               found_error = 1;
1504               return;
1505             }
1506           
1507           if (next < limit && *next != ')')
1508             fputs (", ", stream);
1509           str = next;
1510         }
1511       
1512       fputs (")", stream);
1513     }
1514 }
1515
1516 /* This is a helper for print_stub_or_jni.  */
1517 static void
1518 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1519                             int signature_index, int is_init,
1520                             const char *name_override, int flags)
1521 {
1522   const char *const prefix = flag_jni ? "Java_" : "";
1523   print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1524   fputs (flag_jni ? "_" : "::", stream);
1525   print_full_cxx_name (stream, jcf, name_index, 
1526                        signature_index, is_init, name_override,
1527                        flags);
1528 }
1529
1530 static void
1531 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1532                    int signature_index, int is_init,
1533                    const char *name_override, int flags)
1534 {
1535   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1536     {
1537       fprintf (stream, "<not a UTF8 constant>");
1538       found_error = 1;
1539     }
1540   else
1541     {
1542       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1543       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1544       register const unsigned char *str = str0;
1545       const unsigned char *limit = str + length;
1546       int need_space = 0;
1547       int is_method = str[0] == '(';
1548       const unsigned char *next;
1549
1550       /* Don't print fields in the JNI case.  */
1551       if (! is_method && flag_jni)
1552         return;
1553
1554       if (flag_jni && ! stubs)
1555         fputs ("extern JNIEXPORT ", stream);
1556
1557       /* If printing a method, skip to the return signature and print
1558          that first.  However, there is no return value if this is a
1559          constructor.  */
1560       if (is_method && ! is_init)
1561         {
1562           while (str < limit)
1563             {
1564               int ch = *str++;
1565               if (ch == ')')
1566                 break;
1567             }
1568         }
1569
1570       /* If printing a field or an ordinary method, then print the
1571          "return value" now.  Note that a constructor can't be native,
1572          so we don't bother checking this in the JNI case.  */
1573       if (! is_method || ! is_init)
1574         {
1575           next = decode_signature_piece (stream, str, limit, &need_space);
1576           if (! next)
1577             {
1578               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1579               found_error = 1;
1580               return;
1581             }
1582         }
1583
1584       /* When printing a JNI header we need to respect the space.  In
1585          other cases we're just going to insert a newline anyway.  */
1586       fputs (need_space && ! stubs ? " " : "\n", stream);
1587
1588       if (flag_jni && ! stubs)
1589         fputs ("JNICALL ", stream);
1590       
1591       /* Now print the name of the thing.  */
1592       print_name_for_stub_or_jni (stream, jcf, name_index,
1593                                   signature_index, is_init, name_override,
1594                                   flags);
1595
1596       /* Print the body.  */
1597       if (stubs)
1598         {
1599           if (flag_jni)
1600             fputs ("\n{\n  (*env)->FatalError (\"", stream);
1601           else
1602             fputs ("\n{\n  throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1603           print_name_for_stub_or_jni (stream, jcf, name_index,
1604                                       signature_index, is_init,
1605                                       name_override,
1606                                       flags);
1607           fprintf (stream, " not implemented\")%s;\n}\n\n",
1608                    flag_jni ? "" : ")");
1609         }
1610     }
1611 }
1612
1613 static void
1614 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1615 {
1616   int name_index = JPOOL_USHORT1 (jcf, index);
1617   fputs (prefix, stream);
1618   jcf_print_utf8_replace (out,
1619                           JPOOL_UTF_DATA (jcf, name_index),
1620                           JPOOL_UTF_LENGTH (jcf, name_index),
1621                           '/', '_');
1622 }
1623
1624 /* Print PREFIX, then a class name in C++ format.  If the name refers
1625    to an array, ignore it and don't print PREFIX.  Returns 1 if
1626    something was printed, 0 otherwise.  */
1627 static int
1628 print_cxx_classname (FILE *stream, const char *prefix,
1629                      JCF *jcf, int index, int add_scope)
1630 {
1631   int name_index = JPOOL_USHORT1 (jcf, index);
1632   int len, c;
1633   const unsigned char *s, *p, *limit;
1634
1635   s = JPOOL_UTF_DATA (jcf, name_index);
1636   len = JPOOL_UTF_LENGTH (jcf, name_index);
1637   limit = s + len;
1638
1639   /* Explicitly omit arrays here.  */
1640   p = s;
1641   c = UTF8_GET (p, limit);
1642   if (c == '[')
1643     return 0;
1644
1645   fputs (prefix, stream);
1646
1647   /* Print a leading "::" so we look in the right namespace.  */
1648   if (! flag_jni && ! stubs && add_scope)
1649     fputs ("::", stream);
1650
1651   while (s < limit)
1652     {
1653       c = UTF8_GET (s, limit);
1654       if (c == '/')
1655         fputs (flag_jni ? "_" : "::", stream);
1656       else
1657         jni_print_char (stream, c);
1658     }
1659
1660   return 1;
1661 }
1662
1663 int written_class_count = 0;
1664
1665 /* Return name of superclass.  If LEN is not NULL, fill it with length
1666    of name.  */
1667 static const unsigned char *
1668 super_class_name (JCF *derived_jcf, int *len)
1669 {
1670   int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1671   int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1672   const unsigned char *supername =
1673     JPOOL_UTF_DATA (derived_jcf, supername_index);
1674
1675   if (len)
1676     *len = supername_length;
1677
1678   return supername;
1679 }
1680
1681 static void
1682 handle_inner_classes (int count)
1683 {
1684   int i;
1685
1686   if (out && ! flag_jni && ! stubs && count > 0)
1687     fprintf (out, "\n");
1688
1689   for (i = 0; i < count; ++i)
1690     {
1691       JCF_u2 inner_info_index = JCF_readu2 (current_jcf);
1692
1693       /* There are a few more values here, but we don't care about
1694          them.  The (void) cast is apparently the only way to avoid a
1695          warning here.  */
1696       (void) JCF_readu2 (current_jcf);
1697       (void) JCF_readu2 (current_jcf);
1698       (void) JCF_readu2 (current_jcf);
1699
1700       if (out && ! flag_jni && ! stubs)
1701         {
1702           print_mangled_classname (out, current_jcf, "  friend class ",
1703                                    inner_info_index);
1704           fprintf (out, ";\n");
1705         }
1706     }
1707 }
1708
1709 \f
1710
1711 /* We keep track of all the `#include's we generate, so we can avoid
1712    duplicates.  */
1713 struct include
1714 {
1715   char *name;
1716   struct include *next;
1717 };
1718
1719 /* List of all includes.  */
1720 static struct include *all_includes = NULL;
1721
1722 /* Generate a #include.  */
1723 static void
1724 print_include (FILE *out, const unsigned char *utf8, int len)
1725 {
1726   struct include *incl;
1727
1728   if (! out)
1729     return;
1730
1731   if (len == -1)
1732     len = strlen (utf8);
1733
1734   for (incl = all_includes; incl; incl = incl->next)
1735     {
1736       /* We check the length because we might have a proper prefix.  */
1737       if (len == (int) strlen (incl->name)
1738           && ! strncmp (incl->name, utf8, len))
1739         return;
1740     }
1741
1742   incl = xmalloc (sizeof (struct include));
1743   incl->name = xmalloc (len + 1);
1744   strncpy (incl->name, utf8, len);
1745   incl->name[len] = '\0';
1746   incl->next = all_includes;
1747   all_includes = incl;
1748
1749   fputs ("#include <", out);
1750   jcf_print_utf8_replace (out, utf8, len,
1751                           '/',
1752                           flag_jni ? '_' : '/');
1753   fputs (".h>\n", out);
1754 }
1755
1756 \f
1757
1758 /* This is used to represent part of a package or class name.  */
1759 struct namelet
1760 {
1761   /* The text of this part of the name.  */
1762   char *name;
1763   /* True if this represents a class.  */
1764   int is_class;
1765   /* Linked list of all classes and packages inside this one.  */
1766   struct namelet *subnamelets;
1767   /* Pointer to next sibling.  */
1768   struct namelet *next;
1769 };
1770
1771 static void add_namelet (const unsigned char *, const unsigned char *,
1772                          struct namelet *);
1773 static void print_namelet (FILE *, struct namelet *, int);
1774
1775 /* The special root namelet.  */
1776 static struct namelet root =
1777 {
1778   NULL,
1779   0,
1780   NULL,
1781   NULL
1782 };
1783
1784 /* This extracts the next name segment from the full UTF-8 encoded
1785    package or class name and links it into the tree.  It does this
1786    recursively.  */
1787 static void
1788 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1789              struct namelet *parent)
1790 {
1791   const unsigned char *p;
1792   struct namelet *n = NULL, *np;
1793
1794   /* We want to skip the standard namespaces that we assume the
1795      runtime already knows about.  We only do this at the top level,
1796      though, hence the check for `root'.  */
1797   if (parent == &root)
1798     {
1799 #define JAVALANG "java/lang/"
1800 #define JAVAIO "java/io/"
1801 #define JAVAUTIL "java/util/"
1802       if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1803            && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1804           || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1805               && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1806           || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1807               && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1808         return;
1809     }
1810
1811   for (p = name; p < name_limit && *p != '/'; ++p)
1812     ;
1813
1814   /* Search for this name beneath the PARENT node.  */
1815   for (np = parent->subnamelets; np != NULL; np = np->next)
1816     {
1817       /* We check the length because we might have a proper prefix.  */
1818       if ((int) strlen (np->name) == p - name &&
1819           ! strncmp (name, np->name, p - name))
1820         {
1821           n = np;
1822           break;
1823         }
1824     }
1825
1826   if (n == NULL)
1827     {
1828       n = xmalloc (sizeof (struct namelet));
1829       n->name = xmalloc (p - name + 1);
1830       strncpy (n->name, name, p - name);
1831       n->name[p - name] = '\0';
1832       n->is_class = (p == name_limit);
1833       n->subnamelets = NULL;
1834       n->next = parent->subnamelets;
1835       parent->subnamelets = n;
1836     }
1837
1838   /* We recurse if there is more text, and if the trailing piece does
1839      not represent an inner class. */
1840   if (p < name_limit)
1841     add_namelet (p + 1, name_limit, n);
1842 }
1843
1844 /* Print a single namelet.  Destroys namelets while printing.  */
1845 static void
1846 print_namelet (FILE *out, struct namelet *name, int depth)
1847 {
1848   int i, term = 0;
1849   struct namelet *c;
1850
1851   if (name->name)
1852     {
1853       for (i = 0; i < depth; ++i)
1854         fputc (' ', out);
1855       fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1856                name->name);
1857       if (name->is_class && name->subnamelets == NULL)
1858         fputs (";\n", out);
1859       else
1860         {
1861           term = 1;
1862           fputs ("\n", out);
1863           for (i = 0; i < depth; ++i)
1864             fputc (' ', out);
1865           fputs ("{\n", out);
1866         }
1867     }
1868
1869   c = name->subnamelets;
1870   while (c != NULL)
1871     {
1872       struct namelet *next = c->next;
1873       print_namelet (out, c, depth + 2);
1874       c = next;
1875     }
1876   name->subnamelets = NULL;
1877
1878   if (name->name)
1879     {
1880       if (term)
1881         {
1882           for (i = 0; i < depth; ++i)
1883             fputc (' ', out);
1884           fputs ("}\n", out);
1885           /* Only print a `;' when printing a class.  C++ is evil.  */
1886           if (name->is_class)
1887             fputs (";", out);
1888         }
1889
1890       free (name->name);
1891       free (name);
1892     }
1893 }
1894
1895 /* This is called to add some classes to the list of classes for which
1896    we need decls.  The signature argument can be a function
1897    signature.  */
1898 static void
1899 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1900 {
1901   const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1902   int len = JPOOL_UTF_LENGTH (jcf, signature);
1903   int i;
1904
1905   for (i = 0; i < len; ++i)
1906     {
1907       int start;
1908
1909       /* If we see an array, then we include the array header.  */
1910       if (s[i] == '[')
1911         {
1912           print_include (out, "gcj/array", -1);
1913           continue;
1914         }
1915
1916       /* We're looking for `L<stuff>;' -- everything else is
1917          ignorable.  */
1918       if (s[i] != 'L')
1919         continue;
1920
1921       for (start = ++i; i < len && s[i] != ';'; ++i)
1922         ;
1923
1924       add_namelet (&s[start], &s[i], &root);
1925     }
1926 }
1927
1928 /* Print declarations for all classes required by this class.  Any
1929    class or package in the `java' package is assumed to be handled
1930    statically in libjava; we don't generate declarations for these.
1931    This makes the generated headers a bit easier to read.  */
1932 static void
1933 print_class_decls (FILE *out, JCF *jcf, int self)
1934 {
1935   /* Make sure to always add the current class to the list of things
1936      that should be declared.  */
1937   int name_index = JPOOL_USHORT1 (jcf, self);
1938   int len;
1939   const unsigned char *s;
1940
1941   s = JPOOL_UTF_DATA (jcf, name_index);
1942   len = JPOOL_UTF_LENGTH (jcf, name_index);
1943   add_namelet (s, s + len, &root);
1944
1945   if (root.subnamelets)
1946     {
1947       fputs ("extern \"Java\"\n{\n", out);
1948       /* We use an initial offset of 0 because the root namelet
1949          doesn't cause anything to print.  */
1950       print_namelet (out, &root, 0);
1951       fputs ("}\n\n", out);
1952     }
1953 }
1954
1955 \f
1956
1957 static void
1958 process_file (JCF *jcf, FILE *out)
1959 {
1960   int code, i;
1961   uint32 field_start, method_end, method_start;
1962
1963   current_jcf = jcf;
1964
1965   last_access = -1;
1966
1967   if (jcf_parse_preamble (jcf) != 0)
1968     {
1969       fprintf (stderr, "Not a valid Java .class file.\n");
1970       found_error = 1;
1971       return;
1972     }
1973
1974   /* Parse and possibly print constant pool */
1975   code = jcf_parse_constant_pool (jcf);
1976   if (code != 0)
1977     {
1978       fprintf (stderr, "error while parsing constant pool\n");
1979       found_error = 1;
1980       return;
1981     }
1982   code = verify_constant_pool (jcf);
1983   if (code > 0)
1984     {
1985       fprintf (stderr, "error in constant pool entry #%d\n", code);
1986       found_error = 1;
1987       return;
1988     }
1989
1990   jcf_parse_class (jcf);
1991
1992   if (written_class_count++ == 0 && out)
1993     {
1994       const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1995       if (flag_jni)
1996         {
1997           cstart = "/*";
1998           cstart2 = "  ";
1999           cend = " */";
2000           mode = "";
2001           what = "JNI";
2002           jflag = " -jni";
2003         }
2004       else
2005         {
2006           cstart = "//";
2007           cstart2 = "//";
2008           cend = "";
2009           mode = " -*- c++ -*-";
2010           what = "CNI";
2011           jflag = "";
2012         }
2013
2014       if (! stubs)
2015         fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2016                  cstart, mode, cend);
2017       else
2018         {
2019           fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2020 %s\n\
2021 %s This file is intended to give you a head start on implementing native\n\
2022 %s methods using %s.\n\
2023 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2024 %s overwrite any edits you have made to this file.%s\n\n",
2025                    cstart, jflag, mode,
2026                    cstart2,
2027                    cstart2,
2028                    cstart2,
2029                    what,
2030                    cstart2,
2031                    jflag,
2032                    cstart2,
2033                    cend);
2034         }
2035     }
2036
2037   if (out)
2038     {
2039       if (! stubs)
2040         {
2041           print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2042           fprintf (out, "__\n");
2043
2044           print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2045           fprintf (out, "__\n\n");
2046
2047           if (flag_jni)
2048             {
2049               fprintf (out, "#include <jni.h>\n\n");
2050               fprintf (out, "#ifdef __cplusplus\n");
2051               fprintf (out, "extern \"C\"\n");
2052               fprintf (out, "{\n");
2053               fprintf (out, "#endif\n");
2054             }
2055           else  
2056             {
2057               /* We do this to ensure that inline methods won't be
2058                  `outlined' by g++.  This works as long as method and
2059                  fields are not added by the user.  */
2060               fprintf (out, "#pragma interface\n");
2061
2062               if (jcf->super_class)
2063                 {
2064                   int super_length;
2065                   const unsigned char *supername =
2066                     super_class_name (jcf, &super_length);
2067
2068                   fputs ("\n", out);
2069                   print_include (out, supername, super_length);
2070                 }
2071             }
2072         }
2073       else
2074         {
2075           /* Strip off the ".class" portion of the name when printing
2076              the include file name.  */
2077           char *name;
2078           int i, len = strlen (jcf->classname);
2079           if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2080             len -= 6;
2081           /* Turn the class name into a file name.  */
2082           name = xmalloc (len + 1);
2083           for (i = 0; i < len; ++i)
2084             name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2085           name[i] = '\0';
2086           print_include (out, name, len);
2087           free (name);
2088
2089           if (! flag_jni)
2090             {
2091               print_include (out, "gcj/cni", -1);
2092               print_include (out, "java/lang/UnsupportedOperationException",
2093                              -1);
2094             }
2095         }
2096     }
2097
2098   /* We want to parse the methods first.  But we need to find where
2099      they start.  So first we skip the fields, then parse the methods.
2100      Then we parse the fields and skip the methods.  This is ugly, but
2101      not too bad since we need two full passes to get class decl
2102      information anyway.  */
2103   field_pass = 0;
2104   field_start = JCF_TELL (jcf);
2105   jcf_parse_fields (jcf);
2106
2107   method_start = JCF_TELL (jcf);
2108   method_pass = 0;
2109   jcf_parse_methods (jcf);
2110
2111   if (out)
2112     fputs ("\n", out);
2113
2114   if (out && ! flag_jni)
2115     {
2116       if (! stubs)
2117         print_class_decls (out, jcf, jcf->this_class);
2118
2119       for (i = 0; i < prepend_count; ++i)
2120         fprintf (out, "%s\n", prepend_specs[i]);
2121       if (prepend_count > 0)
2122         fputc ('\n', out);
2123
2124       if (! stubs)
2125         {
2126           if (! print_cxx_classname (out, "class ", jcf,
2127                                      jcf->this_class, 0))
2128             {
2129               fprintf (stderr, "class is of array type\n");
2130               found_error = 1;
2131               return;
2132             }
2133           if (jcf->super_class)
2134             {
2135               if (! print_cxx_classname (out, " : public ", 
2136                                          jcf, jcf->super_class, 1))
2137                 {
2138                   fprintf (stderr, "base class is of array type\n");
2139                   found_error = 1;
2140                   return;
2141                 }
2142             }
2143
2144           fputs ("\n{\n", out);
2145         }
2146     }
2147
2148   /* Now go back for second pass over methods and fields.  */
2149   is_first_data_member = 1;
2150
2151   JCF_SEEK (jcf, method_start);
2152   method_pass = 1;
2153   jcf_parse_methods (jcf);
2154   method_end = JCF_TELL (jcf);
2155
2156   field_pass = 1;
2157   JCF_SEEK (jcf, field_start);
2158   jcf_parse_fields (jcf);
2159   JCF_SEEK (jcf, method_end);
2160
2161   jcf_parse_final_attributes (jcf);
2162
2163   if (out && ! stubs)
2164     {
2165       if (flag_jni)
2166         {
2167           fprintf (out, "\n#ifdef __cplusplus\n");
2168           fprintf (out, "}\n");
2169           fprintf (out, "#endif\n");
2170         }
2171       else
2172         {
2173           /* Generate friend decl if we still must.  */
2174           for (i = 0; i < friend_count; ++i)
2175             fprintf (out, "  friend %s\n", friend_specs[i]);
2176
2177           /* Generate extra declarations.  */
2178           if (add_count > 0)
2179             fputc ('\n', out);
2180           for (i = 0; i < add_count; ++i)
2181             fprintf (out, "  %s\n", add_specs[i]);
2182
2183           /* Generate an entry for the class object.  */
2184           generate_access (out, ACC_PUBLIC);
2185           fprintf (out, "\n  static ::java::lang::Class class$;\n");
2186
2187           fputs ("}", out);
2188           
2189           if (jcf->access_flags & ACC_INTERFACE)
2190             fputs (" __attribute__ ((java_interface))", out);
2191
2192           fputs (";\n", out);
2193
2194           if (append_count > 0)
2195             fputc ('\n', out);
2196           for (i = 0; i < append_count; ++i)
2197             fprintf (out, "%s\n", append_specs[i]);
2198         }
2199
2200       print_mangled_classname (out, jcf, 
2201                                "\n#endif /* __", jcf->this_class);
2202       fprintf (out, "__ */\n");
2203     }
2204 }
2205
2206 \f
2207
2208 /* This is used to mark options with no short value.  */
2209 #define LONG_OPT(Num)  ((Num) + 128)
2210
2211 #define OPT_classpath     LONG_OPT (0)
2212 #define OPT_CLASSPATH     OPT_classpath
2213 #define OPT_bootclasspath LONG_OPT (1)
2214 #define OPT_extdirs       LONG_OPT (2)
2215 #define OPT_HELP          LONG_OPT (3)
2216 #define OPT_TEMP          LONG_OPT (4)
2217 #define OPT_VERSION       LONG_OPT (5)
2218 #define OPT_PREPEND       LONG_OPT (6)
2219 #define OPT_FRIEND        LONG_OPT (7)
2220 #define OPT_ADD           LONG_OPT (8)
2221 #define OPT_APPEND        LONG_OPT (9)
2222 #define OPT_M             LONG_OPT (10)
2223 #define OPT_MM            LONG_OPT (11)
2224 #define OPT_MG            LONG_OPT (12)
2225 #define OPT_MD            LONG_OPT (13)
2226 #define OPT_MMD           LONG_OPT (14)
2227
2228 static const struct option options[] =
2229 {
2230   { "classpath",     required_argument, NULL, OPT_classpath },
2231   { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2232   { "extdirs",       required_argument, NULL, OPT_extdirs },
2233   { "CLASSPATH",     required_argument, NULL, OPT_CLASSPATH },
2234   { "help",          no_argument,       NULL, OPT_HELP },
2235   { "stubs",         no_argument,       &stubs, 1 },
2236   { "td",            required_argument, NULL, OPT_TEMP },
2237   { "verbose",       no_argument,       NULL, 'v' },
2238   { "version",       no_argument,       NULL, OPT_VERSION },
2239   { "prepend",       required_argument, NULL, OPT_PREPEND },
2240   { "friend",        required_argument, NULL, OPT_FRIEND },
2241   { "add",           required_argument, NULL, OPT_ADD },
2242   { "append",        required_argument, NULL, OPT_APPEND },
2243   { "M",             no_argument,       NULL, OPT_M   },
2244   { "MM",            no_argument,       NULL, OPT_MM  },
2245   { "MG",            no_argument,       NULL, OPT_MG  },
2246   { "MD",            no_argument,       NULL, OPT_MD  },
2247   { "MMD",           no_argument,       NULL, OPT_MMD },
2248   { "jni",           no_argument,       &flag_jni, 1 },
2249   { NULL,            no_argument,       NULL, 0 }
2250 };
2251
2252 static void
2253 usage (void)
2254 {
2255   fprintf (stderr, "Try `gcjh --help' for more information.\n");
2256   exit (1);
2257 }
2258
2259 static void
2260 help (void)
2261 {
2262   printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2263   printf ("Generate C++ header files from .class files\n\n");
2264   printf ("  -stubs                  Generate an implementation stub file\n");
2265   printf ("  -jni                    Generate a JNI header or stub\n");
2266   printf ("\n");
2267   printf ("  -add TEXT               Insert TEXT into class body\n");
2268   printf ("  -append TEXT            Insert TEXT after class declaration\n");
2269   printf ("  -friend TEXT            Insert TEXT as `friend' declaration\n");
2270   printf ("  -prepend TEXT           Insert TEXT before start of class\n");
2271   printf ("\n");
2272   printf ("  --classpath PATH        Set path to find .class files\n");
2273   printf ("  -IDIR                   Append directory to class path\n");
2274   printf ("  --bootclasspath PATH    Override built-in class path\n");
2275   printf ("  --extdirs PATH          Set extensions directory path\n");
2276   printf ("  -d DIRECTORY            Set output directory name\n");
2277   printf ("  -o FILE                 Set output file name\n");
2278   printf ("  -td DIRECTORY           Set temporary directory name\n");
2279   printf ("\n");
2280   printf ("  --help                  Print this help, then exit\n");
2281   printf ("  --version               Print version number, then exit\n");
2282   printf ("  -v, --verbose           Print extra information while running\n");
2283   printf ("\n");
2284   printf ("  -M                      Print all dependencies to stdout;\n");
2285   printf ("                             suppress ordinary output\n");
2286   printf ("  -MM                     Print non-system dependencies to stdout;\n");
2287   printf ("                             suppress ordinary output\n");
2288   printf ("  -MD                     Print all dependencies to stdout\n");
2289   printf ("  -MMD                    Print non-system dependencies to stdout\n");
2290   /* We omit -MG until it is implemented.  */
2291   printf ("\n");
2292   printf ("For bug reporting instructions, please see:\n");
2293   printf ("%s.\n", bug_report_url);
2294   exit (0);
2295 }
2296
2297 static void
2298 version (void)
2299 {
2300   printf ("gcjh (GCC) %s\n\n", version_string);
2301   printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2302   printf ("This is free software; see the source for copying conditions.  There is NO\n");
2303   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2304   exit (0);
2305 }
2306
2307 int
2308 main (int argc, char** argv)
2309 {
2310   JCF jcf;
2311   int argi;
2312   char *output_file = NULL;
2313   int emit_dependencies = 0, suppress_output = 0;
2314   int opt;
2315
2316   if (argc <= 1)
2317     {
2318       fprintf (stderr, "gcjh: no classes specified\n");
2319       usage ();
2320     }
2321
2322   jcf_path_init ();
2323
2324   /* We use getopt_long_only to allow single `-' long options.  For
2325      some of our options this is more natural.  */
2326   while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2327     {
2328       switch (opt)
2329         {
2330         case 0:
2331           /* Already handled.  */
2332           break;
2333
2334         case 'o':
2335           output_file = optarg;
2336           break;
2337
2338         case 'd':
2339           output_directory = optarg;
2340           break;
2341
2342         case 'I':
2343           jcf_path_include_arg (optarg);
2344           break;
2345
2346         case 'v':
2347           verbose++;
2348           break;
2349
2350         case OPT_classpath:
2351           jcf_path_classpath_arg (optarg);
2352           break;
2353
2354         case OPT_bootclasspath:
2355           jcf_path_bootclasspath_arg (optarg);
2356           break;
2357
2358         case OPT_extdirs:
2359           jcf_path_extdirs_arg (optarg);
2360           break;
2361
2362         case OPT_HELP:
2363           help ();
2364           break;
2365
2366         case OPT_TEMP:
2367           temp_directory = optarg;
2368           break;
2369
2370         case OPT_VERSION:
2371           version ();
2372           break;
2373
2374         case OPT_PREPEND:
2375           if (prepend_count == 0)
2376             prepend_specs = ALLOC (argc * sizeof (char*));
2377           prepend_specs[prepend_count++] = optarg;
2378           break;
2379
2380         case OPT_FRIEND:
2381           if (friend_count == 0)
2382             friend_specs = ALLOC (argc * sizeof (char*));
2383           friend_specs[friend_count++] = optarg;
2384           break;
2385
2386         case OPT_ADD:
2387           if (add_count == 0)
2388             add_specs = ALLOC (argc * sizeof (char*));
2389           add_specs[add_count++] = optarg;
2390           break;
2391
2392         case OPT_APPEND:
2393           if (append_count == 0)
2394             append_specs = ALLOC (argc * sizeof (char*));
2395           append_specs[append_count++] = optarg;
2396           break;
2397
2398         case OPT_M:
2399           emit_dependencies = 1;
2400           suppress_output = 1;
2401           jcf_dependency_init (1);
2402           break;
2403
2404         case OPT_MM:
2405           emit_dependencies = 1;
2406           suppress_output = 1;
2407           jcf_dependency_init (0);
2408           break;
2409
2410         case OPT_MG:
2411           fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2412           exit (1);
2413
2414         case OPT_MD:
2415           emit_dependencies = 1;
2416           jcf_dependency_init (1);
2417           break;
2418
2419         case OPT_MMD:
2420           emit_dependencies = 1;
2421           jcf_dependency_init (0);
2422           break;
2423
2424         default:
2425           usage ();
2426           break;
2427         }
2428     }
2429
2430   if (optind == argc)
2431     {
2432       fprintf (stderr, "gcjh: no classes specified\n");
2433       usage ();
2434     }
2435
2436   jcf_path_seal (verbose);
2437
2438   if (output_file && emit_dependencies)
2439     {
2440       fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2441       exit (1);
2442     }
2443
2444   for (argi = optind; argi < argc; argi++)
2445     {
2446       char *classname = argv[argi];
2447       char *current_output_file;
2448       const char *classfile_name;
2449
2450       if (verbose)
2451         fprintf (stderr, "Processing %s\n", classname);
2452       if (! output_file)
2453         jcf_dependency_reset ();
2454       classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2455       if (classfile_name == NULL)
2456         {
2457           fprintf (stderr, "%s: no such class\n", classname);
2458           exit (1);
2459         }
2460       if (verbose)
2461         fprintf (stderr, "Found in %s\n", classfile_name);
2462       if (output_file)
2463         {
2464           if (strcmp (output_file, "-") == 0)
2465             out = stdout;
2466           else if (out == NULL)
2467             {
2468               out = fopen (output_file, "w");
2469             }
2470           if (out == NULL)
2471             {
2472               perror (output_file);
2473               exit (1);
2474             }
2475           current_output_file = output_file;
2476         }
2477       else
2478         {
2479           int dir_len = strlen (output_directory);
2480           int i, classname_length = strlen (classname);
2481           current_output_file = ALLOC (dir_len + classname_length + 5);
2482           strcpy (current_output_file, output_directory);
2483           if (dir_len > 0 && output_directory[dir_len-1] != '/')
2484             current_output_file[dir_len++] = '/';
2485           for (i = 0; classname[i] != '\0'; i++)
2486             {
2487               char ch = classname[i];
2488               if (ch == '.')
2489                 ch = '/';
2490               if (flag_jni && ch == '/')
2491                 ch = '_';
2492               current_output_file[dir_len++] = ch;
2493             }
2494           if (emit_dependencies)
2495             {
2496               if (suppress_output)
2497                 {
2498                   jcf_dependency_set_dep_file ("-");
2499                   out = NULL;
2500                 }
2501               else
2502                 {
2503                   /* We use `.hd' and not `.d' to avoid clashes with
2504                      dependency tracking from straight compilation.  */
2505                   strcpy (current_output_file + dir_len, ".hd");
2506                   jcf_dependency_set_dep_file (current_output_file);
2507                 }
2508             }
2509           strcpy (current_output_file + dir_len, 
2510                   stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2511           jcf_dependency_set_target (current_output_file);
2512           if (! suppress_output)
2513             {
2514               out = fopen (current_output_file, "w");
2515               if (out == NULL)
2516                 {
2517                   perror (current_output_file);
2518                   exit (1);
2519                 }
2520             }
2521         }
2522       process_file (&jcf, out);
2523       JCF_FINISH (&jcf);
2524       if (current_output_file != output_file)
2525         free (current_output_file);
2526       jcf_dependency_write ();
2527     }
2528
2529   if (out != NULL && out != stdout)
2530     fclose (out);
2531
2532   return found_error;
2533 }