2002-03-31 Segher Boessenkool <segher@koffie.nl>
[official-gcc.git] / gcc / java / gjavah.c
blob51cfe7cffbc5a46244fe594b98472cc6588186b9
1 /* Program to write C++-suitable header files from a Java(TM) .class
2 file. This is similar to SUN's javah.
4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003
5 Free Software Foundation, Inc.
7 This file is part of GCC.
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.
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.
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.
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. */
28 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "tm.h"
34 #include <math.h>
36 #include "jcf.h"
37 #include "tree.h"
38 #include "javaop.h"
39 #include "java-tree.h"
40 #include "java-opcodes.h"
41 #include "ggc.h"
42 #include "hashtab.h"
44 #include <getopt.h>
48 /* The output file. */
49 FILE *out = NULL;
51 /* Nonzero on failure. */
52 static int found_error = 0;
54 /* Nonzero if we're generating JNI output. */
55 static int flag_jni = 0;
57 /* When nonzero, warn when source file is newer than matching class
58 file. */
59 int flag_newer = 1;
61 /* Directory to place resulting files in. Set by -d option. */
62 const char *output_directory = "";
64 /* Directory to place temporary file. Set by -td option. Currently unused. */
65 const char *temp_directory = "/tmp";
67 /* Number of friend functions we have to declare. */
68 static int friend_count;
70 /* A class can optionally have a `friend' function declared. If
71 non-NULL, this is that function. */
72 static char **friend_specs = NULL;
74 /* Number of lines we are prepending before the class. */
75 static int prepend_count;
77 /* We can prepend extra lines before the class's start. */
78 static char **prepend_specs = NULL;
80 /* Number of lines we are appending at the end of the class. */
81 static int add_count;
83 /* We can append extra lines just before the class's end. */
84 static char **add_specs = NULL;
86 /* Number of lines we are appending after the class. */
87 static int append_count;
89 /* We can append extra lines after the class's end. */
90 static char **append_specs = NULL;
92 int verbose = 0;
94 int stubs = 0;
96 struct JCF *current_jcf;
98 /* This holds access information for the last field we examined. They
99 let us generate "private:", "public:", and "protected:" properly.
100 If 0 then we haven't previously examined any field. */
101 static JCF_u2 last_access;
103 /* Pass this macro the flags for a class and for a method. It will
104 return true if the method should be considered `final'. */
105 #define METHOD_IS_FINAL(Class, Method) \
106 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
108 /* Pass this macro the flags for a method. It will return true if the
109 method is native. */
110 #define METHOD_IS_NATIVE(Method) \
111 ((Method) & ACC_NATIVE)
113 /* We keep a linked list of all method names we have seen. This lets
114 us determine if a method name and a field name are in conflict. */
115 struct method_name
117 unsigned char *name;
118 int length;
119 unsigned char *signature;
120 int sig_length;
121 struct method_name *next;
124 /* List of method names we've seen. */
125 static struct method_name *method_name_list;
127 static void print_field_info (FILE*, JCF*, int, int, JCF_u2);
128 static void print_mangled_classname (FILE*, JCF*, const char*, int);
129 static int print_cxx_classname (FILE*, const char*, JCF*, int, int);
130 static void print_method_info (FILE*, JCF*, int, int, JCF_u2);
131 static void print_c_decl (FILE*, JCF*, int, int, int, const char *, int);
132 static void print_stub_or_jni (FILE*, JCF*, int, int, int, const char *, int);
133 static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int);
134 static void decompile_method (FILE*, JCF*, int);
135 static void add_class_decl (FILE*, JCF*, JCF_u2);
137 static void print_name (FILE *, JCF *, int);
138 static void print_base_classname (FILE *, JCF *, int);
139 static int utf8_cmp (const unsigned char *, int, const char *);
140 static char *cxx_keyword_subst (const unsigned char *, int);
141 static void generate_access (FILE *, JCF_u2);
142 static int name_is_method_p (const unsigned char *, int);
143 static char *get_field_name (JCF *, int, JCF_u2);
144 static void print_field_name (FILE *, JCF *, int, JCF_u2);
145 static const unsigned char *super_class_name (JCF *, int *);
146 static void print_include (FILE *, const unsigned char *, int);
147 static int gcjh_streq (const void *p1, const void *p2);
148 static int throwable_p (const unsigned char *signature);
149 static const unsigned char *
150 decode_signature_piece (FILE *, const unsigned char *,
151 const unsigned char *, int *);
152 static void print_class_decls (FILE *, JCF *, int);
153 static void usage (void) ATTRIBUTE_NORETURN;
154 static void help (void) ATTRIBUTE_NORETURN;
155 static void version (void) ATTRIBUTE_NORETURN;
156 static int overloaded_jni_method_exists_p (const unsigned char *, int,
157 const char *, int);
158 static void jni_print_char (FILE *, int);
159 static void jni_print_float (FILE *, jfloat);
160 static void jni_print_double (FILE *, jdouble);
161 static void decompile_return_statement (FILE *, JCF *, int, int, int);
163 JCF_u2 current_field_name;
164 JCF_u2 current_field_value;
165 JCF_u2 current_field_signature;
166 JCF_u2 current_field_flags;
168 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
169 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
170 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
172 /* We pass over fields twice. The first time we just note the types
173 of the fields and then the start of the methods. Then we go back
174 and parse the fields for real. This is ugly. */
175 static int field_pass;
176 /* Likewise we pass over methods twice. The first time we generate
177 class decl information; the second time we generate actual method
178 decls. */
179 static int method_pass;
181 #define HANDLE_END_FIELD() \
182 if (field_pass) \
184 if (out && ! stubs && ! flag_jni) \
185 print_field_info (out, jcf, current_field_name, \
186 current_field_signature, \
187 current_field_flags); \
189 else if (! stubs && ! flag_jni) \
190 add_class_decl (out, jcf, current_field_signature);
192 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
194 static int method_declared = 0;
195 static int method_access = 0;
196 static int method_printed = 0;
197 static int method_synthetic = 0;
198 static int method_signature = 0;
200 /* Set to 1 while the very first data member of a class is being handled. */
201 static int is_first_data_member = 0;
203 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
205 method_synthetic = 0; \
206 method_printed = 0; \
207 decompiled = 0; \
208 method_signature = SIGNATURE; \
209 if (ATTRIBUTE_COUNT) \
210 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
211 (const char *)"Synthetic", 9); \
212 /* If a synthetic methods have been declared, its attribute aren't \
213 worth reading (and triggering side-effects). We skip them an \
214 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
215 jcf_parse_one_method. */ \
216 if (method_synthetic) \
218 skip_attribute (jcf, ATTRIBUTE_COUNT); \
219 ATTRIBUTE_COUNT = 0; \
221 if (method_pass && !method_synthetic) \
223 if (out) \
224 print_method_info (out, jcf, NAME, SIGNATURE, \
225 ACCESS_FLAGS); \
227 else if (!method_synthetic) \
229 print_method_info (NULL, jcf, NAME, SIGNATURE, \
230 ACCESS_FLAGS); \
231 if (! stubs && ! flag_jni) \
232 add_class_decl (out, jcf, SIGNATURE); \
236 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
237 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
239 static int decompiled = 0;
240 #define HANDLE_END_METHOD() \
241 if (out && method_printed && !method_synthetic) \
242 fputs (decompiled || stubs ? "\n" : ";\n", out);
244 /* We're going to need {peek,skip}_attribute, enable their definition. */
245 #define NEED_PEEK_ATTRIBUTE
246 #define NEED_SKIP_ATTRIBUTE
248 #include "jcf-reader.c"
250 /* Print a single-precision float, suitable for parsing by g++. */
251 static void
252 jni_print_float (FILE *stream, jfloat f)
254 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
255 work in data initializers. FIXME. */
256 if (JFLOAT_FINITE (f))
258 fputs (" = ", stream);
259 if (f.negative)
260 putc ('-', stream);
261 if (f.exponent)
262 fprintf (stream, "0x1.%.6xp%+df",
263 ((unsigned int)f.mantissa) << 1,
264 f.exponent - JFLOAT_EXP_BIAS);
265 else
266 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
267 because the implicit leading 1 bit is no longer present. */
268 fprintf (stream, "0x0.%.6xp%+df",
269 ((unsigned int)f.mantissa) << 1,
270 f.exponent + 1 - JFLOAT_EXP_BIAS);
272 fputs (";\n", stream);
275 /* Print a double-precision float, suitable for parsing by g++. */
276 static void
277 jni_print_double (FILE *stream, jdouble f)
279 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
280 work in data initializers. FIXME. */
281 if (JDOUBLE_FINITE (f))
283 fputs (" = ", stream);
284 if (f.negative)
285 putc ('-', stream);
286 if (f.exponent)
287 fprintf (stream, "0x1.%.5x%.8xp%+d",
288 f.mantissa0, f.mantissa1,
289 f.exponent - JDOUBLE_EXP_BIAS);
290 else
291 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
292 because the implicit leading 1 bit is no longer present. */
293 fprintf (stream, "0x0.%.5x%.8xp%+d",
294 f.mantissa0, f.mantissa1,
295 f.exponent + 1 - JDOUBLE_EXP_BIAS);
297 fputs (";\n", stream);
300 /* Print a character, appropriately mangled for JNI. */
302 static void
303 jni_print_char (FILE *stream, int ch)
305 if (! flag_jni)
306 jcf_print_char (stream, ch);
307 else if (ch == '(' || ch == ')')
309 /* Ignore. */
311 else if (ch == '_')
312 fputs ("_1", stream);
313 else if (ch == ';')
314 fputs ("_2", stream);
315 else if (ch == '[')
316 fputs ("_3", stream);
317 else if (ch == '/')
318 fputs ("_", stream);
319 else if (ISALNUM (ch))
320 fputc (ch, stream);
321 else
323 /* "Unicode" character. */
324 fprintf (stream, "_0%04x", ch);
328 /* Print a name from the class data. If the index does not point to a
329 string, an error results. */
331 static void
332 print_name (FILE* stream, JCF* jcf, int name_index)
334 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
336 fprintf (stream, "<not a UTF8 constant>");
337 found_error = 1;
339 else if (! flag_jni)
340 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
341 JPOOL_UTF_LENGTH (jcf, name_index));
342 else
344 /* For JNI we must correctly quote each character. */
345 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
346 int length = JPOOL_UTF_LENGTH (jcf, name_index);
347 const unsigned char *limit = str + length;
348 while (str < limit)
350 int ch = UTF8_GET (str, limit);
351 if (ch < 0)
353 fprintf (stream, "\\<invalid>");
354 return;
356 jni_print_char (stream, ch);
361 /* Print base name of class. The base name is everything after the
362 final separator. */
364 static void
365 print_base_classname (FILE *stream, JCF *jcf, int index)
367 int name_index = JPOOL_USHORT1 (jcf, index);
368 int len;
369 const unsigned char *s, *p, *limit;
371 s = JPOOL_UTF_DATA (jcf, name_index);
372 len = JPOOL_UTF_LENGTH (jcf, name_index);
373 limit = s + len;
374 p = s;
375 while (s < limit)
377 int c = UTF8_GET (s, limit);
378 if (c == '/')
379 p = s;
382 while (p < limit)
384 int ch = UTF8_GET (p, limit);
385 if (ch == '/')
386 fputs ("::", stream);
387 else
388 jcf_print_char (stream, ch);
392 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
393 and 1 if STR is "greater" than NAME. */
395 static int
396 utf8_cmp (const unsigned char *str, int length, const char *name)
398 const unsigned char *limit = str + length;
399 int i;
401 for (i = 0; name[i]; ++i)
403 int ch = UTF8_GET (str, limit);
404 if (ch != name[i])
405 return ch - name[i];
408 return str == limit ? 0 : 1;
411 /* This is a sorted list of all C++ keywords. */
413 static const char *const cxx_keywords[] =
415 "_Complex",
416 "__alignof",
417 "__alignof__",
418 "__asm",
419 "__asm__",
420 "__attribute",
421 "__attribute__",
422 "__builtin_va_arg",
423 "__complex",
424 "__complex__",
425 "__const",
426 "__const__",
427 "__extension__",
428 "__imag",
429 "__imag__",
430 "__inline",
431 "__inline__",
432 "__label__",
433 "__null",
434 "__real",
435 "__real__",
436 "__restrict",
437 "__restrict__",
438 "__signed",
439 "__signed__",
440 "__typeof",
441 "__typeof__",
442 "__volatile",
443 "__volatile__",
444 "and",
445 "and_eq",
446 "asm",
447 "auto",
448 "bitand",
449 "bitor",
450 "bool",
451 "break",
452 "case",
453 "catch",
454 "char",
455 "class",
456 "compl",
457 "const",
458 "const_cast",
459 "continue",
460 "default",
461 "delete",
462 "do",
463 "double",
464 "dynamic_cast",
465 "else",
466 "enum",
467 "explicit",
468 "export",
469 "extern",
470 "false",
471 "float",
472 "for",
473 "friend",
474 "goto",
475 "if",
476 "inline",
477 "int",
478 "long",
479 "mutable",
480 "namespace",
481 "new",
482 "not",
483 "not_eq",
484 "operator",
485 "or",
486 "or_eq",
487 "private",
488 "protected",
489 "public",
490 "register",
491 "reinterpret_cast",
492 "return",
493 "short",
494 "signed",
495 "sizeof",
496 "static",
497 "static_cast",
498 "struct",
499 "switch",
500 "template",
501 "this",
502 "throw",
503 "true",
504 "try",
505 "typedef",
506 "typeid",
507 "typename",
508 "typeof",
509 "union",
510 "unsigned",
511 "using",
512 "virtual",
513 "void",
514 "volatile",
515 "wchar_t",
516 "while",
517 "xor",
518 "xor_eq"
522 /* If NAME is the name of a C++ keyword, then return an override name.
523 This is a name that can be used in place of the keyword.
524 Otherwise, return NULL. The return value is malloc()d. */
526 static char *
527 cxx_keyword_subst (const unsigned char *str, int length)
529 int last = ARRAY_SIZE (cxx_keywords);
530 int first = 0;
531 int mid = (last + first) / 2;
532 int old = -1;
534 for (mid = (last + first) / 2;
535 mid != old;
536 old = mid, mid = (last + first) / 2)
538 int kwl = strlen (cxx_keywords[mid]);
539 int min_length = kwl > length ? length : kwl;
540 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
542 if (r == 0)
544 int i;
546 /* Skip all trailing `$'. */
547 for (i = min_length; i < length && str[i] == '$'; ++i)
549 /* We've only found a match if all the remaining characters
550 are `$'. */
551 if (i == length)
553 char *dup = xmalloc (2 + length - min_length + kwl);
554 strcpy (dup, cxx_keywords[mid]);
555 for (i = kwl; i < length + 1; ++i)
556 dup[i] = '$';
557 dup[i] = '\0';
558 return dup;
560 r = 1;
563 if (r < 0)
564 last = mid;
565 else
566 first = mid;
568 return NULL;
571 /* Generate an access control keyword based on FLAGS. */
573 static void
574 generate_access (FILE *stream, JCF_u2 flags)
576 if ((flags & ACC_VISIBILITY) == last_access)
577 return;
578 last_access = (flags & ACC_VISIBILITY);
580 switch (last_access)
582 case 0:
583 fputs ("public: // actually package-private\n", stream);
584 break;
585 case ACC_PUBLIC:
586 fputs ("public:\n", stream);
587 break;
588 case ACC_PRIVATE:
589 fputs ("private:\n", stream);
590 break;
591 case ACC_PROTECTED:
592 fputs ("public: // actually protected\n", stream);
593 break;
594 default:
595 found_error = 1;
596 fprintf (stream, "#error unrecognized visibility %d\n",
597 (flags & ACC_VISIBILITY));
598 break;
602 /* See if NAME is already the name of a method. */
603 static int
604 name_is_method_p (const unsigned char *name, int length)
606 struct method_name *p;
608 for (p = method_name_list; p != NULL; p = p->next)
610 if (p->length == length && ! memcmp (p->name, name, length))
611 return 1;
613 return 0;
616 /* If there is already a method named NAME, whose signature is not
617 SIGNATURE, then return true. Otherwise return false. */
618 static int
619 overloaded_jni_method_exists_p (const unsigned char *name, int length,
620 const char *signature, int sig_length)
622 struct method_name *p;
624 for (p = method_name_list; p != NULL; p = p->next)
626 if (p->length == length
627 && ! memcmp (p->name, name, length)
628 && (p->sig_length != sig_length
629 || memcmp (p->signature, signature, sig_length)))
630 return 1;
632 return 0;
635 /* Get name of a field. This handles renamings due to C++ clash. */
636 static char *
637 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
639 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
640 int length = JPOOL_UTF_LENGTH (jcf, name_index);
641 char *override;
643 if (name_is_method_p (name, length))
645 /* This field name matches a method. So override the name with
646 a dummy name. This is yucky, but it isn't clear what else to
647 do. FIXME: if the field is static, then we'll be in real
648 trouble. */
649 if ((flags & ACC_STATIC))
651 fprintf (stderr, "static field has same name as method\n");
652 found_error = 1;
653 return NULL;
656 override = xmalloc (length + 3);
657 memcpy (override, name, length);
658 strcpy (override + length, "__");
660 else
661 override = cxx_keyword_subst (name, length);
663 return override;
666 /* Print a field name. Convenience function for use with
667 get_field_name. */
668 static void
669 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
671 char *override = get_field_name (jcf, name_index, flags);
673 if (override)
675 fputs (override, stream);
676 free (override);
678 else
679 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
680 JPOOL_UTF_LENGTH (jcf, name_index));
683 static void
684 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
685 JCF_u2 flags)
687 char *override = NULL;
689 generate_access (stream, flags);
690 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
692 fprintf (stream, "<not a UTF8 constant>");
693 found_error = 1;
694 return;
697 fputs (" ", out);
698 if ((flags & ACC_STATIC))
699 fputs ("static ", out);
701 if ((flags & ACC_FINAL))
703 if (current_field_value > 0)
705 char buffer[25];
706 int done = 1;
708 switch (JPOOL_TAG (jcf, current_field_value))
710 case CONSTANT_Integer:
712 jint num;
713 int most_negative = 0;
714 fputs ("const jint ", out);
715 print_field_name (out, jcf, name_index, 0);
716 fputs (" = ", out);
717 num = JPOOL_INT (jcf, current_field_value);
718 /* We single out the most negative number to print
719 specially. This avoids later warnings from g++. */
720 if (num == (jint) 0x80000000)
722 most_negative = 1;
723 ++num;
725 format_int (buffer, (jlong) num, 10);
726 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
728 break;
729 case CONSTANT_Long:
731 jlong num;
732 int most_negative = 0;
733 fputs ("const jlong ", out);
734 print_field_name (out, jcf, name_index, 0);
735 fputs (" = ", out);
736 num = JPOOL_LONG (jcf, current_field_value);
737 /* We single out the most negative number to print
738 specially.. This avoids later warnings from g++. */
739 if (num == (jlong) 0x8000000000000000LL)
741 most_negative = 1;
742 ++num;
744 format_int (buffer, num, 10);
745 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
747 break;
748 case CONSTANT_Float:
750 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
751 fputs ("const jfloat ", out);
752 print_field_name (out, jcf, name_index, 0);
753 jni_print_float (out, fnum);
755 break;
756 case CONSTANT_Double:
758 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
759 fputs ("const jdouble ", out);
760 print_field_name (out, jcf, name_index, 0);
761 jni_print_double (out, dnum);
763 break;
764 default:
765 /* We can't print this as a constant, but we can still
766 print something sensible. */
767 done = 0;
768 break;
771 if (done)
772 return;
776 override = get_field_name (jcf, name_index, flags);
777 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
778 fputs (";\n", out);
780 if (override)
781 free (override);
785 static void
786 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
787 JCF_u2 flags)
789 const unsigned char *str;
790 int length, is_init = 0;
791 char *override = NULL;
793 method_declared = 0;
794 method_access = flags;
795 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
796 fprintf (stream, "<not a UTF8 constant>");
797 str = JPOOL_UTF_DATA (jcf, name_index);
798 length = JPOOL_UTF_LENGTH (jcf, name_index);
800 if (str[0] == '<')
802 /* Ignore the internally generated method <clinit>. However,
803 treat <init> as a constructor. */
804 if (! utf8_cmp (str, length, "<init>"))
805 is_init = 1;
806 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
807 && ! (flags & ACC_STATIC))
809 /* FIXME: i18n bug here. Order of prints should not be
810 fixed. */
811 fprintf (stderr, "ignored method `");
812 jcf_print_utf8 (stderr, str, length);
813 fprintf (stderr, "' marked virtual\n");
814 found_error = 1;
815 return;
817 else
818 return;
821 /* During the first method pass, build a list of method names. This will
822 be used to determine if field names conflict with method names. */
823 if (! stream)
825 struct method_name *nn;
827 nn = xmalloc (sizeof (struct method_name));
828 nn->name = xmalloc (length);
829 memcpy (nn->name, str, length);
830 nn->length = length;
831 nn->next = method_name_list;
832 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
833 nn->signature = xmalloc (nn->sig_length);
834 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
835 nn->sig_length);
836 method_name_list = nn;
838 /* The rest of this function doesn't matter. */
839 return;
842 /* We don't worry about overrides in JNI mode. */
843 if (! flag_jni)
845 /* We can't generate a method whose name is a C++ reserved word.
846 We can't just ignore the function, because that will cause
847 incorrect code to be generated if the function is virtual
848 (not only for calls to this function for for other functions
849 after it in the vtbl). So we give it a dummy name instead. */
850 override = cxx_keyword_subst (str, length);
853 if (! stubs && ! flag_jni)
855 method_printed = 1;
857 generate_access (stream, flags);
859 fputs (" ", out);
860 if ((flags & ACC_STATIC))
861 fputs ("static ", out);
862 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
864 /* Don't print `virtual' if we have a constructor. */
865 if (! is_init)
866 fputs ("virtual ", out);
868 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
870 if ((flags & ACC_ABSTRACT))
871 fputs (" = 0", out);
872 else
873 method_declared = 1;
875 else
877 if (METHOD_IS_NATIVE (flags))
879 method_printed = 1;
880 print_stub_or_jni (out, jcf, name_index, sig_index,
881 is_init, override, flags);
885 if (override)
886 free (override);
889 /* A helper for the decompiler which prints a `return' statement where
890 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
891 identical, we emit a cast. We do this because the C++ compiler
892 doesn't know that a reference can be cast to the type of an
893 interface it implements. METHODTYPE is the index of the method's
894 signature. NAMEINDEX is the index of the field name; -1 for
895 `this'. OBJECTTYPE is the index of the object's type. */
896 static void
897 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
898 int nameindex, int objecttype)
900 int cast = 0;
901 int obj_name_len, method_name_len;
902 const unsigned char *obj_data, *method_data;
904 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
905 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
907 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
908 method_data = JPOOL_UTF_DATA (jcf, methodtype);
910 /* Skip forward to return type part of method. */
911 while (*method_data != ')')
913 ++method_data;
914 --method_name_len;
916 /* Skip past `)'. */
917 ++method_data;
918 --method_name_len;
920 /* If we see an `L', skip it and the trailing `;'. */
921 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
923 ++method_data;
924 method_name_len -= 2;
926 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
928 ++obj_data;
929 obj_name_len -= 2;
932 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
933 need a cast. Right now there is no way to determine if this is
934 the case. */
935 if (method_name_len != obj_name_len)
936 cast = 1;
937 else
939 int i;
940 for (i = 0; i < method_name_len; ++i)
942 if (method_data[i] != obj_data[i])
944 cast = 1;
945 break;
950 fputs (" { return ", out);
952 if (cast)
954 int array_depth = 0;
955 const unsigned char *limit;
957 fputs ("reinterpret_cast<", out);
959 while (*method_data == '[')
961 ++method_data;
962 ++array_depth;
963 --method_name_len;
964 fputs ("JArray<", out);
967 /* Leading space to avoid C++ digraphs. */
968 fputs (" ::", out);
970 /* If we see an `L', skip it and the trailing `;'. Only do this
971 if we've seen an array specification. If we don't have an
972 array then the `L' was stripped earlier. */
973 if (array_depth && method_data[0] == 'L'
974 && method_data[method_name_len - 1] == ';')
976 ++method_data;
977 method_name_len -= 2;
980 limit = method_data + method_name_len;
981 while (method_data < limit)
983 int ch = UTF8_GET (method_data, limit);
984 if (ch == '/')
985 fputs ("::", out);
986 else
987 jcf_print_char (out, ch);
989 fputs (" *", out);
991 /* Close each array. */
992 while (array_depth > 0)
994 fputs ("> *", out);
995 --array_depth;
998 /* Close the cast. */
999 fputs ("> (", out);
1002 if (nameindex == -1)
1003 fputs ("this", out);
1004 else
1005 print_field_name (out, jcf, nameindex, 0);
1007 if (cast)
1008 fputs (")", out);
1010 fputs ("; }", out);
1014 /* Try to decompile a method body. Right now we just try to handle a
1015 simple case that we can do. Expand as desired. */
1016 static void
1017 decompile_method (FILE *out, JCF *jcf, int code_len)
1019 const unsigned char *codes = jcf->read_ptr;
1020 int index;
1021 uint16 name_and_type, name;
1023 /* If the method is synchronized, don't touch it. */
1024 if ((method_access & ACC_SYNCHRONIZED))
1025 return;
1027 if (code_len == 5
1028 && codes[0] == OPCODE_aload_0
1029 && codes[1] == OPCODE_getfield
1030 && (codes[4] == OPCODE_areturn
1031 || codes[4] == OPCODE_dreturn
1032 || codes[4] == OPCODE_freturn
1033 || codes[4] == OPCODE_ireturn
1034 || codes[4] == OPCODE_lreturn))
1036 /* Found code like `return FIELD'. */
1037 index = (codes[2] << 8) | codes[3];
1038 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1039 name_and_type = JPOOL_USHORT2 (jcf, index);
1040 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1041 name = JPOOL_USHORT1 (jcf, name_and_type);
1042 if (codes[4] == OPCODE_areturn)
1043 decompile_return_statement (out, jcf, method_signature,
1044 name, JPOOL_USHORT2 (jcf, name_and_type));
1045 else
1047 fputs (" { return ", out);
1048 /* FIXME: flags. */
1049 print_field_name (out, jcf, name, 0);
1050 fputs ("; }", out);
1052 decompiled = 1;
1054 else if (code_len == 2
1055 && codes[0] == OPCODE_aload_0
1056 && codes[1] == OPCODE_areturn
1057 /* We're going to generate `return this'. This only makes
1058 sense for non-static methods. */
1059 && ! (method_access & ACC_STATIC))
1061 decompile_return_statement (out, jcf, method_signature, -1,
1062 JPOOL_USHORT1 (jcf, jcf->this_class));
1063 decompiled = 1;
1065 else if (code_len == 1 && codes[0] == OPCODE_return)
1067 /* Found plain `return'. */
1068 fputs (" { }", out);
1069 decompiled = 1;
1071 else if (code_len == 2
1072 && codes[0] == OPCODE_aconst_null
1073 && codes[1] == OPCODE_areturn)
1075 /* Found `return null'. We don't want to depend on NULL being
1076 defined. */
1077 fputs (" { return 0; }", out);
1078 decompiled = 1;
1082 /* Like strcmp, but invert the return result for the hash table. This
1083 should probably be in hashtab.c to complement the existing string
1084 hash function. */
1085 static int
1086 gcjh_streq (const void *p1, const void *p2)
1088 return ! strcmp ((char *) p1, (char *) p2);
1091 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1092 or 0 if not. CLNAME may be extracted from a signature, and can be
1093 terminated with either `;' or NULL. */
1094 static int
1095 throwable_p (const unsigned char *clname)
1097 int length;
1098 unsigned char *current;
1099 int i;
1100 int result = 0;
1102 /* We keep two hash tables of class names. In one we list all the
1103 classes which are subclasses of Throwable. In the other we will
1104 all other classes. We keep two tables to make the code a bit
1105 simpler; we don't have to have a structure mapping class name to
1106 a `throwable?' bit. */
1107 static htab_t throw_hash;
1108 static htab_t non_throw_hash;
1109 static int init_done = 0;
1111 if (! init_done)
1113 void **slot;
1114 unsigned char *str;
1116 /* Self-initializing. The cost of this really doesn't matter.
1117 We also don't care about freeing these, either. */
1118 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1119 (htab_del) free);
1120 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1121 (htab_del) free);
1123 /* Make sure the root classes show up in the tables. */
1124 str = xstrdup ("java.lang.Throwable");
1125 slot = htab_find_slot (throw_hash, str, INSERT);
1126 *slot = str;
1128 str = xstrdup ("java.lang.Object");
1129 slot = htab_find_slot (non_throw_hash, str, INSERT);
1130 *slot = str;
1132 init_done = 1;
1135 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1137 current = ALLOC (length + 1);
1138 for (i = 0; i < length; ++i)
1139 current[i] = clname[i] == '/' ? '.' : clname[i];
1140 current[length] = '\0';
1142 /* We don't compute the hash slot here because the table might be
1143 modified by the recursion. In that case the slot could be
1144 invalidated. */
1145 if (htab_find (throw_hash, current))
1146 result = 1;
1147 else if (htab_find (non_throw_hash, current))
1148 result = 0;
1149 else
1151 JCF jcf;
1152 void **slot;
1153 unsigned char *super, *tmp;
1154 int super_length = -1;
1155 const char *classfile_name = find_class (current, strlen (current),
1156 &jcf, 0);
1158 if (! classfile_name)
1160 fprintf (stderr, "couldn't find class %s\n", current);
1161 found_error = 1;
1162 return 0;
1164 if (jcf_parse_preamble (&jcf) != 0
1165 || jcf_parse_constant_pool (&jcf) != 0
1166 || verify_constant_pool (&jcf) > 0)
1168 fprintf (stderr, "parse error while reading %s\n", classfile_name);
1169 found_error = 1;
1170 return 0;
1172 jcf_parse_class (&jcf);
1174 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1175 super = ALLOC (super_length + 1);
1176 memcpy (super, tmp, super_length);
1177 super[super_length] = '\0';
1179 result = throwable_p (super);
1180 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1181 current, INSERT);
1182 *slot = current;
1183 current = NULL;
1185 JCF_FINISH (&jcf);
1188 return result;
1191 /* Print one piece of a signature. Returns pointer to next parseable
1192 character on success, NULL on error. */
1193 static const unsigned char *
1194 decode_signature_piece (FILE *stream, const unsigned char *signature,
1195 const unsigned char *limit, int *need_space)
1197 const char *ctype;
1198 int array_depth = 0;
1200 switch (signature[0])
1202 case '[':
1203 /* More spaghetti. */
1205 array_loop:
1206 for (signature++; (signature < limit
1207 && ISDIGIT (*signature)); signature++)
1209 switch (*signature)
1211 case 'B':
1212 ctype = "jbyteArray";
1213 break;
1214 case 'C':
1215 ctype = "jcharArray";
1216 break;
1217 case 'D':
1218 ctype = "jdoubleArray";
1219 break;
1220 case 'F':
1221 ctype = "jfloatArray";
1222 break;
1223 case 'I':
1224 ctype = "jintArray";
1225 break;
1226 case 'S':
1227 ctype = "jshortArray";
1228 break;
1229 case 'J':
1230 ctype = "jlongArray";
1231 break;
1232 case 'Z':
1233 ctype = "jbooleanArray";
1234 break;
1235 case '[':
1236 /* We have a nested array. */
1237 ++array_depth;
1238 if (! flag_jni)
1239 fputs ("JArray<", stream);
1240 goto array_loop;
1242 case 'L':
1243 /* We have to generate a reference to JArray here, so that
1244 our output matches what the compiler does. */
1245 ++signature;
1246 /* Space between `<' and `:' to avoid C++ digraphs. */
1247 if (! flag_jni)
1248 fputs ("JArray< ::", stream);
1249 while (signature < limit && *signature != ';')
1251 int ch = UTF8_GET (signature, limit);
1252 if (! flag_jni)
1254 if (ch == '/')
1255 fputs ("::", stream);
1256 else
1257 jcf_print_char (stream, ch);
1260 if (! flag_jni)
1261 fputs (" *> *", stream);
1262 *need_space = 0;
1263 ctype = NULL;
1264 break;
1265 default:
1266 /* Unparseable signature. */
1267 return NULL;
1270 /* If the previous iterations left us with something to print,
1271 print it. For JNI, we always print `jobjectArray' in the
1272 nested cases. */
1273 if (flag_jni && (ctype == NULL || array_depth > 0))
1275 ctype = "jobjectArray";
1276 *need_space = 1;
1278 /* The `printit' case will advance SIGNATURE for us. If we
1279 don't go there, we must advance past the `;' ourselves. */
1280 if (ctype != NULL)
1281 goto printit;
1282 ++signature;
1283 break;
1285 case '(':
1286 case ')':
1287 /* This shouldn't happen. */
1288 return NULL;
1290 case 'B': ctype = "jbyte"; goto printit;
1291 case 'C': ctype = "jchar"; goto printit;
1292 case 'D': ctype = "jdouble"; goto printit;
1293 case 'F': ctype = "jfloat"; goto printit;
1294 case 'I': ctype = "jint"; goto printit;
1295 case 'J': ctype = "jlong"; goto printit;
1296 case 'S': ctype = "jshort"; goto printit;
1297 case 'Z': ctype = "jboolean"; goto printit;
1298 case 'V': ctype = "void"; goto printit;
1299 case 'L':
1300 if (flag_jni)
1302 /* We know about certain types and special-case their names. */
1303 if (! strncmp (signature, "Ljava/lang/String;",
1304 sizeof ("Ljava/lang/String;") -1))
1305 ctype = "jstring";
1306 else if (! strncmp (signature, "Ljava/lang/Class;",
1307 sizeof ("Ljava/lang/Class;") - 1))
1308 ctype = "jclass";
1309 /* Skip leading 'L' for throwable_p call. */
1310 else if (throwable_p (signature + 1))
1311 ctype = "jthrowable";
1312 else
1313 ctype = "jobject";
1315 while (*signature && *signature != ';')
1316 ++signature;
1318 goto printit;
1320 /* Print a leading "::" so we look in the right namespace. */
1321 fputs ("::", stream);
1322 ++signature;
1323 while (*signature && *signature != ';')
1325 int ch = UTF8_GET (signature, limit);
1326 if (ch == '/')
1327 fputs ("::", stream);
1328 else
1329 jcf_print_char (stream, ch);
1331 fputs (" *", stream);
1332 if (*signature == ';')
1333 signature++;
1334 *need_space = 0;
1335 break;
1336 default:
1337 *need_space = 1;
1338 jni_print_char (stream, *signature++);
1339 break;
1340 printit:
1341 signature++;
1342 *need_space = 1;
1343 fputs (ctype, stream);
1344 break;
1347 if (! flag_jni)
1349 while (array_depth-- > 0)
1350 fputs ("> *", stream);
1353 return signature;
1356 static void
1357 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1358 int is_init, const char *name_override, int flags)
1360 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1362 fprintf (stream, "<not a UTF8 constant>");
1363 found_error = 1;
1365 else
1367 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1368 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1369 register const unsigned char *str = str0;
1370 const unsigned char *limit = str + length;
1371 int need_space = 0;
1372 int is_method = str[0] == '(';
1373 const unsigned char *next;
1375 /* If printing a method, skip to the return signature and print
1376 that first. However, there is no return value if this is a
1377 constructor. */
1378 if (is_method && ! is_init)
1380 while (str < limit)
1382 int ch = *str++;
1383 if (ch == ')')
1384 break;
1388 /* If printing a field or an ordinary method, then print the
1389 "return value" now. */
1390 if (! is_method || ! is_init)
1392 next = decode_signature_piece (stream, str, limit, &need_space);
1393 if (! next)
1395 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1396 found_error = 1;
1397 return;
1401 /* Force the alignment of the first data member. This is
1402 because the "new" C++ ABI changed the alignemnt of non-POD
1403 classes. gcj, however, still uses the "old" alignment. */
1404 if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
1406 is_first_data_member = 0;
1407 print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1408 jcf, jcf->super_class, 1);
1409 fputs (" )))) ", stream);
1412 /* Now print the name of the thing. */
1413 if (need_space)
1414 fputs (" ", stream);
1415 print_full_cxx_name (stream, jcf, name_index,
1416 signature_index, is_init, name_override,
1417 flags);
1421 /* Print the unqualified method name followed by the signature. */
1422 static void
1423 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1424 int signature_index, int is_init,
1425 const char *name_override, int flags)
1427 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1428 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1429 register const unsigned char *str = str0;
1430 const unsigned char *limit = str + length;
1431 int need_space = 0;
1432 int is_method = str[0] == '(';
1433 const unsigned char *next;
1435 if (name_override)
1436 fputs (name_override, stream);
1437 else if (name_index)
1439 /* Declare constructors specially. */
1440 if (is_init)
1441 print_base_classname (stream, jcf, jcf->this_class);
1442 else
1443 print_name (stream, jcf, name_index);
1446 if (flag_jni)
1448 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1449 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1450 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1451 JPOOL_UTF_LENGTH (jcf, name_index),
1452 signature, sig_len))
1454 /* If this method is overloaded by another native method,
1455 then include the argument information in the mangled
1456 name. */
1457 unsigned char *limit = signature + sig_len;
1458 fputs ("__", stream);
1459 while (signature < limit)
1461 int ch = UTF8_GET (signature, limit);
1462 jni_print_char (stream, ch);
1463 if (ch == ')')
1465 /* Done. */
1466 break;
1472 if (is_method)
1474 /* Have a method or a constructor. Print signature pieces
1475 until done. */
1476 fputs (" (", stream);
1478 str = str0 + 1;
1480 /* In JNI mode, add extra arguments. */
1481 if (flag_jni)
1483 /* FIXME: it would be nice to know if we are printing a decl
1484 or a definition, and only print `env' for the latter. */
1485 fputs ("JNIEnv *env", stream);
1487 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1489 if (*str != ')')
1490 fputs (", ", stream);
1493 while (str < limit && *str != ')')
1495 next = decode_signature_piece (stream, str, limit, &need_space);
1496 if (! next)
1498 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1499 found_error = 1;
1500 return;
1503 if (next < limit && *next != ')')
1504 fputs (", ", stream);
1505 str = next;
1508 fputs (")", stream);
1512 /* This is a helper for print_stub_or_jni. */
1513 static void
1514 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1515 int signature_index, int is_init,
1516 const char *name_override, int flags)
1518 const char *const prefix = flag_jni ? "Java_" : "";
1519 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1520 fputs (flag_jni ? "_" : "::", stream);
1521 print_full_cxx_name (stream, jcf, name_index,
1522 signature_index, is_init, name_override,
1523 flags);
1526 static void
1527 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1528 int signature_index, int is_init,
1529 const char *name_override, int flags)
1531 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1533 fprintf (stream, "<not a UTF8 constant>");
1534 found_error = 1;
1536 else
1538 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1539 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1540 register const unsigned char *str = str0;
1541 const unsigned char *limit = str + length;
1542 int need_space = 0;
1543 int is_method = str[0] == '(';
1544 const unsigned char *next;
1546 /* Don't print fields in the JNI case. */
1547 if (! is_method && flag_jni)
1548 return;
1550 if (flag_jni && ! stubs)
1551 fputs ("extern JNIEXPORT ", stream);
1553 /* If printing a method, skip to the return signature and print
1554 that first. However, there is no return value if this is a
1555 constructor. */
1556 if (is_method && ! is_init)
1558 while (str < limit)
1560 int ch = *str++;
1561 if (ch == ')')
1562 break;
1566 /* If printing a field or an ordinary method, then print the
1567 "return value" now. Note that a constructor can't be native,
1568 so we don't bother checking this in the JNI case. */
1569 if (! is_method || ! is_init)
1571 next = decode_signature_piece (stream, str, limit, &need_space);
1572 if (! next)
1574 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1575 found_error = 1;
1576 return;
1580 /* When printing a JNI header we need to respect the space. In
1581 other cases we're just going to insert a newline anyway. */
1582 fputs (need_space && ! stubs ? " " : "\n", stream);
1584 if (flag_jni && ! stubs)
1585 fputs ("JNICALL ", stream);
1587 /* Now print the name of the thing. */
1588 print_name_for_stub_or_jni (stream, jcf, name_index,
1589 signature_index, is_init, name_override,
1590 flags);
1592 /* Print the body. */
1593 if (stubs)
1595 if (flag_jni)
1596 fputs ("\n{\n (*env)->FatalError (\"", stream);
1597 else
1598 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1599 print_name_for_stub_or_jni (stream, jcf, name_index,
1600 signature_index, is_init,
1601 name_override,
1602 flags);
1603 fprintf (stream, " not implemented\")%s;\n}\n\n",
1604 flag_jni ? "" : ")");
1609 static void
1610 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1612 int name_index = JPOOL_USHORT1 (jcf, index);
1613 fputs (prefix, stream);
1614 jcf_print_utf8_replace (out,
1615 JPOOL_UTF_DATA (jcf, name_index),
1616 JPOOL_UTF_LENGTH (jcf, name_index),
1617 '/', '_');
1620 /* Print PREFIX, then a class name in C++ format. If the name refers
1621 to an array, ignore it and don't print PREFIX. Returns 1 if
1622 something was printed, 0 otherwise. */
1623 static int
1624 print_cxx_classname (FILE *stream, const char *prefix,
1625 JCF *jcf, int index, int add_scope)
1627 int name_index = JPOOL_USHORT1 (jcf, index);
1628 int len, c;
1629 const unsigned char *s, *p, *limit;
1631 s = JPOOL_UTF_DATA (jcf, name_index);
1632 len = JPOOL_UTF_LENGTH (jcf, name_index);
1633 limit = s + len;
1635 /* Explicitly omit arrays here. */
1636 p = s;
1637 c = UTF8_GET (p, limit);
1638 if (c == '[')
1639 return 0;
1641 fputs (prefix, stream);
1643 /* Print a leading "::" so we look in the right namespace. */
1644 if (! flag_jni && ! stubs && add_scope)
1645 fputs ("::", stream);
1647 while (s < limit)
1649 c = UTF8_GET (s, limit);
1650 if (c == '/')
1651 fputs (flag_jni ? "_" : "::", stream);
1652 else
1653 jni_print_char (stream, c);
1656 return 1;
1659 int written_class_count = 0;
1661 /* Return name of superclass. If LEN is not NULL, fill it with length
1662 of name. */
1663 static const unsigned char *
1664 super_class_name (JCF *derived_jcf, int *len)
1666 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1667 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1668 const unsigned char *supername =
1669 JPOOL_UTF_DATA (derived_jcf, supername_index);
1671 if (len)
1672 *len = supername_length;
1674 return supername;
1679 /* We keep track of all the `#include's we generate, so we can avoid
1680 duplicates. */
1681 struct include
1683 char *name;
1684 struct include *next;
1687 /* List of all includes. */
1688 static struct include *all_includes = NULL;
1690 /* Generate a #include. */
1691 static void
1692 print_include (FILE *out, const unsigned char *utf8, int len)
1694 struct include *incl;
1696 if (! out)
1697 return;
1699 if (len == -1)
1700 len = strlen (utf8);
1702 for (incl = all_includes; incl; incl = incl->next)
1704 /* We check the length because we might have a proper prefix. */
1705 if (len == (int) strlen (incl->name)
1706 && ! strncmp (incl->name, utf8, len))
1707 return;
1710 incl = xmalloc (sizeof (struct include));
1711 incl->name = xmalloc (len + 1);
1712 strncpy (incl->name, utf8, len);
1713 incl->name[len] = '\0';
1714 incl->next = all_includes;
1715 all_includes = incl;
1717 fputs ("#include <", out);
1718 jcf_print_utf8_replace (out, utf8, len,
1719 '/',
1720 flag_jni ? '_' : '/');
1721 fputs (".h>\n", out);
1726 /* This is used to represent part of a package or class name. */
1727 struct namelet
1729 /* The text of this part of the name. */
1730 char *name;
1731 /* True if this represents a class. */
1732 int is_class;
1733 /* Linked list of all classes and packages inside this one. */
1734 struct namelet *subnamelets;
1735 /* Pointer to next sibling. */
1736 struct namelet *next;
1739 static void add_namelet (const unsigned char *, const unsigned char *,
1740 struct namelet *);
1741 static void print_namelet (FILE *, struct namelet *, int);
1743 /* The special root namelet. */
1744 static struct namelet root =
1746 NULL,
1748 NULL,
1749 NULL
1752 /* This extracts the next name segment from the full UTF-8 encoded
1753 package or class name and links it into the tree. It does this
1754 recursively. */
1755 static void
1756 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1757 struct namelet *parent)
1759 const unsigned char *p;
1760 struct namelet *n = NULL, *np;
1762 /* We want to skip the standard namespaces that we assume the
1763 runtime already knows about. We only do this at the top level,
1764 though, hence the check for `root'. */
1765 if (parent == &root)
1767 #define JAVALANG "java/lang/"
1768 #define JAVAIO "java/io/"
1769 #define JAVAUTIL "java/util/"
1770 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1771 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1772 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1773 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1774 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1775 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1776 return;
1779 for (p = name; p < name_limit && *p != '/'; ++p)
1782 /* Search for this name beneath the PARENT node. */
1783 for (np = parent->subnamelets; np != NULL; np = np->next)
1785 /* We check the length because we might have a proper prefix. */
1786 if ((int) strlen (np->name) == p - name &&
1787 ! strncmp (name, np->name, p - name))
1789 n = np;
1790 break;
1794 if (n == NULL)
1796 n = xmalloc (sizeof (struct namelet));
1797 n->name = xmalloc (p - name + 1);
1798 strncpy (n->name, name, p - name);
1799 n->name[p - name] = '\0';
1800 n->is_class = (p == name_limit);
1801 n->subnamelets = NULL;
1802 n->next = parent->subnamelets;
1803 parent->subnamelets = n;
1806 /* We recurse if there is more text, and if the trailing piece does
1807 not represent an inner class. */
1808 if (p < name_limit)
1809 add_namelet (p + 1, name_limit, n);
1812 /* Print a single namelet. Destroys namelets while printing. */
1813 static void
1814 print_namelet (FILE *out, struct namelet *name, int depth)
1816 int i, term = 0;
1817 struct namelet *c;
1819 if (name->name)
1821 for (i = 0; i < depth; ++i)
1822 fputc (' ', out);
1823 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1824 name->name);
1825 if (name->is_class && name->subnamelets == NULL)
1826 fputs (";\n", out);
1827 else
1829 term = 1;
1830 fputs ("\n", out);
1831 for (i = 0; i < depth; ++i)
1832 fputc (' ', out);
1833 fputs ("{\n", out);
1837 c = name->subnamelets;
1838 while (c != NULL)
1840 struct namelet *next = c->next;
1841 print_namelet (out, c, depth + 2);
1842 c = next;
1844 name->subnamelets = NULL;
1846 if (name->name)
1848 if (term)
1850 for (i = 0; i < depth; ++i)
1851 fputc (' ', out);
1852 fputs ("}\n", out);
1853 /* Only print a `;' when printing a class. C++ is evil. */
1854 if (name->is_class)
1855 fputs (";", out);
1858 free (name->name);
1859 free (name);
1863 /* This is called to add some classes to the list of classes for which
1864 we need decls. The signature argument can be a function
1865 signature. */
1866 static void
1867 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1869 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1870 int len = JPOOL_UTF_LENGTH (jcf, signature);
1871 int i;
1873 for (i = 0; i < len; ++i)
1875 int start;
1877 /* If we see an array, then we include the array header. */
1878 if (s[i] == '[')
1880 print_include (out, "gcj/array", -1);
1881 continue;
1884 /* We're looking for `L<stuff>;' -- everything else is
1885 ignorable. */
1886 if (s[i] != 'L')
1887 continue;
1889 for (start = ++i; i < len && s[i] != ';'; ++i)
1892 add_namelet (&s[start], &s[i], &root);
1896 /* Print declarations for all classes required by this class. Any
1897 class or package in the `java' package is assumed to be handled
1898 statically in libjava; we don't generate declarations for these.
1899 This makes the generated headers a bit easier to read. */
1900 static void
1901 print_class_decls (FILE *out, JCF *jcf, int self)
1903 /* Make sure to always add the current class to the list of things
1904 that should be declared. */
1905 int name_index = JPOOL_USHORT1 (jcf, self);
1906 int len;
1907 const unsigned char *s;
1909 s = JPOOL_UTF_DATA (jcf, name_index);
1910 len = JPOOL_UTF_LENGTH (jcf, name_index);
1911 add_namelet (s, s + len, &root);
1913 if (root.subnamelets)
1915 fputs ("extern \"Java\"\n{\n", out);
1916 /* We use an initial offset of 0 because the root namelet
1917 doesn't cause anything to print. */
1918 print_namelet (out, &root, 0);
1919 fputs ("}\n\n", out);
1925 static void
1926 process_file (JCF *jcf, FILE *out)
1928 int code, i;
1929 uint32 field_start, method_end, method_start;
1931 current_jcf = jcf;
1933 last_access = -1;
1935 if (jcf_parse_preamble (jcf) != 0)
1937 fprintf (stderr, "Not a valid Java .class file.\n");
1938 found_error = 1;
1939 return;
1942 /* Parse and possibly print constant pool */
1943 code = jcf_parse_constant_pool (jcf);
1944 if (code != 0)
1946 fprintf (stderr, "error while parsing constant pool\n");
1947 found_error = 1;
1948 return;
1950 code = verify_constant_pool (jcf);
1951 if (code > 0)
1953 fprintf (stderr, "error in constant pool entry #%d\n", code);
1954 found_error = 1;
1955 return;
1958 jcf_parse_class (jcf);
1960 if (written_class_count++ == 0 && out)
1962 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1963 if (flag_jni)
1965 cstart = "/*";
1966 cstart2 = " ";
1967 cend = " */";
1968 mode = "";
1969 what = "JNI";
1970 jflag = " -jni";
1972 else
1974 cstart = "//";
1975 cstart2 = "//";
1976 cend = "";
1977 mode = " -*- c++ -*-";
1978 what = "CNI";
1979 jflag = "";
1982 if (! stubs)
1983 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1984 cstart, mode, cend);
1985 else
1987 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1988 %s\n\
1989 %s This file is intended to give you a head start on implementing native\n\
1990 %s methods using %s.\n\
1991 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1992 %s overwrite any edits you have made to this file.%s\n\n",
1993 cstart, jflag, mode,
1994 cstart2,
1995 cstart2,
1996 cstart2,
1997 what,
1998 cstart2,
1999 jflag,
2000 cstart2,
2001 cend);
2005 if (out)
2007 if (! stubs)
2009 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2010 fprintf (out, "__\n");
2012 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2013 fprintf (out, "__\n\n");
2015 if (flag_jni)
2017 fprintf (out, "#include <jni.h>\n\n");
2018 fprintf (out, "#ifdef __cplusplus\n");
2019 fprintf (out, "extern \"C\"\n");
2020 fprintf (out, "{\n");
2021 fprintf (out, "#endif\n");
2023 else
2025 /* We do this to ensure that inline methods won't be
2026 `outlined' by g++. This works as long as method and
2027 fields are not added by the user. */
2028 fprintf (out, "#pragma interface\n");
2030 if (jcf->super_class)
2032 int super_length;
2033 const unsigned char *supername =
2034 super_class_name (jcf, &super_length);
2036 fputs ("\n", out);
2037 print_include (out, supername, super_length);
2041 else
2043 /* Strip off the ".class" portion of the name when printing
2044 the include file name. */
2045 char *name;
2046 int i, len = strlen (jcf->classname);
2047 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2048 len -= 6;
2049 /* Turn the class name into a file name. */
2050 name = xmalloc (len + 1);
2051 for (i = 0; i < len; ++i)
2052 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2053 name[i] = '\0';
2054 print_include (out, name, len);
2055 free (name);
2057 if (! flag_jni)
2059 print_include (out, "gcj/cni", -1);
2060 print_include (out, "java/lang/UnsupportedOperationException",
2061 -1);
2066 /* We want to parse the methods first. But we need to find where
2067 they start. So first we skip the fields, then parse the methods.
2068 Then we parse the fields and skip the methods. This is ugly, but
2069 not too bad since we need two full passes to get class decl
2070 information anyway. */
2071 field_pass = 0;
2072 field_start = JCF_TELL (jcf);
2073 jcf_parse_fields (jcf);
2075 method_start = JCF_TELL (jcf);
2076 method_pass = 0;
2077 jcf_parse_methods (jcf);
2079 if (out)
2080 fputs ("\n", out);
2082 if (out && ! flag_jni)
2084 if (! stubs)
2085 print_class_decls (out, jcf, jcf->this_class);
2087 for (i = 0; i < prepend_count; ++i)
2088 fprintf (out, "%s\n", prepend_specs[i]);
2089 if (prepend_count > 0)
2090 fputc ('\n', out);
2092 if (! stubs)
2094 if (! print_cxx_classname (out, "class ", jcf,
2095 jcf->this_class, 0))
2097 fprintf (stderr, "class is of array type\n");
2098 found_error = 1;
2099 return;
2101 if (jcf->super_class)
2103 if (! print_cxx_classname (out, " : public ",
2104 jcf, jcf->super_class, 1))
2106 fprintf (stderr, "base class is of array type\n");
2107 found_error = 1;
2108 return;
2112 fputs ("\n{\n", out);
2116 /* Now go back for second pass over methods and fields. */
2117 is_first_data_member = 1;
2119 JCF_SEEK (jcf, method_start);
2120 method_pass = 1;
2121 jcf_parse_methods (jcf);
2122 method_end = JCF_TELL (jcf);
2124 field_pass = 1;
2125 JCF_SEEK (jcf, field_start);
2126 jcf_parse_fields (jcf);
2127 JCF_SEEK (jcf, method_end);
2129 jcf_parse_final_attributes (jcf);
2131 if (out && ! stubs)
2133 if (flag_jni)
2135 fprintf (out, "\n#ifdef __cplusplus\n");
2136 fprintf (out, "}\n");
2137 fprintf (out, "#endif\n");
2139 else
2141 /* Generate friend decl if we still must. */
2142 for (i = 0; i < friend_count; ++i)
2143 fprintf (out, " friend %s\n", friend_specs[i]);
2145 /* Generate extra declarations. */
2146 if (add_count > 0)
2147 fputc ('\n', out);
2148 for (i = 0; i < add_count; ++i)
2149 fprintf (out, " %s\n", add_specs[i]);
2151 /* Generate an entry for the class object. */
2152 generate_access (out, ACC_PUBLIC);
2153 fprintf (out, "\n static ::java::lang::Class class$;\n");
2155 fputs ("}", out);
2157 if (jcf->access_flags & ACC_INTERFACE)
2158 fputs (" __attribute__ ((java_interface))", out);
2160 fputs (";\n", out);
2162 if (append_count > 0)
2163 fputc ('\n', out);
2164 for (i = 0; i < append_count; ++i)
2165 fprintf (out, "%s\n", append_specs[i]);
2168 print_mangled_classname (out, jcf,
2169 "\n#endif /* __", jcf->this_class);
2170 fprintf (out, "__ */\n");
2176 /* This is used to mark options with no short value. */
2177 #define LONG_OPT(Num) ((Num) + 128)
2179 #define OPT_classpath LONG_OPT (0)
2180 #define OPT_CLASSPATH OPT_classpath
2181 #define OPT_bootclasspath LONG_OPT (1)
2182 #define OPT_extdirs LONG_OPT (2)
2183 #define OPT_HELP LONG_OPT (3)
2184 #define OPT_TEMP LONG_OPT (4)
2185 #define OPT_VERSION LONG_OPT (5)
2186 #define OPT_PREPEND LONG_OPT (6)
2187 #define OPT_FRIEND LONG_OPT (7)
2188 #define OPT_ADD LONG_OPT (8)
2189 #define OPT_APPEND LONG_OPT (9)
2190 #define OPT_M LONG_OPT (10)
2191 #define OPT_MM LONG_OPT (11)
2192 #define OPT_MG LONG_OPT (12)
2193 #define OPT_MD LONG_OPT (13)
2194 #define OPT_MMD LONG_OPT (14)
2196 static const struct option options[] =
2198 { "classpath", required_argument, NULL, OPT_classpath },
2199 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2200 { "extdirs", required_argument, NULL, OPT_extdirs },
2201 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2202 { "help", no_argument, NULL, OPT_HELP },
2203 { "stubs", no_argument, &stubs, 1 },
2204 { "td", required_argument, NULL, OPT_TEMP },
2205 { "verbose", no_argument, NULL, 'v' },
2206 { "version", no_argument, NULL, OPT_VERSION },
2207 { "prepend", required_argument, NULL, OPT_PREPEND },
2208 { "friend", required_argument, NULL, OPT_FRIEND },
2209 { "add", required_argument, NULL, OPT_ADD },
2210 { "append", required_argument, NULL, OPT_APPEND },
2211 { "M", no_argument, NULL, OPT_M },
2212 { "MM", no_argument, NULL, OPT_MM },
2213 { "MG", no_argument, NULL, OPT_MG },
2214 { "MD", no_argument, NULL, OPT_MD },
2215 { "MMD", no_argument, NULL, OPT_MMD },
2216 { "jni", no_argument, &flag_jni, 1 },
2217 { NULL, no_argument, NULL, 0 }
2220 static void
2221 usage (void)
2223 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2224 exit (1);
2227 static void
2228 help (void)
2230 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2231 printf ("Generate C++ header files from .class files\n\n");
2232 printf (" -stubs Generate an implementation stub file\n");
2233 printf (" -jni Generate a JNI header or stub\n");
2234 printf ("\n");
2235 printf (" -add TEXT Insert TEXT into class body\n");
2236 printf (" -append TEXT Insert TEXT after class declaration\n");
2237 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2238 printf (" -prepend TEXT Insert TEXT before start of class\n");
2239 printf ("\n");
2240 printf (" --classpath PATH Set path to find .class files\n");
2241 printf (" -IDIR Append directory to class path\n");
2242 printf (" --bootclasspath PATH Override built-in class path\n");
2243 printf (" --extdirs PATH Set extensions directory path\n");
2244 printf (" -d DIRECTORY Set output directory name\n");
2245 printf (" -o FILE Set output file name\n");
2246 printf (" -td DIRECTORY Set temporary directory name\n");
2247 printf ("\n");
2248 printf (" --help Print this help, then exit\n");
2249 printf (" --version Print version number, then exit\n");
2250 printf (" -v, --verbose Print extra information while running\n");
2251 printf ("\n");
2252 printf (" -M Print all dependencies to stdout;\n");
2253 printf (" suppress ordinary output\n");
2254 printf (" -MM Print non-system dependencies to stdout;\n");
2255 printf (" suppress ordinary output\n");
2256 printf (" -MD Print all dependencies to stdout\n");
2257 printf (" -MMD Print non-system dependencies to stdout\n");
2258 /* We omit -MG until it is implemented. */
2259 printf ("\n");
2260 printf ("For bug reporting instructions, please see:\n");
2261 printf ("%s.\n", bug_report_url);
2262 exit (0);
2265 static void
2266 version (void)
2268 printf ("gcjh (GCC) %s\n\n", version_string);
2269 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2270 printf ("This is free software; see the source for copying conditions. There is NO\n");
2271 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2272 exit (0);
2276 main (int argc, char** argv)
2278 JCF jcf;
2279 int argi;
2280 char *output_file = NULL;
2281 int emit_dependencies = 0, suppress_output = 0;
2282 int opt;
2284 if (argc <= 1)
2286 fprintf (stderr, "gcjh: no classes specified\n");
2287 usage ();
2290 jcf_path_init ();
2292 /* We use getopt_long_only to allow single `-' long options. For
2293 some of our options this is more natural. */
2294 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2296 switch (opt)
2298 case 0:
2299 /* Already handled. */
2300 break;
2302 case 'o':
2303 output_file = optarg;
2304 break;
2306 case 'd':
2307 output_directory = optarg;
2308 break;
2310 case 'I':
2311 jcf_path_include_arg (optarg);
2312 break;
2314 case 'v':
2315 verbose++;
2316 break;
2318 case OPT_classpath:
2319 jcf_path_classpath_arg (optarg);
2320 break;
2322 case OPT_bootclasspath:
2323 jcf_path_bootclasspath_arg (optarg);
2324 break;
2326 case OPT_extdirs:
2327 jcf_path_extdirs_arg (optarg);
2328 break;
2330 case OPT_HELP:
2331 help ();
2332 break;
2334 case OPT_TEMP:
2335 temp_directory = optarg;
2336 break;
2338 case OPT_VERSION:
2339 version ();
2340 break;
2342 case OPT_PREPEND:
2343 if (prepend_count == 0)
2344 prepend_specs = ALLOC (argc * sizeof (char*));
2345 prepend_specs[prepend_count++] = optarg;
2346 break;
2348 case OPT_FRIEND:
2349 if (friend_count == 0)
2350 friend_specs = ALLOC (argc * sizeof (char*));
2351 friend_specs[friend_count++] = optarg;
2352 break;
2354 case OPT_ADD:
2355 if (add_count == 0)
2356 add_specs = ALLOC (argc * sizeof (char*));
2357 add_specs[add_count++] = optarg;
2358 break;
2360 case OPT_APPEND:
2361 if (append_count == 0)
2362 append_specs = ALLOC (argc * sizeof (char*));
2363 append_specs[append_count++] = optarg;
2364 break;
2366 case OPT_M:
2367 emit_dependencies = 1;
2368 suppress_output = 1;
2369 jcf_dependency_init (1);
2370 break;
2372 case OPT_MM:
2373 emit_dependencies = 1;
2374 suppress_output = 1;
2375 jcf_dependency_init (0);
2376 break;
2378 case OPT_MG:
2379 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2380 exit (1);
2382 case OPT_MD:
2383 emit_dependencies = 1;
2384 jcf_dependency_init (1);
2385 break;
2387 case OPT_MMD:
2388 emit_dependencies = 1;
2389 jcf_dependency_init (0);
2390 break;
2392 default:
2393 usage ();
2394 break;
2398 if (optind == argc)
2400 fprintf (stderr, "gcjh: no classes specified\n");
2401 usage ();
2404 jcf_path_seal (verbose);
2406 if (output_file && emit_dependencies)
2408 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2409 exit (1);
2412 for (argi = optind; argi < argc; argi++)
2414 char *classname = argv[argi];
2415 char *current_output_file;
2416 const char *classfile_name;
2418 if (verbose)
2419 fprintf (stderr, "Processing %s\n", classname);
2420 if (! output_file)
2421 jcf_dependency_reset ();
2422 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2423 if (classfile_name == NULL)
2425 fprintf (stderr, "%s: no such class\n", classname);
2426 exit (1);
2428 if (verbose)
2429 fprintf (stderr, "Found in %s\n", classfile_name);
2430 if (output_file)
2432 if (strcmp (output_file, "-") == 0)
2433 out = stdout;
2434 else if (out == NULL)
2436 out = fopen (output_file, "w");
2438 if (out == NULL)
2440 perror (output_file);
2441 exit (1);
2443 current_output_file = output_file;
2445 else
2447 int dir_len = strlen (output_directory);
2448 int i, classname_length = strlen (classname);
2449 current_output_file = ALLOC (dir_len + classname_length + 5);
2450 strcpy (current_output_file, output_directory);
2451 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2452 current_output_file[dir_len++] = '/';
2453 for (i = 0; classname[i] != '\0'; i++)
2455 char ch = classname[i];
2456 if (ch == '.')
2457 ch = '/';
2458 if (flag_jni && ch == '/')
2459 ch = '_';
2460 current_output_file[dir_len++] = ch;
2462 if (emit_dependencies)
2464 if (suppress_output)
2466 jcf_dependency_set_dep_file ("-");
2467 out = NULL;
2469 else
2471 /* We use `.hd' and not `.d' to avoid clashes with
2472 dependency tracking from straight compilation. */
2473 strcpy (current_output_file + dir_len, ".hd");
2474 jcf_dependency_set_dep_file (current_output_file);
2477 strcpy (current_output_file + dir_len,
2478 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2479 jcf_dependency_set_target (current_output_file);
2480 if (! suppress_output)
2482 out = fopen (current_output_file, "w");
2483 if (out == NULL)
2485 perror (current_output_file);
2486 exit (1);
2490 process_file (&jcf, out);
2491 JCF_FINISH (&jcf);
2492 if (current_output_file != output_file)
2493 free (current_output_file);
2494 jcf_dependency_write ();
2497 if (out != NULL && out != stdout)
2498 fclose (out);
2500 return found_error;