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, 2004
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)
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. */
32 #include "coretypes.h"
40 #include "java-tree.h"
41 #include "java-opcodes.h"
50 /* The output file. */
53 /* Nonzero on failure. */
54 static int found_error
= 0;
56 /* Nonzero if we're generating JNI output. */
59 /* When nonzero, warn when source file is newer than matching class
63 /* Directory to place resulting files in. Set by -d option. */
64 static const char *output_directory
= "";
66 /* Directory to place temporary file. Set by -td option. Currently unused. */
67 static const char *temp_directory
= "/tmp";
69 /* Number of friend functions we have to declare. */
70 static int friend_count
;
72 /* A class can optionally have a `friend' function declared. If
73 non-NULL, this is that function. */
74 static char **friend_specs
= NULL
;
76 /* Number of lines we are prepending before the class. */
77 static int prepend_count
;
79 /* We can prepend extra lines before the class's start. */
80 static char **prepend_specs
= NULL
;
82 /* Number of lines we are appending at the end of the class. */
85 /* We can append extra lines just before the class's end. */
86 static char **add_specs
= NULL
;
88 /* Number of lines we are appending after the class. */
89 static int append_count
;
91 /* We can append extra lines after the class's end. */
92 static char **append_specs
= NULL
;
98 struct JCF
*current_jcf
;
100 /* This holds access information for the last field we examined. They
101 let us generate "private:", "public:", and "protected:" properly.
102 If 0 then we haven't previously examined any field. */
103 static JCF_u2 last_access
;
105 /* Pass this macro the flags for a class and for a method. It will
106 return true if the method should be considered `final'. */
107 #define METHOD_IS_FINAL(Class, Method) \
108 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
110 /* Pass this macro the flags for a method. It will return true if the
112 #define METHOD_IS_NATIVE(Method) \
113 ((Method) & ACC_NATIVE)
115 #define METHOD_IS_PRIVATE(Class, Method) \
116 (((Method) & ACC_PRIVATE) != 0)
118 /* We keep a linked list of all method names we have seen. This lets
119 us determine if a method name and a field name are in conflict. */
124 unsigned char *signature
;
127 struct method_name
*next
;
130 /* List of method names we've seen. */
131 static struct method_name
*method_name_list
;
133 static void print_field_info (FILE*, JCF
*, int, int, JCF_u2
);
134 static void print_mangled_classname (FILE*, JCF
*, const char*, int);
135 static int print_cxx_classname (FILE*, const char*, JCF
*, int, int);
136 static void print_method_info (FILE*, JCF
*, int, int, JCF_u2
);
137 static void print_c_decl (FILE*, JCF
*, int, int, int, const char *, int);
138 static void print_stub_or_jni (FILE*, JCF
*, int, int, int, const char *, int);
139 static void print_full_cxx_name (FILE*, JCF
*, int, int, int, const char *, int);
140 static void decompile_method (FILE*, JCF
*, int);
141 static void add_class_decl (FILE*, JCF
*, JCF_u2
);
143 static void print_name (FILE *, JCF
*, int);
144 static void print_base_classname (FILE *, JCF
*, int);
145 static int utf8_cmp (const unsigned char *, int, const char *);
146 static char *cxx_keyword_subst (const unsigned char *, int);
147 static void generate_access (FILE *, JCF_u2
);
148 static int name_is_method_p (const unsigned char *, int);
149 static char *get_field_name (JCF
*, int, JCF_u2
);
150 static void print_field_name (FILE *, JCF
*, int, JCF_u2
);
151 static const unsigned char *super_class_name (JCF
*, int *);
152 static void print_include (FILE *, const unsigned char *, int);
153 static int gcjh_streq (const void *p1
, const void *p2
);
154 static int throwable_p (const unsigned char *signature
);
155 static const unsigned char *
156 decode_signature_piece (FILE *, const unsigned char *,
157 const unsigned char *, int *);
158 static void print_class_decls (FILE *, JCF
*, int);
159 static void error (const char *msgid
, ...);
160 static void usage (void) ATTRIBUTE_NORETURN
;
161 static void help (void) ATTRIBUTE_NORETURN
;
162 static void version (void) ATTRIBUTE_NORETURN
;
163 static int overloaded_jni_method_exists_p (const unsigned char *, int,
165 static void jni_print_char (FILE *, int);
166 static void jni_print_float (FILE *, jfloat
);
167 static void jni_print_double (FILE *, jdouble
);
168 static void decompile_return_statement (FILE *, JCF
*, int, int, int);
170 static void handle_inner_classes (int);
172 JCF_u2 current_field_name
;
173 JCF_u2 current_field_value
;
174 JCF_u2 current_field_signature
;
175 JCF_u2 current_field_flags
;
177 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
178 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
179 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
181 /* We pass over fields twice. The first time we just note the types
182 of the fields and then the start of the methods. Then we go back
183 and parse the fields for real. This is ugly. */
184 static int field_pass
;
185 /* Likewise we pass over methods twice. The first time we generate
186 class decl information; the second time we generate actual method
188 static int method_pass
;
190 #define HANDLE_END_FIELD() \
193 if (out && ! stubs) \
194 print_field_info (out, jcf, current_field_name, \
195 current_field_signature, \
196 current_field_flags); \
198 else if (! stubs && ! flag_jni) \
199 add_class_decl (out, jcf, current_field_signature);
201 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
203 static int method_declared
= 0;
204 static int method_access
= 0;
205 static int method_printed
= 0;
206 static int method_synthetic
= 0;
207 static int method_signature
= 0;
209 /* Set to 1 while the very first data member of a class is being handled. */
210 static int is_first_data_member
= 0;
212 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
214 method_synthetic = 0; \
215 method_printed = 0; \
217 method_signature = SIGNATURE; \
218 if (ATTRIBUTE_COUNT) \
219 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
220 (const char *)"Synthetic", 9); \
221 /* If a synthetic methods have been declared, its attribute aren't \
222 worth reading (and triggering side-effects). We skip them an \
223 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
224 jcf_parse_one_method. */ \
225 if (method_synthetic) \
227 skip_attribute (jcf, ATTRIBUTE_COUNT); \
228 ATTRIBUTE_COUNT = 0; \
230 if (method_pass && !method_synthetic) \
233 print_method_info (out, jcf, NAME, SIGNATURE, \
236 else if (!method_synthetic) \
238 print_method_info (NULL, jcf, NAME, SIGNATURE, \
240 if (! stubs && ! flag_jni) \
241 add_class_decl (out, jcf, SIGNATURE); \
245 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
246 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
248 static int decompiled
= 0;
249 #define HANDLE_END_METHOD() \
250 if (out && method_printed && !method_synthetic) \
251 fputs (decompiled || stubs ? "\n" : ";\n", out);
253 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
255 /* We're going to need {peek,skip}_attribute, enable their definition. */
256 #define NEED_PEEK_ATTRIBUTE
257 #define NEED_SKIP_ATTRIBUTE
259 #include "jcf-reader.c"
261 /* Print an error message and set found_error. */
263 error (const char *msgid
, ...)
267 va_start (ap
, msgid
);
269 fprintf (stderr
, "gcjh: ");
270 vfprintf (stderr
, _(msgid
), ap
);
272 fprintf (stderr
, "\n");
276 /* Print a single-precision float, suitable for parsing by g++. */
278 jni_print_float (FILE *stream
, jfloat f
)
280 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
281 work in data initializers. FIXME. */
282 if (JFLOAT_FINITE (f
))
284 fputs (flag_jni
? " " : " = ", out
);
288 fprintf (stream
, "0x1.%.6xp%+df",
289 ((unsigned int)f
.mantissa
) << 1,
290 f
.exponent
- JFLOAT_EXP_BIAS
);
292 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
293 because the implicit leading 1 bit is no longer present. */
294 fprintf (stream
, "0x0.%.6xp%+df",
295 ((unsigned int)f
.mantissa
) << 1,
296 f
.exponent
+ 1 - JFLOAT_EXP_BIAS
);
299 fputs (";\n", stream
);
302 /* Print a double-precision float, suitable for parsing by g++. */
304 jni_print_double (FILE *stream
, jdouble f
)
306 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
307 work in data initializers. FIXME. */
308 if (JDOUBLE_FINITE (f
))
310 fputs (flag_jni
? " " : " = ", out
);
314 fprintf (stream
, "0x1.%.5x%.8xp%+d",
315 f
.mantissa0
, f
.mantissa1
,
316 f
.exponent
- JDOUBLE_EXP_BIAS
);
318 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
319 because the implicit leading 1 bit is no longer present. */
320 fprintf (stream
, "0x0.%.5x%.8xp%+d",
321 f
.mantissa0
, f
.mantissa1
,
322 f
.exponent
+ 1 - JDOUBLE_EXP_BIAS
);
324 fputs (flag_jni
? "\n" : ";\n", stream
);
327 /* Print a character, appropriately mangled for JNI. */
330 jni_print_char (FILE *stream
, int ch
)
333 jcf_print_char (stream
, ch
);
334 else if (ch
== '(' || ch
== ')')
339 fputs ("_1", stream
);
341 fputs ("_2", stream
);
343 fputs ("_3", stream
);
346 else if (ISALNUM (ch
))
350 /* "Unicode" character. */
351 fprintf (stream
, "_0%04x", ch
);
355 /* Print a name from the class data. If the index does not point to a
356 string, an error results. */
359 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
361 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
363 fprintf (stream
, "<not a UTF8 constant>");
367 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
368 JPOOL_UTF_LENGTH (jcf
, name_index
));
371 /* For JNI we must correctly quote each character. */
372 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, name_index
);
373 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
374 const unsigned char *limit
= str
+ length
;
377 int ch
= UTF8_GET (str
, limit
);
380 fprintf (stream
, "\\<invalid>");
383 jni_print_char (stream
, ch
);
388 /* Print base name of class. The base name is everything after the
392 print_base_classname (FILE *stream
, JCF
*jcf
, int index
)
394 int name_index
= JPOOL_USHORT1 (jcf
, index
);
396 const unsigned char *s
, *p
, *limit
;
398 s
= JPOOL_UTF_DATA (jcf
, name_index
);
399 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
404 int c
= UTF8_GET (s
, limit
);
411 int ch
= UTF8_GET (p
, limit
);
413 fputs ("::", stream
);
415 jcf_print_char (stream
, ch
);
419 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
420 and 1 if STR is "greater" than NAME. */
423 utf8_cmp (const unsigned char *str
, int length
, const char *name
)
425 const unsigned char *limit
= str
+ length
;
428 for (i
= 0; name
[i
]; ++i
)
430 int ch
= UTF8_GET (str
, limit
);
435 return str
== limit
? 0 : 1;
438 /* This is a sorted list of all C++ keywords. */
440 static const char *const cxx_keywords
[] =
549 /* If NAME is the name of a C++ keyword, then return an override name.
550 This is a name that can be used in place of the keyword.
551 Otherwise, return NULL. The return value is malloc()d. */
554 cxx_keyword_subst (const unsigned char *str
, int length
)
556 int last
= ARRAY_SIZE (cxx_keywords
);
558 int mid
= (last
+ first
) / 2;
561 for (mid
= (last
+ first
) / 2;
563 old
= mid
, mid
= (last
+ first
) / 2)
565 int kwl
= strlen (cxx_keywords
[mid
]);
566 int min_length
= kwl
> length
? length
: kwl
;
567 int r
= utf8_cmp (str
, min_length
, cxx_keywords
[mid
]);
573 /* Skip all trailing `$'. */
574 for (i
= min_length
; i
< length
&& str
[i
] == '$'; ++i
)
576 /* We've only found a match if all the remaining characters
580 char *dup
= xmalloc (2 + length
- min_length
+ kwl
);
581 strcpy (dup
, cxx_keywords
[mid
]);
582 for (i
= kwl
; i
< length
+ 1; ++i
)
598 /* Generate an access control keyword based on FLAGS. */
601 generate_access (FILE *stream
, JCF_u2 flags
)
603 if ((flags
& ACC_VISIBILITY
) == last_access
)
605 last_access
= (flags
& ACC_VISIBILITY
);
610 fputs ("public: // actually package-private\n", stream
);
613 fputs ("public:\n", stream
);
616 fputs ("private:\n", stream
);
619 fputs ("public: // actually protected\n", stream
);
623 fprintf (stream
, "#error unrecognized visibility %d\n",
624 (flags
& ACC_VISIBILITY
));
629 /* See if NAME is already the name of a method. */
631 name_is_method_p (const unsigned char *name
, int length
)
633 struct method_name
*p
;
635 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
637 if (p
->length
== length
&& ! memcmp (p
->name
, name
, length
))
643 /* Free the method name list. */
645 free_method_name_list (void)
647 struct method_name
*p
= method_name_list
;
650 struct method_name
*next
= p
->next
;
656 method_name_list
= NULL
;
659 /* If there is already a native method named NAME, whose signature is not
660 SIGNATURE, then return true. Otherwise return false. */
662 overloaded_jni_method_exists_p (const unsigned char *name
, int length
,
663 const char *signature
, int sig_length
)
665 struct method_name
*p
;
667 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
670 && p
->length
== length
671 && ! memcmp (p
->name
, name
, length
)
672 && (p
->sig_length
!= sig_length
673 || memcmp (p
->signature
, signature
, sig_length
)))
679 /* Get name of a field. This handles renamings due to C++ clash. */
681 get_field_name (JCF
*jcf
, int name_index
, JCF_u2 flags
)
683 unsigned char *name
= JPOOL_UTF_DATA (jcf
, name_index
);
684 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
687 if (name_is_method_p (name
, length
))
689 /* This field name matches a method. So override the name with
690 a dummy name. This is yucky, but it isn't clear what else to
691 do. FIXME: if the field is static, then we'll be in real
693 if ((flags
& ACC_STATIC
))
695 error ("static field has same name as method");
699 override
= xmalloc (length
+ 3);
700 memcpy (override
, name
, length
);
701 strcpy (override
+ length
, "__");
704 override
= cxx_keyword_subst (name
, length
);
709 /* Print a field name. Convenience function for use with
712 print_field_name (FILE *stream
, JCF
*jcf
, int name_index
, JCF_u2 flags
)
714 char *override
= get_field_name (jcf
, name_index
, flags
);
718 fputs (override
, stream
);
722 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
723 JPOOL_UTF_LENGTH (jcf
, name_index
));
727 print_field_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
730 char *override
= NULL
;
733 generate_access (stream
, flags
);
734 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
736 fprintf (stream
, "<not a UTF8 constant>");
743 /* For JNI we only want to print real constants. */
745 if (! (flags
& ACC_STATIC
)
746 || ! (flags
& ACC_FINAL
)
747 || current_field_value
<= 0)
749 val
= JPOOL_TAG (jcf
, current_field_value
);
750 if (val
!= CONSTANT_Integer
&& val
!= CONSTANT_Long
751 && val
!= CONSTANT_Float
&& val
!= CONSTANT_Double
)
756 /* Initial indentation. */
760 if ((flags
& ACC_STATIC
))
764 print_cxx_classname (stream
, "#undef ", jcf
, jcf
->this_class
, 1);
766 print_field_name (stream
, jcf
, name_index
, 0);
767 fputs ("\n", stream
);
768 print_cxx_classname (stream
, "#define ", jcf
, jcf
->this_class
, 1);
772 fputs ("static ", stream
);
774 if ((flags
& ACC_FINAL
) && current_field_value
> 0)
779 switch (JPOOL_TAG (jcf
, current_field_value
))
781 case CONSTANT_Integer
:
784 int most_negative
= 0;
786 fputs ("const jint ", stream
);
787 print_field_name (stream
, jcf
, name_index
, 0);
788 fputs (flag_jni
? " " : " = ", stream
);
789 num
= JPOOL_INT (jcf
, current_field_value
);
790 /* We single out the most negative number to print
791 specially. This avoids later warnings from g++. */
792 if (num
== (jint
) 0x80000000)
797 format_int (buffer
, (jlong
) num
, 10);
798 fprintf (stream
, "%sL%s%s\n", buffer
,
799 most_negative
? " - 1" : "",
800 flag_jni
? "" : ";");
806 int most_negative
= 0;
808 fputs ("const jlong ", stream
);
809 print_field_name (stream
, jcf
, name_index
, 0);
810 fputs (flag_jni
? " " : " = ", stream
);
811 num
= JPOOL_LONG (jcf
, current_field_value
);
812 /* We single out the most negative number to print
813 specially.. This avoids later warnings from g++. */
814 if (num
== (jlong
) 0x8000000000000000LL
)
819 format_int (buffer
, num
, 10);
820 fprintf (stream
, "%sLL%s%s\n", buffer
,
821 most_negative
? " - 1" :"",
822 flag_jni
? "" : ";");
827 jfloat fnum
= JPOOL_FLOAT (jcf
, current_field_value
);
829 fputs ("const jfloat ", stream
);
830 print_field_name (stream
, jcf
, name_index
, 0);
831 jni_print_float (stream
, fnum
);
834 case CONSTANT_Double
:
836 jdouble dnum
= JPOOL_DOUBLE (jcf
, current_field_value
);
838 fputs ("const jdouble ", stream
);
839 print_field_name (stream
, jcf
, name_index
, 0);
840 jni_print_double (stream
, dnum
);
844 /* We can't print this as a constant, but we can still
845 print something sensible. */
855 /* assert (! flag_jni); */
856 override
= get_field_name (jcf
, name_index
, flags
);
857 print_c_decl (stream
, jcf
, name_index
, sig_index
, 0, override
, flags
);
858 fputs (";\n", stream
);
866 print_method_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
869 const unsigned char *str
;
870 int length
, is_init
= 0;
871 char *override
= NULL
;
874 method_access
= flags
;
875 if (stream
&& JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
876 fprintf (stream
, "<not a UTF8 constant>");
877 str
= JPOOL_UTF_DATA (jcf
, name_index
);
878 length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
882 /* Ignore the internally generated method <clinit>. However,
883 treat <init> as a constructor. */
884 if (! utf8_cmp (str
, length
, "<init>"))
886 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
)
887 && ! (flags
& ACC_STATIC
))
889 /* FIXME: i18n bug here. Order of prints should not be
891 fprintf (stderr
, _("ignored method '"));
892 jcf_print_utf8 (stderr
, str
, length
);
893 fprintf (stderr
, _("' marked virtual\n"));
901 /* During the first method pass, build a list of method names. This will
902 be used to determine if field names conflict with method names. */
905 struct method_name
*nn
;
907 nn
= xmalloc (sizeof (struct method_name
));
908 nn
->name
= xmalloc (length
);
909 memcpy (nn
->name
, str
, length
);
911 nn
->next
= method_name_list
;
912 nn
->sig_length
= JPOOL_UTF_LENGTH (jcf
, sig_index
);
913 nn
->signature
= xmalloc (nn
->sig_length
);
914 nn
->is_native
= METHOD_IS_NATIVE (flags
);
915 memcpy (nn
->signature
, JPOOL_UTF_DATA (jcf
, sig_index
),
917 method_name_list
= nn
;
919 /* The rest of this function doesn't matter. */
923 /* We don't worry about overrides in JNI mode. */
926 /* We can't generate a method whose name is a C++ reserved word.
927 We can't just ignore the function, because that will cause
928 incorrect code to be generated if the function is virtual
929 (not only for calls to this function for for other functions
930 after it in the vtbl). So we give it a dummy name instead. */
931 override
= cxx_keyword_subst (str
, length
);
934 if (! stubs
&& ! flag_jni
)
938 generate_access (stream
, flags
);
941 if ((flags
& ACC_STATIC
))
942 fputs ("static ", out
);
943 else if (! METHOD_IS_PRIVATE (jcf
->access_flags
, flags
))
945 /* Don't print `virtual' if we have a constructor. */
947 fputs ("virtual ", out
);
949 print_c_decl (out
, jcf
, name_index
, sig_index
, is_init
, override
, flags
);
951 if ((flags
& ACC_ABSTRACT
))
958 if (METHOD_IS_NATIVE (flags
))
961 print_stub_or_jni (out
, jcf
, name_index
, sig_index
,
962 is_init
, override
, flags
);
970 /* A helper for the decompiler which prints a `return' statement where
971 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
972 identical, we emit a cast. We do this because the C++ compiler
973 doesn't know that a reference can be cast to the type of an
974 interface it implements. METHODTYPE is the index of the method's
975 signature. NAMEINDEX is the index of the field name; -1 for
976 `this'. OBJECTTYPE is the index of the object's type. */
978 decompile_return_statement (FILE *out
, JCF
*jcf
, int methodtype
,
979 int nameindex
, int objecttype
)
982 int obj_name_len
, method_name_len
;
983 const unsigned char *obj_data
, *method_data
;
985 obj_name_len
= JPOOL_UTF_LENGTH (jcf
, objecttype
);
986 obj_data
= JPOOL_UTF_DATA (jcf
, objecttype
);
988 method_name_len
= JPOOL_UTF_LENGTH (jcf
, methodtype
);
989 method_data
= JPOOL_UTF_DATA (jcf
, methodtype
);
991 /* Skip forward to return type part of method. */
992 while (*method_data
!= ')')
1001 /* If we see an `L', skip it and the trailing `;'. */
1002 if (method_data
[0] == 'L' && method_data
[method_name_len
- 1] == ';')
1005 method_name_len
-= 2;
1007 if (obj_data
[0] == 'L' && obj_data
[obj_name_len
- 1] == ';')
1013 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
1014 need a cast. Right now there is no way to determine if this is
1016 if (method_name_len
!= obj_name_len
)
1021 for (i
= 0; i
< method_name_len
; ++i
)
1023 if (method_data
[i
] != obj_data
[i
])
1031 fputs (" { return ", out
);
1035 int array_depth
= 0;
1036 const unsigned char *limit
;
1038 fputs ("reinterpret_cast<", out
);
1040 while (*method_data
== '[')
1045 fputs ("JArray<", out
);
1048 /* Leading space to avoid C++ digraphs. */
1051 /* If we see an `L', skip it and the trailing `;'. Only do this
1052 if we've seen an array specification. If we don't have an
1053 array then the `L' was stripped earlier. */
1054 if (array_depth
&& method_data
[0] == 'L'
1055 && method_data
[method_name_len
- 1] == ';')
1058 method_name_len
-= 2;
1061 limit
= method_data
+ method_name_len
;
1062 while (method_data
< limit
)
1064 int ch
= UTF8_GET (method_data
, limit
);
1068 jcf_print_char (out
, ch
);
1072 /* Close each array. */
1073 while (array_depth
> 0)
1079 /* Close the cast. */
1083 if (nameindex
== -1)
1084 fputs ("this", out
);
1086 print_field_name (out
, jcf
, nameindex
, 0);
1095 /* Try to decompile a method body. Right now we just try to handle a
1096 simple case that we can do. Expand as desired. */
1098 decompile_method (FILE *out
, JCF
*jcf
, int code_len
)
1100 const unsigned char *codes
= jcf
->read_ptr
;
1102 uint16 name_and_type
, name
;
1104 /* If the method is synchronized, don't touch it. */
1105 if ((method_access
& ACC_SYNCHRONIZED
))
1109 && codes
[0] == OPCODE_aload_0
1110 && codes
[1] == OPCODE_getfield
1111 && (codes
[4] == OPCODE_areturn
1112 || codes
[4] == OPCODE_dreturn
1113 || codes
[4] == OPCODE_freturn
1114 || codes
[4] == OPCODE_ireturn
1115 || codes
[4] == OPCODE_lreturn
))
1117 /* Found code like `return FIELD'. */
1118 index
= (codes
[2] << 8) | codes
[3];
1119 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1120 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
1121 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1122 name
= JPOOL_USHORT1 (jcf
, name_and_type
);
1123 if (codes
[4] == OPCODE_areturn
)
1124 decompile_return_statement (out
, jcf
, method_signature
,
1125 name
, JPOOL_USHORT2 (jcf
, name_and_type
));
1128 fputs (" { return ", out
);
1130 print_field_name (out
, jcf
, name
, 0);
1135 else if (code_len
== 2
1136 && codes
[0] == OPCODE_aload_0
1137 && codes
[1] == OPCODE_areturn
1138 /* We're going to generate `return this'. This only makes
1139 sense for non-static methods. */
1140 && ! (method_access
& ACC_STATIC
))
1142 decompile_return_statement (out
, jcf
, method_signature
, -1,
1143 JPOOL_USHORT1 (jcf
, jcf
->this_class
));
1146 else if (code_len
== 1 && codes
[0] == OPCODE_return
)
1148 /* Found plain `return'. */
1149 fputs (" { }", out
);
1152 else if (code_len
== 2
1153 && codes
[0] == OPCODE_aconst_null
1154 && codes
[1] == OPCODE_areturn
)
1156 /* Found `return null'. We don't want to depend on NULL being
1158 fputs (" { return 0; }", out
);
1163 /* Like strcmp, but invert the return result for the hash table. This
1164 should probably be in hashtab.c to complement the existing string
1167 gcjh_streq (const void *p1
, const void *p2
)
1169 return ! strcmp ((char *) p1
, (char *) p2
);
1172 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1173 or 0 if not. CLNAME may be extracted from a signature, and can be
1174 terminated with either `;' or NULL. */
1176 throwable_p (const unsigned char *clname
)
1179 unsigned char *current
;
1183 /* We keep two hash tables of class names. In one we list all the
1184 classes which are subclasses of Throwable. In the other we will
1185 all other classes. We keep two tables to make the code a bit
1186 simpler; we don't have to have a structure mapping class name to
1187 a `throwable?' bit. */
1188 static htab_t throw_hash
;
1189 static htab_t non_throw_hash
;
1190 static int init_done
= 0;
1197 /* Self-initializing. The cost of this really doesn't matter.
1198 We also don't care about freeing these, either. */
1199 throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1201 non_throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1204 /* Make sure the root classes show up in the tables. */
1205 str
= (unsigned char *) xstrdup ("java.lang.Throwable");
1206 slot
= htab_find_slot (throw_hash
, str
, INSERT
);
1209 str
= (unsigned char *) xstrdup ("java.lang.Object");
1210 slot
= htab_find_slot (non_throw_hash
, str
, INSERT
);
1216 for (length
= 0; clname
[length
] != ';' && clname
[length
] != '\0'; ++length
)
1218 current
= ALLOC (length
+ 1);
1219 for (i
= 0; i
< length
; ++i
)
1220 current
[i
] = clname
[i
] == '/' ? '.' : clname
[i
];
1221 current
[length
] = '\0';
1223 /* We don't compute the hash slot here because the table might be
1224 modified by the recursion. In that case the slot could be
1226 if (htab_find (throw_hash
, current
))
1228 else if (htab_find (non_throw_hash
, current
))
1234 unsigned char *super
, *tmp
;
1235 int super_length
= -1;
1236 const char *classfile_name
= find_class ((char *) current
, strlen ((const char *) current
),
1239 if (! classfile_name
)
1241 error ("couldn't find class %s", current
);
1244 if (jcf_parse_preamble (&jcf
) != 0
1245 || jcf_parse_constant_pool (&jcf
) != 0
1246 || verify_constant_pool (&jcf
) > 0)
1248 error ("parse error while reading %s", classfile_name
);
1251 jcf_parse_class (&jcf
);
1253 tmp
= (unsigned char *) super_class_name (&jcf
, &super_length
);
1254 super
= ALLOC (super_length
+ 1);
1255 memcpy (super
, tmp
, super_length
);
1256 super
[super_length
] = '\0';
1258 result
= throwable_p (super
);
1259 slot
= htab_find_slot (result
? throw_hash
: non_throw_hash
,
1270 /* Print one piece of a signature. Returns pointer to next parseable
1271 character on success, NULL on error. */
1272 static const unsigned char *
1273 decode_signature_piece (FILE *stream
, const unsigned char *signature
,
1274 const unsigned char *limit
, int *need_space
)
1277 int array_depth
= 0;
1279 switch (signature
[0])
1282 /* More spaghetti. */
1285 for (signature
++; (signature
< limit
1286 && ISDIGIT (*signature
)); signature
++)
1291 ctype
= "jbyteArray";
1294 ctype
= "jcharArray";
1297 ctype
= "jdoubleArray";
1300 ctype
= "jfloatArray";
1303 ctype
= "jintArray";
1306 ctype
= "jshortArray";
1309 ctype
= "jlongArray";
1312 ctype
= "jbooleanArray";
1315 /* We have a nested array. */
1318 fputs ("JArray<", stream
);
1322 /* We have to generate a reference to JArray here, so that
1323 our output matches what the compiler does. */
1325 /* Space between `<' and `:' to avoid C++ digraphs. */
1327 fputs ("JArray< ::", stream
);
1328 while (signature
< limit
&& *signature
!= ';')
1330 int ch
= UTF8_GET (signature
, limit
);
1334 fputs ("::", stream
);
1336 jcf_print_char (stream
, ch
);
1340 fputs (" *> *", stream
);
1345 /* Unparseable signature. */
1349 /* If the previous iterations left us with something to print,
1350 print it. For JNI, we always print `jobjectArray' in the
1352 if (flag_jni
&& (ctype
== NULL
|| array_depth
> 0))
1354 ctype
= "jobjectArray";
1357 /* The `printit' case will advance SIGNATURE for us. If we
1358 don't go there, we must advance past the `;' ourselves. */
1366 /* This shouldn't happen. */
1369 case 'B': ctype
= "jbyte"; goto printit
;
1370 case 'C': ctype
= "jchar"; goto printit
;
1371 case 'D': ctype
= "jdouble"; goto printit
;
1372 case 'F': ctype
= "jfloat"; goto printit
;
1373 case 'I': ctype
= "jint"; goto printit
;
1374 case 'J': ctype
= "jlong"; goto printit
;
1375 case 'S': ctype
= "jshort"; goto printit
;
1376 case 'Z': ctype
= "jboolean"; goto printit
;
1377 case 'V': ctype
= "void"; goto printit
;
1381 /* We know about certain types and special-case their names. */
1382 if (! strncmp ((const char *) signature
, "Ljava/lang/String;",
1383 sizeof ("Ljava/lang/String;") -1))
1385 else if (! strncmp ((const char *) signature
, "Ljava/lang/Class;",
1386 sizeof ("Ljava/lang/Class;") - 1))
1388 /* Skip leading 'L' for throwable_p call. */
1389 else if (throwable_p (signature
+ 1))
1390 ctype
= "jthrowable";
1394 while (*signature
&& *signature
!= ';')
1399 /* Print a leading "::" so we look in the right namespace. */
1400 fputs ("::", stream
);
1402 while (*signature
&& *signature
!= ';')
1404 int ch
= UTF8_GET (signature
, limit
);
1406 fputs ("::", stream
);
1408 jcf_print_char (stream
, ch
);
1410 fputs (" *", stream
);
1411 if (*signature
== ';')
1417 jni_print_char (stream
, *signature
++);
1422 fputs (ctype
, stream
);
1428 while (array_depth
-- > 0)
1429 fputs ("> *", stream
);
1436 print_c_decl (FILE* stream
, JCF
* jcf
, int name_index
, int signature_index
,
1437 int is_init
, const char *name_override
, int flags
)
1439 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1441 fprintf (stream
, "<not a UTF8 constant>");
1446 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1447 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1448 const unsigned char *str
= str0
;
1449 const unsigned char *limit
= str
+ length
;
1451 int is_method
= str
[0] == '(';
1452 const unsigned char *next
;
1454 /* If printing a method, skip to the return signature and print
1455 that first. However, there is no return value if this is a
1457 if (is_method
&& ! is_init
)
1467 /* If printing a field or an ordinary method, then print the
1468 "return value" now. */
1469 if (! is_method
|| ! is_init
)
1471 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1474 error ("unparseable signature: '%s'", str0
);
1479 /* Force the alignment of the first data member. This is
1480 because the "new" C++ ABI changed the alignment of non-POD
1481 classes. gcj, however, still uses the "old" alignment. */
1482 if (is_first_data_member
&& ! (flags
& ACC_STATIC
) && ! is_method
)
1484 is_first_data_member
= 0;
1485 print_cxx_classname (out
, " __attribute__((aligned(__alignof__( ",
1486 jcf
, jcf
->super_class
, 1);
1487 fputs (" )))) ", stream
);
1490 /* Now print the name of the thing. */
1492 fputs (" ", stream
);
1493 print_full_cxx_name (stream
, jcf
, name_index
,
1494 signature_index
, is_init
, name_override
,
1499 /* Print the unqualified method name followed by the signature. */
1501 print_full_cxx_name (FILE* stream
, JCF
* jcf
, int name_index
,
1502 int signature_index
, int is_init
,
1503 const char *name_override
, int flags
)
1505 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1506 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1507 const unsigned char *str
= str0
;
1508 const unsigned char *limit
= str
+ length
;
1510 int is_method
= str
[0] == '(';
1511 const unsigned char *next
;
1514 fputs (name_override
, stream
);
1515 else if (name_index
)
1517 /* Declare constructors specially. */
1519 print_base_classname (stream
, jcf
, jcf
->this_class
);
1521 print_name (stream
, jcf
, name_index
);
1526 unsigned char *signature
= JPOOL_UTF_DATA (jcf
, signature_index
);
1527 int sig_len
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1528 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf
, name_index
),
1529 JPOOL_UTF_LENGTH (jcf
, name_index
),
1530 (const char *) signature
, sig_len
))
1532 /* If this method is overloaded by another native method,
1533 then include the argument information in the mangled
1535 unsigned char *limit
= signature
+ sig_len
;
1536 fputs ("__", stream
);
1537 while (signature
< limit
)
1539 int ch
= UTF8_GET (signature
, limit
);
1540 jni_print_char (stream
, ch
);
1552 /* Have a method or a constructor. Print signature pieces
1554 fputs (" (", stream
);
1558 /* In JNI mode, add extra arguments. */
1561 /* FIXME: it would be nice to know if we are printing a decl
1562 or a definition, and only print `env' for the latter. */
1563 fputs ("JNIEnv *env", stream
);
1565 fputs ((flags
& ACC_STATIC
) ? ", jclass" : ", jobject", stream
);
1568 fputs (", ", stream
);
1571 while (str
< limit
&& *str
!= ')')
1573 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1576 error ("unparseable signature: '%s'", str0
);
1580 if (next
< limit
&& *next
!= ')')
1581 fputs (", ", stream
);
1585 fputs (")", stream
);
1589 /* This is a helper for print_stub_or_jni. */
1591 print_name_for_stub_or_jni (FILE *stream
, JCF
*jcf
, int name_index
,
1592 int signature_index
, int is_init
,
1593 const char *name_override
, int flags
)
1595 const char *const prefix
= flag_jni
? "Java_" : "";
1596 print_cxx_classname (stream
, prefix
, jcf
, jcf
->this_class
, 1);
1597 fputs (flag_jni
? "_" : "::", stream
);
1598 print_full_cxx_name (stream
, jcf
, name_index
,
1599 signature_index
, is_init
, name_override
,
1604 print_stub_or_jni (FILE* stream
, JCF
* jcf
, int name_index
,
1605 int signature_index
, int is_init
,
1606 const char *name_override
, int flags
)
1608 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1610 fprintf (stream
, "<not a UTF8 constant>");
1615 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1616 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1617 const unsigned char *str
= str0
;
1618 const unsigned char *limit
= str
+ length
;
1620 int is_method
= str
[0] == '(';
1621 const unsigned char *next
;
1623 /* Don't print fields in the JNI case. */
1624 if (! is_method
&& flag_jni
)
1627 if (flag_jni
&& ! stubs
)
1628 fputs ("JNIEXPORT ", stream
);
1630 /* If printing a method, skip to the return signature and print
1631 that first. However, there is no return value if this is a
1633 if (is_method
&& ! is_init
)
1643 /* If printing a field or an ordinary method, then print the
1644 "return value" now. Note that a constructor can't be native,
1645 so we don't bother checking this in the JNI case. */
1646 if (! is_method
|| ! is_init
)
1648 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1651 error ("unparseable signature: '%s'", str0
);
1656 /* When printing a JNI header we need to respect the space. In
1657 other cases we're just going to insert a newline anyway. */
1658 fputs (need_space
&& ! stubs
? " " : "\n", stream
);
1660 if (flag_jni
&& ! stubs
)
1661 fputs ("JNICALL ", stream
);
1663 /* Now print the name of the thing. */
1664 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1665 signature_index
, is_init
, name_override
,
1668 /* Print the body. */
1672 fputs ("\n{\n (*env)->FatalError (env, \"", stream
);
1674 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream
);
1675 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1676 signature_index
, is_init
,
1679 fprintf (stream
, " not implemented\")%s;\n}\n\n",
1680 flag_jni
? "" : ")");
1686 print_mangled_classname (FILE *stream
, JCF
*jcf
, const char *prefix
, int index
)
1688 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1689 fputs (prefix
, stream
);
1690 jcf_print_utf8_replace (out
,
1691 JPOOL_UTF_DATA (jcf
, name_index
),
1692 JPOOL_UTF_LENGTH (jcf
, name_index
),
1696 /* Print PREFIX, then a class name in C++ format. If the name refers
1697 to an array, ignore it and don't print PREFIX. Returns 1 if
1698 something was printed, 0 otherwise. */
1700 print_cxx_classname (FILE *stream
, const char *prefix
,
1701 JCF
*jcf
, int index
, int add_scope
)
1703 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1705 const unsigned char *s
, *p
, *limit
;
1707 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1708 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1711 /* Explicitly omit arrays here. */
1713 c
= UTF8_GET (p
, limit
);
1717 fputs (prefix
, stream
);
1719 /* Print a leading "::" so we look in the right namespace. */
1720 if (! flag_jni
&& ! stubs
&& add_scope
)
1721 fputs ("::", stream
);
1725 c
= UTF8_GET (s
, limit
);
1727 fputs (flag_jni
? "_" : "::", stream
);
1729 jni_print_char (stream
, c
);
1735 int written_class_count
= 0;
1737 /* Return name of superclass. If LEN is not NULL, fill it with length
1739 static const unsigned char *
1740 super_class_name (JCF
*derived_jcf
, int *len
)
1742 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
1743 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
1744 const unsigned char *supername
=
1745 JPOOL_UTF_DATA (derived_jcf
, supername_index
);
1748 *len
= supername_length
;
1754 handle_inner_classes (int count
)
1758 if (out
&& ! flag_jni
&& ! stubs
&& count
> 0)
1759 fprintf (out
, "\n");
1761 for (i
= 0; i
< count
; ++i
)
1763 JCF_u2 inner_info_index
= JCF_readu2 (current_jcf
);
1765 /* There are a few more values here, but we don't care about
1766 them. The (void) cast is apparently the only way to avoid a
1768 (void) JCF_readu2 (current_jcf
);
1769 (void) JCF_readu2 (current_jcf
);
1770 (void) JCF_readu2 (current_jcf
);
1772 if (out
&& ! flag_jni
&& ! stubs
)
1774 print_mangled_classname (out
, current_jcf
, " friend class ",
1776 fprintf (out
, ";\n");
1783 /* We keep track of all the `#include's we generate, so we can avoid
1788 struct include
*next
;
1791 /* List of all includes. */
1792 static struct include
*all_includes
= NULL
;
1794 /* Generate a #include. */
1796 print_include (FILE *out
, const unsigned char *utf8
, int len
)
1798 struct include
*incl
;
1804 len
= strlen ((const char *) utf8
);
1806 for (incl
= all_includes
; incl
; incl
= incl
->next
)
1808 /* We check the length because we might have a proper prefix. */
1809 if (len
== (int) strlen (incl
->name
)
1810 && ! strncmp (incl
->name
, (const char *) utf8
, len
))
1814 incl
= xmalloc (sizeof (struct include
));
1815 incl
->name
= xmalloc (len
+ 1);
1816 strncpy (incl
->name
, (const char *) utf8
, len
);
1817 incl
->name
[len
] = '\0';
1818 incl
->next
= all_includes
;
1819 all_includes
= incl
;
1821 fputs ("#include <", out
);
1822 jcf_print_utf8_replace (out
, utf8
, len
,
1824 flag_jni
? '_' : '/');
1825 fputs (".h>\n", out
);
1830 /* This is used to represent part of a package or class name. */
1833 /* The text of this part of the name. */
1835 /* True if this represents a class. */
1837 /* Linked list of all classes and packages inside this one. */
1838 struct namelet
*subnamelets
;
1839 /* Pointer to next sibling. */
1840 struct namelet
*next
;
1843 static void add_namelet (const unsigned char *, const unsigned char *,
1845 static void print_namelet (FILE *, struct namelet
*, int);
1847 /* The special root namelet. */
1848 static struct namelet root
=
1856 /* This extracts the next name segment from the full UTF-8 encoded
1857 package or class name and links it into the tree. It does this
1860 add_namelet (const unsigned char *name
, const unsigned char *name_limit
,
1861 struct namelet
*parent
)
1863 const unsigned char *p
;
1864 struct namelet
*n
= NULL
, *np
;
1866 /* We want to skip the standard namespaces that we assume the
1867 runtime already knows about. We only do this at the top level,
1868 though, hence the check for `root'. */
1869 if (parent
== &root
)
1871 #define JAVALANG "java/lang/"
1872 #define JAVAIO "java/io/"
1873 #define JAVAUTIL "java/util/"
1874 if ((name_limit
- name
>= (int) sizeof (JAVALANG
) - 1
1875 && ! strncmp ((const char *) name
, JAVALANG
, sizeof (JAVALANG
) - 1))
1876 || (name_limit
- name
>= (int) sizeof (JAVAUTIL
) - 1
1877 && ! strncmp ((const char *) name
, JAVAUTIL
, sizeof (JAVAUTIL
) - 1))
1878 || (name_limit
- name
>= (int) sizeof (JAVAIO
) - 1
1879 && ! strncmp ((const char *) name
, JAVAIO
, sizeof (JAVAIO
) - 1)))
1883 for (p
= name
; p
< name_limit
&& *p
!= '/'; ++p
)
1886 /* Search for this name beneath the PARENT node. */
1887 for (np
= parent
->subnamelets
; np
!= NULL
; np
= np
->next
)
1889 /* We check the length because we might have a proper prefix. */
1890 if ((int) strlen (np
->name
) == p
- name
&&
1891 ! strncmp ((const char *) name
, np
->name
, p
- name
))
1900 n
= xmalloc (sizeof (struct namelet
));
1901 n
->name
= xmalloc (p
- name
+ 1);
1902 strncpy (n
->name
, (const char *) name
, p
- name
);
1903 n
->name
[p
- name
] = '\0';
1904 n
->is_class
= (p
== name_limit
);
1905 n
->subnamelets
= NULL
;
1906 n
->next
= parent
->subnamelets
;
1907 parent
->subnamelets
= n
;
1910 /* We recurse if there is more text, and if the trailing piece does
1911 not represent an inner class. */
1913 add_namelet (p
+ 1, name_limit
, n
);
1916 /* Print a single namelet. Destroys namelets while printing. */
1918 print_namelet (FILE *out
, struct namelet
*name
, int depth
)
1925 for (i
= 0; i
< depth
; ++i
)
1927 fprintf (out
, "%s %s", name
->is_class
? "class" : "namespace",
1929 if (name
->is_class
&& name
->subnamelets
== NULL
)
1935 for (i
= 0; i
< depth
; ++i
)
1941 c
= name
->subnamelets
;
1944 struct namelet
*next
= c
->next
;
1945 print_namelet (out
, c
, depth
+ 2);
1948 name
->subnamelets
= NULL
;
1954 for (i
= 0; i
< depth
; ++i
)
1957 /* Only print a `;' when printing a class. C++ is evil. */
1967 /* This is called to add some classes to the list of classes for which
1968 we need decls. The signature argument can be a function
1971 add_class_decl (FILE *out
, JCF
*jcf
, JCF_u2 signature
)
1973 const unsigned char *s
= JPOOL_UTF_DATA (jcf
, signature
);
1974 int len
= JPOOL_UTF_LENGTH (jcf
, signature
);
1977 for (i
= 0; i
< len
; ++i
)
1981 /* If we see an array, then we include the array header. */
1984 print_include (out
, (const unsigned char *) "gcj/array", -1);
1988 /* We're looking for `L<stuff>;' -- everything else is
1993 for (start
= ++i
; i
< len
&& s
[i
] != ';'; ++i
)
1996 add_namelet (&s
[start
], &s
[i
], &root
);
2000 /* Print declarations for all classes required by this class. Any
2001 class or package in the `java' package is assumed to be handled
2002 statically in libjava; we don't generate declarations for these.
2003 This makes the generated headers a bit easier to read. */
2005 print_class_decls (FILE *out
, JCF
*jcf
, int self
)
2007 /* Make sure to always add the current class to the list of things
2008 that should be declared. */
2009 int name_index
= JPOOL_USHORT1 (jcf
, self
);
2011 const unsigned char *s
;
2013 s
= JPOOL_UTF_DATA (jcf
, name_index
);
2014 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
2015 add_namelet (s
, s
+ len
, &root
);
2017 if (root
.subnamelets
)
2019 fputs ("extern \"Java\"\n{\n", out
);
2020 /* We use an initial offset of 0 because the root namelet
2021 doesn't cause anything to print. */
2022 print_namelet (out
, &root
, 0);
2023 fputs ("}\n\n", out
);
2030 process_file (JCF
*jcf
, FILE *out
)
2033 uint32 field_start
, method_end
, method_start
;
2039 if (jcf_parse_preamble (jcf
) != 0)
2041 error ("Not a valid Java .class file.");
2045 /* Parse and possibly print constant pool */
2046 code
= jcf_parse_constant_pool (jcf
);
2049 error ("error while parsing constant pool");
2052 code
= verify_constant_pool (jcf
);
2055 error ("error in constant pool entry #%d", code
);
2059 jcf_parse_class (jcf
);
2061 if (written_class_count
++ == 0 && out
)
2063 const char *cstart
, *cstart2
, *mode
, *cend
, *what
, *jflag
;
2078 mode
= " -*- c++ -*-";
2084 fprintf (out
, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2085 cstart
, mode
, cend
);
2088 fprintf (out
, "%s This file was created by `gcjh -stubs%s'.%s\n\
2090 %s This file is intended to give you a head start on implementing native\n\
2091 %s methods using %s.\n\
2092 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2093 %s overwrite any edits you have made to this file.%s\n\n",
2094 cstart
, jflag
, mode
,
2110 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
2111 fprintf (out
, "__\n");
2113 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
2114 fprintf (out
, "__\n\n");
2118 fprintf (out
, "#include <jni.h>\n\n");
2119 fprintf (out
, "#ifdef __cplusplus\n");
2120 fprintf (out
, "extern \"C\"\n");
2121 fprintf (out
, "{\n");
2122 fprintf (out
, "#endif\n");
2126 /* We do this to ensure that inline methods won't be
2127 `outlined' by g++. This works as long as method and
2128 fields are not added by the user. */
2129 fprintf (out
, "#pragma interface\n");
2131 if (jcf
->super_class
)
2134 const unsigned char *supername
=
2135 super_class_name (jcf
, &super_length
);
2138 print_include (out
, supername
, super_length
);
2144 /* Strip off the ".class" portion of the name when printing
2145 the include file name. */
2147 int i
, len
= strlen (jcf
->classname
);
2148 if (len
> 6 && ! strcmp (&jcf
->classname
[len
- 6], ".class"))
2150 /* Turn the class name into a file name. */
2151 name
= xmalloc (len
+ 1);
2152 for (i
= 0; i
< len
; ++i
)
2153 name
[i
] = jcf
->classname
[i
] == '.' ? '/' : jcf
->classname
[i
];
2155 print_include (out
, (const unsigned char *) name
, len
);
2160 print_include (out
, (const unsigned char *) "gcj/cni", -1);
2161 print_include (out
, (const unsigned char *) "java/lang/UnsupportedOperationException",
2167 /* We want to parse the methods first. But we need to find where
2168 they start. So first we skip the fields, then parse the methods.
2169 Then we parse the fields and skip the methods. This is ugly, but
2170 not too bad since we need two full passes to get class decl
2171 information anyway. */
2173 field_start
= JCF_TELL (jcf
);
2174 jcf_parse_fields (jcf
);
2176 method_start
= JCF_TELL (jcf
);
2178 jcf_parse_methods (jcf
);
2183 if (out
&& ! flag_jni
)
2186 print_class_decls (out
, jcf
, jcf
->this_class
);
2188 for (i
= 0; i
< prepend_count
; ++i
)
2189 fprintf (out
, "%s\n", prepend_specs
[i
]);
2190 if (prepend_count
> 0)
2195 if (! print_cxx_classname (out
, "class ", jcf
,
2196 jcf
->this_class
, 0))
2198 error ("class is of array type\n");
2201 if (jcf
->super_class
)
2203 if (! print_cxx_classname (out
, " : public ",
2204 jcf
, jcf
->super_class
, 1))
2206 error ("base class is of array type");
2211 fputs ("\n{\n", out
);
2215 /* Now go back for second pass over methods and fields. */
2216 is_first_data_member
= 1;
2218 JCF_SEEK (jcf
, method_start
);
2220 jcf_parse_methods (jcf
);
2221 method_end
= JCF_TELL (jcf
);
2224 JCF_SEEK (jcf
, field_start
);
2225 jcf_parse_fields (jcf
);
2226 JCF_SEEK (jcf
, method_end
);
2228 jcf_parse_final_attributes (jcf
);
2234 fprintf (out
, "\n#ifdef __cplusplus\n");
2235 fprintf (out
, "}\n");
2236 fprintf (out
, "#endif\n");
2240 /* Generate friend decl if we still must. */
2241 for (i
= 0; i
< friend_count
; ++i
)
2242 fprintf (out
, " friend %s\n", friend_specs
[i
]);
2244 /* Generate extra declarations. */
2247 for (i
= 0; i
< add_count
; ++i
)
2248 fprintf (out
, " %s\n", add_specs
[i
]);
2250 /* Generate an entry for the class object. */
2251 generate_access (out
, ACC_PUBLIC
);
2252 fprintf (out
, "\n static ::java::lang::Class class$;\n");
2256 if (jcf
->access_flags
& ACC_INTERFACE
)
2257 fputs (" __attribute__ ((java_interface))", out
);
2261 if (append_count
> 0)
2263 for (i
= 0; i
< append_count
; ++i
)
2264 fprintf (out
, "%s\n", append_specs
[i
]);
2267 print_mangled_classname (out
, jcf
,
2268 "\n#endif /* __", jcf
->this_class
);
2269 fprintf (out
, "__ */\n");
2275 /* This is used to mark options with no short value. */
2276 #define LONG_OPT(Num) ((Num) + 128)
2278 #define OPT_classpath LONG_OPT (0)
2279 #define OPT_CLASSPATH OPT_classpath
2280 #define OPT_bootclasspath LONG_OPT (1)
2281 #define OPT_extdirs LONG_OPT (2)
2282 #define OPT_HELP LONG_OPT (3)
2283 #define OPT_TEMP LONG_OPT (4)
2284 #define OPT_VERSION LONG_OPT (5)
2285 #define OPT_PREPEND LONG_OPT (6)
2286 #define OPT_FRIEND LONG_OPT (7)
2287 #define OPT_ADD LONG_OPT (8)
2288 #define OPT_APPEND LONG_OPT (9)
2289 #define OPT_M LONG_OPT (10)
2290 #define OPT_MM LONG_OPT (11)
2291 #define OPT_MG LONG_OPT (12)
2292 #define OPT_MD LONG_OPT (13)
2293 #define OPT_MMD LONG_OPT (14)
2295 static const struct option options
[] =
2297 { "classpath", required_argument
, NULL
, OPT_classpath
},
2298 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
2299 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
2300 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
2301 { "help", no_argument
, NULL
, OPT_HELP
},
2302 { "stubs", no_argument
, &stubs
, 1 },
2303 { "td", required_argument
, NULL
, OPT_TEMP
},
2304 { "verbose", no_argument
, NULL
, 'v' },
2305 { "version", no_argument
, NULL
, OPT_VERSION
},
2306 { "prepend", required_argument
, NULL
, OPT_PREPEND
},
2307 { "friend", required_argument
, NULL
, OPT_FRIEND
},
2308 { "add", required_argument
, NULL
, OPT_ADD
},
2309 { "append", required_argument
, NULL
, OPT_APPEND
},
2310 { "M", no_argument
, NULL
, OPT_M
},
2311 { "MM", no_argument
, NULL
, OPT_MM
},
2312 { "MG", no_argument
, NULL
, OPT_MG
},
2313 { "MD", no_argument
, NULL
, OPT_MD
},
2314 { "MMD", no_argument
, NULL
, OPT_MMD
},
2315 { "jni", no_argument
, &flag_jni
, 1 },
2316 { NULL
, no_argument
, NULL
, 0 }
2322 fprintf (stderr
, _("Try 'gcjh --help' for more information.\n"));
2329 printf (_("Usage: gcjh [OPTION]... CLASS...\n\n"));
2330 printf (_("Generate C++ header files from .class files\n\n"));
2331 printf (_(" -stubs Generate an implementation stub file\n"));
2332 printf (_(" -jni Generate a JNI header or stub\n"));
2334 printf (_(" -add TEXT Insert TEXT into class body\n"));
2335 printf (_(" -append TEXT Insert TEXT after class declaration\n"));
2336 printf (_(" -friend TEXT Insert TEXT as 'friend' declaration\n"));
2337 printf (_(" -prepend TEXT Insert TEXT before start of class\n"));
2339 printf (_(" --classpath PATH Set path to find .class files\n"));
2340 printf (_(" -IDIR Append directory to class path\n"));
2341 printf (_(" --bootclasspath PATH Override built-in class path\n"));
2342 printf (_(" --extdirs PATH Set extensions directory path\n"));
2343 printf (_(" -d DIRECTORY Set output directory name\n"));
2344 printf (_(" -o FILE Set output file name\n"));
2345 printf (_(" -td DIRECTORY Set temporary directory name\n"));
2347 printf (_(" --help Print this help, then exit\n"));
2348 printf (_(" --version Print version number, then exit\n"));
2349 printf (_(" -v, --verbose Print extra information while running\n"));
2351 printf (_(" -M Print all dependencies to stdout;\n"
2352 " suppress ordinary output\n"));
2353 printf (_(" -MM Print non-system dependencies to stdout;\n"
2354 " suppress ordinary output\n"));
2355 printf (_(" -MD Print all dependencies to stdout\n"));
2356 printf (_(" -MMD Print non-system dependencies to stdout\n"));
2357 /* We omit -MG until it is implemented. */
2359 printf (_("For bug reporting instructions, please see:\n"
2360 "%s.\n"), bug_report_url
);
2367 printf ("gcjh (GCC) %s\n\n", version_string
);
2368 printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
2369 printf (_("This is free software; see the source for copying conditions. There is NO\n"
2370 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
2375 main (int argc
, char** argv
)
2379 char *output_file
= NULL
;
2380 int emit_dependencies
= 0, suppress_output
= 0;
2383 gcc_init_libintl ();
2387 error ("no classes specified");
2393 /* We use getopt_long_only to allow single `-' long options. For
2394 some of our options this is more natural. */
2395 while ((opt
= getopt_long_only (argc
, argv
, "I:d:o:v", options
, NULL
)) != -1)
2400 /* Already handled. */
2404 output_file
= optarg
;
2408 output_directory
= optarg
;
2412 jcf_path_include_arg (optarg
);
2420 jcf_path_classpath_arg (optarg
);
2423 case OPT_bootclasspath
:
2424 jcf_path_bootclasspath_arg (optarg
);
2428 jcf_path_extdirs_arg (optarg
);
2436 temp_directory
= optarg
;
2444 if (prepend_count
== 0)
2445 prepend_specs
= ALLOC (argc
* sizeof (char*));
2446 prepend_specs
[prepend_count
++] = optarg
;
2450 if (friend_count
== 0)
2451 friend_specs
= ALLOC (argc
* sizeof (char*));
2452 friend_specs
[friend_count
++] = optarg
;
2457 add_specs
= ALLOC (argc
* sizeof (char*));
2458 add_specs
[add_count
++] = optarg
;
2462 if (append_count
== 0)
2463 append_specs
= ALLOC (argc
* sizeof (char*));
2464 append_specs
[append_count
++] = optarg
;
2468 emit_dependencies
= 1;
2469 suppress_output
= 1;
2470 jcf_dependency_init (1);
2474 emit_dependencies
= 1;
2475 suppress_output
= 1;
2476 jcf_dependency_init (0);
2480 error ("'-MG' option is unimplemented");
2484 emit_dependencies
= 1;
2485 jcf_dependency_init (1);
2489 emit_dependencies
= 1;
2490 jcf_dependency_init (0);
2501 error ("no classes specified");
2505 jcf_path_seal (verbose
);
2507 if (output_file
&& emit_dependencies
)
2509 error ("can't specify both -o and -MD");
2513 for (argi
= optind
; argi
< argc
; argi
++)
2515 char *classname
= argv
[argi
];
2516 char *current_output_file
;
2517 const char *classfile_name
;
2520 printf (_("Processing %s\n"), classname
);
2522 jcf_dependency_reset ();
2523 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 0);
2524 if (classfile_name
== NULL
)
2526 error ("%s: no such class", classname
);
2530 printf (_("Found in %s\n"), classfile_name
);
2533 if (strcmp (output_file
, "-") == 0)
2535 else if (out
== NULL
)
2537 out
= fopen (output_file
, "w");
2541 perror (output_file
);
2544 current_output_file
= output_file
;
2548 int dir_len
= strlen (output_directory
);
2549 int i
, classname_length
= strlen (classname
);
2550 current_output_file
= ALLOC (dir_len
+ classname_length
+ 5);
2551 strcpy (current_output_file
, output_directory
);
2552 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
2553 current_output_file
[dir_len
++] = '/';
2554 for (i
= 0; classname
[i
] != '\0'; i
++)
2556 char ch
= classname
[i
];
2559 if (flag_jni
&& ch
== '/')
2561 current_output_file
[dir_len
++] = ch
;
2563 if (emit_dependencies
)
2565 if (suppress_output
)
2567 jcf_dependency_set_dep_file ("-");
2572 /* We use `.hd' and not `.d' to avoid clashes with
2573 dependency tracking from straight compilation. */
2574 strcpy (current_output_file
+ dir_len
, ".hd");
2575 jcf_dependency_set_dep_file (current_output_file
);
2578 strcpy (current_output_file
+ dir_len
,
2579 stubs
? (flag_jni
? ".c" : ".cc") : ".h");
2580 jcf_dependency_set_target (current_output_file
);
2581 if (! suppress_output
)
2583 out
= fopen (current_output_file
, "w");
2586 perror (current_output_file
);
2591 free_method_name_list ();
2592 process_file (&jcf
, out
);
2594 if (current_output_file
!= output_file
)
2595 free (current_output_file
);
2596 jcf_dependency_write ();
2599 if (out
!= NULL
&& out
!= stdout
)