OSDN Git Service

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