OSDN Git Service

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