OSDN Git Service

* expr.c (build_java_jsr): Use emit_jump, not expand_goto.
[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           if (ch == '/')
994             fputs ("::", stream);
995           else
996             jcf_print_char (stream, ch);
997         }
998       fputs (" *", stream);
999       if (*signature == ';')
1000         signature++;
1001       *need_space = 0;
1002       break;
1003     default:
1004       *need_space = 1;
1005       jni_print_char (stream, *signature++);
1006       break;
1007     printit:
1008       signature++;
1009       *need_space = 1;
1010       fputs (ctype, stream);
1011       break;
1012     }
1013
1014   if (! flag_jni)
1015     {
1016       while (array_depth-- > 0)
1017         fputs ("> *", stream);
1018     }
1019
1020   return signature;
1021 }
1022
1023 static void
1024 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
1025                      name_override, flags),
1026       FILE* stream AND JCF* jcf
1027       AND int name_index AND int signature_index
1028       AND int is_init AND const char *name_override AND int flags)
1029 {
1030   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1031     {
1032       fprintf (stream, "<not a UTF8 constant>");
1033       found_error = 1;
1034     }
1035   else
1036     {
1037       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1038       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1039       register const  unsigned char *str = str0;
1040       const unsigned char *limit = str + length;
1041       int need_space = 0;
1042       int is_method = str[0] == '(';
1043       const unsigned char *next;
1044
1045       /* If printing a method, skip to the return signature and print
1046          that first.  However, there is no return value if this is a
1047          constructor.  */
1048       if (is_method && ! is_init)
1049         {
1050           while (str < limit)
1051             {
1052               int ch = *str++;
1053               if (ch == ')')
1054                 break;
1055             }
1056         }
1057
1058       /* If printing a field or an ordinary method, then print the
1059          "return value" now.  */
1060       if (! is_method || ! is_init)
1061         {
1062           next = decode_signature_piece (stream, str, limit, &need_space);
1063           if (! next)
1064             {
1065               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1066               found_error = 1;
1067               return;
1068             }
1069         }
1070
1071       /* Now print the name of the thing.  */
1072       if (need_space)
1073         fputs (" ", stream);
1074       print_full_cxx_name (stream, jcf, name_index, 
1075                            signature_index, is_init, name_override,
1076                            flags);
1077     }
1078 }
1079
1080 /* Print the unqualified method name followed by the signature. */
1081 static void
1082 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index,
1083                             is_init, name_override, flags),
1084       FILE* stream AND JCF* jcf
1085       AND int name_index AND int signature_index AND int is_init 
1086       AND const char *name_override AND int flags)
1087 {
1088   int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1089   const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1090   register const unsigned char *str = str0;
1091   const unsigned char *limit = str + length;
1092   int need_space = 0;
1093   int is_method = str[0] == '(';
1094   const unsigned char *next;
1095
1096   if (name_override)
1097     fputs (name_override, stream);
1098   else if (name_index)
1099     {
1100       /* Declare constructors specially.  */
1101       if (is_init)
1102         print_base_classname (stream, jcf, jcf->this_class);
1103       else
1104         print_name (stream, jcf, name_index);
1105     }
1106
1107   if (flag_jni)
1108     {
1109       unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1110       int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1111       if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1112                                           JPOOL_UTF_LENGTH (jcf, name_index),
1113                                           signature, sig_len))
1114         {
1115           /* If this method is overloaded by another native method,
1116              then include the argument information in the mangled
1117              name.  */
1118           unsigned char *limit = signature + sig_len;
1119           fputs ("__", stream);
1120           while (signature < limit)
1121             {
1122               int ch = UTF8_GET (signature, limit);
1123               jni_print_char (stream, ch);
1124               if (ch == ')')
1125                 {
1126                   /* Done.  */
1127                   break;
1128                 }
1129             }
1130         }
1131     }
1132
1133   if (is_method)
1134     {
1135       /* Have a method or a constructor.  Print signature pieces
1136          until done.  */
1137       fputs (" (", stream);
1138
1139       str = str0 + 1;
1140
1141       /* In JNI mode, add extra arguments.  */
1142       if (flag_jni)
1143         {
1144           /* FIXME: it would be nice to know if we are printing a decl
1145              or a definition, and only print `env' for the latter.  */
1146           fputs ("JNIEnv *env", stream);
1147
1148           fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1149
1150           if (*str != ')')
1151             fputs (", ", stream);
1152         }
1153
1154       while (str < limit && *str != ')')
1155         {
1156           next = decode_signature_piece (stream, str, limit, &need_space);
1157           if (! next)
1158             {
1159               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1160               found_error = 1;
1161               return;
1162             }
1163           
1164           if (next < limit && *next != ')')
1165             fputs (", ", stream);
1166           str = next;
1167         }
1168       
1169       fputs (")", stream);
1170     }
1171 }
1172
1173 /* This is a helper for print_stub_or_jni.  */
1174 static void
1175 DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index,
1176                                     is_init, name_override, flags),
1177        FILE *stream AND JCF *jcf
1178        AND int name_index AND int signature_index
1179        AND int is_init AND const char *name_override AND int flags)
1180 {
1181   const char *const prefix = flag_jni ? "Java_" : "";
1182   print_cxx_classname (stream, prefix, jcf, jcf->this_class);
1183   fputs (flag_jni ? "_" : "::", stream);
1184   print_full_cxx_name (stream, jcf, name_index, 
1185                        signature_index, is_init, name_override,
1186                        flags);
1187 }
1188
1189 static void
1190 DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init,
1191                           name_override, flags),
1192       FILE* stream AND JCF* jcf
1193       AND int name_index AND int signature_index
1194       AND int is_init AND const char *name_override AND int flags)
1195 {
1196   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1197     {
1198       fprintf (stream, "<not a UTF8 constant>");
1199       found_error = 1;
1200     }
1201   else
1202     {
1203       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1204       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1205       register const unsigned char *str = str0;
1206       const unsigned char *limit = str + length;
1207       int need_space = 0;
1208       int is_method = str[0] == '(';
1209       const unsigned char *next;
1210
1211       /* Don't print fields in the JNI case.  */
1212       if (! is_method && flag_jni)
1213         return;
1214
1215       if (flag_jni && ! stubs)
1216         fputs ("extern ", stream);
1217
1218       /* If printing a method, skip to the return signature and print
1219          that first.  However, there is no return value if this is a
1220          constructor.  */
1221       if (is_method && ! is_init)
1222         {
1223           while (str < limit)
1224             {
1225               int ch = *str++;
1226               if (ch == ')')
1227                 break;
1228             }
1229         }
1230
1231       /* If printing a field or an ordinary method, then print the
1232          "return value" now.  Note that a constructor can't be native,
1233          so we don't bother checking this in the JNI case.  */
1234       if (! is_method || ! is_init)
1235         {
1236           next = decode_signature_piece (stream, str, limit, &need_space);
1237           if (! next)
1238             {
1239               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1240               found_error = 1;
1241               return;
1242             }
1243         }
1244
1245       /* When printing a JNI header we need to respect the space.  In
1246          other cases we're just going to insert a newline anyway.  */
1247       fputs (need_space && ! stubs ? " " : "\n", stream);
1248       
1249       /* Now print the name of the thing.  */
1250       print_name_for_stub_or_jni (stream, jcf, name_index,
1251                                   signature_index, is_init, name_override,
1252                                   flags);
1253
1254       /* Print the body.  */
1255       if (stubs)
1256         {
1257           if (flag_jni)
1258             fputs ("\n{\n  (*env)->FatalError (\"", stream);
1259           else
1260             fputs ("\n{\n  JvFail (\"", stream);
1261           print_name_for_stub_or_jni (stream, jcf, name_index,
1262                                       signature_index, is_init,
1263                                       name_override,
1264                                       flags);
1265           fputs (" not implemented\");\n}\n\n", stream);
1266         }
1267     }
1268 }
1269
1270 static void
1271 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
1272       FILE *stream AND JCF *jcf AND const char *prefix AND int index)
1273 {
1274   int name_index = JPOOL_USHORT1 (jcf, index);
1275   fputs (prefix, stream);
1276   jcf_print_utf8_replace (out,
1277                           JPOOL_UTF_DATA (jcf, name_index),
1278                           JPOOL_UTF_LENGTH (jcf, name_index),
1279                           '/', '_');
1280 }
1281
1282 /* Print PREFIX, then a class name in C++ format.  If the name refers
1283    to an array, ignore it and don't print PREFIX.  Returns 1 if
1284    something was printed, 0 otherwise.  */
1285 static int
1286 print_cxx_classname (stream, prefix, jcf, index)
1287      FILE *stream;
1288      const char *prefix;
1289      JCF *jcf;
1290      int index;
1291 {
1292   int name_index = JPOOL_USHORT1 (jcf, index);
1293   int len, c;
1294   const unsigned char *s, *p, *limit;
1295
1296   s = JPOOL_UTF_DATA (jcf, name_index);
1297   len = JPOOL_UTF_LENGTH (jcf, name_index);
1298   limit = s + len;
1299
1300   /* Explicitly omit arrays here.  */
1301   p = s;
1302   c = UTF8_GET (p, limit);
1303   if (c == '[')
1304     return 0;
1305
1306   fputs (prefix, stream);
1307
1308   /* Print a leading "::" so we look in the right namespace.  */
1309   if (! flag_jni && ! stubs)
1310     fputs ("::", stream);
1311
1312   while (s < limit)
1313     {
1314       c = UTF8_GET (s, limit);
1315       if (c == '/')
1316         fputs (flag_jni ? "_" : "::", stream);
1317       else
1318         jni_print_char (stream, c);
1319     }
1320
1321   return 1;
1322 }
1323
1324 int written_class_count = 0;
1325
1326 /* Return name of superclass.  If LEN is not NULL, fill it with length
1327    of name.  */
1328 static const unsigned char *
1329 super_class_name (derived_jcf, len)
1330      JCF *derived_jcf;
1331      int *len;
1332 {
1333   int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1334   int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1335   const unsigned char *supername =
1336     JPOOL_UTF_DATA (derived_jcf, supername_index);
1337
1338   if (len)
1339     *len = supername_length;
1340
1341   return supername;
1342 }
1343
1344 \f
1345
1346 /* We keep track of all the `#include's we generate, so we can avoid
1347    duplicates.  */
1348 struct include
1349 {
1350   char *name;
1351   struct include *next;
1352 };
1353
1354 /* List of all includes.  */
1355 static struct include *all_includes = NULL;
1356
1357 /* Generate a #include.  */
1358 static void
1359 print_include (out, utf8, len)
1360      FILE *out;
1361      const unsigned char *utf8;
1362      int len;
1363 {
1364   struct include *incl;
1365
1366   if (! out)
1367     return;
1368
1369   if (len == -1)
1370     len = strlen (utf8);
1371
1372   for (incl = all_includes; incl; incl = incl->next)
1373     {
1374       /* We check the length because we might have a proper prefix.  */
1375       if (len == (int) strlen (incl->name)
1376           && ! strncmp (incl->name, utf8, len))
1377         return;
1378     }
1379
1380   incl = (struct include *) xmalloc (sizeof (struct include));
1381   incl->name = xmalloc (len + 1);
1382   strncpy (incl->name, utf8, len);
1383   incl->name[len] = '\0';
1384   incl->next = all_includes;
1385   all_includes = incl;
1386
1387   fputs ("#include <", out);
1388   jcf_print_utf8_replace (out, utf8, len,
1389                           '/',
1390                           flag_jni ? '_' : '/');
1391   fputs (".h>\n", out);
1392 }
1393
1394 \f
1395
1396 /* This is used to represent part of a package or class name.  */
1397 struct namelet
1398 {
1399   /* The text of this part of the name.  */
1400   char *name;
1401   /* True if this represents a class.  */
1402   int is_class;
1403   /* Linked list of all classes and packages inside this one.  */
1404   struct namelet *subnamelets;
1405   /* Pointer to next sibling.  */
1406   struct namelet *next;
1407 };
1408
1409 static void add_namelet PARAMS ((const unsigned char *,
1410                                 const unsigned char *, struct namelet *));
1411 static void print_namelet PARAMS ((FILE *, struct namelet *, int));
1412
1413 /* The special root namelet.  */
1414 static struct namelet root =
1415 {
1416   NULL,
1417   0,
1418   NULL,
1419   NULL
1420 };
1421
1422 /* This extracts the next name segment from the full UTF-8 encoded
1423    package or class name and links it into the tree.  It does this
1424    recursively.  */
1425 static void
1426 add_namelet (name, name_limit, parent)
1427      const unsigned char *name, *name_limit;
1428      struct namelet *parent;
1429 {
1430   const unsigned char *p;
1431   struct namelet *n = NULL, *np;
1432
1433   /* We want to skip the standard namespaces that we assume the
1434      runtime already knows about.  We only do this at the top level,
1435      though, hence the check for `root'.  */
1436   if (parent == &root)
1437     {
1438 #define JAVALANG "java/lang/"
1439 #define JAVAIO "java/io/"
1440 #define JAVAUTIL "java/util/"
1441       if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1442            && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1443           || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1444               && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1445           || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1446               && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1447         return;
1448     }
1449
1450   for (p = name; p < name_limit && *p != '/' && *p != '$'; ++p)
1451     ;
1452
1453   /* Search for this name beneath the PARENT node.  */
1454   for (np = parent->subnamelets; np != NULL; np = np->next)
1455     {
1456       /* We check the length because we might have a proper prefix.  */
1457       if ((int) strlen (np->name) == p - name &&
1458           ! strncmp (name, np->name, p - name))
1459         {
1460           n = np;
1461           break;
1462         }
1463     }
1464
1465   if (n == NULL)
1466     {
1467       n = (struct namelet *) xmalloc (sizeof (struct namelet));
1468       n->name = xmalloc (p - name + 1);
1469       strncpy (n->name, name, p - name);
1470       n->name[p - name] = '\0';
1471       n->is_class = (p == name_limit || *p == '$');
1472       n->subnamelets = NULL;
1473       n->next = parent->subnamelets;
1474       parent->subnamelets = n;
1475     }
1476
1477   /* We recurse if there is more text, and if the trailing piece does
1478      not represent an inner class. */
1479   if (p < name_limit && *p != '$')
1480     add_namelet (p + 1, name_limit, n);
1481 }
1482
1483 /* Print a single namelet.  Destroys namelets while printing.  */
1484 static void
1485 print_namelet (out, name, depth)
1486      FILE *out;
1487      struct namelet *name;
1488      int depth;
1489 {
1490   int i, term = 0;
1491   struct namelet *c;
1492
1493   if (name->name)
1494     {
1495       for (i = 0; i < depth; ++i)
1496         fputc (' ', out);
1497       fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1498                name->name);
1499       if (name->is_class && name->subnamelets == NULL)
1500         fputs (";\n", out);
1501       else
1502         {
1503           term = 1;
1504           fputs ("\n", out);
1505           for (i = 0; i < depth; ++i)
1506             fputc (' ', out);
1507           fputs ("{\n", out);
1508         }
1509     }
1510
1511   c = name->subnamelets;
1512   while (c != NULL)
1513     {
1514       struct namelet *next = c->next;
1515       print_namelet (out, c, depth + 2);
1516       c = next;
1517     }
1518
1519   if (name->name)
1520     {
1521       if (term)
1522         {
1523           for (i = 0; i < depth; ++i)
1524             fputc (' ', out);
1525           fputs ("}\n", out);
1526           /* Only print a `;' when printing a class.  C++ is evil.  */
1527           if (name->is_class)
1528             fputs (";", out);
1529         }
1530
1531       free (name->name);
1532       free (name);
1533     }
1534 }
1535
1536 /* This is called to add some classes to the list of classes for which
1537    we need decls.  The signature argument can be a function
1538    signature.  */
1539 static void
1540 add_class_decl (out, jcf, signature)
1541      FILE *out;
1542      JCF *jcf;
1543      JCF_u2 signature;
1544 {
1545   const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1546   int len = JPOOL_UTF_LENGTH (jcf, signature);
1547   int i;
1548   /* Name of class we are processing.  */
1549   int name_index = JPOOL_USHORT1 (jcf, jcf->this_class);
1550   int tlen = JPOOL_UTF_LENGTH (jcf, name_index);
1551   const char *tname = JPOOL_UTF_DATA (jcf, name_index);
1552
1553   for (i = 0; i < len; ++i)
1554     {
1555       int start, saw_dollar;
1556
1557       /* If we see an array, then we include the array header.  */
1558       if (s[i] == '[')
1559         {
1560           print_include (out, "gcj/array", -1);
1561           continue;
1562         }
1563
1564       /* We're looking for `L<stuff>;' -- everything else is
1565          ignorable.  */
1566       if (s[i] != 'L')
1567         continue;
1568
1569       saw_dollar = 0;
1570       for (start = ++i; i < len && s[i] != ';'; ++i)
1571         {
1572           if (! saw_dollar && s[i] == '$' && out)
1573             {
1574               saw_dollar = 1;
1575               /* If this class represents an inner class, then
1576                  generate a `#include' for the outer class.  However,
1577                  don't generate the include if the outer class is the
1578                  class we are processing.  */
1579               if (i - start < tlen || strncmp (&s[start], tname, i - start))
1580                 print_include (out, &s[start], i - start);
1581               break;
1582             }
1583         }
1584
1585       /* If we saw an inner class, then the generated #include will
1586          declare the class.  So in this case we needn't bother.  */
1587       if (! saw_dollar)
1588         add_namelet (&s[start], &s[i], &root);
1589     }
1590 }
1591
1592 /* Print declarations for all classes required by this class.  Any
1593    class or package in the `java' package is assumed to be handled
1594    statically in libjava; we don't generate declarations for these.
1595    This makes the generated headers a bit easier to read.  */
1596 static void
1597 print_class_decls (out, jcf, self)
1598      FILE *out;
1599      JCF *jcf;
1600      int self;
1601 {
1602   /* Make sure to always add the current class to the list of things
1603      that should be declared.  */
1604   int name_index = JPOOL_USHORT1 (jcf, self);
1605   int len;
1606   const unsigned char *s;
1607
1608   s = JPOOL_UTF_DATA (jcf, name_index);
1609   len = JPOOL_UTF_LENGTH (jcf, name_index);
1610   add_namelet (s, s + len, &root);
1611
1612   if (root.subnamelets)
1613     {
1614       fputs ("extern \"Java\"\n{\n", out);
1615       /* We use an initial offset of 0 because the root namelet
1616          doesn't cause anything to print.  */
1617       print_namelet (out, &root, 0);
1618       fputs ("};\n\n", out);
1619     }
1620 }
1621
1622 \f
1623
1624 static void
1625 DEFUN(process_file, (jcf, out),
1626       JCF *jcf AND FILE *out)
1627 {
1628   int code, i;
1629   uint32 field_start, method_end, method_start;
1630
1631   current_jcf = jcf;
1632
1633   last_access = -1;
1634
1635   if (jcf_parse_preamble (jcf) != 0)
1636     {
1637       fprintf (stderr, "Not a valid Java .class file.\n");
1638       found_error = 1;
1639       return;
1640     }
1641
1642   /* Parse and possibly print constant pool */
1643   code = jcf_parse_constant_pool (jcf);
1644   if (code != 0)
1645     {
1646       fprintf (stderr, "error while parsing constant pool\n");
1647       found_error = 1;
1648       return;
1649     }
1650   code = verify_constant_pool (jcf);
1651   if (code > 0)
1652     {
1653       fprintf (stderr, "error in constant pool entry #%d\n", code);
1654       found_error = 1;
1655       return;
1656     }
1657
1658   jcf_parse_class (jcf);
1659
1660   if (written_class_count++ == 0 && out)
1661     {
1662       const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1663       if (flag_jni)
1664         {
1665           cstart = "/*";
1666           cstart2 = "  ";
1667           cend = " */";
1668           mode = "";
1669           what = "JNI";
1670           jflag = " -jni";
1671         }
1672       else
1673         {
1674           cstart = "//";
1675           cstart2 = "//";
1676           cend = "";
1677           mode = " -*- c++ -*-";
1678           what = "CNI";
1679           jflag = "";
1680         }
1681
1682       if (! stubs)
1683         fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1684                  cstart, mode, cend);
1685       else
1686         {
1687           fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1688 %s\n\
1689 %s This file is intended to give you a head start on implementing native\n\
1690 %s methods using %s.\n\
1691 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1692 %s overwrite any edits you have made to this file.%s\n\n",
1693                    cstart, jflag, mode,
1694                    cstart2,
1695                    cstart2,
1696                    cstart2,
1697                    what,
1698                    cstart2,
1699                    jflag,
1700                    cstart2,
1701                    cend);
1702         }
1703     }
1704
1705   if (out)
1706     {
1707       if (! stubs)
1708         {
1709           print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1710           fprintf (out, "__\n");
1711
1712           print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1713           fprintf (out, "__\n\n");
1714
1715           if (flag_jni)
1716             {
1717               fprintf (out, "#include <jni.h>\n\n");
1718               fprintf (out, "#ifdef __cplusplus\n");
1719               fprintf (out, "extern \"C\"\n");
1720               fprintf (out, "{\n");
1721               fprintf (out, "#endif\n");
1722             }
1723           else  
1724             {
1725               /* We do this to ensure that inline methods won't be
1726                  `outlined' by g++.  This works as long as method and
1727                  fields are not added by the user.  */
1728               fprintf (out, "#pragma interface\n");
1729
1730               if (jcf->super_class)
1731                 {
1732                   int super_length;
1733                   const unsigned char *supername =
1734                     super_class_name (jcf, &super_length);
1735
1736                   fputs ("\n", out);
1737                   print_include (out, supername, super_length);
1738                 }
1739             }
1740         }
1741       else
1742         {
1743           /* Strip off the ".class" portion of the name when printing
1744              the include file name.  */
1745           int len = strlen (jcf->classname);
1746           if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
1747             len -= 6;
1748           print_include (out, jcf->classname, len);
1749           print_include (out, "gcj/cni", -1);
1750         }
1751     }
1752
1753   /* We want to parse the methods first.  But we need to find where
1754      they start.  So first we skip the fields, then parse the methods.
1755      Then we parse the fields and skip the methods.  This is ugly, but
1756      not too bad since we need two full passes to get class decl
1757      information anyway.  */
1758   field_pass = 0;
1759   field_start = JCF_TELL (jcf);
1760   jcf_parse_fields (jcf);
1761
1762   method_start = JCF_TELL (jcf);
1763   method_pass = 0;
1764   jcf_parse_methods (jcf);
1765
1766   if (out)
1767     fputs ("\n", out);
1768
1769   if (out && ! flag_jni)
1770     {
1771       if (! stubs)
1772         print_class_decls (out, jcf, jcf->this_class);
1773
1774       for (i = 0; i < prepend_count; ++i)
1775         fprintf (out, "%s\n", prepend_specs[i]);
1776       if (prepend_count > 0)
1777         fputc ('\n', out);
1778
1779       if (! stubs)
1780         {
1781           if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1782             {
1783               fprintf (stderr, "class is of array type\n");
1784               found_error = 1;
1785               return;
1786             }
1787           if (jcf->super_class)
1788             {
1789               if (! print_cxx_classname (out, " : public ", 
1790                                          jcf, jcf->super_class))
1791                 {
1792                   fprintf (stderr, "base class is of array type\n");
1793                   found_error = 1;
1794                   return;
1795                 }
1796             }
1797
1798           fputs ("\n{\n", out);
1799         }
1800     }
1801
1802   /* Now go back for second pass over methods and fields.  */
1803   JCF_SEEK (jcf, method_start);
1804   method_pass = 1;
1805   jcf_parse_methods (jcf);
1806   method_end = JCF_TELL (jcf);
1807
1808   field_pass = 1;
1809   JCF_SEEK (jcf, field_start);
1810   jcf_parse_fields (jcf);
1811   JCF_SEEK (jcf, method_end);
1812
1813   jcf_parse_final_attributes (jcf);
1814
1815   if (out && ! stubs)
1816     {
1817       if (flag_jni)
1818         {
1819               fprintf (out, "\n#ifdef __cplusplus\n");
1820               fprintf (out, "}\n");
1821               fprintf (out, "#endif\n");
1822         }
1823       else
1824         {
1825           /* Generate friend decl if we still must.  */
1826           for (i = 0; i < friend_count; ++i)
1827             fprintf (out, "  friend %s\n", friend_specs[i]);
1828
1829           /* Generate extra declarations.  */
1830           if (add_count > 0)
1831             fputc ('\n', out);
1832           for (i = 0; i < add_count; ++i)
1833             fprintf (out, "  %s\n", add_specs[i]);
1834
1835           if (! stubs)
1836             fputs ("};\n", out);
1837
1838           if (append_count > 0)
1839             fputc ('\n', out);
1840           for (i = 0; i < append_count; ++i)
1841             fprintf (out, "%s\n", append_specs[i]);
1842         }
1843
1844       print_mangled_classname (out, jcf, 
1845                                "\n#endif /* __", jcf->this_class);
1846       fprintf (out, "__ */\n");
1847     }
1848 }
1849
1850 \f
1851
1852 /* This is used to mark options with no short value.  */
1853 #define LONG_OPT(Num)  ((Num) + 128)
1854
1855 #define OPT_classpath LONG_OPT (0)
1856 #define OPT_CLASSPATH LONG_OPT (1)
1857 #define OPT_HELP      LONG_OPT (2)
1858 #define OPT_TEMP      LONG_OPT (3)
1859 #define OPT_VERSION   LONG_OPT (4)
1860 #define OPT_PREPEND   LONG_OPT (5)
1861 #define OPT_FRIEND    LONG_OPT (6)
1862 #define OPT_ADD       LONG_OPT (7)
1863 #define OPT_APPEND    LONG_OPT (8)
1864 #define OPT_M         LONG_OPT (9)
1865 #define OPT_MM        LONG_OPT (10)
1866 #define OPT_MG        LONG_OPT (11)
1867 #define OPT_MD        LONG_OPT (12)
1868 #define OPT_MMD       LONG_OPT (13)
1869
1870 static struct option options[] =
1871 {
1872   { "classpath", required_argument, NULL, OPT_classpath },
1873   { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
1874   { "help",      no_argument,       NULL, OPT_HELP },
1875   { "stubs",     no_argument,       &stubs, 1 },
1876   { "td",        required_argument, NULL, OPT_TEMP },
1877   { "verbose",   no_argument,       NULL, 'v' },
1878   { "version",   no_argument,       NULL, OPT_VERSION },
1879   { "prepend",   required_argument, NULL, OPT_PREPEND },
1880   { "friend",    required_argument, NULL, OPT_FRIEND },
1881   { "add",       required_argument, NULL, OPT_ADD },
1882   { "append",    required_argument, NULL, OPT_APPEND },
1883   { "M",         no_argument,       NULL, OPT_M   },
1884   { "MM",        no_argument,       NULL, OPT_MM  },
1885   { "MG",        no_argument,       NULL, OPT_MG  },
1886   { "MD",        no_argument,       NULL, OPT_MD  },
1887   { "MMD",       no_argument,       NULL, OPT_MMD },
1888   { "jni",       no_argument,       &flag_jni, 1 },
1889   { NULL,        no_argument,       NULL, 0 }
1890 };
1891
1892 static void
1893 usage ()
1894 {
1895   fprintf (stderr, "Try `gcjh --help' for more information.\n");
1896   exit (1);
1897 }
1898
1899 static void
1900 help ()
1901 {
1902   printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1903   printf ("Generate C++ header files from .class files\n\n");
1904   printf ("  -stubs                  Generate an implementation stub file\n");
1905   printf ("  -jni                    Generate a JNI header or stub\n");
1906   printf ("\n");
1907   printf ("  -add TEXT               Insert TEXT into class body\n");
1908   printf ("  -append TEXT            Insert TEXT after class declaration\n");
1909   printf ("  -friend TEXT            Insert TEXT as `friend' declaration\n");
1910   printf ("  -prepend TEXT           Insert TEXT before start of class\n");
1911   printf ("\n");
1912   printf ("  --classpath PATH        Set path to find .class files\n");
1913   printf ("  --CLASSPATH PATH        Set path to find .class files\n");
1914   printf ("  -IDIR                   Append directory to class path\n");
1915   printf ("  -d DIRECTORY            Set output directory name\n");
1916   printf ("  -o FILE                 Set output file name\n");
1917   printf ("  -td DIRECTORY           Set temporary directory name\n");
1918   printf ("\n");
1919   printf ("  --help                  Print this help, then exit\n");
1920   printf ("  --version               Print version number, then exit\n");
1921   printf ("  -v, --verbose           Print extra information while running\n");
1922   printf ("\n");
1923   printf ("  -M                      Print all dependencies to stdout;\n");
1924   printf ("                             suppress ordinary output\n");
1925   printf ("  -MM                     Print non-system dependencies to stdout;\n");
1926   printf ("                             suppress ordinary output\n");
1927   printf ("  -MD                     Print all dependencies to stdout\n");
1928   printf ("  -MMD                    Print non-system dependencies to stdout\n");
1929   /* We omit -MG until it is implemented.  */
1930   printf ("\n");
1931   printf ("For bug reporting instructions, please see:\n");
1932   printf ("%s.\n", GCCBUGURL);
1933   exit (0);
1934 }
1935
1936 static void
1937 version ()
1938 {
1939   printf ("gcjh (%s)\n\n", version_string);
1940   printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1941   printf ("This is free software; see the source for copying conditions.  There is NO\n");
1942   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1943   exit (0);
1944 }
1945
1946 int
1947 DEFUN(main, (argc, argv),
1948       int argc AND char** argv)
1949 {
1950   JCF jcf;
1951   int argi;
1952   char *output_file = NULL;
1953   int emit_dependencies = 0, suppress_output = 0;
1954   int opt;
1955
1956   if (argc <= 1)
1957     {
1958       fprintf (stderr, "gcjh: no classes specified\n");
1959       usage ();
1960     }
1961
1962   jcf_path_init ();
1963
1964   /* We use getopt_long_only to allow single `-' long options.  For
1965      some of our options this is more natural.  */
1966   while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
1967     {
1968       switch (opt)
1969         {
1970         case 0:
1971           /* Already handled.  */
1972           break;
1973
1974         case 'o':
1975           output_file = optarg;
1976           break;
1977
1978         case 'd':
1979           output_directory = optarg;
1980           break;
1981
1982         case 'I':
1983           jcf_path_include_arg (optarg);
1984           break;
1985
1986         case 'v':
1987           verbose++;
1988           break;
1989
1990         case OPT_classpath:
1991           jcf_path_classpath_arg (optarg);
1992           break;
1993
1994         case OPT_CLASSPATH:
1995           jcf_path_CLASSPATH_arg (optarg);
1996           break;
1997
1998         case OPT_HELP:
1999           help ();
2000           break;
2001
2002         case OPT_TEMP:
2003           temp_directory = optarg;
2004           break;
2005
2006         case OPT_VERSION:
2007           version ();
2008           break;
2009
2010         case OPT_PREPEND:
2011           if (prepend_count == 0)
2012             prepend_specs = (char**) ALLOC (argc * sizeof (char*));
2013           prepend_specs[prepend_count++] = optarg;
2014           break;
2015
2016         case OPT_FRIEND:
2017           if (friend_count == 0)
2018             friend_specs = (char**) ALLOC (argc * sizeof (char*));
2019           friend_specs[friend_count++] = optarg;
2020           break;
2021
2022         case OPT_ADD:
2023           if (add_count == 0)
2024             add_specs = (char**) ALLOC (argc * sizeof (char*));
2025           add_specs[add_count++] = optarg;
2026           break;
2027
2028         case OPT_APPEND:
2029           if (append_count == 0)
2030             append_specs = (char**) ALLOC (argc * sizeof (char*));
2031           append_specs[append_count++] = optarg;
2032           break;
2033
2034         case OPT_M:
2035           emit_dependencies = 1;
2036           suppress_output = 1;
2037           jcf_dependency_init (1);
2038           break;
2039
2040         case OPT_MM:
2041           emit_dependencies = 1;
2042           suppress_output = 1;
2043           jcf_dependency_init (0);
2044           break;
2045
2046         case OPT_MG:
2047           fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2048           exit (1);
2049
2050         case OPT_MD:
2051           emit_dependencies = 1;
2052           jcf_dependency_init (1);
2053           break;
2054
2055         case OPT_MMD:
2056           emit_dependencies = 1;
2057           jcf_dependency_init (0);
2058           break;
2059
2060         default:
2061           usage ();
2062           break;
2063         }
2064     }
2065
2066   if (optind == argc)
2067     {
2068       fprintf (stderr, "gcjh: no classes specified\n");
2069       usage ();
2070     }
2071
2072   jcf_path_seal ();
2073
2074   if (output_file && emit_dependencies)
2075     {
2076       fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2077       exit (1);
2078     }
2079
2080   for (argi = optind; argi < argc; argi++)
2081     {
2082       char *classname = argv[argi];
2083       char *current_output_file;
2084       const char *classfile_name;
2085
2086       if (verbose)
2087         fprintf (stderr, "Processing %s\n", classname);
2088       if (! output_file)
2089         jcf_dependency_reset ();
2090       classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2091       if (classfile_name == NULL)
2092         {
2093           fprintf (stderr, "%s: no such class\n", classname);
2094           exit (1);
2095         }
2096       if (verbose)
2097         fprintf (stderr, "Found in %s\n", classfile_name);
2098       if (output_file)
2099         {
2100           if (strcmp (output_file, "-") == 0)
2101             out = stdout;
2102           else if (out == NULL)
2103             {
2104               out = fopen (output_file, "w");
2105             }
2106           if (out == NULL)
2107             {
2108               perror (output_file);
2109               exit (1);
2110             }
2111           current_output_file = output_file;
2112         }
2113       else
2114         {
2115           int dir_len = strlen (output_directory);
2116           int i, classname_length = strlen (classname);
2117           current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2118           strcpy (current_output_file, output_directory);
2119           if (dir_len > 0 && output_directory[dir_len-1] != '/')
2120             current_output_file[dir_len++] = '/';
2121           for (i = 0; classname[i] != '\0'; i++)
2122             {
2123               char ch = classname[i];
2124               if (ch == '.')
2125                 ch = '/';
2126               if (flag_jni && ch == '/')
2127                 ch = '_';
2128               current_output_file[dir_len++] = ch;
2129             }
2130           if (emit_dependencies)
2131             {
2132               if (suppress_output)
2133                 {
2134                   jcf_dependency_set_dep_file ("-");
2135                   out = NULL;
2136                 }
2137               else
2138                 {
2139                   /* We use `.hd' and not `.d' to avoid clashes with
2140                      dependency tracking from straight compilation.  */
2141                   strcpy (current_output_file + dir_len, ".hd");
2142                   jcf_dependency_set_dep_file (current_output_file);
2143                 }
2144             }
2145           strcpy (current_output_file + dir_len, 
2146                   stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2147           jcf_dependency_set_target (current_output_file);
2148           if (! suppress_output)
2149             {
2150               out = fopen (current_output_file, "w");
2151               if (out == NULL)
2152                 {
2153                   perror (current_output_file);
2154                   exit (1);
2155                 }
2156             }
2157         }
2158       process_file (&jcf, out);
2159       JCF_FINISH (&jcf);
2160       if (current_output_file != output_file)
2161         free (current_output_file);
2162       jcf_dependency_write ();
2163     }
2164
2165   if (out != NULL && out != stdout)
2166     fclose (out);
2167
2168   return found_error;
2169 }