OSDN Git Service

2000-04-17 Bryce McKinlay <bryce@albatross.co.nz>
[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 static void jni_print_char PARAMS ((FILE *, int));
150
151 JCF_u2 current_field_name;
152 JCF_u2 current_field_value;
153 JCF_u2 current_field_signature;
154 JCF_u2 current_field_flags;
155
156 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
157 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
158   current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
159
160 /* We pass over fields twice.  The first time we just note the types
161    of the fields and then the start of the methods.  Then we go back
162    and parse the fields for real.  This is ugly.  */
163 static int field_pass;
164 /* Likewise we pass over methods twice.  The first time we generate
165    class decl information; the second time we generate actual method
166    decls.  */
167 static int method_pass;
168
169 #define HANDLE_END_FIELD()                                                    \
170   if (field_pass)                                                             \
171     {                                                                         \
172       if (out && ! stubs && ! flag_jni)                                       \
173         print_field_info (out, jcf, current_field_name,                       \
174                           current_field_signature,                            \
175                           current_field_flags);                               \
176     }                                                                         \
177   else if (! stubs && ! flag_jni)                                             \
178     add_class_decl (out, jcf, current_field_signature);
179
180 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
181
182 static int method_declared = 0;
183 static int method_access = 0;
184 static int method_printed = 0;
185 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT)         \
186   if (method_pass)                                                            \
187     {                                                                         \
188       decompiled = 0; method_printed = 0;                                     \
189       if (out)                                                                \
190         print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS);          \
191     }                                                                         \
192   else if (flag_jni)                                                          \
193     print_method_info (NULL, jcf, NAME, SIGNATURE, ACCESS_FLAGS);             \
194   else if (! stubs) add_class_decl (out, jcf, SIGNATURE);
195
196 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
197   if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
198
199 static int decompiled = 0;
200 #define HANDLE_END_METHOD() \
201   if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out);
202
203 #include "jcf-reader.c"
204
205 /* Some useful constants.  */
206 #define F_NAN_MASK 0x7f800000
207 #if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN)
208 #define D_NAN_MASK 0x000000007ff00000LL
209 #else
210 #define D_NAN_MASK 0x7ff0000000000000LL
211 #endif
212
213 /* Return 1 if F is not Inf or NaN.  */
214 static int
215 java_float_finite (f)
216      jfloat f;
217 {
218   union Word u;
219   u.f = f;
220
221   /* We happen to know that F_NAN_MASK will match all NaN values, and
222      also positive and negative infinity.  That's why we only need one
223      test here.  See The Java Language Specification, section 20.9.  */
224   return (u.i & F_NAN_MASK) != F_NAN_MASK;
225 }
226
227 /* Return 1 if D is not Inf or NaN.  */
228 static int
229 java_double_finite (d)
230      jdouble d;
231 {
232   union DWord u;
233   u.d = d;
234
235   /* Now check for all NaNs.  */
236   return (u.l & D_NAN_MASK) != D_NAN_MASK;
237 }
238
239 /* Print a character, appropriately mangled for JNI.  */
240
241 static void
242 jni_print_char (stream, ch)
243      FILE *stream;
244      int ch;
245 {
246   if (! flag_jni)
247     jcf_print_char (stream, ch);
248   else if (ch == '(' || ch == ')')
249     {
250       /* Ignore.  */
251     }
252   else if (ch == '_')
253     fputs ("_1", stream);
254   else if (ch == ';')
255     fputs ("_2", stream);
256   else if (ch == '[')
257     fputs ("_3", stream);
258   else if (ch == '/')
259     fputs ("_", stream);
260   else if ((ch >= '0' && ch <= '9')
261            || (ch >= 'a' && ch <= 'z')
262            || (ch >= 'A' && ch <= 'Z'))
263     fputc (ch, stream);
264   else
265     {
266       /* "Unicode" character.  */
267       fprintf (stream, "_0%04x", ch);
268     }
269 }
270
271 /* Print a name from the class data.  If the index does not point to a
272    string, an error results.  */
273
274 static void
275 DEFUN(print_name, (stream, jcf, name_index),
276       FILE* stream AND JCF* jcf AND int name_index)
277 {
278   if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
279     {
280       fprintf (stream, "<not a UTF8 constant>");
281       found_error = 1;
282     }
283   else if (! flag_jni)
284     jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
285                     JPOOL_UTF_LENGTH (jcf, name_index));
286   else
287     {
288       /* For JNI we must correctly quote each character.  */
289       const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
290       int length = JPOOL_UTF_LENGTH (jcf, name_index);
291       const unsigned char *limit = str + length;
292       while (str < limit)
293         {
294           int ch = UTF8_GET (str, limit);
295           if (ch < 0)
296             {
297               fprintf (stream, "\\<invalid>");
298               return;
299             }
300           jni_print_char (stream, ch);
301         }
302     }
303 }
304
305 /* Print base name of class.  The base name is everything after the
306    final separator.  */
307
308 static void
309 print_base_classname (stream, jcf, index)
310      FILE *stream;
311      JCF *jcf;
312      int index;
313 {
314   int name_index = JPOOL_USHORT1 (jcf, index);
315   int len;
316   const unsigned char *s, *p, *limit;
317
318   s = JPOOL_UTF_DATA (jcf, name_index);
319   len = JPOOL_UTF_LENGTH (jcf, name_index);
320   limit = s + len;
321   p = s;
322   while (s < limit)
323     {
324       int c = UTF8_GET (s, limit);
325       if (c == '/')
326         p = s;
327     }
328
329   while (p < limit)
330     {
331       int ch = UTF8_GET (p, limit);
332       if (ch == '/')
333         fputs ("::", stream);
334       else
335         jcf_print_char (stream, ch);
336     }
337 }
338
339 /* Return 0 if NAME is equal to STR, nonzero otherwise.  */
340
341 static int
342 utf8_cmp (str, length, name)
343      const unsigned char *str;
344      int length;
345      const char *name;
346 {
347   const unsigned char *limit = str + length;
348   int i;
349
350   for (i = 0; name[i]; ++i)
351     {
352       int ch = UTF8_GET (str, limit);
353       if (ch != name[i])
354         return 1;
355     }
356
357   return str != limit;
358 }
359
360 /* If NAME is the name of a C++ keyword, then return an override name.
361    This is a name that can be used in place of the keyword.
362    Otherwise, return NULL.  FIXME: for now, we only handle those
363    keywords we know to be a problem for libgcj.  */
364
365 static const char *
366 cxx_keyword_subst (str, length)
367      const unsigned char *str;
368      int length;
369 {
370   if (! utf8_cmp (str, length, "delete"))
371     return "__dummy_delete";
372   else if (! utf8_cmp (str, length, "enum"))
373     return "__dummy_enum";
374   return NULL;
375 }
376
377 /* Generate an access control keyword based on FLAGS.  */
378
379 static void
380 generate_access (stream, flags)
381      FILE *stream;
382      JCF_u2 flags;
383 {
384   if ((flags & ACC_VISIBILITY) == last_access)
385     return;
386   last_access = (flags & ACC_VISIBILITY);
387
388   switch (last_access)
389     {
390     case 0:
391       fputs ("public: // actually package-private\n", stream);
392       break;
393     case ACC_PUBLIC:
394       fputs ("public:\n", stream);
395       break;
396     case ACC_PRIVATE:
397       fputs ("private:\n", stream);
398       break;
399     case ACC_PROTECTED:
400       fputs ("public:  // actually protected\n", stream);
401       break;
402     default:
403       found_error = 1;
404       fprintf (stream, "#error unrecognized visibility %d\n",
405                (flags & ACC_VISIBILITY));
406       break;
407     }
408 }
409
410 /* See if NAME is already the name of a method.  */
411 static int
412 name_is_method_p (name, length)
413      const unsigned char *name;
414      int length;
415 {
416   struct method_name *p;
417
418   for (p = method_name_list; p != NULL; p = p->next)
419     {
420       if (p->length == length && ! memcmp (p->name, name, length))
421         return 1;
422     }
423   return 0;
424 }
425
426 /* If there is already a method named NAME, whose signature is not
427    SIGNATURE, then return true.  Otherwise return false.  */
428 static int
429 overloaded_jni_method_exists_p (name, length, signature, sig_length)
430      const unsigned char *name;
431      int length;
432      const char *signature;
433      int sig_length;
434 {
435   struct method_name *p;
436
437   for (p = method_name_list; p != NULL; p = p->next)
438     {
439       if (p->length == length
440           && ! memcmp (p->name, name, length)
441           && (p->sig_length != sig_length
442               || memcmp (p->signature, signature, sig_length)))
443         return 1;
444     }
445   return 0;
446 }
447
448 /* Get name of a field.  This handles renamings due to C++ clash.  */
449 static char *
450 get_field_name (jcf, name_index, flags)
451      JCF *jcf;
452      int name_index;
453      JCF_u2 flags;
454 {
455   unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
456   int length = JPOOL_UTF_LENGTH (jcf, name_index);
457   char *override;
458   const char *tmpconstptr;
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       /* FIXME: flags.  */
761       print_field_name (out, jcf, name, 0);
762       fputs ("; }", out);
763       decompiled = 1;
764     }
765   else if (code_len == 2
766            && codes[0] == OPCODE_aload_0
767            && codes[1] == OPCODE_areturn)
768     {
769       /* Found `return this'.  */
770       fputs (" { return this; }", out);
771       decompiled = 1;
772     }
773   else if (code_len == 1 && codes[0] == OPCODE_return)
774     {
775       /* Found plain `return'.  */
776       fputs (" { }", out);
777       decompiled = 1;
778     }
779   else if (code_len == 2
780            && codes[0] == OPCODE_aconst_null
781            && codes[1] == OPCODE_areturn)
782     {
783       /* Found `return null'.  We don't want to depend on NULL being
784          defined.  */
785       fputs (" { return 0; }", out);
786       decompiled = 1;
787     }
788 }
789
790 /* Print one piece of a signature.  Returns pointer to next parseable
791    character on success, NULL on error.  */
792 static const unsigned char *
793 decode_signature_piece (stream, signature, limit, need_space)
794      FILE *stream;
795      const unsigned char *signature, *limit;
796      int *need_space;
797 {
798   const char *ctype;
799   int array_depth = 0;
800
801   switch (signature[0])
802     {
803     case '[':
804       /* More spaghetti.  */
805
806     array_loop:
807       for (signature++; (signature < limit
808                          && *signature >= '0'
809                          && *signature <= '9'); signature++)
810         ;
811       switch (*signature)
812         {
813         case 'B':
814           ctype = "jbyteArray";
815           break;
816         case 'C':
817           ctype = "jcharArray";
818           break;
819         case 'D':
820           ctype = "jdoubleArray";
821           break;
822         case 'F':
823           ctype = "jfloatArray";
824           break;
825         case 'I':
826           ctype = "jintArray";
827           break;
828         case 'S':
829           ctype = "jshortArray";
830           break;
831         case 'J':
832           ctype = "jlongArray";
833           break;
834         case 'Z':
835           ctype = "jbooleanArray";
836           break;
837         case '[':
838           /* We have a nested array.  */
839           ++array_depth;
840           if (! flag_jni)
841             fputs ("JArray<", stream);
842           goto array_loop;
843
844         case 'L':
845           /* We have to generate a reference to JArray here, so that
846              our output matches what the compiler does.  */
847           ++signature;
848           /* Space between `<' and `:' to avoid C++ digraphs.  */
849           if (! flag_jni)
850             fputs ("JArray< ::", stream);
851           while (signature < limit && *signature != ';')
852             {
853               int ch = UTF8_GET (signature, limit);
854               if (! flag_jni)
855                 {
856                   if (ch == '/')
857                     fputs ("::", stream);
858                   else
859                     jcf_print_char (stream, ch);
860                 }
861             }
862           if (! flag_jni)
863             fputs (" *> *", stream);
864           *need_space = 0;
865           ctype = NULL;
866           break;
867         default:
868           /* Unparseable signature.  */
869           return NULL;
870         }
871
872       /* If the previous iterations left us with something to print,
873          print it.  For JNI, we always print `jobjectArray' in the
874          nested cases.  */
875       if (flag_jni && ctype == NULL)
876         {
877           ctype = "jobjectArray";
878           *need_space = 1;
879         }
880       /* The `printit' case will advance SIGNATURE for us.  If we
881          don't go there, we must advance past the `;' ourselves.  */
882       if (ctype != NULL)
883         goto printit;
884       ++signature;
885       break;
886
887     case '(':
888     case ')':
889       /* This shouldn't happen.  */
890       return NULL;
891
892     case 'B': ctype = "jbyte";  goto printit;
893     case 'C': ctype = "jchar";  goto printit;
894     case 'D': ctype = "jdouble";  goto printit;
895     case 'F': ctype = "jfloat";  goto printit;
896     case 'I': ctype = "jint";  goto printit;
897     case 'J': ctype = "jlong";  goto printit;
898     case 'S': ctype = "jshort";  goto printit;
899     case 'Z': ctype = "jboolean";  goto printit;
900     case 'V': ctype = "void";  goto printit;
901     case 'L':
902       if (flag_jni)
903         {
904           /* We know about certain types and special-case their
905              names.
906              FIXME: something like java.lang.Exception should be
907              printed as `jthrowable', because it is a subclass.  This
908              means that gcjh must read the entire hierarchy and
909              comprehend it.  */
910           if (! strncmp (signature, "Ljava/lang/String;",
911                          sizeof ("Ljava/lang/String;") -1))
912             ctype = "jstring";
913           else if (! strncmp (signature, "Ljava/lang/Class;",
914                               sizeof ("Ljava/lang/Class;") - 1))
915             ctype = "jclass";
916           else if (! strncmp (signature, "Ljava/lang/Throwable;",
917                               sizeof ("Ljava/lang/Throwable;") - 1))
918             ctype = "jthrowable";
919           else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;",
920                               sizeof ("Ljava/lang/ref/WeakReference;") - 1))
921             ctype = "jweak";
922           else
923             ctype = "jobject";
924
925           while (*signature && *signature != ';')
926             ++signature;
927
928           goto printit;
929         }
930       /* Print a leading "::" so we look in the right namespace.  */
931       fputs ("::", stream);
932       ++signature;
933       while (*signature && *signature != ';')
934         {
935           int ch = UTF8_GET (signature, limit);
936           /* `$' is the separator for an inner class.  */
937           if (ch == '/' || ch == '$')
938             fputs ("::", stream);
939           else
940             jcf_print_char (stream, ch);
941         }
942       fputs (" *", stream);
943       if (*signature == ';')
944         signature++;
945       *need_space = 0;
946       break;
947     default:
948       *need_space = 1;
949       jni_print_char (stream, *signature++);
950       break;
951     printit:
952       signature++;
953       *need_space = 1;
954       fputs (ctype, stream);
955       break;
956     }
957
958   if (! flag_jni)
959     {
960       while (array_depth-- > 0)
961         fputs ("> *", stream);
962     }
963
964   return signature;
965 }
966
967 static void
968 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
969                      name_override, flags),
970       FILE* stream AND JCF* jcf
971       AND int name_index AND int signature_index
972       AND int is_init AND const char *name_override AND int flags)
973 {
974   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
975     {
976       fprintf (stream, "<not a UTF8 constant>");
977       found_error = 1;
978     }
979   else
980     {
981       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
982       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
983       register const  unsigned char *str = str0;
984       const unsigned char *limit = str + length;
985       int need_space = 0;
986       int is_method = str[0] == '(';
987       const unsigned char *next;
988
989       /* If printing a method, skip to the return signature and print
990          that first.  However, there is no return value if this is a
991          constructor.  */
992       if (is_method && ! is_init)
993         {
994           while (str < limit)
995             {
996               int ch = *str++;
997               if (ch == ')')
998                 break;
999             }
1000         }
1001
1002       /* If printing a field or an ordinary method, then print the
1003          "return value" now.  */
1004       if (! is_method || ! is_init)
1005         {
1006           next = decode_signature_piece (stream, str, limit, &need_space);
1007           if (! next)
1008             {
1009               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1010               found_error = 1;
1011               return;
1012             }
1013         }
1014
1015       /* Now print the name of the thing.  */
1016       if (need_space)
1017         fputs (" ", stream);
1018       print_full_cxx_name (stream, jcf, name_index, 
1019                            signature_index, is_init, name_override,
1020                            flags);
1021     }
1022 }
1023
1024 /* Print the unqualified method name followed by the signature. */
1025 static void
1026 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index,
1027                             is_init, name_override, flags),
1028       FILE* stream AND JCF* jcf
1029       AND int name_index AND int signature_index AND int is_init 
1030       AND const char *name_override AND int flags)
1031 {
1032   int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1033   const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1034   register const unsigned char *str = str0;
1035   const unsigned char *limit = str + length;
1036   int need_space = 0;
1037   int is_method = str[0] == '(';
1038   const unsigned char *next;
1039
1040   if (name_override)
1041     fputs (name_override, stream);
1042   else if (name_index)
1043     {
1044       /* Declare constructors specially.  */
1045       if (is_init)
1046         print_base_classname (stream, jcf, jcf->this_class);
1047       else
1048         print_name (stream, jcf, name_index);
1049     }
1050
1051   if (flag_jni)
1052     {
1053       unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1054       int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1055       if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1056                                           JPOOL_UTF_LENGTH (jcf, name_index),
1057                                           signature, sig_len))
1058         {
1059           /* If this method is overloaded by another native method,
1060              then include the argument information in the mangled
1061              name.  */
1062           unsigned char *limit = signature + sig_len;
1063           fputs ("__", stream);
1064           while (signature < limit)
1065             {
1066               int ch = UTF8_GET (signature, limit);
1067               jni_print_char (stream, ch);
1068               if (ch == ')')
1069                 {
1070                   /* Done.  */
1071                   break;
1072                 }
1073             }
1074         }
1075     }
1076
1077   if (is_method)
1078     {
1079       /* Have a method or a constructor.  Print signature pieces
1080          until done.  */
1081       fputs (" (", stream);
1082
1083       str = str0 + 1;
1084
1085       /* In JNI mode, add extra arguments.  */
1086       if (flag_jni)
1087         {
1088           /* FIXME: it would be nice to know if we are printing a decl
1089              or a definition, and only print `env' for the latter.  */
1090           fputs ("JNIEnv *env", stream);
1091
1092           fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1093
1094           if (*str != ')')
1095             fputs (", ", stream);
1096         }
1097
1098       while (str < limit && *str != ')')
1099         {
1100           next = decode_signature_piece (stream, str, limit, &need_space);
1101           if (! next)
1102             {
1103               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1104               found_error = 1;
1105               return;
1106             }
1107           
1108           if (next < limit && *next != ')')
1109             fputs (", ", stream);
1110           str = next;
1111         }
1112       
1113       fputs (")", stream);
1114     }
1115 }
1116
1117 /* This is a helper for print_stub_or_jni.  */
1118 static void
1119 DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index,
1120                                     is_init, name_override, flags),
1121        FILE *stream AND JCF *jcf
1122        AND int name_index AND int signature_index
1123        AND int is_init AND const char *name_override AND int flags)
1124 {
1125   const char *const prefix = flag_jni ? "Java_" : "";
1126   print_cxx_classname (stream, prefix, jcf, jcf->this_class);
1127   fputs (flag_jni ? "_" : "::", stream);
1128   print_full_cxx_name (stream, jcf, name_index, 
1129                        signature_index, is_init, name_override,
1130                        flags);
1131 }
1132
1133 static void
1134 DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init,
1135                           name_override, flags),
1136       FILE* stream AND JCF* jcf
1137       AND int name_index AND int signature_index
1138       AND int is_init AND const char *name_override AND int flags)
1139 {
1140   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1141     {
1142       fprintf (stream, "<not a UTF8 constant>");
1143       found_error = 1;
1144     }
1145   else
1146     {
1147       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1148       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1149       register const unsigned char *str = str0;
1150       const unsigned char *limit = str + length;
1151       int need_space = 0;
1152       int is_method = str[0] == '(';
1153       const unsigned char *next;
1154
1155       /* Don't print fields in the JNI case.  */
1156       if (! is_method && flag_jni)
1157         return;
1158
1159       if (flag_jni && ! stubs)
1160         fputs ("extern ", stream);
1161
1162       /* If printing a method, skip to the return signature and print
1163          that first.  However, there is no return value if this is a
1164          constructor.  */
1165       if (is_method && ! is_init)
1166         {
1167           while (str < limit)
1168             {
1169               int ch = *str++;
1170               if (ch == ')')
1171                 break;
1172             }
1173         }
1174
1175       /* If printing a field or an ordinary method, then print the
1176          "return value" now.  Note that a constructor can't be native,
1177          so we don't bother checking this in the JNI case.  */
1178       if (! is_method || ! is_init)
1179         {
1180           next = decode_signature_piece (stream, str, limit, &need_space);
1181           if (! next)
1182             {
1183               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1184               found_error = 1;
1185               return;
1186             }
1187         }
1188
1189       /* When printing a JNI header we need to respect the space.  In
1190          other cases we're just going to insert a newline anyway.  */
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 && ! stubs)
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           print_include (out, "gcj/cni", -1);
1694         }
1695     }
1696
1697   /* We want to parse the methods first.  But we need to find where
1698      they start.  So first we skip the fields, then parse the methods.
1699      Then we parse the fields and skip the methods.  This is ugly, but
1700      not too bad since we need two full passes to get class decl
1701      information anyway.  */
1702   field_pass = 0;
1703   field_start = JCF_TELL (jcf);
1704   jcf_parse_fields (jcf);
1705
1706   method_start = JCF_TELL (jcf);
1707   method_pass = 0;
1708   jcf_parse_methods (jcf);
1709
1710   if (out)
1711     fputs ("\n", out);
1712
1713   if (out && ! flag_jni)
1714     {
1715       if (! stubs)
1716         print_class_decls (out, jcf, jcf->this_class);
1717
1718       for (i = 0; i < prepend_count; ++i)
1719         fprintf (out, "%s\n", prepend_specs[i]);
1720       if (prepend_count > 0)
1721         fputc ('\n', out);
1722
1723       if (! stubs)
1724         {
1725           if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1726             {
1727               fprintf (stderr, "class is of array type\n");
1728               found_error = 1;
1729               return;
1730             }
1731           if (jcf->super_class)
1732             {
1733               if (! print_cxx_classname (out, " : public ", 
1734                                          jcf, jcf->super_class))
1735                 {
1736                   fprintf (stderr, "base class is of array type\n");
1737                   found_error = 1;
1738                   return;
1739                 }
1740             }
1741
1742           fputs ("\n{\n", out);
1743         }
1744     }
1745
1746   /* Now go back for second pass over methods and fields.  */
1747   JCF_SEEK (jcf, method_start);
1748   method_pass = 1;
1749   jcf_parse_methods (jcf);
1750   method_end = JCF_TELL (jcf);
1751
1752   field_pass = 1;
1753   JCF_SEEK (jcf, field_start);
1754   jcf_parse_fields (jcf);
1755   JCF_SEEK (jcf, method_end);
1756
1757   jcf_parse_final_attributes (jcf);
1758
1759   if (out && ! stubs)
1760     {
1761       if (flag_jni)
1762         {
1763               fprintf (out, "\n#ifdef __cplusplus\n");
1764               fprintf (out, "}\n");
1765               fprintf (out, "#endif\n");
1766         }
1767       else
1768         {
1769           /* Generate friend decl if we still must.  */
1770           for (i = 0; i < friend_count; ++i)
1771             fprintf (out, "  friend %s\n", friend_specs[i]);
1772
1773           /* Generate extra declarations.  */
1774           if (add_count > 0)
1775             fputc ('\n', out);
1776           for (i = 0; i < add_count; ++i)
1777             fprintf (out, "  %s\n", add_specs[i]);
1778
1779           if (! stubs)
1780             fputs ("};\n", out);
1781
1782           if (append_count > 0)
1783             fputc ('\n', out);
1784           for (i = 0; i < append_count; ++i)
1785             fprintf (out, "%s\n", append_specs[i]);
1786         }
1787
1788       print_mangled_classname (out, jcf, 
1789                                "\n#endif /* __", jcf->this_class);
1790       fprintf (out, "__ */\n");
1791     }
1792 }
1793
1794 \f
1795
1796 /* This is used to mark options with no short value.  */
1797 #define LONG_OPT(Num)  ((Num) + 128)
1798
1799 #define OPT_classpath LONG_OPT (0)
1800 #define OPT_CLASSPATH LONG_OPT (1)
1801 #define OPT_HELP      LONG_OPT (2)
1802 #define OPT_TEMP      LONG_OPT (3)
1803 #define OPT_VERSION   LONG_OPT (4)
1804 #define OPT_PREPEND   LONG_OPT (5)
1805 #define OPT_FRIEND    LONG_OPT (6)
1806 #define OPT_ADD       LONG_OPT (7)
1807 #define OPT_APPEND    LONG_OPT (8)
1808 #define OPT_M         LONG_OPT (9)
1809 #define OPT_MM        LONG_OPT (10)
1810 #define OPT_MG        LONG_OPT (11)
1811 #define OPT_MD        LONG_OPT (12)
1812 #define OPT_MMD       LONG_OPT (13)
1813
1814 static struct option options[] =
1815 {
1816   { "classpath", required_argument, NULL, OPT_classpath },
1817   { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
1818   { "help",      no_argument,       NULL, OPT_HELP },
1819   { "stubs",     no_argument,       &stubs, 1 },
1820   { "td",        required_argument, NULL, OPT_TEMP },
1821   { "verbose",   no_argument,       NULL, 'v' },
1822   { "version",   no_argument,       NULL, OPT_VERSION },
1823   { "prepend",   required_argument, NULL, OPT_PREPEND },
1824   { "friend",    required_argument, NULL, OPT_FRIEND },
1825   { "add",       required_argument, NULL, OPT_ADD },
1826   { "append",    required_argument, NULL, OPT_APPEND },
1827   { "M",         no_argument,       NULL, OPT_M   },
1828   { "MM",        no_argument,       NULL, OPT_MM  },
1829   { "MG",        no_argument,       NULL, OPT_MG  },
1830   { "MD",        no_argument,       NULL, OPT_MD  },
1831   { "MMD",       no_argument,       NULL, OPT_MMD },
1832   { "jni",       no_argument,       &flag_jni, 1 },
1833   { NULL,        no_argument,       NULL, 0 }
1834 };
1835
1836 static void
1837 usage ()
1838 {
1839   fprintf (stderr, "Try `gcjh --help' for more information.\n");
1840   exit (1);
1841 }
1842
1843 static void
1844 help ()
1845 {
1846   printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1847   printf ("Generate C++ header files from .class files\n\n");
1848   printf ("  -stubs                  Generate an implementation stub file\n");
1849   printf ("  -jni                    Generate a JNI header or stub\n");
1850   printf ("\n");
1851   printf ("  -add TEXT               Insert TEXT into class body\n");
1852   printf ("  -append TEXT            Insert TEXT after class declaration\n");
1853   printf ("  -friend TEXT            Insert TEXT as `friend' declaration\n");
1854   printf ("  -prepend TEXT           Insert TEXT before start of class\n");
1855   printf ("\n");
1856   printf ("  --classpath PATH        Set path to find .class files\n");
1857   printf ("  --CLASSPATH PATH        Set path to find .class files\n");
1858   printf ("  -IDIR                   Append directory to class path\n");
1859   printf ("  -d DIRECTORY            Set output directory name\n");
1860   printf ("  -o FILE                 Set output file name\n");
1861   printf ("  -td DIRECTORY           Set temporary directory name\n");
1862   printf ("\n");
1863   printf ("  --help                  Print this help, then exit\n");
1864   printf ("  --version               Print version number, then exit\n");
1865   printf ("  -v, --verbose           Print extra information while running\n");
1866   printf ("\n");
1867   printf ("  -M                      Print all dependencies to stdout;\n");
1868   printf ("                             suppress ordinary output\n");
1869   printf ("  -MM                     Print non-system dependencies to stdout;\n");
1870   printf ("                             suppress ordinary output\n");
1871   printf ("  -MD                     Print all dependencies to stdout\n");
1872   printf ("  -MMD                    Print non-system dependencies to stdout\n");
1873   /* We omit -MG until it is implemented.  */
1874   printf ("\n");
1875   printf ("For bug reporting instructions, please see:\n");
1876   printf ("%s.\n", GCCBUGURL);
1877   exit (0);
1878 }
1879
1880 static void
1881 version ()
1882 {
1883   printf ("gcjh (%s)\n\n", version_string);
1884   printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1885   printf ("This is free software; see the source for copying conditions.  There is NO\n");
1886   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1887   exit (0);
1888 }
1889
1890 int
1891 DEFUN(main, (argc, argv),
1892       int argc AND char** argv)
1893 {
1894   JCF jcf;
1895   int argi;
1896   char *output_file = NULL;
1897   int emit_dependencies = 0, suppress_output = 0;
1898   int opt;
1899
1900   if (argc <= 1)
1901     {
1902       fprintf (stderr, "gcjh: no classes specified\n");
1903       usage ();
1904     }
1905
1906   jcf_path_init ();
1907
1908   /* We use getopt_long_only to allow single `-' long options.  For
1909      some of our options this is more natural.  */
1910   while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
1911     {
1912       switch (opt)
1913         {
1914         case 0:
1915           /* Already handled.  */
1916           break;
1917
1918         case 'o':
1919           output_file = optarg;
1920           break;
1921
1922         case 'd':
1923           output_directory = optarg;
1924           break;
1925
1926         case 'I':
1927           jcf_path_include_arg (optarg);
1928           break;
1929
1930         case 'v':
1931           verbose++;
1932           break;
1933
1934         case OPT_classpath:
1935           jcf_path_classpath_arg (optarg);
1936           break;
1937
1938         case OPT_CLASSPATH:
1939           jcf_path_CLASSPATH_arg (optarg);
1940           break;
1941
1942         case OPT_HELP:
1943           help ();
1944           break;
1945
1946         case OPT_TEMP:
1947           temp_directory = optarg;
1948           break;
1949
1950         case OPT_VERSION:
1951           version ();
1952           break;
1953
1954         case OPT_PREPEND:
1955           if (prepend_count == 0)
1956             prepend_specs = (char**) ALLOC (argc * sizeof (char*));
1957           prepend_specs[prepend_count++] = optarg;
1958           break;
1959
1960         case OPT_FRIEND:
1961           if (friend_count == 0)
1962             friend_specs = (char**) ALLOC (argc * sizeof (char*));
1963           friend_specs[friend_count++] = optarg;
1964           break;
1965
1966         case OPT_ADD:
1967           if (add_count == 0)
1968             add_specs = (char**) ALLOC (argc * sizeof (char*));
1969           add_specs[add_count++] = optarg;
1970           break;
1971
1972         case OPT_APPEND:
1973           if (append_count == 0)
1974             append_specs = (char**) ALLOC (argc * sizeof (char*));
1975           append_specs[append_count++] = optarg;
1976           break;
1977
1978         case OPT_M:
1979           emit_dependencies = 1;
1980           suppress_output = 1;
1981           jcf_dependency_init (1);
1982           break;
1983
1984         case OPT_MM:
1985           emit_dependencies = 1;
1986           suppress_output = 1;
1987           jcf_dependency_init (0);
1988           break;
1989
1990         case OPT_MG:
1991           fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
1992           exit (1);
1993
1994         case OPT_MD:
1995           emit_dependencies = 1;
1996           jcf_dependency_init (1);
1997           break;
1998
1999         case OPT_MMD:
2000           emit_dependencies = 1;
2001           jcf_dependency_init (0);
2002           break;
2003
2004         default:
2005           usage ();
2006           break;
2007         }
2008     }
2009
2010   if (optind == argc)
2011     {
2012       fprintf (stderr, "gcjh: no classes specified\n");
2013       usage ();
2014     }
2015
2016   jcf_path_seal ();
2017
2018   if (output_file && emit_dependencies)
2019     {
2020       fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2021       exit (1);
2022     }
2023
2024   for (argi = optind; argi < argc; argi++)
2025     {
2026       char *classname = argv[argi];
2027       char *current_output_file;
2028       const char *classfile_name;
2029
2030       if (verbose)
2031         fprintf (stderr, "Processing %s\n", classname);
2032       if (! output_file)
2033         jcf_dependency_reset ();
2034       classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2035       if (classfile_name == NULL)
2036         {
2037           fprintf (stderr, "%s: no such class\n", classname);
2038           exit (1);
2039         }
2040       if (verbose)
2041         fprintf (stderr, "Found in %s\n", classfile_name);
2042       if (output_file)
2043         {
2044           if (strcmp (output_file, "-") == 0)
2045             out = stdout;
2046           else if (out == NULL)
2047             {
2048               out = fopen (output_file, "w");
2049             }
2050           if (out == NULL)
2051             {
2052               perror (output_file);
2053               exit (1);
2054             }
2055           current_output_file = output_file;
2056         }
2057       else
2058         {
2059           int dir_len = strlen (output_directory);
2060           int i, classname_length = strlen (classname);
2061           current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2062           strcpy (current_output_file, output_directory);
2063           if (dir_len > 0 && output_directory[dir_len-1] != '/')
2064             current_output_file[dir_len++] = '/';
2065           for (i = 0; classname[i] != '\0'; i++)
2066             {
2067               char ch = classname[i];
2068               if (ch == '.')
2069                 ch = '/';
2070               if (flag_jni && ch == '/')
2071                 ch = '_';
2072               current_output_file[dir_len++] = ch;
2073             }
2074           if (emit_dependencies)
2075             {
2076               if (suppress_output)
2077                 {
2078                   jcf_dependency_set_dep_file ("-");
2079                   out = NULL;
2080                 }
2081               else
2082                 {
2083                   /* We use `.hd' and not `.d' to avoid clashes with
2084                      dependency tracking from straight compilation.  */
2085                   strcpy (current_output_file + dir_len, ".hd");
2086                   jcf_dependency_set_dep_file (current_output_file);
2087                 }
2088             }
2089           strcpy (current_output_file + dir_len, 
2090                   stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2091           jcf_dependency_set_target (current_output_file);
2092           if (! suppress_output)
2093             {
2094               out = fopen (current_output_file, "w");
2095               if (out == NULL)
2096                 {
2097                   perror (current_output_file);
2098                   exit (1);
2099                 }
2100             }
2101         }
2102       process_file (&jcf, out);
2103       JCF_FINISH (&jcf);
2104       if (current_output_file != output_file)
2105         free (current_output_file);
2106       jcf_dependency_write ();
2107     }
2108
2109   if (out != NULL && out != stdout)
2110     fclose (out);
2111
2112   return found_error;
2113 }