OSDN Git Service

Fix for PR java/5365:
[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, 2002 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            /* We're going to generate `return this'.  This only makes
1070               sense for non-static methods.  */
1071            && ! (method_access & ACC_STATIC))
1072     {
1073       decompile_return_statement (out, jcf, method_signature, -1,
1074                                   JPOOL_USHORT1 (jcf, jcf->this_class));
1075       decompiled = 1;
1076     }
1077   else if (code_len == 1 && codes[0] == OPCODE_return)
1078     {
1079       /* Found plain `return'.  */
1080       fputs (" { }", out);
1081       decompiled = 1;
1082     }
1083   else if (code_len == 2
1084            && codes[0] == OPCODE_aconst_null
1085            && codes[1] == OPCODE_areturn)
1086     {
1087       /* Found `return null'.  We don't want to depend on NULL being
1088          defined.  */
1089       fputs (" { return 0; }", out);
1090       decompiled = 1;
1091     }
1092 }
1093
1094 /* Print one piece of a signature.  Returns pointer to next parseable
1095    character on success, NULL on error.  */
1096 static const unsigned char *
1097 decode_signature_piece (stream, signature, limit, need_space)
1098      FILE *stream;
1099      const unsigned char *signature, *limit;
1100      int *need_space;
1101 {
1102   const char *ctype;
1103   int array_depth = 0;
1104
1105   switch (signature[0])
1106     {
1107     case '[':
1108       /* More spaghetti.  */
1109
1110     array_loop:
1111       for (signature++; (signature < limit
1112                          && ISDIGIT (*signature)); signature++)
1113         ;
1114       switch (*signature)
1115         {
1116         case 'B':
1117           ctype = "jbyteArray";
1118           break;
1119         case 'C':
1120           ctype = "jcharArray";
1121           break;
1122         case 'D':
1123           ctype = "jdoubleArray";
1124           break;
1125         case 'F':
1126           ctype = "jfloatArray";
1127           break;
1128         case 'I':
1129           ctype = "jintArray";
1130           break;
1131         case 'S':
1132           ctype = "jshortArray";
1133           break;
1134         case 'J':
1135           ctype = "jlongArray";
1136           break;
1137         case 'Z':
1138           ctype = "jbooleanArray";
1139           break;
1140         case '[':
1141           /* We have a nested array.  */
1142           ++array_depth;
1143           if (! flag_jni)
1144             fputs ("JArray<", stream);
1145           goto array_loop;
1146
1147         case 'L':
1148           /* We have to generate a reference to JArray here, so that
1149              our output matches what the compiler does.  */
1150           ++signature;
1151           /* Space between `<' and `:' to avoid C++ digraphs.  */
1152           if (! flag_jni)
1153             fputs ("JArray< ::", stream);
1154           while (signature < limit && *signature != ';')
1155             {
1156               int ch = UTF8_GET (signature, limit);
1157               if (! flag_jni)
1158                 {
1159                   if (ch == '/')
1160                     fputs ("::", stream);
1161                   else
1162                     jcf_print_char (stream, ch);
1163                 }
1164             }
1165           if (! flag_jni)
1166             fputs (" *> *", stream);
1167           *need_space = 0;
1168           ctype = NULL;
1169           break;
1170         default:
1171           /* Unparseable signature.  */
1172           return NULL;
1173         }
1174
1175       /* If the previous iterations left us with something to print,
1176          print it.  For JNI, we always print `jobjectArray' in the
1177          nested cases.  */
1178       if (flag_jni && ctype == NULL)
1179         {
1180           ctype = "jobjectArray";
1181           *need_space = 1;
1182         }
1183       /* The `printit' case will advance SIGNATURE for us.  If we
1184          don't go there, we must advance past the `;' ourselves.  */
1185       if (ctype != NULL)
1186         goto printit;
1187       ++signature;
1188       break;
1189
1190     case '(':
1191     case ')':
1192       /* This shouldn't happen.  */
1193       return NULL;
1194
1195     case 'B': ctype = "jbyte";  goto printit;
1196     case 'C': ctype = "jchar";  goto printit;
1197     case 'D': ctype = "jdouble";  goto printit;
1198     case 'F': ctype = "jfloat";  goto printit;
1199     case 'I': ctype = "jint";  goto printit;
1200     case 'J': ctype = "jlong";  goto printit;
1201     case 'S': ctype = "jshort";  goto printit;
1202     case 'Z': ctype = "jboolean";  goto printit;
1203     case 'V': ctype = "void";  goto printit;
1204     case 'L':
1205       if (flag_jni)
1206         {
1207           /* We know about certain types and special-case their
1208              names.
1209              FIXME: something like java.lang.Exception should be
1210              printed as `jthrowable', because it is a subclass.  This
1211              means that gcjh must read the entire hierarchy and
1212              comprehend it.  */
1213           if (! strncmp (signature, "Ljava/lang/String;",
1214                          sizeof ("Ljava/lang/String;") -1))
1215             ctype = "jstring";
1216           else if (! strncmp (signature, "Ljava/lang/Class;",
1217                               sizeof ("Ljava/lang/Class;") - 1))
1218             ctype = "jclass";
1219           else if (! strncmp (signature, "Ljava/lang/Throwable;",
1220                               sizeof ("Ljava/lang/Throwable;") - 1))
1221             ctype = "jthrowable";
1222           else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;",
1223                               sizeof ("Ljava/lang/ref/WeakReference;") - 1))
1224             ctype = "jweak";
1225           else
1226             ctype = "jobject";
1227
1228           while (*signature && *signature != ';')
1229             ++signature;
1230
1231           goto printit;
1232         }
1233       /* Print a leading "::" so we look in the right namespace.  */
1234       fputs ("::", stream);
1235       ++signature;
1236       while (*signature && *signature != ';')
1237         {
1238           int ch = UTF8_GET (signature, limit);
1239           if (ch == '/')
1240             fputs ("::", stream);
1241           else
1242             jcf_print_char (stream, ch);
1243         }
1244       fputs (" *", stream);
1245       if (*signature == ';')
1246         signature++;
1247       *need_space = 0;
1248       break;
1249     default:
1250       *need_space = 1;
1251       jni_print_char (stream, *signature++);
1252       break;
1253     printit:
1254       signature++;
1255       *need_space = 1;
1256       fputs (ctype, stream);
1257       break;
1258     }
1259
1260   if (! flag_jni)
1261     {
1262       while (array_depth-- > 0)
1263         fputs ("> *", stream);
1264     }
1265
1266   return signature;
1267 }
1268
1269 static void
1270 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
1271                      name_override, flags),
1272       FILE* stream AND JCF* jcf
1273       AND int name_index AND int signature_index
1274       AND int is_init AND const char *name_override AND int flags)
1275 {
1276   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1277     {
1278       fprintf (stream, "<not a UTF8 constant>");
1279       found_error = 1;
1280     }
1281   else
1282     {
1283       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1284       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1285       register const  unsigned char *str = str0;
1286       const unsigned char *limit = str + length;
1287       int need_space = 0;
1288       int is_method = str[0] == '(';
1289       const unsigned char *next;
1290
1291       /* If printing a method, skip to the return signature and print
1292          that first.  However, there is no return value if this is a
1293          constructor.  */
1294       if (is_method && ! is_init)
1295         {
1296           while (str < limit)
1297             {
1298               int ch = *str++;
1299               if (ch == ')')
1300                 break;
1301             }
1302         }
1303
1304       /* If printing a field or an ordinary method, then print the
1305          "return value" now.  */
1306       if (! is_method || ! is_init)
1307         {
1308           next = decode_signature_piece (stream, str, limit, &need_space);
1309           if (! next)
1310             {
1311               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1312               found_error = 1;
1313               return;
1314             }
1315         }
1316
1317       /* Now print the name of the thing.  */
1318       if (need_space)
1319         fputs (" ", stream);
1320       print_full_cxx_name (stream, jcf, name_index, 
1321                            signature_index, is_init, name_override,
1322                            flags);
1323     }
1324 }
1325
1326 /* Print the unqualified method name followed by the signature. */
1327 static void
1328 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index,
1329                             is_init, name_override, flags),
1330       FILE* stream AND JCF* jcf
1331       AND int name_index AND int signature_index AND int is_init 
1332       AND const char *name_override AND int flags)
1333 {
1334   int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1335   const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1336   register const unsigned char *str = str0;
1337   const unsigned char *limit = str + length;
1338   int need_space = 0;
1339   int is_method = str[0] == '(';
1340   const unsigned char *next;
1341
1342   if (name_override)
1343     fputs (name_override, stream);
1344   else if (name_index)
1345     {
1346       /* Declare constructors specially.  */
1347       if (is_init)
1348         print_base_classname (stream, jcf, jcf->this_class);
1349       else
1350         print_name (stream, jcf, name_index);
1351     }
1352
1353   if (flag_jni)
1354     {
1355       unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1356       int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1357       if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1358                                           JPOOL_UTF_LENGTH (jcf, name_index),
1359                                           signature, sig_len))
1360         {
1361           /* If this method is overloaded by another native method,
1362              then include the argument information in the mangled
1363              name.  */
1364           unsigned char *limit = signature + sig_len;
1365           fputs ("__", stream);
1366           while (signature < limit)
1367             {
1368               int ch = UTF8_GET (signature, limit);
1369               jni_print_char (stream, ch);
1370               if (ch == ')')
1371                 {
1372                   /* Done.  */
1373                   break;
1374                 }
1375             }
1376         }
1377     }
1378
1379   if (is_method)
1380     {
1381       /* Have a method or a constructor.  Print signature pieces
1382          until done.  */
1383       fputs (" (", stream);
1384
1385       str = str0 + 1;
1386
1387       /* In JNI mode, add extra arguments.  */
1388       if (flag_jni)
1389         {
1390           /* FIXME: it would be nice to know if we are printing a decl
1391              or a definition, and only print `env' for the latter.  */
1392           fputs ("JNIEnv *env", stream);
1393
1394           fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1395
1396           if (*str != ')')
1397             fputs (", ", stream);
1398         }
1399
1400       while (str < limit && *str != ')')
1401         {
1402           next = decode_signature_piece (stream, str, limit, &need_space);
1403           if (! next)
1404             {
1405               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1406               found_error = 1;
1407               return;
1408             }
1409           
1410           if (next < limit && *next != ')')
1411             fputs (", ", stream);
1412           str = next;
1413         }
1414       
1415       fputs (")", stream);
1416     }
1417 }
1418
1419 /* This is a helper for print_stub_or_jni.  */
1420 static void
1421 DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index,
1422                                     is_init, name_override, flags),
1423        FILE *stream AND JCF *jcf
1424        AND int name_index AND int signature_index
1425        AND int is_init AND const char *name_override AND int flags)
1426 {
1427   const char *const prefix = flag_jni ? "Java_" : "";
1428   print_cxx_classname (stream, prefix, jcf, jcf->this_class);
1429   fputs (flag_jni ? "_" : "::", stream);
1430   print_full_cxx_name (stream, jcf, name_index, 
1431                        signature_index, is_init, name_override,
1432                        flags);
1433 }
1434
1435 static void
1436 DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init,
1437                           name_override, flags),
1438       FILE* stream AND JCF* jcf
1439       AND int name_index AND int signature_index
1440       AND int is_init AND const char *name_override AND int flags)
1441 {
1442   if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1443     {
1444       fprintf (stream, "<not a UTF8 constant>");
1445       found_error = 1;
1446     }
1447   else
1448     {
1449       int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1450       const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1451       register const unsigned char *str = str0;
1452       const unsigned char *limit = str + length;
1453       int need_space = 0;
1454       int is_method = str[0] == '(';
1455       const unsigned char *next;
1456
1457       /* Don't print fields in the JNI case.  */
1458       if (! is_method && flag_jni)
1459         return;
1460
1461       if (flag_jni && ! stubs)
1462         fputs ("extern ", stream);
1463
1464       /* If printing a method, skip to the return signature and print
1465          that first.  However, there is no return value if this is a
1466          constructor.  */
1467       if (is_method && ! is_init)
1468         {
1469           while (str < limit)
1470             {
1471               int ch = *str++;
1472               if (ch == ')')
1473                 break;
1474             }
1475         }
1476
1477       /* If printing a field or an ordinary method, then print the
1478          "return value" now.  Note that a constructor can't be native,
1479          so we don't bother checking this in the JNI case.  */
1480       if (! is_method || ! is_init)
1481         {
1482           next = decode_signature_piece (stream, str, limit, &need_space);
1483           if (! next)
1484             {
1485               fprintf (stderr, "unparseable signature: `%s'\n", str0);
1486               found_error = 1;
1487               return;
1488             }
1489         }
1490
1491       /* When printing a JNI header we need to respect the space.  In
1492          other cases we're just going to insert a newline anyway.  */
1493       fputs (need_space && ! stubs ? " " : "\n", stream);
1494       
1495       /* Now print the name of the thing.  */
1496       print_name_for_stub_or_jni (stream, jcf, name_index,
1497                                   signature_index, is_init, name_override,
1498                                   flags);
1499
1500       /* Print the body.  */
1501       if (stubs)
1502         {
1503           if (flag_jni)
1504             fputs ("\n{\n  (*env)->FatalError (\"", stream);
1505           else
1506             fputs ("\n{\n  JvFail (\"", stream);
1507           print_name_for_stub_or_jni (stream, jcf, name_index,
1508                                       signature_index, is_init,
1509                                       name_override,
1510                                       flags);
1511           fputs (" not implemented\");\n}\n\n", stream);
1512         }
1513     }
1514 }
1515
1516 static void
1517 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
1518       FILE *stream AND JCF *jcf AND const char *prefix AND int index)
1519 {
1520   int name_index = JPOOL_USHORT1 (jcf, index);
1521   fputs (prefix, stream);
1522   jcf_print_utf8_replace (out,
1523                           JPOOL_UTF_DATA (jcf, name_index),
1524                           JPOOL_UTF_LENGTH (jcf, name_index),
1525                           '/', '_');
1526 }
1527
1528 /* Print PREFIX, then a class name in C++ format.  If the name refers
1529    to an array, ignore it and don't print PREFIX.  Returns 1 if
1530    something was printed, 0 otherwise.  */
1531 static int
1532 print_cxx_classname (stream, prefix, jcf, index)
1533      FILE *stream;
1534      const char *prefix;
1535      JCF *jcf;
1536      int index;
1537 {
1538   int name_index = JPOOL_USHORT1 (jcf, index);
1539   int len, c;
1540   const unsigned char *s, *p, *limit;
1541
1542   s = JPOOL_UTF_DATA (jcf, name_index);
1543   len = JPOOL_UTF_LENGTH (jcf, name_index);
1544   limit = s + len;
1545
1546   /* Explicitly omit arrays here.  */
1547   p = s;
1548   c = UTF8_GET (p, limit);
1549   if (c == '[')
1550     return 0;
1551
1552   fputs (prefix, stream);
1553
1554   /* Print a leading "::" so we look in the right namespace.  */
1555   if (! flag_jni && ! stubs)
1556     fputs ("::", stream);
1557
1558   while (s < limit)
1559     {
1560       c = UTF8_GET (s, limit);
1561       if (c == '/')
1562         fputs (flag_jni ? "_" : "::", stream);
1563       else
1564         jni_print_char (stream, c);
1565     }
1566
1567   return 1;
1568 }
1569
1570 int written_class_count = 0;
1571
1572 /* Return name of superclass.  If LEN is not NULL, fill it with length
1573    of name.  */
1574 static const unsigned char *
1575 super_class_name (derived_jcf, len)
1576      JCF *derived_jcf;
1577      int *len;
1578 {
1579   int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1580   int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1581   const unsigned char *supername =
1582     JPOOL_UTF_DATA (derived_jcf, supername_index);
1583
1584   if (len)
1585     *len = supername_length;
1586
1587   return supername;
1588 }
1589
1590 \f
1591
1592 /* We keep track of all the `#include's we generate, so we can avoid
1593    duplicates.  */
1594 struct include
1595 {
1596   char *name;
1597   struct include *next;
1598 };
1599
1600 /* List of all includes.  */
1601 static struct include *all_includes = NULL;
1602
1603 /* Generate a #include.  */
1604 static void
1605 print_include (out, utf8, len)
1606      FILE *out;
1607      const unsigned char *utf8;
1608      int len;
1609 {
1610   struct include *incl;
1611
1612   if (! out)
1613     return;
1614
1615   if (len == -1)
1616     len = strlen (utf8);
1617
1618   for (incl = all_includes; incl; incl = incl->next)
1619     {
1620       /* We check the length because we might have a proper prefix.  */
1621       if (len == (int) strlen (incl->name)
1622           && ! strncmp (incl->name, utf8, len))
1623         return;
1624     }
1625
1626   incl = (struct include *) xmalloc (sizeof (struct include));
1627   incl->name = xmalloc (len + 1);
1628   strncpy (incl->name, utf8, len);
1629   incl->name[len] = '\0';
1630   incl->next = all_includes;
1631   all_includes = incl;
1632
1633   fputs ("#include <", out);
1634   jcf_print_utf8_replace (out, utf8, len,
1635                           '/',
1636                           flag_jni ? '_' : '/');
1637   fputs (".h>\n", out);
1638 }
1639
1640 \f
1641
1642 /* This is used to represent part of a package or class name.  */
1643 struct namelet
1644 {
1645   /* The text of this part of the name.  */
1646   char *name;
1647   /* True if this represents a class.  */
1648   int is_class;
1649   /* Linked list of all classes and packages inside this one.  */
1650   struct namelet *subnamelets;
1651   /* Pointer to next sibling.  */
1652   struct namelet *next;
1653 };
1654
1655 static void add_namelet PARAMS ((const unsigned char *,
1656                                 const unsigned char *, struct namelet *));
1657 static void print_namelet PARAMS ((FILE *, struct namelet *, int));
1658
1659 /* The special root namelet.  */
1660 static struct namelet root =
1661 {
1662   NULL,
1663   0,
1664   NULL,
1665   NULL
1666 };
1667
1668 /* This extracts the next name segment from the full UTF-8 encoded
1669    package or class name and links it into the tree.  It does this
1670    recursively.  */
1671 static void
1672 add_namelet (name, name_limit, parent)
1673      const unsigned char *name, *name_limit;
1674      struct namelet *parent;
1675 {
1676   const unsigned char *p;
1677   struct namelet *n = NULL, *np;
1678
1679   /* We want to skip the standard namespaces that we assume the
1680      runtime already knows about.  We only do this at the top level,
1681      though, hence the check for `root'.  */
1682   if (parent == &root)
1683     {
1684 #define JAVALANG "java/lang/"
1685 #define JAVAIO "java/io/"
1686 #define JAVAUTIL "java/util/"
1687       if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1688            && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1689           || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1690               && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1691           || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1692               && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1693         return;
1694     }
1695
1696   for (p = name; p < name_limit && *p != '/'; ++p)
1697     ;
1698
1699   /* Search for this name beneath the PARENT node.  */
1700   for (np = parent->subnamelets; np != NULL; np = np->next)
1701     {
1702       /* We check the length because we might have a proper prefix.  */
1703       if ((int) strlen (np->name) == p - name &&
1704           ! strncmp (name, np->name, p - name))
1705         {
1706           n = np;
1707           break;
1708         }
1709     }
1710
1711   if (n == NULL)
1712     {
1713       n = (struct namelet *) xmalloc (sizeof (struct namelet));
1714       n->name = xmalloc (p - name + 1);
1715       strncpy (n->name, name, p - name);
1716       n->name[p - name] = '\0';
1717       n->is_class = (p == name_limit);
1718       n->subnamelets = NULL;
1719       n->next = parent->subnamelets;
1720       parent->subnamelets = n;
1721     }
1722
1723   /* We recurse if there is more text, and if the trailing piece does
1724      not represent an inner class. */
1725   if (p < name_limit)
1726     add_namelet (p + 1, name_limit, n);
1727 }
1728
1729 /* Print a single namelet.  Destroys namelets while printing.  */
1730 static void
1731 print_namelet (out, name, depth)
1732      FILE *out;
1733      struct namelet *name;
1734      int depth;
1735 {
1736   int i, term = 0;
1737   struct namelet *c;
1738
1739   if (name->name)
1740     {
1741       for (i = 0; i < depth; ++i)
1742         fputc (' ', out);
1743       fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1744                name->name);
1745       if (name->is_class && name->subnamelets == NULL)
1746         fputs (";\n", out);
1747       else
1748         {
1749           term = 1;
1750           fputs ("\n", out);
1751           for (i = 0; i < depth; ++i)
1752             fputc (' ', out);
1753           fputs ("{\n", out);
1754         }
1755     }
1756
1757   c = name->subnamelets;
1758   while (c != NULL)
1759     {
1760       struct namelet *next = c->next;
1761       print_namelet (out, c, depth + 2);
1762       c = next;
1763     }
1764   name->subnamelets = NULL;
1765
1766   if (name->name)
1767     {
1768       if (term)
1769         {
1770           for (i = 0; i < depth; ++i)
1771             fputc (' ', out);
1772           fputs ("}\n", out);
1773           /* Only print a `;' when printing a class.  C++ is evil.  */
1774           if (name->is_class)
1775             fputs (";", out);
1776         }
1777
1778       free (name->name);
1779       free (name);
1780     }
1781 }
1782
1783 /* This is called to add some classes to the list of classes for which
1784    we need decls.  The signature argument can be a function
1785    signature.  */
1786 static void
1787 add_class_decl (out, jcf, signature)
1788      FILE *out;
1789      JCF *jcf;
1790      JCF_u2 signature;
1791 {
1792   const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1793   int len = JPOOL_UTF_LENGTH (jcf, signature);
1794   int i;
1795
1796   for (i = 0; i < len; ++i)
1797     {
1798       int start;
1799
1800       /* If we see an array, then we include the array header.  */
1801       if (s[i] == '[')
1802         {
1803           print_include (out, "gcj/array", -1);
1804           continue;
1805         }
1806
1807       /* We're looking for `L<stuff>;' -- everything else is
1808          ignorable.  */
1809       if (s[i] != 'L')
1810         continue;
1811
1812       for (start = ++i; i < len && s[i] != ';'; ++i)
1813         ;
1814
1815       add_namelet (&s[start], &s[i], &root);
1816     }
1817 }
1818
1819 /* Print declarations for all classes required by this class.  Any
1820    class or package in the `java' package is assumed to be handled
1821    statically in libjava; we don't generate declarations for these.
1822    This makes the generated headers a bit easier to read.  */
1823 static void
1824 print_class_decls (out, jcf, self)
1825      FILE *out;
1826      JCF *jcf;
1827      int self;
1828 {
1829   /* Make sure to always add the current class to the list of things
1830      that should be declared.  */
1831   int name_index = JPOOL_USHORT1 (jcf, self);
1832   int len;
1833   const unsigned char *s;
1834
1835   s = JPOOL_UTF_DATA (jcf, name_index);
1836   len = JPOOL_UTF_LENGTH (jcf, name_index);
1837   add_namelet (s, s + len, &root);
1838
1839   if (root.subnamelets)
1840     {
1841       fputs ("extern \"Java\"\n{\n", out);
1842       /* We use an initial offset of 0 because the root namelet
1843          doesn't cause anything to print.  */
1844       print_namelet (out, &root, 0);
1845       fputs ("};\n\n", out);
1846     }
1847 }
1848
1849 \f
1850
1851 static void
1852 DEFUN(process_file, (jcf, out),
1853       JCF *jcf AND FILE *out)
1854 {
1855   int code, i;
1856   uint32 field_start, method_end, method_start;
1857
1858   current_jcf = jcf;
1859
1860   last_access = -1;
1861
1862   if (jcf_parse_preamble (jcf) != 0)
1863     {
1864       fprintf (stderr, "Not a valid Java .class file.\n");
1865       found_error = 1;
1866       return;
1867     }
1868
1869   /* Parse and possibly print constant pool */
1870   code = jcf_parse_constant_pool (jcf);
1871   if (code != 0)
1872     {
1873       fprintf (stderr, "error while parsing constant pool\n");
1874       found_error = 1;
1875       return;
1876     }
1877   code = verify_constant_pool (jcf);
1878   if (code > 0)
1879     {
1880       fprintf (stderr, "error in constant pool entry #%d\n", code);
1881       found_error = 1;
1882       return;
1883     }
1884
1885   jcf_parse_class (jcf);
1886
1887   if (written_class_count++ == 0 && out)
1888     {
1889       const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1890       if (flag_jni)
1891         {
1892           cstart = "/*";
1893           cstart2 = "  ";
1894           cend = " */";
1895           mode = "";
1896           what = "JNI";
1897           jflag = " -jni";
1898         }
1899       else
1900         {
1901           cstart = "//";
1902           cstart2 = "//";
1903           cend = "";
1904           mode = " -*- c++ -*-";
1905           what = "CNI";
1906           jflag = "";
1907         }
1908
1909       if (! stubs)
1910         fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1911                  cstart, mode, cend);
1912       else
1913         {
1914           fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1915 %s\n\
1916 %s This file is intended to give you a head start on implementing native\n\
1917 %s methods using %s.\n\
1918 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1919 %s overwrite any edits you have made to this file.%s\n\n",
1920                    cstart, jflag, mode,
1921                    cstart2,
1922                    cstart2,
1923                    cstart2,
1924                    what,
1925                    cstart2,
1926                    jflag,
1927                    cstart2,
1928                    cend);
1929         }
1930     }
1931
1932   if (out)
1933     {
1934       if (! stubs)
1935         {
1936           print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1937           fprintf (out, "__\n");
1938
1939           print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1940           fprintf (out, "__\n\n");
1941
1942           if (flag_jni)
1943             {
1944               fprintf (out, "#include <jni.h>\n\n");
1945               fprintf (out, "#ifdef __cplusplus\n");
1946               fprintf (out, "extern \"C\"\n");
1947               fprintf (out, "{\n");
1948               fprintf (out, "#endif\n");
1949             }
1950           else  
1951             {
1952               /* We do this to ensure that inline methods won't be
1953                  `outlined' by g++.  This works as long as method and
1954                  fields are not added by the user.  */
1955               fprintf (out, "#pragma interface\n");
1956
1957               if (jcf->super_class)
1958                 {
1959                   int super_length;
1960                   const unsigned char *supername =
1961                     super_class_name (jcf, &super_length);
1962
1963                   fputs ("\n", out);
1964                   print_include (out, supername, super_length);
1965                 }
1966             }
1967         }
1968       else
1969         {
1970           /* Strip off the ".class" portion of the name when printing
1971              the include file name.  */
1972           char *name;
1973           int i, len = strlen (jcf->classname);
1974           if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
1975             len -= 6;
1976           /* Turn the class name into a file name.  */
1977           name = xmalloc (len + 1);
1978           for (i = 0; i < len; ++i)
1979             name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
1980           name[i] = '\0';
1981           print_include (out, name, len);
1982           free (name);
1983
1984           if (! flag_jni)
1985             print_include (out, "gcj/cni", -1);
1986         }
1987     }
1988
1989   /* We want to parse the methods first.  But we need to find where
1990      they start.  So first we skip the fields, then parse the methods.
1991      Then we parse the fields and skip the methods.  This is ugly, but
1992      not too bad since we need two full passes to get class decl
1993      information anyway.  */
1994   field_pass = 0;
1995   field_start = JCF_TELL (jcf);
1996   jcf_parse_fields (jcf);
1997
1998   method_start = JCF_TELL (jcf);
1999   method_pass = 0;
2000   jcf_parse_methods (jcf);
2001
2002   if (out)
2003     fputs ("\n", out);
2004
2005   if (out && ! flag_jni)
2006     {
2007       if (! stubs)
2008         print_class_decls (out, jcf, jcf->this_class);
2009
2010       for (i = 0; i < prepend_count; ++i)
2011         fprintf (out, "%s\n", prepend_specs[i]);
2012       if (prepend_count > 0)
2013         fputc ('\n', out);
2014
2015       if (! stubs)
2016         {
2017           if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
2018             {
2019               fprintf (stderr, "class is of array type\n");
2020               found_error = 1;
2021               return;
2022             }
2023           if (jcf->super_class)
2024             {
2025               if (! print_cxx_classname (out, " : public ", 
2026                                          jcf, jcf->super_class))
2027                 {
2028                   fprintf (stderr, "base class is of array type\n");
2029                   found_error = 1;
2030                   return;
2031                 }
2032             }
2033
2034           fputs ("\n{\n", out);
2035         }
2036     }
2037
2038   /* Now go back for second pass over methods and fields.  */
2039   JCF_SEEK (jcf, method_start);
2040   method_pass = 1;
2041   jcf_parse_methods (jcf);
2042   method_end = JCF_TELL (jcf);
2043
2044   field_pass = 1;
2045   JCF_SEEK (jcf, field_start);
2046   jcf_parse_fields (jcf);
2047   JCF_SEEK (jcf, method_end);
2048
2049   jcf_parse_final_attributes (jcf);
2050
2051   if (out && ! stubs)
2052     {
2053       if (flag_jni)
2054         {
2055           fprintf (out, "\n#ifdef __cplusplus\n");
2056           fprintf (out, "}\n");
2057           fprintf (out, "#endif\n");
2058         }
2059       else
2060         {
2061           /* Generate friend decl if we still must.  */
2062           for (i = 0; i < friend_count; ++i)
2063             fprintf (out, "  friend %s\n", friend_specs[i]);
2064
2065           /* Generate extra declarations.  */
2066           if (add_count > 0)
2067             fputc ('\n', out);
2068           for (i = 0; i < add_count; ++i)
2069             fprintf (out, "  %s\n", add_specs[i]);
2070
2071           /* Generate an entry for the class object.  */
2072           generate_access (out, ACC_PUBLIC);
2073           fprintf (out, "\n  static ::java::lang::Class class$;\n");
2074
2075           fputs ("}", out);
2076           
2077           if (jcf->access_flags & ACC_INTERFACE)
2078             fputs (" __attribute__ ((java_interface))", out);
2079
2080           fputs (";\n", out);
2081
2082           if (append_count > 0)
2083             fputc ('\n', out);
2084           for (i = 0; i < append_count; ++i)
2085             fprintf (out, "%s\n", append_specs[i]);
2086         }
2087
2088       print_mangled_classname (out, jcf, 
2089                                "\n#endif /* __", jcf->this_class);
2090       fprintf (out, "__ */\n");
2091     }
2092 }
2093
2094 \f
2095
2096 /* This is used to mark options with no short value.  */
2097 #define LONG_OPT(Num)  ((Num) + 128)
2098
2099 #define OPT_classpath LONG_OPT (0)
2100 #define OPT_CLASSPATH LONG_OPT (1)
2101 #define OPT_HELP      LONG_OPT (2)
2102 #define OPT_TEMP      LONG_OPT (3)
2103 #define OPT_VERSION   LONG_OPT (4)
2104 #define OPT_PREPEND   LONG_OPT (5)
2105 #define OPT_FRIEND    LONG_OPT (6)
2106 #define OPT_ADD       LONG_OPT (7)
2107 #define OPT_APPEND    LONG_OPT (8)
2108 #define OPT_M         LONG_OPT (9)
2109 #define OPT_MM        LONG_OPT (10)
2110 #define OPT_MG        LONG_OPT (11)
2111 #define OPT_MD        LONG_OPT (12)
2112 #define OPT_MMD       LONG_OPT (13)
2113
2114 static const struct option options[] =
2115 {
2116   { "classpath", required_argument, NULL, OPT_classpath },
2117   { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2118   { "help",      no_argument,       NULL, OPT_HELP },
2119   { "stubs",     no_argument,       &stubs, 1 },
2120   { "td",        required_argument, NULL, OPT_TEMP },
2121   { "verbose",   no_argument,       NULL, 'v' },
2122   { "version",   no_argument,       NULL, OPT_VERSION },
2123   { "prepend",   required_argument, NULL, OPT_PREPEND },
2124   { "friend",    required_argument, NULL, OPT_FRIEND },
2125   { "add",       required_argument, NULL, OPT_ADD },
2126   { "append",    required_argument, NULL, OPT_APPEND },
2127   { "M",         no_argument,       NULL, OPT_M   },
2128   { "MM",        no_argument,       NULL, OPT_MM  },
2129   { "MG",        no_argument,       NULL, OPT_MG  },
2130   { "MD",        no_argument,       NULL, OPT_MD  },
2131   { "MMD",       no_argument,       NULL, OPT_MMD },
2132   { "jni",       no_argument,       &flag_jni, 1 },
2133   { NULL,        no_argument,       NULL, 0 }
2134 };
2135
2136 static void
2137 usage ()
2138 {
2139   fprintf (stderr, "Try `gcjh --help' for more information.\n");
2140   exit (1);
2141 }
2142
2143 static void
2144 help ()
2145 {
2146   printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2147   printf ("Generate C++ header files from .class files\n\n");
2148   printf ("  -stubs                  Generate an implementation stub file\n");
2149   printf ("  -jni                    Generate a JNI header or stub\n");
2150   printf ("\n");
2151   printf ("  -add TEXT               Insert TEXT into class body\n");
2152   printf ("  -append TEXT            Insert TEXT after class declaration\n");
2153   printf ("  -friend TEXT            Insert TEXT as `friend' declaration\n");
2154   printf ("  -prepend TEXT           Insert TEXT before start of class\n");
2155   printf ("\n");
2156   printf ("  --classpath PATH        Set path to find .class files\n");
2157   printf ("  --CLASSPATH PATH        Set path to find .class files\n");
2158   printf ("  -IDIR                   Append directory to class path\n");
2159   printf ("  -d DIRECTORY            Set output directory name\n");
2160   printf ("  -o FILE                 Set output file name\n");
2161   printf ("  -td DIRECTORY           Set temporary directory name\n");
2162   printf ("\n");
2163   printf ("  --help                  Print this help, then exit\n");
2164   printf ("  --version               Print version number, then exit\n");
2165   printf ("  -v, --verbose           Print extra information while running\n");
2166   printf ("\n");
2167   printf ("  -M                      Print all dependencies to stdout;\n");
2168   printf ("                             suppress ordinary output\n");
2169   printf ("  -MM                     Print non-system dependencies to stdout;\n");
2170   printf ("                             suppress ordinary output\n");
2171   printf ("  -MD                     Print all dependencies to stdout\n");
2172   printf ("  -MMD                    Print non-system dependencies to stdout\n");
2173   /* We omit -MG until it is implemented.  */
2174   printf ("\n");
2175   printf ("For bug reporting instructions, please see:\n");
2176   printf ("%s.\n", GCCBUGURL);
2177   exit (0);
2178 }
2179
2180 static void
2181 version ()
2182 {
2183   printf ("gcjh (%s)\n\n", version_string);
2184   printf ("Copyright (C) 2001 Free Software Foundation, Inc.\n");
2185   printf ("This is free software; see the source for copying conditions.  There is NO\n");
2186   printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2187   exit (0);
2188 }
2189
2190 int
2191 DEFUN(main, (argc, argv),
2192       int argc AND char** argv)
2193 {
2194   JCF jcf;
2195   int argi;
2196   char *output_file = NULL;
2197   int emit_dependencies = 0, suppress_output = 0;
2198   int opt;
2199
2200   if (argc <= 1)
2201     {
2202       fprintf (stderr, "gcjh: no classes specified\n");
2203       usage ();
2204     }
2205
2206   jcf_path_init ();
2207
2208   /* We use getopt_long_only to allow single `-' long options.  For
2209      some of our options this is more natural.  */
2210   while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2211     {
2212       switch (opt)
2213         {
2214         case 0:
2215           /* Already handled.  */
2216           break;
2217
2218         case 'o':
2219           output_file = optarg;
2220           break;
2221
2222         case 'd':
2223           output_directory = optarg;
2224           break;
2225
2226         case 'I':
2227           jcf_path_include_arg (optarg);
2228           break;
2229
2230         case 'v':
2231           verbose++;
2232           break;
2233
2234         case OPT_classpath:
2235           jcf_path_classpath_arg (optarg);
2236           break;
2237
2238         case OPT_CLASSPATH:
2239           jcf_path_CLASSPATH_arg (optarg);
2240           break;
2241
2242         case OPT_HELP:
2243           help ();
2244           break;
2245
2246         case OPT_TEMP:
2247           temp_directory = optarg;
2248           break;
2249
2250         case OPT_VERSION:
2251           version ();
2252           break;
2253
2254         case OPT_PREPEND:
2255           if (prepend_count == 0)
2256             prepend_specs = (char**) ALLOC (argc * sizeof (char*));
2257           prepend_specs[prepend_count++] = optarg;
2258           break;
2259
2260         case OPT_FRIEND:
2261           if (friend_count == 0)
2262             friend_specs = (char**) ALLOC (argc * sizeof (char*));
2263           friend_specs[friend_count++] = optarg;
2264           break;
2265
2266         case OPT_ADD:
2267           if (add_count == 0)
2268             add_specs = (char**) ALLOC (argc * sizeof (char*));
2269           add_specs[add_count++] = optarg;
2270           break;
2271
2272         case OPT_APPEND:
2273           if (append_count == 0)
2274             append_specs = (char**) ALLOC (argc * sizeof (char*));
2275           append_specs[append_count++] = optarg;
2276           break;
2277
2278         case OPT_M:
2279           emit_dependencies = 1;
2280           suppress_output = 1;
2281           jcf_dependency_init (1);
2282           break;
2283
2284         case OPT_MM:
2285           emit_dependencies = 1;
2286           suppress_output = 1;
2287           jcf_dependency_init (0);
2288           break;
2289
2290         case OPT_MG:
2291           fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2292           exit (1);
2293
2294         case OPT_MD:
2295           emit_dependencies = 1;
2296           jcf_dependency_init (1);
2297           break;
2298
2299         case OPT_MMD:
2300           emit_dependencies = 1;
2301           jcf_dependency_init (0);
2302           break;
2303
2304         default:
2305           usage ();
2306           break;
2307         }
2308     }
2309
2310   if (optind == argc)
2311     {
2312       fprintf (stderr, "gcjh: no classes specified\n");
2313       usage ();
2314     }
2315
2316   jcf_path_seal (verbose);
2317
2318   if (output_file && emit_dependencies)
2319     {
2320       fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2321       exit (1);
2322     }
2323
2324   for (argi = optind; argi < argc; argi++)
2325     {
2326       char *classname = argv[argi];
2327       char *current_output_file;
2328       const char *classfile_name;
2329
2330       if (verbose)
2331         fprintf (stderr, "Processing %s\n", classname);
2332       if (! output_file)
2333         jcf_dependency_reset ();
2334       classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2335       if (classfile_name == NULL)
2336         {
2337           fprintf (stderr, "%s: no such class\n", classname);
2338           exit (1);
2339         }
2340       if (verbose)
2341         fprintf (stderr, "Found in %s\n", classfile_name);
2342       if (output_file)
2343         {
2344           if (strcmp (output_file, "-") == 0)
2345             out = stdout;
2346           else if (out == NULL)
2347             {
2348               out = fopen (output_file, "w");
2349             }
2350           if (out == NULL)
2351             {
2352               perror (output_file);
2353               exit (1);
2354             }
2355           current_output_file = output_file;
2356         }
2357       else
2358         {
2359           int dir_len = strlen (output_directory);
2360           int i, classname_length = strlen (classname);
2361           current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2362           strcpy (current_output_file, output_directory);
2363           if (dir_len > 0 && output_directory[dir_len-1] != '/')
2364             current_output_file[dir_len++] = '/';
2365           for (i = 0; classname[i] != '\0'; i++)
2366             {
2367               char ch = classname[i];
2368               if (ch == '.')
2369                 ch = '/';
2370               if (flag_jni && ch == '/')
2371                 ch = '_';
2372               current_output_file[dir_len++] = ch;
2373             }
2374           if (emit_dependencies)
2375             {
2376               if (suppress_output)
2377                 {
2378                   jcf_dependency_set_dep_file ("-");
2379                   out = NULL;
2380                 }
2381               else
2382                 {
2383                   /* We use `.hd' and not `.d' to avoid clashes with
2384                      dependency tracking from straight compilation.  */
2385                   strcpy (current_output_file + dir_len, ".hd");
2386                   jcf_dependency_set_dep_file (current_output_file);
2387                 }
2388             }
2389           strcpy (current_output_file + dir_len, 
2390                   stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2391           jcf_dependency_set_target (current_output_file);
2392           if (! suppress_output)
2393             {
2394               out = fopen (current_output_file, "w");
2395               if (out == NULL)
2396                 {
2397                   perror (current_output_file);
2398                   exit (1);
2399                 }
2400             }
2401         }
2402       process_file (&jcf, out);
2403       JCF_FINISH (&jcf);
2404       if (current_output_file != output_file)
2405         free (current_output_file);
2406       jcf_dependency_write ();
2407     }
2408
2409   if (out != NULL && out != stdout)
2410     fclose (out);
2411
2412   return found_error;
2413 }