OSDN Git Service

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