OSDN Git Service

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