OSDN Git Service

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