OSDN Git Service

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