OSDN Git Service

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