OSDN Git Service

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