OSDN Git Service

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