OSDN Git Service

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