OSDN Git Service

Fix for PR gcj/356:
[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   /* Name of class we are processing.  */
1565   int name_index = JPOOL_USHORT1 (jcf, jcf->this_class);
1566   int tlen = JPOOL_UTF_LENGTH (jcf, name_index);
1567   const char *tname = JPOOL_UTF_DATA (jcf, name_index);
1568
1569   for (i = 0; i < len; ++i)
1570     {
1571       int start;
1572
1573       /* If we see an array, then we include the array header.  */
1574       if (s[i] == '[')
1575         {
1576           print_include (out, "gcj/array", -1);
1577           continue;
1578         }
1579
1580       /* We're looking for `L<stuff>;' -- everything else is
1581          ignorable.  */
1582       if (s[i] != 'L')
1583         continue;
1584
1585       for (start = ++i; i < len && s[i] != ';'; ++i)
1586         ;
1587
1588       add_namelet (&s[start], &s[i], &root);
1589     }
1590 }
1591
1592 /* Print declarations for all classes required by this class.  Any
1593    class or package in the `java' package is assumed to be handled
1594    statically in libjava; we don't generate declarations for these.
1595    This makes the generated headers a bit easier to read.  */
1596 static void
1597 print_class_decls (out, jcf, self)
1598      FILE *out;
1599      JCF *jcf;
1600      int self;
1601 {
1602   /* Make sure to always add the current class to the list of things
1603      that should be declared.  */
1604   int name_index = JPOOL_USHORT1 (jcf, self);
1605   int len;
1606   const unsigned char *s;
1607
1608   s = JPOOL_UTF_DATA (jcf, name_index);
1609   len = JPOOL_UTF_LENGTH (jcf, name_index);
1610   add_namelet (s, s + len, &root);
1611
1612   if (root.subnamelets)
1613     {
1614       fputs ("extern \"Java\"\n{\n", out);
1615       /* We use an initial offset of 0 because the root namelet
1616          doesn't cause anything to print.  */
1617       print_namelet (out, &root, 0);
1618       fputs ("};\n\n", out);
1619     }
1620 }
1621
1622 \f
1623
1624 static void
1625 DEFUN(process_file, (jcf, out),
1626       JCF *jcf AND FILE *out)
1627 {
1628   int code, i;
1629   uint32 field_start, method_end, method_start;
1630
1631   current_jcf = jcf;
1632
1633   last_access = -1;
1634
1635   if (jcf_parse_preamble (jcf) != 0)
1636     {
1637       fprintf (stderr, "Not a valid Java .class file.\n");
1638       found_error = 1;
1639       return;
1640     }
1641
1642   /* Parse and possibly print constant pool */
1643   code = jcf_parse_constant_pool (jcf);
1644   if (code != 0)
1645     {
1646       fprintf (stderr, "error while parsing constant pool\n");
1647       found_error = 1;
1648       return;
1649     }
1650   code = verify_constant_pool (jcf);
1651   if (code > 0)
1652     {
1653       fprintf (stderr, "error in constant pool entry #%d\n", code);
1654       found_error = 1;
1655       return;
1656     }
1657
1658   jcf_parse_class (jcf);
1659
1660   if (written_class_count++ == 0 && out)
1661     {
1662       const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1663       if (flag_jni)
1664         {
1665           cstart = "/*";
1666           cstart2 = "  ";
1667           cend = " */";
1668           mode = "";
1669           what = "JNI";
1670           jflag = " -jni";
1671         }
1672       else
1673         {
1674           cstart = "//";
1675           cstart2 = "//";
1676           cend = "";
1677           mode = " -*- c++ -*-";
1678           what = "CNI";
1679           jflag = "";
1680         }
1681
1682       if (! stubs)
1683         fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1684                  cstart, mode, cend);
1685       else
1686         {
1687           fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1688 %s\n\
1689 %s This file is intended to give you a head start on implementing native\n\
1690 %s methods using %s.\n\
1691 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1692 %s overwrite any edits you have made to this file.%s\n\n",
1693                    cstart, jflag, mode,
1694                    cstart2,
1695                    cstart2,
1696                    cstart2,
1697                    what,
1698                    cstart2,
1699                    jflag,
1700                    cstart2,
1701                    cend);
1702         }
1703     }
1704
1705   if (out)
1706     {
1707       if (! stubs)
1708         {
1709           print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1710           fprintf (out, "__\n");
1711
1712           print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1713           fprintf (out, "__\n\n");
1714
1715           if (flag_jni)
1716             {
1717               fprintf (out, "#include <jni.h>\n\n");
1718               fprintf (out, "#ifdef __cplusplus\n");
1719               fprintf (out, "extern \"C\"\n");
1720               fprintf (out, "{\n");
1721               fprintf (out, "#endif\n");
1722             }
1723           else  
1724             {
1725               /* We do this to ensure that inline methods won't be
1726                  `outlined' by g++.  This works as long as method and
1727                  fields are not added by the user.  */
1728               fprintf (out, "#pragma interface\n");
1729
1730               if (jcf->super_class)
1731                 {
1732                   int super_length;
1733                   const unsigned char *supername =
1734                     super_class_name (jcf, &super_length);
1735
1736                   fputs ("\n", out);
1737                   print_include (out, supername, super_length);
1738                 }
1739             }
1740         }
1741       else
1742         {
1743           /* Strip off the ".class" portion of the name when printing
1744              the include file name.  */
1745           int len = strlen (jcf->classname);
1746           if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
1747             len -= 6;
1748           print_include (out, jcf->classname, len);
1749           print_include (out, "gcj/cni", -1);
1750         }
1751     }
1752
1753   /* We want to parse the methods first.  But we need to find where
1754      they start.  So first we skip the fields, then parse the methods.
1755      Then we parse the fields and skip the methods.  This is ugly, but
1756      not too bad since we need two full passes to get class decl
1757      information anyway.  */
1758   field_pass = 0;
1759   field_start = JCF_TELL (jcf);
1760   jcf_parse_fields (jcf);
1761
1762   method_start = JCF_TELL (jcf);
1763   method_pass = 0;
1764   jcf_parse_methods (jcf);
1765
1766   if (out)
1767     fputs ("\n", out);
1768
1769   if (out && ! flag_jni)
1770     {
1771       if (! stubs)
1772         print_class_decls (out, jcf, jcf->this_class);
1773
1774       for (i = 0; i < prepend_count; ++i)
1775         fprintf (out, "%s\n", prepend_specs[i]);
1776       if (prepend_count > 0)
1777         fputc ('\n', out);
1778
1779       if (! stubs)
1780         {
1781           if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1782             {
1783               fprintf (stderr, "class is of array type\n");
1784               found_error = 1;
1785               return;
1786             }
1787           if (jcf->super_class)
1788             {
1789               if (! print_cxx_classname (out, " : public ", 
1790                                          jcf, jcf->super_class))
1791                 {
1792                   fprintf (stderr, "base class is of array type\n");
1793                   found_error = 1;
1794                   return;
1795                 }
1796             }
1797
1798           fputs ("\n{\n", out);
1799         }
1800     }
1801
1802   /* Now go back for second pass over methods and fields.  */
1803   JCF_SEEK (jcf, method_start);
1804   method_pass = 1;
1805   jcf_parse_methods (jcf);
1806   method_end = JCF_TELL (jcf);
1807
1808   field_pass = 1;
1809   JCF_SEEK (jcf, field_start);
1810   jcf_parse_fields (jcf);
1811   JCF_SEEK (jcf, method_end);
1812
1813   jcf_parse_final_attributes (jcf);
1814
1815   if (out && ! stubs)
1816     {
1817       if (flag_jni)
1818         {
1819           fprintf (out, "\n#ifdef __cplusplus\n");
1820           fprintf (out, "}\n");
1821           fprintf (out, "#endif\n");
1822         }
1823       else
1824         {
1825           /* Generate friend decl if we still must.  */
1826           for (i = 0; i < friend_count; ++i)
1827             fprintf (out, "  friend %s\n", friend_specs[i]);
1828
1829           /* Generate extra declarations.  */
1830           if (add_count > 0)
1831             fputc ('\n', out);
1832           for (i = 0; i < add_count; ++i)
1833             fprintf (out, "  %s\n", add_specs[i]);
1834
1835           /* Generate an entry for the class object.  */
1836           generate_access (out, ACC_PUBLIC);
1837           fprintf (out, "\n  static ::java::lang::Class class$;\n");
1838
1839           fputs ("};\n", out);
1840
1841           if (append_count > 0)
1842             fputc ('\n', out);
1843           for (i = 0; i < append_count; ++i)
1844             fprintf (out, "%s\n", append_specs[i]);
1845         }
1846
1847       print_mangled_classname (out, jcf, 
1848                                "\n#endif /* __", jcf->this_class);
1849       fprintf (out, "__ */\n");
1850     }
1851 }
1852
1853 \f
1854
1855 /* This is used to mark options with no short value.  */
1856 #define LONG_OPT(Num)  ((Num) + 128)
1857
1858 #define OPT_classpath LONG_OPT (0)
1859 #define OPT_CLASSPATH LONG_OPT (1)
1860 #define OPT_HELP      LONG_OPT (2)
1861 #define OPT_TEMP      LONG_OPT (3)
1862 #define OPT_VERSION   LONG_OPT (4)
1863 #define OPT_PREPEND   LONG_OPT (5)
1864 #define OPT_FRIEND    LONG_OPT (6)
1865 #define OPT_ADD       LONG_OPT (7)
1866 #define OPT_APPEND    LONG_OPT (8)
1867 #define OPT_M         LONG_OPT (9)
1868 #define OPT_MM        LONG_OPT (10)
1869 #define OPT_MG        LONG_OPT (11)
1870 #define OPT_MD        LONG_OPT (12)
1871 #define OPT_MMD       LONG_OPT (13)
1872
1873 static struct option options[] =
1874 {
1875   { "classpath", required_argument, NULL, OPT_classpath },
1876   { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
1877   { "help",      no_argument,       NULL, OPT_HELP },
1878   { "stubs",     no_argument,       &stubs, 1 },
1879   { "td",        required_argument, NULL, OPT_TEMP },
1880   { "verbose",   no_argument,       NULL, 'v' },
1881   { "version",   no_argument,       NULL, OPT_VERSION },
1882   { "prepend",   required_argument, NULL, OPT_PREPEND },
1883   { "friend",    required_argument, NULL, OPT_FRIEND },
1884   { "add",       required_argument, NULL, OPT_ADD },
1885   { "append",    required_argument, NULL, OPT_APPEND },
1886   { "M",         no_argument,       NULL, OPT_M   },
1887   { "MM",        no_argument,       NULL, OPT_MM  },
1888   { "MG",        no_argument,       NULL, OPT_MG  },
1889   { "MD",        no_argument,       NULL, OPT_MD  },
1890   { "MMD",       no_argument,       NULL, OPT_MMD },
1891   { "jni",       no_argument,       &flag_jni, 1 },
1892   { NULL,        no_argument,       NULL, 0 }
1893 };
1894
1895 static void
1896 usage ()
1897 {
1898   fprintf (stderr, "Try `gcjh --help' for more information.\n");
1899   exit (1);
1900 }
1901
1902 static void
1903 help ()
1904 {
1905   printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1906   printf ("Generate C++ header files from .class files\n\n");
1907   printf ("  -stubs                  Generate an implementation stub file\n");
1908   printf ("  -jni                    Generate a JNI header or stub\n");
1909   printf ("\n");
1910   printf ("  -add TEXT               Insert TEXT into class body\n");
1911   printf ("  -append TEXT            Insert TEXT after class declaration\n");
1912   printf ("  -friend TEXT            Insert TEXT as `friend' declaration\n");
1913   printf ("  -prepend TEXT           Insert TEXT before start of class\n");
1914   printf ("\n");
1915   printf ("  --classpath PATH        Set path to find .class files\n");
1916   printf ("  --CLASSPATH PATH        Set path to find .class files\n");
1917   printf ("  -IDIR                   Append directory to class path\n");
1918   printf ("  -d DIRECTORY            Set output directory name\n");
1919   printf ("  -o FILE                 Set output file name\n");
1920   printf ("  -td DIRECTORY           Set temporary directory name\n");
1921   printf ("\n");
1922   printf ("  --help                  Print this help, then exit\n");
1923   printf ("  --version               Print version number, then exit\n");
1924   printf ("  -v, --verbose           Print extra information while running\n");
1925   printf ("\n");
1926   printf ("  -M                      Print all dependencies to stdout;\n");
1927   printf ("                             suppress ordinary output\n");
1928   printf ("  -MM                     Print non-system dependencies to stdout;\n");
1929   printf ("                             suppress ordinary output\n");
1930   printf ("  -MD                     Print all dependencies to stdout\n");
1931   printf ("  -MMD                    Print non-system dependencies to stdout\n");
1932   /* We omit -MG until it is implemented.  */
1933   printf ("\n");
1934   printf ("For bug reporting instructions, please see:\n");
1935   printf ("%s.\n", GCCBUGURL);
1936   exit (0);
1937 }
1938
1939 static void
1940 version ()
1941 {
1942   printf ("gcjh (%s)\n\n", version_string);
1943   printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1944   printf ("This is free software; see the source for copying conditions.  There is NO\n");
1945   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1946   exit (0);
1947 }
1948
1949 int
1950 DEFUN(main, (argc, argv),
1951       int argc AND char** argv)
1952 {
1953   JCF jcf;
1954   int argi;
1955   char *output_file = NULL;
1956   int emit_dependencies = 0, suppress_output = 0;
1957   int opt;
1958
1959   if (argc <= 1)
1960     {
1961       fprintf (stderr, "gcjh: no classes specified\n");
1962       usage ();
1963     }
1964
1965   jcf_path_init ();
1966
1967   /* We use getopt_long_only to allow single `-' long options.  For
1968      some of our options this is more natural.  */
1969   while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
1970     {
1971       switch (opt)
1972         {
1973         case 0:
1974           /* Already handled.  */
1975           break;
1976
1977         case 'o':
1978           output_file = optarg;
1979           break;
1980
1981         case 'd':
1982           output_directory = optarg;
1983           break;
1984
1985         case 'I':
1986           jcf_path_include_arg (optarg);
1987           break;
1988
1989         case 'v':
1990           verbose++;
1991           break;
1992
1993         case OPT_classpath:
1994           jcf_path_classpath_arg (optarg);
1995           break;
1996
1997         case OPT_CLASSPATH:
1998           jcf_path_CLASSPATH_arg (optarg);
1999           break;
2000
2001         case OPT_HELP:
2002           help ();
2003           break;
2004
2005         case OPT_TEMP:
2006           temp_directory = optarg;
2007           break;
2008
2009         case OPT_VERSION:
2010           version ();
2011           break;
2012
2013         case OPT_PREPEND:
2014           if (prepend_count == 0)
2015             prepend_specs = (char**) ALLOC (argc * sizeof (char*));
2016           prepend_specs[prepend_count++] = optarg;
2017           break;
2018
2019         case OPT_FRIEND:
2020           if (friend_count == 0)
2021             friend_specs = (char**) ALLOC (argc * sizeof (char*));
2022           friend_specs[friend_count++] = optarg;
2023           break;
2024
2025         case OPT_ADD:
2026           if (add_count == 0)
2027             add_specs = (char**) ALLOC (argc * sizeof (char*));
2028           add_specs[add_count++] = optarg;
2029           break;
2030
2031         case OPT_APPEND:
2032           if (append_count == 0)
2033             append_specs = (char**) ALLOC (argc * sizeof (char*));
2034           append_specs[append_count++] = optarg;
2035           break;
2036
2037         case OPT_M:
2038           emit_dependencies = 1;
2039           suppress_output = 1;
2040           jcf_dependency_init (1);
2041           break;
2042
2043         case OPT_MM:
2044           emit_dependencies = 1;
2045           suppress_output = 1;
2046           jcf_dependency_init (0);
2047           break;
2048
2049         case OPT_MG:
2050           fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2051           exit (1);
2052
2053         case OPT_MD:
2054           emit_dependencies = 1;
2055           jcf_dependency_init (1);
2056           break;
2057
2058         case OPT_MMD:
2059           emit_dependencies = 1;
2060           jcf_dependency_init (0);
2061           break;
2062
2063         default:
2064           usage ();
2065           break;
2066         }
2067     }
2068
2069   if (optind == argc)
2070     {
2071       fprintf (stderr, "gcjh: no classes specified\n");
2072       usage ();
2073     }
2074
2075   jcf_path_seal ();
2076
2077   if (output_file && emit_dependencies)
2078     {
2079       fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2080       exit (1);
2081     }
2082
2083   for (argi = optind; argi < argc; argi++)
2084     {
2085       char *classname = argv[argi];
2086       char *current_output_file;
2087       const char *classfile_name;
2088
2089       if (verbose)
2090         fprintf (stderr, "Processing %s\n", classname);
2091       if (! output_file)
2092         jcf_dependency_reset ();
2093       classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2094       if (classfile_name == NULL)
2095         {
2096           fprintf (stderr, "%s: no such class\n", classname);
2097           exit (1);
2098         }
2099       if (verbose)
2100         fprintf (stderr, "Found in %s\n", classfile_name);
2101       if (output_file)
2102         {
2103           if (strcmp (output_file, "-") == 0)
2104             out = stdout;
2105           else if (out == NULL)
2106             {
2107               out = fopen (output_file, "w");
2108             }
2109           if (out == NULL)
2110             {
2111               perror (output_file);
2112               exit (1);
2113             }
2114           current_output_file = output_file;
2115         }
2116       else
2117         {
2118           int dir_len = strlen (output_directory);
2119           int i, classname_length = strlen (classname);
2120           current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2121           strcpy (current_output_file, output_directory);
2122           if (dir_len > 0 && output_directory[dir_len-1] != '/')
2123             current_output_file[dir_len++] = '/';
2124           for (i = 0; classname[i] != '\0'; i++)
2125             {
2126               char ch = classname[i];
2127               if (ch == '.')
2128                 ch = '/';
2129               if (flag_jni && ch == '/')
2130                 ch = '_';
2131               current_output_file[dir_len++] = ch;
2132             }
2133           if (emit_dependencies)
2134             {
2135               if (suppress_output)
2136                 {
2137                   jcf_dependency_set_dep_file ("-");
2138                   out = NULL;
2139                 }
2140               else
2141                 {
2142                   /* We use `.hd' and not `.d' to avoid clashes with
2143                      dependency tracking from straight compilation.  */
2144                   strcpy (current_output_file + dir_len, ".hd");
2145                   jcf_dependency_set_dep_file (current_output_file);
2146                 }
2147             }
2148           strcpy (current_output_file + dir_len, 
2149                   stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2150           jcf_dependency_set_target (current_output_file);
2151           if (! suppress_output)
2152             {
2153               out = fopen (current_output_file, "w");
2154               if (out == NULL)
2155                 {
2156                   perror (current_output_file);
2157                   exit (1);
2158                 }
2159             }
2160         }
2161       process_file (&jcf, out);
2162       JCF_FINISH (&jcf);
2163       if (current_output_file != output_file)
2164         free (current_output_file);
2165       jcf_dependency_write ();
2166     }
2167
2168   if (out != NULL && out != stdout)
2169     fclose (out);
2170
2171   return found_error;
2172 }