OSDN Git Service

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