OSDN Git Service

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