OSDN Git Service

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