* config/arm/arm.c (use_return_insn): Do not use a single return instruction
[official-gcc.git] / gcc / java / gjavah.c
blob7c7e3685d5d1f3a36a8538863478588a4e10d619
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 int java_float_finite (jfloat);
138 static int java_double_finite (jdouble);
139 static void print_name (FILE *, JCF *, int);
140 static void print_base_classname (FILE *, JCF *, int);
141 static int utf8_cmp (const unsigned char *, int, const char *);
142 static char *cxx_keyword_subst (const unsigned char *, int);
143 static void generate_access (FILE *, JCF_u2);
144 static int name_is_method_p (const unsigned char *, int);
145 static char *get_field_name (JCF *, int, JCF_u2);
146 static void print_field_name (FILE *, JCF *, int, JCF_u2);
147 static const unsigned char *super_class_name (JCF *, int *);
148 static void print_include (FILE *, const unsigned char *, int);
149 static int gcjh_streq (const void *p1, const void *p2);
150 static int throwable_p (const unsigned char *signature);
151 static const unsigned char *
152 decode_signature_piece (FILE *, const unsigned char *,
153 const unsigned char *, int *);
154 static void print_class_decls (FILE *, JCF *, int);
155 static void usage (void) ATTRIBUTE_NORETURN;
156 static void help (void) ATTRIBUTE_NORETURN;
157 static void version (void) ATTRIBUTE_NORETURN;
158 static int overloaded_jni_method_exists_p (const unsigned char *, int,
159 const char *, int);
160 static void jni_print_char (FILE *, int);
161 static void 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 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
202 method_synthetic = 0; \
203 method_printed = 0; \
204 decompiled = 0; \
205 method_signature = SIGNATURE; \
206 if (ATTRIBUTE_COUNT) \
207 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
208 (const char *)"Synthetic", 9); \
209 /* If a synthetic methods have been declared, its attribute aren't \
210 worth reading (and triggering side-effects). We skip them an \
211 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
212 jcf_parse_one_method. */ \
213 if (method_synthetic) \
215 skip_attribute (jcf, ATTRIBUTE_COUNT); \
216 ATTRIBUTE_COUNT = 0; \
218 if (method_pass && !method_synthetic) \
220 if (out) \
221 print_method_info (out, jcf, NAME, SIGNATURE, \
222 ACCESS_FLAGS); \
224 else if (!method_synthetic) \
226 print_method_info (NULL, jcf, NAME, SIGNATURE, \
227 ACCESS_FLAGS); \
228 if (! stubs && ! flag_jni) \
229 add_class_decl (out, jcf, SIGNATURE); \
233 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
234 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
236 static int decompiled = 0;
237 #define HANDLE_END_METHOD() \
238 if (out && method_printed && !method_synthetic) \
239 fputs (decompiled || stubs ? "\n" : ";\n", out);
241 /* We're going to need {peek,skip}_attribute, enable their definition. */
242 #define NEED_PEEK_ATTRIBUTE
243 #define NEED_SKIP_ATTRIBUTE
245 #include "jcf-reader.c"
247 /* Some useful constants. */
248 #define F_NAN_MASK 0x7f800000
249 #if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN)
250 #define D_NAN_MASK 0x000000007ff00000LL
251 #else
252 #define D_NAN_MASK 0x7ff0000000000000LL
253 #endif
255 /* Return 1 if F is not Inf or NaN. */
256 static int
257 java_float_finite (jfloat f)
259 union Word u;
260 u.f = f;
262 /* We happen to know that F_NAN_MASK will match all NaN values, and
263 also positive and negative infinity. That's why we only need one
264 test here. See The Java Language Specification, section 20.9. */
265 return (u.i & F_NAN_MASK) != F_NAN_MASK;
268 /* Return 1 if D is not Inf or NaN. */
269 static int
270 java_double_finite (jdouble d)
272 union DWord u;
273 u.d = d;
275 /* Now check for all NaNs. */
276 return (u.l & D_NAN_MASK) != D_NAN_MASK;
279 /* Print a character, appropriately mangled for JNI. */
281 static void
282 jni_print_char (FILE *stream, int ch)
284 if (! flag_jni)
285 jcf_print_char (stream, ch);
286 else if (ch == '(' || ch == ')')
288 /* Ignore. */
290 else if (ch == '_')
291 fputs ("_1", stream);
292 else if (ch == ';')
293 fputs ("_2", stream);
294 else if (ch == '[')
295 fputs ("_3", stream);
296 else if (ch == '/')
297 fputs ("_", stream);
298 else if (ISALNUM (ch))
299 fputc (ch, stream);
300 else
302 /* "Unicode" character. */
303 fprintf (stream, "_0%04x", ch);
307 /* Print a name from the class data. If the index does not point to a
308 string, an error results. */
310 static void
311 print_name (FILE* stream, JCF* jcf, int name_index)
313 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
315 fprintf (stream, "<not a UTF8 constant>");
316 found_error = 1;
318 else if (! flag_jni)
319 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
320 JPOOL_UTF_LENGTH (jcf, name_index));
321 else
323 /* For JNI we must correctly quote each character. */
324 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
325 int length = JPOOL_UTF_LENGTH (jcf, name_index);
326 const unsigned char *limit = str + length;
327 while (str < limit)
329 int ch = UTF8_GET (str, limit);
330 if (ch < 0)
332 fprintf (stream, "\\<invalid>");
333 return;
335 jni_print_char (stream, ch);
340 /* Print base name of class. The base name is everything after the
341 final separator. */
343 static void
344 print_base_classname (FILE *stream, JCF *jcf, int index)
346 int name_index = JPOOL_USHORT1 (jcf, index);
347 int len;
348 const unsigned char *s, *p, *limit;
350 s = JPOOL_UTF_DATA (jcf, name_index);
351 len = JPOOL_UTF_LENGTH (jcf, name_index);
352 limit = s + len;
353 p = s;
354 while (s < limit)
356 int c = UTF8_GET (s, limit);
357 if (c == '/')
358 p = s;
361 while (p < limit)
363 int ch = UTF8_GET (p, limit);
364 if (ch == '/')
365 fputs ("::", stream);
366 else
367 jcf_print_char (stream, ch);
371 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
372 and 1 if STR is "greater" than NAME. */
374 static int
375 utf8_cmp (const unsigned char *str, int length, const char *name)
377 const unsigned char *limit = str + length;
378 int i;
380 for (i = 0; name[i]; ++i)
382 int ch = UTF8_GET (str, limit);
383 if (ch != name[i])
384 return ch - name[i];
387 return str == limit ? 0 : 1;
390 /* This is a sorted list of all C++ keywords. */
392 static const char *const cxx_keywords[] =
394 "_Complex",
395 "__alignof",
396 "__alignof__",
397 "__asm",
398 "__asm__",
399 "__attribute",
400 "__attribute__",
401 "__builtin_va_arg",
402 "__complex",
403 "__complex__",
404 "__const",
405 "__const__",
406 "__extension__",
407 "__imag",
408 "__imag__",
409 "__inline",
410 "__inline__",
411 "__label__",
412 "__null",
413 "__real",
414 "__real__",
415 "__restrict",
416 "__restrict__",
417 "__signed",
418 "__signed__",
419 "__typeof",
420 "__typeof__",
421 "__volatile",
422 "__volatile__",
423 "and",
424 "and_eq",
425 "asm",
426 "auto",
427 "bitand",
428 "bitor",
429 "bool",
430 "break",
431 "case",
432 "catch",
433 "char",
434 "class",
435 "compl",
436 "const",
437 "const_cast",
438 "continue",
439 "default",
440 "delete",
441 "do",
442 "double",
443 "dynamic_cast",
444 "else",
445 "enum",
446 "explicit",
447 "export",
448 "extern",
449 "false",
450 "float",
451 "for",
452 "friend",
453 "goto",
454 "if",
455 "inline",
456 "int",
457 "long",
458 "mutable",
459 "namespace",
460 "new",
461 "not",
462 "not_eq",
463 "operator",
464 "or",
465 "or_eq",
466 "private",
467 "protected",
468 "public",
469 "register",
470 "reinterpret_cast",
471 "return",
472 "short",
473 "signed",
474 "sizeof",
475 "static",
476 "static_cast",
477 "struct",
478 "switch",
479 "template",
480 "this",
481 "throw",
482 "true",
483 "try",
484 "typedef",
485 "typeid",
486 "typename",
487 "typeof",
488 "union",
489 "unsigned",
490 "using",
491 "virtual",
492 "void",
493 "volatile",
494 "wchar_t",
495 "while",
496 "xor",
497 "xor_eq"
501 /* If NAME is the name of a C++ keyword, then return an override name.
502 This is a name that can be used in place of the keyword.
503 Otherwise, return NULL. The return value is malloc()d. */
505 static char *
506 cxx_keyword_subst (const unsigned char *str, int length)
508 int last = ARRAY_SIZE (cxx_keywords);
509 int first = 0;
510 int mid = (last + first) / 2;
511 int old = -1;
513 for (mid = (last + first) / 2;
514 mid != old;
515 old = mid, mid = (last + first) / 2)
517 int kwl = strlen (cxx_keywords[mid]);
518 int min_length = kwl > length ? length : kwl;
519 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
521 if (r == 0)
523 int i;
525 /* Skip all trailing `$'. */
526 for (i = min_length; i < length && str[i] == '$'; ++i)
528 /* We've only found a match if all the remaining characters
529 are `$'. */
530 if (i == length)
532 char *dup = xmalloc (2 + length - min_length + kwl);
533 strcpy (dup, cxx_keywords[mid]);
534 for (i = kwl; i < length + 1; ++i)
535 dup[i] = '$';
536 dup[i] = '\0';
537 return dup;
539 r = 1;
542 if (r < 0)
543 last = mid;
544 else
545 first = mid;
547 return NULL;
550 /* Generate an access control keyword based on FLAGS. */
552 static void
553 generate_access (FILE *stream, JCF_u2 flags)
555 if ((flags & ACC_VISIBILITY) == last_access)
556 return;
557 last_access = (flags & ACC_VISIBILITY);
559 switch (last_access)
561 case 0:
562 fputs ("public: // actually package-private\n", stream);
563 break;
564 case ACC_PUBLIC:
565 fputs ("public:\n", stream);
566 break;
567 case ACC_PRIVATE:
568 fputs ("private:\n", stream);
569 break;
570 case ACC_PROTECTED:
571 fputs ("public: // actually protected\n", stream);
572 break;
573 default:
574 found_error = 1;
575 fprintf (stream, "#error unrecognized visibility %d\n",
576 (flags & ACC_VISIBILITY));
577 break;
581 /* See if NAME is already the name of a method. */
582 static int
583 name_is_method_p (const unsigned char *name, int length)
585 struct method_name *p;
587 for (p = method_name_list; p != NULL; p = p->next)
589 if (p->length == length && ! memcmp (p->name, name, length))
590 return 1;
592 return 0;
595 /* If there is already a method named NAME, whose signature is not
596 SIGNATURE, then return true. Otherwise return false. */
597 static int
598 overloaded_jni_method_exists_p (const unsigned char *name, int length,
599 const char *signature, int sig_length)
601 struct method_name *p;
603 for (p = method_name_list; p != NULL; p = p->next)
605 if (p->length == length
606 && ! memcmp (p->name, name, length)
607 && (p->sig_length != sig_length
608 || memcmp (p->signature, signature, sig_length)))
609 return 1;
611 return 0;
614 /* Get name of a field. This handles renamings due to C++ clash. */
615 static char *
616 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
618 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
619 int length = JPOOL_UTF_LENGTH (jcf, name_index);
620 char *override;
622 if (name_is_method_p (name, length))
624 /* This field name matches a method. So override the name with
625 a dummy name. This is yucky, but it isn't clear what else to
626 do. FIXME: if the field is static, then we'll be in real
627 trouble. */
628 if ((flags & ACC_STATIC))
630 fprintf (stderr, "static field has same name as method\n");
631 found_error = 1;
632 return NULL;
635 override = xmalloc (length + 3);
636 memcpy (override, name, length);
637 strcpy (override + length, "__");
639 else
640 override = cxx_keyword_subst (name, length);
642 return override;
645 /* Print a field name. Convenience function for use with
646 get_field_name. */
647 static void
648 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
650 char *override = get_field_name (jcf, name_index, flags);
652 if (override)
654 fputs (override, stream);
655 free (override);
657 else
658 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
659 JPOOL_UTF_LENGTH (jcf, name_index));
662 static void
663 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
664 JCF_u2 flags)
666 char *override = NULL;
668 generate_access (stream, flags);
669 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
671 fprintf (stream, "<not a UTF8 constant>");
672 found_error = 1;
673 return;
676 fputs (" ", out);
677 if ((flags & ACC_STATIC))
678 fputs ("static ", out);
680 if ((flags & ACC_FINAL))
682 if (current_field_value > 0)
684 char buffer[25];
685 int done = 1;
687 switch (JPOOL_TAG (jcf, current_field_value))
689 case CONSTANT_Integer:
691 jint num;
692 int most_negative = 0;
693 fputs ("const jint ", out);
694 print_field_name (out, jcf, name_index, 0);
695 fputs (" = ", out);
696 num = JPOOL_INT (jcf, current_field_value);
697 /* We single out the most negative number to print
698 specially. This avoids later warnings from g++. */
699 if (num == (jint) 0x80000000)
701 most_negative = 1;
702 ++num;
704 format_int (buffer, (jlong) num, 10);
705 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
707 break;
708 case CONSTANT_Long:
710 jlong num;
711 int most_negative = 0;
712 fputs ("const jlong ", out);
713 print_field_name (out, jcf, name_index, 0);
714 fputs (" = ", out);
715 num = JPOOL_LONG (jcf, current_field_value);
716 /* We single out the most negative number to print
717 specially.. This avoids later warnings from g++. */
718 if (num == (jlong) 0x8000000000000000LL)
720 most_negative = 1;
721 ++num;
723 format_int (buffer, num, 10);
724 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
726 break;
727 case CONSTANT_Float:
729 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
730 fputs ("const jfloat ", out);
731 print_field_name (out, jcf, name_index, 0);
732 if (! java_float_finite (fnum))
733 fputs (";\n", out);
734 else
735 fprintf (out, " = %.10g;\n", fnum);
737 break;
738 case CONSTANT_Double:
740 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
741 fputs ("const jdouble ", out);
742 print_field_name (out, jcf, name_index, 0);
743 if (! java_double_finite (dnum))
744 fputs (";\n", out);
745 else
746 fprintf (out, " = %.17g;\n", dnum);
748 break;
749 default:
750 /* We can't print this as a constant, but we can still
751 print something sensible. */
752 done = 0;
753 break;
756 if (done)
757 return;
761 override = get_field_name (jcf, name_index, flags);
762 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
763 fputs (";\n", out);
765 if (override)
766 free (override);
770 static void
771 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
772 JCF_u2 flags)
774 const unsigned char *str;
775 int length, is_init = 0;
776 char *override = NULL;
778 method_declared = 0;
779 method_access = flags;
780 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
781 fprintf (stream, "<not a UTF8 constant>");
782 str = JPOOL_UTF_DATA (jcf, name_index);
783 length = JPOOL_UTF_LENGTH (jcf, name_index);
785 if (str[0] == '<')
787 /* Ignore the internally generated method <clinit>. However,
788 treat <init> as a constructor. */
789 if (! utf8_cmp (str, length, "<init>"))
790 is_init = 1;
791 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
792 && ! (flags & ACC_STATIC))
794 /* FIXME: i18n bug here. Order of prints should not be
795 fixed. */
796 fprintf (stderr, "ignored method `");
797 jcf_print_utf8 (stderr, str, length);
798 fprintf (stderr, "' marked virtual\n");
799 found_error = 1;
800 return;
802 else
803 return;
806 /* During the first method pass, build a list of method names. This will
807 be used to determine if field names conflict with method names. */
808 if (! stream)
810 struct method_name *nn;
812 nn = xmalloc (sizeof (struct method_name));
813 nn->name = xmalloc (length);
814 memcpy (nn->name, str, length);
815 nn->length = length;
816 nn->next = method_name_list;
817 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
818 nn->signature = xmalloc (nn->sig_length);
819 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
820 nn->sig_length);
821 method_name_list = nn;
823 /* The rest of this function doesn't matter. */
824 return;
827 /* We don't worry about overrides in JNI mode. */
828 if (! flag_jni)
830 /* We can't generate a method whose name is a C++ reserved word.
831 We can't just ignore the function, because that will cause
832 incorrect code to be generated if the function is virtual
833 (not only for calls to this function for for other functions
834 after it in the vtbl). So we give it a dummy name instead. */
835 override = cxx_keyword_subst (str, length);
838 if (! stubs && ! flag_jni)
840 method_printed = 1;
842 generate_access (stream, flags);
844 fputs (" ", out);
845 if ((flags & ACC_STATIC))
846 fputs ("static ", out);
847 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
849 /* Don't print `virtual' if we have a constructor. */
850 if (! is_init)
851 fputs ("virtual ", out);
853 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
855 if ((flags & ACC_ABSTRACT))
856 fputs (" = 0", out);
857 else
858 method_declared = 1;
860 else
862 if (METHOD_IS_NATIVE (flags))
864 method_printed = 1;
865 print_stub_or_jni (out, jcf, name_index, sig_index,
866 is_init, override, flags);
870 if (override)
871 free (override);
874 /* A helper for the decompiler which prints a `return' statement where
875 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
876 identical, we emit a cast. We do this because the C++ compiler
877 doesn't know that a reference can be cast to the type of an
878 interface it implements. METHODTYPE is the index of the method's
879 signature. NAMEINDEX is the index of the field name; -1 for
880 `this'. OBJECTTYPE is the index of the object's type. */
881 static void
882 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
883 int nameindex, int objecttype)
885 int cast = 0;
886 int obj_name_len, method_name_len;
887 const unsigned char *obj_data, *method_data;
889 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
890 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
892 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
893 method_data = JPOOL_UTF_DATA (jcf, methodtype);
895 /* Skip forward to return type part of method. */
896 while (*method_data != ')')
898 ++method_data;
899 --method_name_len;
901 /* Skip past `)'. */
902 ++method_data;
903 --method_name_len;
905 /* If we see an `L', skip it and the trailing `;'. */
906 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
908 ++method_data;
909 method_name_len -= 2;
911 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
913 ++obj_data;
914 obj_name_len -= 2;
917 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
918 need a cast. Right now there is no way to determine if this is
919 the case. */
920 if (method_name_len != obj_name_len)
921 cast = 1;
922 else
924 int i;
925 for (i = 0; i < method_name_len; ++i)
927 if (method_data[i] != obj_data[i])
929 cast = 1;
930 break;
935 fputs (" { return ", out);
937 if (cast)
939 int array_depth = 0;
940 const unsigned char *limit;
942 fputs ("reinterpret_cast<", out);
944 while (*method_data == '[')
946 ++method_data;
947 ++array_depth;
948 --method_name_len;
949 fputs ("JArray<", out);
952 /* Leading space to avoid C++ digraphs. */
953 fputs (" ::", out);
955 /* If we see an `L', skip it and the trailing `;'. Only do this
956 if we've seen an array specification. If we don't have an
957 array then the `L' was stripped earlier. */
958 if (array_depth && method_data[0] == 'L'
959 && method_data[method_name_len - 1] == ';')
961 ++method_data;
962 method_name_len -= 2;
965 limit = method_data + method_name_len;
966 while (method_data < limit)
968 int ch = UTF8_GET (method_data, limit);
969 if (ch == '/')
970 fputs ("::", out);
971 else
972 jcf_print_char (out, ch);
974 fputs (" *", out);
976 /* Close each array. */
977 while (array_depth > 0)
979 fputs ("> *", out);
980 --array_depth;
983 /* Close the cast. */
984 fputs ("> (", out);
987 if (nameindex == -1)
988 fputs ("this", out);
989 else
990 print_field_name (out, jcf, nameindex, 0);
992 if (cast)
993 fputs (")", out);
995 fputs ("; }", out);
999 /* Try to decompile a method body. Right now we just try to handle a
1000 simple case that we can do. Expand as desired. */
1001 static void
1002 decompile_method (FILE *out, JCF *jcf, int code_len)
1004 const unsigned char *codes = jcf->read_ptr;
1005 int index;
1006 uint16 name_and_type, name;
1008 /* If the method is synchronized, don't touch it. */
1009 if ((method_access & ACC_SYNCHRONIZED))
1010 return;
1012 if (code_len == 5
1013 && codes[0] == OPCODE_aload_0
1014 && codes[1] == OPCODE_getfield
1015 && (codes[4] == OPCODE_areturn
1016 || codes[4] == OPCODE_dreturn
1017 || codes[4] == OPCODE_freturn
1018 || codes[4] == OPCODE_ireturn
1019 || codes[4] == OPCODE_lreturn))
1021 /* Found code like `return FIELD'. */
1022 index = (codes[2] << 8) | codes[3];
1023 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1024 name_and_type = JPOOL_USHORT2 (jcf, index);
1025 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1026 name = JPOOL_USHORT1 (jcf, name_and_type);
1027 if (codes[4] == OPCODE_areturn)
1028 decompile_return_statement (out, jcf, method_signature,
1029 name, JPOOL_USHORT2 (jcf, name_and_type));
1030 else
1032 fputs (" { return ", out);
1033 /* FIXME: flags. */
1034 print_field_name (out, jcf, name, 0);
1035 fputs ("; }", out);
1037 decompiled = 1;
1039 else if (code_len == 2
1040 && codes[0] == OPCODE_aload_0
1041 && codes[1] == OPCODE_areturn
1042 /* We're going to generate `return this'. This only makes
1043 sense for non-static methods. */
1044 && ! (method_access & ACC_STATIC))
1046 decompile_return_statement (out, jcf, method_signature, -1,
1047 JPOOL_USHORT1 (jcf, jcf->this_class));
1048 decompiled = 1;
1050 else if (code_len == 1 && codes[0] == OPCODE_return)
1052 /* Found plain `return'. */
1053 fputs (" { }", out);
1054 decompiled = 1;
1056 else if (code_len == 2
1057 && codes[0] == OPCODE_aconst_null
1058 && codes[1] == OPCODE_areturn)
1060 /* Found `return null'. We don't want to depend on NULL being
1061 defined. */
1062 fputs (" { return 0; }", out);
1063 decompiled = 1;
1067 /* Like strcmp, but invert the return result for the hash table. This
1068 should probably be in hashtab.c to complement the existing string
1069 hash function. */
1070 static int
1071 gcjh_streq (const void *p1, const void *p2)
1073 return ! strcmp ((char *) p1, (char *) p2);
1076 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1077 or 0 if not. CLNAME may be extracted from a signature, and can be
1078 terminated with either `;' or NULL. */
1079 static int
1080 throwable_p (const unsigned char *clname)
1082 int length;
1083 unsigned char *current;
1084 int i;
1085 int result = 0;
1087 /* We keep two hash tables of class names. In one we list all the
1088 classes which are subclasses of Throwable. In the other we will
1089 all other classes. We keep two tables to make the code a bit
1090 simpler; we don't have to have a structure mapping class name to
1091 a `throwable?' bit. */
1092 static htab_t throw_hash;
1093 static htab_t non_throw_hash;
1094 static int init_done = 0;
1096 if (! init_done)
1098 void **slot;
1099 unsigned char *str;
1101 /* Self-initializing. The cost of this really doesn't matter.
1102 We also don't care about freeing these, either. */
1103 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1104 (htab_del) free);
1105 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1106 (htab_del) free);
1108 /* Make sure the root classes show up in the tables. */
1109 str = xstrdup ("java.lang.Throwable");
1110 slot = htab_find_slot (throw_hash, str, INSERT);
1111 *slot = str;
1113 str = xstrdup ("java.lang.Object");
1114 slot = htab_find_slot (non_throw_hash, str, INSERT);
1115 *slot = str;
1117 init_done = 1;
1120 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1122 current = ALLOC (length);
1123 for (i = 0; i < length; ++i)
1124 current[i] = clname[i] == '/' ? '.' : clname[i];
1125 current[length] = '\0';
1127 /* We don't compute the hash slot here because the table might be
1128 modified by the recursion. In that case the slot could be
1129 invalidated. */
1130 if (htab_find (throw_hash, current))
1131 result = 1;
1132 else if (htab_find (non_throw_hash, current))
1133 result = 0;
1134 else
1136 JCF jcf;
1137 void **slot;
1138 unsigned char *super, *tmp;
1139 int super_length = -1;
1140 const char *classfile_name = find_class (current, strlen (current),
1141 &jcf, 0);
1143 if (! classfile_name)
1145 fprintf (stderr, "couldn't find class %s\n", current);
1146 found_error = 1;
1147 return 0;
1149 if (jcf_parse_preamble (&jcf) != 0
1150 || jcf_parse_constant_pool (&jcf) != 0
1151 || verify_constant_pool (&jcf) > 0)
1153 fprintf (stderr, "parse error while reading %s\n", classfile_name);
1154 found_error = 1;
1155 return 0;
1157 jcf_parse_class (&jcf);
1159 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1160 super = ALLOC (super_length + 1);
1161 memcpy (super, tmp, super_length);
1162 super[super_length] = '\0';
1164 result = throwable_p (super);
1165 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1166 current, INSERT);
1167 *slot = current;
1168 current = NULL;
1170 JCF_FINISH (&jcf);
1173 return result;
1176 /* Print one piece of a signature. Returns pointer to next parseable
1177 character on success, NULL on error. */
1178 static const unsigned char *
1179 decode_signature_piece (FILE *stream, const unsigned char *signature,
1180 const unsigned char *limit, int *need_space)
1182 const char *ctype;
1183 int array_depth = 0;
1185 switch (signature[0])
1187 case '[':
1188 /* More spaghetti. */
1190 array_loop:
1191 for (signature++; (signature < limit
1192 && ISDIGIT (*signature)); signature++)
1194 switch (*signature)
1196 case 'B':
1197 ctype = "jbyteArray";
1198 break;
1199 case 'C':
1200 ctype = "jcharArray";
1201 break;
1202 case 'D':
1203 ctype = "jdoubleArray";
1204 break;
1205 case 'F':
1206 ctype = "jfloatArray";
1207 break;
1208 case 'I':
1209 ctype = "jintArray";
1210 break;
1211 case 'S':
1212 ctype = "jshortArray";
1213 break;
1214 case 'J':
1215 ctype = "jlongArray";
1216 break;
1217 case 'Z':
1218 ctype = "jbooleanArray";
1219 break;
1220 case '[':
1221 /* We have a nested array. */
1222 ++array_depth;
1223 if (! flag_jni)
1224 fputs ("JArray<", stream);
1225 goto array_loop;
1227 case 'L':
1228 /* We have to generate a reference to JArray here, so that
1229 our output matches what the compiler does. */
1230 ++signature;
1231 /* Space between `<' and `:' to avoid C++ digraphs. */
1232 if (! flag_jni)
1233 fputs ("JArray< ::", stream);
1234 while (signature < limit && *signature != ';')
1236 int ch = UTF8_GET (signature, limit);
1237 if (! flag_jni)
1239 if (ch == '/')
1240 fputs ("::", stream);
1241 else
1242 jcf_print_char (stream, ch);
1245 if (! flag_jni)
1246 fputs (" *> *", stream);
1247 *need_space = 0;
1248 ctype = NULL;
1249 break;
1250 default:
1251 /* Unparseable signature. */
1252 return NULL;
1255 /* If the previous iterations left us with something to print,
1256 print it. For JNI, we always print `jobjectArray' in the
1257 nested cases. */
1258 if (flag_jni && (ctype == NULL || array_depth > 0))
1260 ctype = "jobjectArray";
1261 *need_space = 1;
1263 /* The `printit' case will advance SIGNATURE for us. If we
1264 don't go there, we must advance past the `;' ourselves. */
1265 if (ctype != NULL)
1266 goto printit;
1267 ++signature;
1268 break;
1270 case '(':
1271 case ')':
1272 /* This shouldn't happen. */
1273 return NULL;
1275 case 'B': ctype = "jbyte"; goto printit;
1276 case 'C': ctype = "jchar"; goto printit;
1277 case 'D': ctype = "jdouble"; goto printit;
1278 case 'F': ctype = "jfloat"; goto printit;
1279 case 'I': ctype = "jint"; goto printit;
1280 case 'J': ctype = "jlong"; goto printit;
1281 case 'S': ctype = "jshort"; goto printit;
1282 case 'Z': ctype = "jboolean"; goto printit;
1283 case 'V': ctype = "void"; goto printit;
1284 case 'L':
1285 if (flag_jni)
1287 /* We know about certain types and special-case their names. */
1288 if (! strncmp (signature, "Ljava/lang/String;",
1289 sizeof ("Ljava/lang/String;") -1))
1290 ctype = "jstring";
1291 else if (! strncmp (signature, "Ljava/lang/Class;",
1292 sizeof ("Ljava/lang/Class;") - 1))
1293 ctype = "jclass";
1294 /* Skip leading 'L' for throwable_p call. */
1295 else if (throwable_p (signature + 1))
1296 ctype = "jthrowable";
1297 else
1298 ctype = "jobject";
1300 while (*signature && *signature != ';')
1301 ++signature;
1303 goto printit;
1305 /* Print a leading "::" so we look in the right namespace. */
1306 fputs ("::", stream);
1307 ++signature;
1308 while (*signature && *signature != ';')
1310 int ch = UTF8_GET (signature, limit);
1311 if (ch == '/')
1312 fputs ("::", stream);
1313 else
1314 jcf_print_char (stream, ch);
1316 fputs (" *", stream);
1317 if (*signature == ';')
1318 signature++;
1319 *need_space = 0;
1320 break;
1321 default:
1322 *need_space = 1;
1323 jni_print_char (stream, *signature++);
1324 break;
1325 printit:
1326 signature++;
1327 *need_space = 1;
1328 fputs (ctype, stream);
1329 break;
1332 if (! flag_jni)
1334 while (array_depth-- > 0)
1335 fputs ("> *", stream);
1338 return signature;
1341 static void
1342 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1343 int is_init, const char *name_override, int flags)
1345 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1347 fprintf (stream, "<not a UTF8 constant>");
1348 found_error = 1;
1350 else
1352 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1353 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1354 register const unsigned char *str = str0;
1355 const unsigned char *limit = str + length;
1356 int need_space = 0;
1357 int is_method = str[0] == '(';
1358 const unsigned char *next;
1360 /* If printing a method, skip to the return signature and print
1361 that first. However, there is no return value if this is a
1362 constructor. */
1363 if (is_method && ! is_init)
1365 while (str < limit)
1367 int ch = *str++;
1368 if (ch == ')')
1369 break;
1373 /* If printing a field or an ordinary method, then print the
1374 "return value" now. */
1375 if (! is_method || ! is_init)
1377 next = decode_signature_piece (stream, str, limit, &need_space);
1378 if (! next)
1380 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1381 found_error = 1;
1382 return;
1386 /* Now print the name of the thing. */
1387 if (need_space)
1388 fputs (" ", stream);
1389 print_full_cxx_name (stream, jcf, name_index,
1390 signature_index, is_init, name_override,
1391 flags);
1395 /* Print the unqualified method name followed by the signature. */
1396 static void
1397 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1398 int signature_index, int is_init,
1399 const char *name_override, int flags)
1401 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1402 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1403 register const unsigned char *str = str0;
1404 const unsigned char *limit = str + length;
1405 int need_space = 0;
1406 int is_method = str[0] == '(';
1407 const unsigned char *next;
1409 if (name_override)
1410 fputs (name_override, stream);
1411 else if (name_index)
1413 /* Declare constructors specially. */
1414 if (is_init)
1415 print_base_classname (stream, jcf, jcf->this_class);
1416 else
1417 print_name (stream, jcf, name_index);
1420 if (flag_jni)
1422 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1423 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1424 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1425 JPOOL_UTF_LENGTH (jcf, name_index),
1426 signature, sig_len))
1428 /* If this method is overloaded by another native method,
1429 then include the argument information in the mangled
1430 name. */
1431 unsigned char *limit = signature + sig_len;
1432 fputs ("__", stream);
1433 while (signature < limit)
1435 int ch = UTF8_GET (signature, limit);
1436 jni_print_char (stream, ch);
1437 if (ch == ')')
1439 /* Done. */
1440 break;
1446 if (is_method)
1448 /* Have a method or a constructor. Print signature pieces
1449 until done. */
1450 fputs (" (", stream);
1452 str = str0 + 1;
1454 /* In JNI mode, add extra arguments. */
1455 if (flag_jni)
1457 /* FIXME: it would be nice to know if we are printing a decl
1458 or a definition, and only print `env' for the latter. */
1459 fputs ("JNIEnv *env", stream);
1461 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1463 if (*str != ')')
1464 fputs (", ", stream);
1467 while (str < limit && *str != ')')
1469 next = decode_signature_piece (stream, str, limit, &need_space);
1470 if (! next)
1472 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1473 found_error = 1;
1474 return;
1477 if (next < limit && *next != ')')
1478 fputs (", ", stream);
1479 str = next;
1482 fputs (")", stream);
1486 /* This is a helper for print_stub_or_jni. */
1487 static void
1488 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1489 int signature_index, int is_init,
1490 const char *name_override, int flags)
1492 const char *const prefix = flag_jni ? "Java_" : "";
1493 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1494 fputs (flag_jni ? "_" : "::", stream);
1495 print_full_cxx_name (stream, jcf, name_index,
1496 signature_index, is_init, name_override,
1497 flags);
1500 static void
1501 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1502 int signature_index, int is_init,
1503 const char *name_override, int flags)
1505 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1507 fprintf (stream, "<not a UTF8 constant>");
1508 found_error = 1;
1510 else
1512 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1513 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1514 register const unsigned char *str = str0;
1515 const unsigned char *limit = str + length;
1516 int need_space = 0;
1517 int is_method = str[0] == '(';
1518 const unsigned char *next;
1520 /* Don't print fields in the JNI case. */
1521 if (! is_method && flag_jni)
1522 return;
1524 if (flag_jni && ! stubs)
1525 fputs ("extern JNIEXPORT ", stream);
1527 /* If printing a method, skip to the return signature and print
1528 that first. However, there is no return value if this is a
1529 constructor. */
1530 if (is_method && ! is_init)
1532 while (str < limit)
1534 int ch = *str++;
1535 if (ch == ')')
1536 break;
1540 /* If printing a field or an ordinary method, then print the
1541 "return value" now. Note that a constructor can't be native,
1542 so we don't bother checking this in the JNI case. */
1543 if (! is_method || ! is_init)
1545 next = decode_signature_piece (stream, str, limit, &need_space);
1546 if (! next)
1548 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1549 found_error = 1;
1550 return;
1554 /* When printing a JNI header we need to respect the space. In
1555 other cases we're just going to insert a newline anyway. */
1556 fputs (need_space && ! stubs ? " " : "\n", stream);
1558 if (flag_jni && ! stubs)
1559 fputs ("JNICALL ", stream);
1561 /* Now print the name of the thing. */
1562 print_name_for_stub_or_jni (stream, jcf, name_index,
1563 signature_index, is_init, name_override,
1564 flags);
1566 /* Print the body. */
1567 if (stubs)
1569 if (flag_jni)
1570 fputs ("\n{\n (*env)->FatalError (\"", stream);
1571 else
1572 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1573 print_name_for_stub_or_jni (stream, jcf, name_index,
1574 signature_index, is_init,
1575 name_override,
1576 flags);
1577 fprintf (stream, " not implemented\")%s;\n}\n\n",
1578 flag_jni ? "" : ")");
1583 static void
1584 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1586 int name_index = JPOOL_USHORT1 (jcf, index);
1587 fputs (prefix, stream);
1588 jcf_print_utf8_replace (out,
1589 JPOOL_UTF_DATA (jcf, name_index),
1590 JPOOL_UTF_LENGTH (jcf, name_index),
1591 '/', '_');
1594 /* Print PREFIX, then a class name in C++ format. If the name refers
1595 to an array, ignore it and don't print PREFIX. Returns 1 if
1596 something was printed, 0 otherwise. */
1597 static int
1598 print_cxx_classname (FILE *stream, const char *prefix,
1599 JCF *jcf, int index, int add_scope)
1601 int name_index = JPOOL_USHORT1 (jcf, index);
1602 int len, c;
1603 const unsigned char *s, *p, *limit;
1605 s = JPOOL_UTF_DATA (jcf, name_index);
1606 len = JPOOL_UTF_LENGTH (jcf, name_index);
1607 limit = s + len;
1609 /* Explicitly omit arrays here. */
1610 p = s;
1611 c = UTF8_GET (p, limit);
1612 if (c == '[')
1613 return 0;
1615 fputs (prefix, stream);
1617 /* Print a leading "::" so we look in the right namespace. */
1618 if (! flag_jni && ! stubs && add_scope)
1619 fputs ("::", stream);
1621 while (s < limit)
1623 c = UTF8_GET (s, limit);
1624 if (c == '/')
1625 fputs (flag_jni ? "_" : "::", stream);
1626 else
1627 jni_print_char (stream, c);
1630 return 1;
1633 int written_class_count = 0;
1635 /* Return name of superclass. If LEN is not NULL, fill it with length
1636 of name. */
1637 static const unsigned char *
1638 super_class_name (JCF *derived_jcf, int *len)
1640 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1641 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1642 const unsigned char *supername =
1643 JPOOL_UTF_DATA (derived_jcf, supername_index);
1645 if (len)
1646 *len = supername_length;
1648 return supername;
1653 /* We keep track of all the `#include's we generate, so we can avoid
1654 duplicates. */
1655 struct include
1657 char *name;
1658 struct include *next;
1661 /* List of all includes. */
1662 static struct include *all_includes = NULL;
1664 /* Generate a #include. */
1665 static void
1666 print_include (FILE *out, const unsigned char *utf8, int len)
1668 struct include *incl;
1670 if (! out)
1671 return;
1673 if (len == -1)
1674 len = strlen (utf8);
1676 for (incl = all_includes; incl; incl = incl->next)
1678 /* We check the length because we might have a proper prefix. */
1679 if (len == (int) strlen (incl->name)
1680 && ! strncmp (incl->name, utf8, len))
1681 return;
1684 incl = xmalloc (sizeof (struct include));
1685 incl->name = xmalloc (len + 1);
1686 strncpy (incl->name, utf8, len);
1687 incl->name[len] = '\0';
1688 incl->next = all_includes;
1689 all_includes = incl;
1691 fputs ("#include <", out);
1692 jcf_print_utf8_replace (out, utf8, len,
1693 '/',
1694 flag_jni ? '_' : '/');
1695 fputs (".h>\n", out);
1700 /* This is used to represent part of a package or class name. */
1701 struct namelet
1703 /* The text of this part of the name. */
1704 char *name;
1705 /* True if this represents a class. */
1706 int is_class;
1707 /* Linked list of all classes and packages inside this one. */
1708 struct namelet *subnamelets;
1709 /* Pointer to next sibling. */
1710 struct namelet *next;
1713 static void add_namelet (const unsigned char *, const unsigned char *,
1714 struct namelet *);
1715 static void print_namelet (FILE *, struct namelet *, int);
1717 /* The special root namelet. */
1718 static struct namelet root =
1720 NULL,
1722 NULL,
1723 NULL
1726 /* This extracts the next name segment from the full UTF-8 encoded
1727 package or class name and links it into the tree. It does this
1728 recursively. */
1729 static void
1730 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1731 struct namelet *parent)
1733 const unsigned char *p;
1734 struct namelet *n = NULL, *np;
1736 /* We want to skip the standard namespaces that we assume the
1737 runtime already knows about. We only do this at the top level,
1738 though, hence the check for `root'. */
1739 if (parent == &root)
1741 #define JAVALANG "java/lang/"
1742 #define JAVAIO "java/io/"
1743 #define JAVAUTIL "java/util/"
1744 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1745 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1746 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1747 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1748 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1749 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1750 return;
1753 for (p = name; p < name_limit && *p != '/'; ++p)
1756 /* Search for this name beneath the PARENT node. */
1757 for (np = parent->subnamelets; np != NULL; np = np->next)
1759 /* We check the length because we might have a proper prefix. */
1760 if ((int) strlen (np->name) == p - name &&
1761 ! strncmp (name, np->name, p - name))
1763 n = np;
1764 break;
1768 if (n == NULL)
1770 n = xmalloc (sizeof (struct namelet));
1771 n->name = xmalloc (p - name + 1);
1772 strncpy (n->name, name, p - name);
1773 n->name[p - name] = '\0';
1774 n->is_class = (p == name_limit);
1775 n->subnamelets = NULL;
1776 n->next = parent->subnamelets;
1777 parent->subnamelets = n;
1780 /* We recurse if there is more text, and if the trailing piece does
1781 not represent an inner class. */
1782 if (p < name_limit)
1783 add_namelet (p + 1, name_limit, n);
1786 /* Print a single namelet. Destroys namelets while printing. */
1787 static void
1788 print_namelet (FILE *out, struct namelet *name, int depth)
1790 int i, term = 0;
1791 struct namelet *c;
1793 if (name->name)
1795 for (i = 0; i < depth; ++i)
1796 fputc (' ', out);
1797 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1798 name->name);
1799 if (name->is_class && name->subnamelets == NULL)
1800 fputs (";\n", out);
1801 else
1803 term = 1;
1804 fputs ("\n", out);
1805 for (i = 0; i < depth; ++i)
1806 fputc (' ', out);
1807 fputs ("{\n", out);
1811 c = name->subnamelets;
1812 while (c != NULL)
1814 struct namelet *next = c->next;
1815 print_namelet (out, c, depth + 2);
1816 c = next;
1818 name->subnamelets = NULL;
1820 if (name->name)
1822 if (term)
1824 for (i = 0; i < depth; ++i)
1825 fputc (' ', out);
1826 fputs ("}\n", out);
1827 /* Only print a `;' when printing a class. C++ is evil. */
1828 if (name->is_class)
1829 fputs (";", out);
1832 free (name->name);
1833 free (name);
1837 /* This is called to add some classes to the list of classes for which
1838 we need decls. The signature argument can be a function
1839 signature. */
1840 static void
1841 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1843 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1844 int len = JPOOL_UTF_LENGTH (jcf, signature);
1845 int i;
1847 for (i = 0; i < len; ++i)
1849 int start;
1851 /* If we see an array, then we include the array header. */
1852 if (s[i] == '[')
1854 print_include (out, "gcj/array", -1);
1855 continue;
1858 /* We're looking for `L<stuff>;' -- everything else is
1859 ignorable. */
1860 if (s[i] != 'L')
1861 continue;
1863 for (start = ++i; i < len && s[i] != ';'; ++i)
1866 add_namelet (&s[start], &s[i], &root);
1870 /* Print declarations for all classes required by this class. Any
1871 class or package in the `java' package is assumed to be handled
1872 statically in libjava; we don't generate declarations for these.
1873 This makes the generated headers a bit easier to read. */
1874 static void
1875 print_class_decls (FILE *out, JCF *jcf, int self)
1877 /* Make sure to always add the current class to the list of things
1878 that should be declared. */
1879 int name_index = JPOOL_USHORT1 (jcf, self);
1880 int len;
1881 const unsigned char *s;
1883 s = JPOOL_UTF_DATA (jcf, name_index);
1884 len = JPOOL_UTF_LENGTH (jcf, name_index);
1885 add_namelet (s, s + len, &root);
1887 if (root.subnamelets)
1889 fputs ("extern \"Java\"\n{\n", out);
1890 /* We use an initial offset of 0 because the root namelet
1891 doesn't cause anything to print. */
1892 print_namelet (out, &root, 0);
1893 fputs ("}\n\n", out);
1899 static void
1900 process_file (JCF *jcf, FILE *out)
1902 int code, i;
1903 uint32 field_start, method_end, method_start;
1905 current_jcf = jcf;
1907 last_access = -1;
1909 if (jcf_parse_preamble (jcf) != 0)
1911 fprintf (stderr, "Not a valid Java .class file.\n");
1912 found_error = 1;
1913 return;
1916 /* Parse and possibly print constant pool */
1917 code = jcf_parse_constant_pool (jcf);
1918 if (code != 0)
1920 fprintf (stderr, "error while parsing constant pool\n");
1921 found_error = 1;
1922 return;
1924 code = verify_constant_pool (jcf);
1925 if (code > 0)
1927 fprintf (stderr, "error in constant pool entry #%d\n", code);
1928 found_error = 1;
1929 return;
1932 jcf_parse_class (jcf);
1934 if (written_class_count++ == 0 && out)
1936 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1937 if (flag_jni)
1939 cstart = "/*";
1940 cstart2 = " ";
1941 cend = " */";
1942 mode = "";
1943 what = "JNI";
1944 jflag = " -jni";
1946 else
1948 cstart = "//";
1949 cstart2 = "//";
1950 cend = "";
1951 mode = " -*- c++ -*-";
1952 what = "CNI";
1953 jflag = "";
1956 if (! stubs)
1957 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1958 cstart, mode, cend);
1959 else
1961 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1962 %s\n\
1963 %s This file is intended to give you a head start on implementing native\n\
1964 %s methods using %s.\n\
1965 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1966 %s overwrite any edits you have made to this file.%s\n\n",
1967 cstart, jflag, mode,
1968 cstart2,
1969 cstart2,
1970 cstart2,
1971 what,
1972 cstart2,
1973 jflag,
1974 cstart2,
1975 cend);
1979 if (out)
1981 if (! stubs)
1983 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1984 fprintf (out, "__\n");
1986 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1987 fprintf (out, "__\n\n");
1989 if (flag_jni)
1991 fprintf (out, "#include <jni.h>\n\n");
1992 fprintf (out, "#ifdef __cplusplus\n");
1993 fprintf (out, "extern \"C\"\n");
1994 fprintf (out, "{\n");
1995 fprintf (out, "#endif\n");
1997 else
1999 /* We do this to ensure that inline methods won't be
2000 `outlined' by g++. This works as long as method and
2001 fields are not added by the user. */
2002 fprintf (out, "#pragma interface\n");
2004 if (jcf->super_class)
2006 int super_length;
2007 const unsigned char *supername =
2008 super_class_name (jcf, &super_length);
2010 fputs ("\n", out);
2011 print_include (out, supername, super_length);
2015 else
2017 /* Strip off the ".class" portion of the name when printing
2018 the include file name. */
2019 char *name;
2020 int i, len = strlen (jcf->classname);
2021 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2022 len -= 6;
2023 /* Turn the class name into a file name. */
2024 name = xmalloc (len + 1);
2025 for (i = 0; i < len; ++i)
2026 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2027 name[i] = '\0';
2028 print_include (out, name, len);
2029 free (name);
2031 if (! flag_jni)
2033 print_include (out, "gcj/cni", -1);
2034 print_include (out, "java/lang/UnsupportedOperationException",
2035 -1);
2040 /* We want to parse the methods first. But we need to find where
2041 they start. So first we skip the fields, then parse the methods.
2042 Then we parse the fields and skip the methods. This is ugly, but
2043 not too bad since we need two full passes to get class decl
2044 information anyway. */
2045 field_pass = 0;
2046 field_start = JCF_TELL (jcf);
2047 jcf_parse_fields (jcf);
2049 method_start = JCF_TELL (jcf);
2050 method_pass = 0;
2051 jcf_parse_methods (jcf);
2053 if (out)
2054 fputs ("\n", out);
2056 if (out && ! flag_jni)
2058 if (! stubs)
2059 print_class_decls (out, jcf, jcf->this_class);
2061 for (i = 0; i < prepend_count; ++i)
2062 fprintf (out, "%s\n", prepend_specs[i]);
2063 if (prepend_count > 0)
2064 fputc ('\n', out);
2066 if (! stubs)
2068 if (! print_cxx_classname (out, "class ", jcf,
2069 jcf->this_class, 0))
2071 fprintf (stderr, "class is of array type\n");
2072 found_error = 1;
2073 return;
2075 if (jcf->super_class)
2077 if (! print_cxx_classname (out, " : public ",
2078 jcf, jcf->super_class, 1))
2080 fprintf (stderr, "base class is of array type\n");
2081 found_error = 1;
2082 return;
2086 fputs ("\n{\n", out);
2090 /* Now go back for second pass over methods and fields. */
2091 JCF_SEEK (jcf, method_start);
2092 method_pass = 1;
2093 jcf_parse_methods (jcf);
2094 method_end = JCF_TELL (jcf);
2096 field_pass = 1;
2097 JCF_SEEK (jcf, field_start);
2098 jcf_parse_fields (jcf);
2099 JCF_SEEK (jcf, method_end);
2101 jcf_parse_final_attributes (jcf);
2103 if (out && ! stubs)
2105 if (flag_jni)
2107 fprintf (out, "\n#ifdef __cplusplus\n");
2108 fprintf (out, "}\n");
2109 fprintf (out, "#endif\n");
2111 else
2113 /* Generate friend decl if we still must. */
2114 for (i = 0; i < friend_count; ++i)
2115 fprintf (out, " friend %s\n", friend_specs[i]);
2117 /* Generate extra declarations. */
2118 if (add_count > 0)
2119 fputc ('\n', out);
2120 for (i = 0; i < add_count; ++i)
2121 fprintf (out, " %s\n", add_specs[i]);
2123 /* Generate an entry for the class object. */
2124 generate_access (out, ACC_PUBLIC);
2125 fprintf (out, "\n static ::java::lang::Class class$;\n");
2127 fputs ("}", out);
2129 if (jcf->access_flags & ACC_INTERFACE)
2130 fputs (" __attribute__ ((java_interface))", out);
2132 fputs (";\n", out);
2134 if (append_count > 0)
2135 fputc ('\n', out);
2136 for (i = 0; i < append_count; ++i)
2137 fprintf (out, "%s\n", append_specs[i]);
2140 print_mangled_classname (out, jcf,
2141 "\n#endif /* __", jcf->this_class);
2142 fprintf (out, "__ */\n");
2148 /* This is used to mark options with no short value. */
2149 #define LONG_OPT(Num) ((Num) + 128)
2151 #define OPT_classpath LONG_OPT (0)
2152 #define OPT_CLASSPATH OPT_classpath
2153 #define OPT_bootclasspath LONG_OPT (1)
2154 #define OPT_extdirs LONG_OPT (2)
2155 #define OPT_HELP LONG_OPT (3)
2156 #define OPT_TEMP LONG_OPT (4)
2157 #define OPT_VERSION LONG_OPT (5)
2158 #define OPT_PREPEND LONG_OPT (6)
2159 #define OPT_FRIEND LONG_OPT (7)
2160 #define OPT_ADD LONG_OPT (8)
2161 #define OPT_APPEND LONG_OPT (9)
2162 #define OPT_M LONG_OPT (10)
2163 #define OPT_MM LONG_OPT (11)
2164 #define OPT_MG LONG_OPT (12)
2165 #define OPT_MD LONG_OPT (13)
2166 #define OPT_MMD LONG_OPT (14)
2168 static const struct option options[] =
2170 { "classpath", required_argument, NULL, OPT_classpath },
2171 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2172 { "extdirs", required_argument, NULL, OPT_extdirs },
2173 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2174 { "help", no_argument, NULL, OPT_HELP },
2175 { "stubs", no_argument, &stubs, 1 },
2176 { "td", required_argument, NULL, OPT_TEMP },
2177 { "verbose", no_argument, NULL, 'v' },
2178 { "version", no_argument, NULL, OPT_VERSION },
2179 { "prepend", required_argument, NULL, OPT_PREPEND },
2180 { "friend", required_argument, NULL, OPT_FRIEND },
2181 { "add", required_argument, NULL, OPT_ADD },
2182 { "append", required_argument, NULL, OPT_APPEND },
2183 { "M", no_argument, NULL, OPT_M },
2184 { "MM", no_argument, NULL, OPT_MM },
2185 { "MG", no_argument, NULL, OPT_MG },
2186 { "MD", no_argument, NULL, OPT_MD },
2187 { "MMD", no_argument, NULL, OPT_MMD },
2188 { "jni", no_argument, &flag_jni, 1 },
2189 { NULL, no_argument, NULL, 0 }
2192 static void
2193 usage (void)
2195 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2196 exit (1);
2199 static void
2200 help (void)
2202 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2203 printf ("Generate C++ header files from .class files\n\n");
2204 printf (" -stubs Generate an implementation stub file\n");
2205 printf (" -jni Generate a JNI header or stub\n");
2206 printf ("\n");
2207 printf (" -add TEXT Insert TEXT into class body\n");
2208 printf (" -append TEXT Insert TEXT after class declaration\n");
2209 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2210 printf (" -prepend TEXT Insert TEXT before start of class\n");
2211 printf ("\n");
2212 printf (" --classpath PATH Set path to find .class files\n");
2213 printf (" -IDIR Append directory to class path\n");
2214 printf (" --bootclasspath PATH Override built-in class path\n");
2215 printf (" --extdirs PATH Set extensions directory path\n");
2216 printf (" -d DIRECTORY Set output directory name\n");
2217 printf (" -o FILE Set output file name\n");
2218 printf (" -td DIRECTORY Set temporary directory name\n");
2219 printf ("\n");
2220 printf (" --help Print this help, then exit\n");
2221 printf (" --version Print version number, then exit\n");
2222 printf (" -v, --verbose Print extra information while running\n");
2223 printf ("\n");
2224 printf (" -M Print all dependencies to stdout;\n");
2225 printf (" suppress ordinary output\n");
2226 printf (" -MM Print non-system dependencies to stdout;\n");
2227 printf (" suppress ordinary output\n");
2228 printf (" -MD Print all dependencies to stdout\n");
2229 printf (" -MMD Print non-system dependencies to stdout\n");
2230 /* We omit -MG until it is implemented. */
2231 printf ("\n");
2232 printf ("For bug reporting instructions, please see:\n");
2233 printf ("%s.\n", bug_report_url);
2234 exit (0);
2237 static void
2238 version (void)
2240 printf ("gcjh (GCC) %s\n\n", version_string);
2241 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2242 printf ("This is free software; see the source for copying conditions. There is NO\n");
2243 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2244 exit (0);
2248 main (int argc, char** argv)
2250 JCF jcf;
2251 int argi;
2252 char *output_file = NULL;
2253 int emit_dependencies = 0, suppress_output = 0;
2254 int opt;
2256 if (argc <= 1)
2258 fprintf (stderr, "gcjh: no classes specified\n");
2259 usage ();
2262 jcf_path_init ();
2264 /* We use getopt_long_only to allow single `-' long options. For
2265 some of our options this is more natural. */
2266 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2268 switch (opt)
2270 case 0:
2271 /* Already handled. */
2272 break;
2274 case 'o':
2275 output_file = optarg;
2276 break;
2278 case 'd':
2279 output_directory = optarg;
2280 break;
2282 case 'I':
2283 jcf_path_include_arg (optarg);
2284 break;
2286 case 'v':
2287 verbose++;
2288 break;
2290 case OPT_classpath:
2291 jcf_path_classpath_arg (optarg);
2292 break;
2294 case OPT_bootclasspath:
2295 jcf_path_bootclasspath_arg (optarg);
2296 break;
2298 case OPT_extdirs:
2299 jcf_path_extdirs_arg (optarg);
2300 break;
2302 case OPT_HELP:
2303 help ();
2304 break;
2306 case OPT_TEMP:
2307 temp_directory = optarg;
2308 break;
2310 case OPT_VERSION:
2311 version ();
2312 break;
2314 case OPT_PREPEND:
2315 if (prepend_count == 0)
2316 prepend_specs = ALLOC (argc * sizeof (char*));
2317 prepend_specs[prepend_count++] = optarg;
2318 break;
2320 case OPT_FRIEND:
2321 if (friend_count == 0)
2322 friend_specs = ALLOC (argc * sizeof (char*));
2323 friend_specs[friend_count++] = optarg;
2324 break;
2326 case OPT_ADD:
2327 if (add_count == 0)
2328 add_specs = ALLOC (argc * sizeof (char*));
2329 add_specs[add_count++] = optarg;
2330 break;
2332 case OPT_APPEND:
2333 if (append_count == 0)
2334 append_specs = ALLOC (argc * sizeof (char*));
2335 append_specs[append_count++] = optarg;
2336 break;
2338 case OPT_M:
2339 emit_dependencies = 1;
2340 suppress_output = 1;
2341 jcf_dependency_init (1);
2342 break;
2344 case OPT_MM:
2345 emit_dependencies = 1;
2346 suppress_output = 1;
2347 jcf_dependency_init (0);
2348 break;
2350 case OPT_MG:
2351 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2352 exit (1);
2354 case OPT_MD:
2355 emit_dependencies = 1;
2356 jcf_dependency_init (1);
2357 break;
2359 case OPT_MMD:
2360 emit_dependencies = 1;
2361 jcf_dependency_init (0);
2362 break;
2364 default:
2365 usage ();
2366 break;
2370 if (optind == argc)
2372 fprintf (stderr, "gcjh: no classes specified\n");
2373 usage ();
2376 jcf_path_seal (verbose);
2378 if (output_file && emit_dependencies)
2380 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2381 exit (1);
2384 for (argi = optind; argi < argc; argi++)
2386 char *classname = argv[argi];
2387 char *current_output_file;
2388 const char *classfile_name;
2390 if (verbose)
2391 fprintf (stderr, "Processing %s\n", classname);
2392 if (! output_file)
2393 jcf_dependency_reset ();
2394 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2395 if (classfile_name == NULL)
2397 fprintf (stderr, "%s: no such class\n", classname);
2398 exit (1);
2400 if (verbose)
2401 fprintf (stderr, "Found in %s\n", classfile_name);
2402 if (output_file)
2404 if (strcmp (output_file, "-") == 0)
2405 out = stdout;
2406 else if (out == NULL)
2408 out = fopen (output_file, "w");
2410 if (out == NULL)
2412 perror (output_file);
2413 exit (1);
2415 current_output_file = output_file;
2417 else
2419 int dir_len = strlen (output_directory);
2420 int i, classname_length = strlen (classname);
2421 current_output_file = ALLOC (dir_len + classname_length + 5);
2422 strcpy (current_output_file, output_directory);
2423 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2424 current_output_file[dir_len++] = '/';
2425 for (i = 0; classname[i] != '\0'; i++)
2427 char ch = classname[i];
2428 if (ch == '.')
2429 ch = '/';
2430 if (flag_jni && ch == '/')
2431 ch = '_';
2432 current_output_file[dir_len++] = ch;
2434 if (emit_dependencies)
2436 if (suppress_output)
2438 jcf_dependency_set_dep_file ("-");
2439 out = NULL;
2441 else
2443 /* We use `.hd' and not `.d' to avoid clashes with
2444 dependency tracking from straight compilation. */
2445 strcpy (current_output_file + dir_len, ".hd");
2446 jcf_dependency_set_dep_file (current_output_file);
2449 strcpy (current_output_file + dir_len,
2450 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2451 jcf_dependency_set_target (current_output_file);
2452 if (! suppress_output)
2454 out = fopen (current_output_file, "w");
2455 if (out == NULL)
2457 perror (current_output_file);
2458 exit (1);
2462 process_file (&jcf, out);
2463 JCF_FINISH (&jcf);
2464 if (current_output_file != output_file)
2465 free (current_output_file);
2466 jcf_dependency_write ();
2469 if (out != NULL && out != stdout)
2470 fclose (out);
2472 return found_error;