OSDN Git Service

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