OSDN Git Service

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