OSDN Git Service

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