OSDN Git Service

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