OSDN Git Service

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