OSDN Git Service

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