OSDN Git Service

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