OSDN Git Service

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