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, 2005
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
))
290 fprintf (stream
, "0x1.%.6xp%+df",
291 ((unsigned int)f
.mantissa
) << 1,
292 f
.exponent
- JFLOAT_EXP_BIAS
);
294 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
295 because the implicit leading 1 bit is no longer present. */
296 fprintf (stream
, "0x0.%.6xp%+df",
297 ((unsigned int)f
.mantissa
) << 1,
298 f
.exponent
+ 1 - JFLOAT_EXP_BIAS
);
302 fputs (";\n", stream
);
305 /* Print a double-precision float, suitable for parsing by g++. */
307 jni_print_double (FILE *stream
, jdouble f
)
309 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
310 work in data initializers. FIXME. */
311 if (JDOUBLE_FINITE (f
))
319 fprintf (stream
, "0x1.%.5x%.8xp%+d",
320 f
.mantissa0
, f
.mantissa1
,
321 f
.exponent
- JDOUBLE_EXP_BIAS
);
323 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
324 because the implicit leading 1 bit is no longer present. */
325 fprintf (stream
, "0x0.%.5x%.8xp%+d",
326 f
.mantissa0
, f
.mantissa1
,
327 f
.exponent
+ 1 - JDOUBLE_EXP_BIAS
);
330 fputs (flag_jni
? "\n" : ";\n", stream
);
333 /* Print a character, appropriately mangled for JNI. */
336 jni_print_char (FILE *stream
, int ch
)
339 jcf_print_char (stream
, ch
);
340 else if (ch
== '(' || ch
== ')')
345 fputs ("_1", stream
);
347 fputs ("_2", stream
);
349 fputs ("_3", stream
);
352 else if (ISALNUM (ch
))
356 /* "Unicode" character. */
357 fprintf (stream
, "_0%04x", ch
);
361 /* Print a name from the class data. If the index does not point to a
362 string, an error results. */
365 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
367 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
369 fprintf (stream
, "<not a UTF8 constant>");
373 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
374 JPOOL_UTF_LENGTH (jcf
, name_index
));
377 /* For JNI we must correctly quote each character. */
378 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, name_index
);
379 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
380 const unsigned char *limit
= str
+ length
;
383 int ch
= UTF8_GET (str
, limit
);
386 fprintf (stream
, "\\<invalid>");
389 jni_print_char (stream
, ch
);
394 /* Print base name of class. The base name is everything after the
398 print_base_classname (FILE *stream
, JCF
*jcf
, int index
)
400 int name_index
= JPOOL_USHORT1 (jcf
, index
);
402 const unsigned char *s
, *p
, *limit
;
404 s
= JPOOL_UTF_DATA (jcf
, name_index
);
405 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
410 int c
= UTF8_GET (s
, limit
);
417 int ch
= UTF8_GET (p
, limit
);
419 fputs ("::", stream
);
421 jcf_print_char (stream
, ch
);
425 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
426 and 1 if STR is "greater" than NAME. */
429 utf8_cmp (const unsigned char *str
, int length
, const char *name
)
431 const unsigned char *limit
= str
+ length
;
434 for (i
= 0; name
[i
]; ++i
)
436 int ch
= UTF8_GET (str
, limit
);
441 return str
== limit
? 0 : 1;
444 /* This is a sorted list of all C++ keywords. */
446 static const char *const cxx_keywords
[] =
555 /* If NAME is the name of a C++ keyword, then return an override name.
556 This is a name that can be used in place of the keyword.
557 Otherwise, return NULL. The return value is malloc()d. */
560 cxx_keyword_subst (const unsigned char *str
, int length
)
562 int last
= ARRAY_SIZE (cxx_keywords
);
564 int mid
= (last
+ first
) / 2;
567 for (mid
= (last
+ first
) / 2;
569 old
= mid
, mid
= (last
+ first
) / 2)
571 int kwl
= strlen (cxx_keywords
[mid
]);
572 int min_length
= kwl
> length
? length
: kwl
;
573 int r
= utf8_cmp (str
, min_length
, cxx_keywords
[mid
]);
579 /* Skip all trailing `$'. */
580 for (i
= min_length
; i
< length
&& str
[i
] == '$'; ++i
)
582 /* We've only found a match if all the remaining characters
586 char *dup
= xmalloc (2 + length
- min_length
+ kwl
);
587 strcpy (dup
, cxx_keywords
[mid
]);
588 for (i
= kwl
; i
< length
+ 1; ++i
)
604 /* Generate an access control keyword based on FLAGS. */
607 generate_access (FILE *stream
, JCF_u2 flags
)
609 if ((flags
& ACC_VISIBILITY
) == last_access
)
611 last_access
= (flags
& ACC_VISIBILITY
);
616 fputs ("public: // actually package-private\n", stream
);
619 fputs ("public:\n", stream
);
622 fputs ("private:\n", stream
);
625 fputs ("public: // actually protected\n", stream
);
629 fprintf (stream
, "#error unrecognized visibility %d\n",
630 (flags
& ACC_VISIBILITY
));
635 /* See if NAME is already the name of a method. */
637 name_is_method_p (const unsigned char *name
, int length
)
639 struct method_name
*p
;
641 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
643 if (p
->length
== length
&& ! memcmp (p
->name
, name
, length
))
649 /* Free the method name list. */
651 free_method_name_list (void)
653 struct method_name
*p
= method_name_list
;
656 struct method_name
*next
= p
->next
;
662 method_name_list
= NULL
;
665 /* If there is already a native method named NAME, whose signature is not
666 SIGNATURE, then return true. Otherwise return false. */
668 overloaded_jni_method_exists_p (const unsigned char *name
, int length
,
669 const char *signature
, int sig_length
)
671 struct method_name
*p
;
673 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
676 && p
->length
== length
677 && ! memcmp (p
->name
, name
, length
)
678 && (p
->sig_length
!= sig_length
679 || memcmp (p
->signature
, signature
, sig_length
)))
685 /* Get name of a field. This handles renamings due to C++ clash. */
687 get_field_name (JCF
*jcf
, int name_index
, JCF_u2 flags
)
689 unsigned char *name
= JPOOL_UTF_DATA (jcf
, name_index
);
690 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
693 if (name_is_method_p (name
, length
))
695 /* This field name matches a method. So override the name with
696 a dummy name. This is yucky, but it isn't clear what else to
697 do. FIXME: if the field is static, then we'll be in real
699 if ((flags
& ACC_STATIC
))
701 error ("static field has same name as method");
705 override
= xmalloc (length
+ 3);
706 memcpy (override
, name
, length
);
707 strcpy (override
+ length
, "__");
712 override
= cxx_keyword_subst (name
, length
);
717 /* Print a field name. Convenience function for use with
720 print_field_name (FILE *stream
, JCF
*jcf
, int name_index
, JCF_u2 flags
)
722 char *override
= get_field_name (jcf
, name_index
, flags
);
726 fputs (override
, stream
);
730 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
731 JPOOL_UTF_LENGTH (jcf
, name_index
));
735 print_field_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
738 char *override
= NULL
;
741 generate_access (stream
, flags
);
742 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
744 fprintf (stream
, "<not a UTF8 constant>");
751 /* For JNI we only want to print real constants. */
753 if (! (flags
& ACC_STATIC
)
754 || ! (flags
& ACC_FINAL
)
755 || current_field_value
<= 0)
757 val
= JPOOL_TAG (jcf
, current_field_value
);
758 if (val
!= CONSTANT_Integer
&& val
!= CONSTANT_Long
759 && val
!= CONSTANT_Float
&& val
!= CONSTANT_Double
)
764 /* Initial indentation. */
768 if ((flags
& ACC_STATIC
))
772 print_cxx_classname (stream
, "#undef ", jcf
, jcf
->this_class
, 1);
774 print_field_name (stream
, jcf
, name_index
, 0);
775 fputs ("\n", stream
);
776 print_cxx_classname (stream
, "#define ", jcf
, jcf
->this_class
, 1);
780 fputs ("static ", stream
);
782 if ((flags
& ACC_FINAL
) && current_field_value
> 0)
787 switch (JPOOL_TAG (jcf
, current_field_value
))
789 case CONSTANT_Integer
:
792 int most_negative
= 0;
794 fputs ("const jint ", stream
);
795 print_field_name (stream
, jcf
, name_index
, 0);
796 fputs (flag_jni
? " " : " = ", stream
);
797 num
= JPOOL_INT (jcf
, current_field_value
);
798 /* We single out the most negative number to print
799 specially. This avoids later warnings from g++. */
800 if (num
== (jint
) 0x80000000)
805 format_int (buffer
, (jlong
) num
, 10);
806 fprintf (stream
, "%sL%s%s\n", buffer
,
807 most_negative
? " - 1" : "",
808 flag_jni
? "" : ";");
814 int most_negative
= 0;
816 fputs ("const jlong ", stream
);
817 print_field_name (stream
, jcf
, name_index
, 0);
818 fputs (flag_jni
? " " : " = ", stream
);
819 num
= JPOOL_LONG (jcf
, current_field_value
);
820 /* We single out the most negative number to print
821 specially.. This avoids later warnings from g++. */
822 if (num
== (jlong
) 0x8000000000000000LL
)
827 format_int (buffer
, num
, 10);
828 fprintf (stream
, "%sLL%s%s\n", buffer
,
829 most_negative
? " - 1" :"",
830 flag_jni
? "" : ";");
835 jfloat fnum
= JPOOL_FLOAT (jcf
, current_field_value
);
837 fputs ("const jfloat ", stream
);
838 print_field_name (stream
, jcf
, name_index
, 0);
839 jni_print_float (stream
, fnum
);
842 case CONSTANT_Double
:
844 jdouble dnum
= JPOOL_DOUBLE (jcf
, current_field_value
);
846 fputs ("const jdouble ", stream
);
847 print_field_name (stream
, jcf
, name_index
, 0);
848 jni_print_double (stream
, dnum
);
852 /* We can't print this as a constant, but we can still
853 print something sensible. */
863 /* assert (! flag_jni); */
864 override
= get_field_name (jcf
, name_index
, flags
);
865 print_c_decl (stream
, jcf
, name_index
, sig_index
, 0, override
, flags
);
866 fputs (";\n", stream
);
874 print_method_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
877 const unsigned char *str
;
878 int length
, is_init
= 0;
879 char *override
= NULL
;
882 method_access
= flags
;
883 if (stream
&& JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
884 fprintf (stream
, "<not a UTF8 constant>");
885 str
= JPOOL_UTF_DATA (jcf
, name_index
);
886 length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
890 /* Ignore the internally generated method <clinit>. However,
891 treat <init> as a constructor. */
892 if (! utf8_cmp (str
, length
, "<init>"))
894 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
)
895 && ! (flags
& ACC_STATIC
))
897 /* FIXME: i18n bug here. Order of prints should not be
899 fprintf (stderr
, _("ignored method '"));
900 jcf_print_utf8 (stderr
, str
, length
);
901 fprintf (stderr
, _("' marked virtual\n"));
909 /* During the first method pass, build a list of method names. This will
910 be used to determine if field names conflict with method names. */
913 struct method_name
*nn
;
915 nn
= xmalloc (sizeof (struct method_name
));
916 nn
->name
= xmalloc (length
);
917 memcpy (nn
->name
, str
, length
);
919 nn
->next
= method_name_list
;
920 nn
->sig_length
= JPOOL_UTF_LENGTH (jcf
, sig_index
);
921 nn
->signature
= xmalloc (nn
->sig_length
);
922 nn
->is_native
= METHOD_IS_NATIVE (flags
);
923 memcpy (nn
->signature
, JPOOL_UTF_DATA (jcf
, sig_index
),
925 method_name_list
= nn
;
927 /* The rest of this function doesn't matter. */
931 /* We don't worry about overrides in JNI mode. */
934 /* We can't generate a method whose name is a C++ reserved word.
935 We can't just ignore the function, because that will cause
936 incorrect code to be generated if the function is virtual
937 (not only for calls to this function for for other functions
938 after it in the vtbl). So we give it a dummy name instead. */
939 override
= cxx_keyword_subst (str
, length
);
942 if (! stubs
&& ! flag_jni
)
946 generate_access (stream
, flags
);
949 if ((flags
& ACC_STATIC
))
950 fputs ("static ", out
);
951 else if (! METHOD_IS_PRIVATE (jcf
->access_flags
, flags
))
953 /* Don't print `virtual' if we have a constructor. */
955 fputs ("virtual ", out
);
957 print_c_decl (out
, jcf
, name_index
, sig_index
, is_init
, override
, flags
);
959 if ((flags
& ACC_ABSTRACT
))
966 if (METHOD_IS_NATIVE (flags
))
969 print_stub_or_jni (out
, jcf
, name_index
, sig_index
,
970 is_init
, override
, flags
);
978 /* A helper for the decompiler which prints a `return' statement where
979 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
980 identical, we emit a cast. We do this because the C++ compiler
981 doesn't know that a reference can be cast to the type of an
982 interface it implements. METHODTYPE is the index of the method's
983 signature. NAMEINDEX is the index of the field name; -1 for
984 `this'. OBJECTTYPE is the index of the object's type. */
986 decompile_return_statement (FILE *out
, JCF
*jcf
, int methodtype
,
987 int nameindex
, int objecttype
)
990 int obj_name_len
, method_name_len
;
991 const unsigned char *obj_data
, *method_data
;
993 obj_name_len
= JPOOL_UTF_LENGTH (jcf
, objecttype
);
994 obj_data
= JPOOL_UTF_DATA (jcf
, objecttype
);
996 method_name_len
= JPOOL_UTF_LENGTH (jcf
, methodtype
);
997 method_data
= JPOOL_UTF_DATA (jcf
, methodtype
);
999 /* Skip forward to return type part of method. */
1000 while (*method_data
!= ')')
1005 /* Skip past `)'. */
1009 /* If we see an `L', skip it and the trailing `;'. */
1010 if (method_data
[0] == 'L' && method_data
[method_name_len
- 1] == ';')
1013 method_name_len
-= 2;
1015 if (obj_data
[0] == 'L' && obj_data
[obj_name_len
- 1] == ';')
1021 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
1022 need a cast. Right now there is no way to determine if this is
1024 if (method_name_len
!= obj_name_len
)
1029 for (i
= 0; i
< method_name_len
; ++i
)
1031 if (method_data
[i
] != obj_data
[i
])
1039 fputs (" { return ", out
);
1043 int array_depth
= 0;
1044 const unsigned char *limit
;
1046 fputs ("reinterpret_cast<", out
);
1048 while (*method_data
== '[')
1053 fputs ("JArray<", out
);
1056 /* Leading space to avoid C++ digraphs. */
1059 /* If we see an `L', skip it and the trailing `;'. Only do this
1060 if we've seen an array specification. If we don't have an
1061 array then the `L' was stripped earlier. */
1062 if (array_depth
&& method_data
[0] == 'L'
1063 && method_data
[method_name_len
- 1] == ';')
1066 method_name_len
-= 2;
1069 limit
= method_data
+ method_name_len
;
1070 while (method_data
< limit
)
1072 int ch
= UTF8_GET (method_data
, limit
);
1076 jcf_print_char (out
, ch
);
1080 /* Close each array. */
1081 while (array_depth
> 0)
1087 /* Close the cast. */
1091 if (nameindex
== -1)
1092 fputs ("this", out
);
1094 print_field_name (out
, jcf
, nameindex
, 0);
1103 /* Try to decompile a method body. Right now we just try to handle a
1104 simple case that we can do. Expand as desired. */
1106 decompile_method (FILE *out
, JCF
*jcf
, int code_len
)
1108 const unsigned char *codes
= jcf
->read_ptr
;
1110 uint16 name_and_type
, name
;
1112 /* If the method is synchronized, don't touch it. */
1113 if ((method_access
& ACC_SYNCHRONIZED
))
1117 && codes
[0] == OPCODE_aload_0
1118 && codes
[1] == OPCODE_getfield
1119 && (codes
[4] == OPCODE_areturn
1120 || codes
[4] == OPCODE_dreturn
1121 || codes
[4] == OPCODE_freturn
1122 || codes
[4] == OPCODE_ireturn
1123 || codes
[4] == OPCODE_lreturn
))
1125 /* Found code like `return FIELD'. */
1126 index
= (codes
[2] << 8) | codes
[3];
1127 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1128 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
1129 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1130 name
= JPOOL_USHORT1 (jcf
, name_and_type
);
1131 if (codes
[4] == OPCODE_areturn
)
1132 decompile_return_statement (out
, jcf
, method_signature
,
1133 name
, JPOOL_USHORT2 (jcf
, name_and_type
));
1136 fputs (" { return ", out
);
1138 print_field_name (out
, jcf
, name
, 0);
1143 else if (code_len
== 2
1144 && codes
[0] == OPCODE_aload_0
1145 && codes
[1] == OPCODE_areturn
1146 /* We're going to generate `return this'. This only makes
1147 sense for non-static methods. */
1148 && ! (method_access
& ACC_STATIC
))
1150 decompile_return_statement (out
, jcf
, method_signature
, -1,
1151 JPOOL_USHORT1 (jcf
, jcf
->this_class
));
1154 else if (code_len
== 1 && codes
[0] == OPCODE_return
)
1156 /* Found plain `return'. */
1157 fputs (" { }", out
);
1160 else if (code_len
== 2
1161 && codes
[0] == OPCODE_aconst_null
1162 && codes
[1] == OPCODE_areturn
)
1164 /* Found `return null'. We don't want to depend on NULL being
1166 fputs (" { return 0; }", out
);
1171 /* Like strcmp, but invert the return result for the hash table. This
1172 should probably be in hashtab.c to complement the existing string
1175 gcjh_streq (const void *p1
, const void *p2
)
1177 return ! strcmp ((char *) p1
, (char *) p2
);
1180 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1181 or 0 if not. CLNAME may be extracted from a signature, and can be
1182 terminated with either `;' or NULL. */
1184 throwable_p (const unsigned char *clname
)
1187 unsigned char *current
;
1191 /* We keep two hash tables of class names. In one we list all the
1192 classes which are subclasses of Throwable. In the other we will
1193 all other classes. We keep two tables to make the code a bit
1194 simpler; we don't have to have a structure mapping class name to
1195 a `throwable?' bit. */
1196 static htab_t throw_hash
;
1197 static htab_t non_throw_hash
;
1198 static int init_done
= 0;
1205 /* Self-initializing. The cost of this really doesn't matter.
1206 We also don't care about freeing these, either. */
1207 throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1209 non_throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1212 /* Make sure the root classes show up in the tables. */
1213 str
= (unsigned char *) xstrdup ("java.lang.Throwable");
1214 slot
= htab_find_slot (throw_hash
, str
, INSERT
);
1217 str
= (unsigned char *) xstrdup ("java.lang.Object");
1218 slot
= htab_find_slot (non_throw_hash
, str
, INSERT
);
1224 for (length
= 0; clname
[length
] != ';' && clname
[length
] != '\0'; ++length
)
1226 current
= ALLOC (length
+ 1);
1227 for (i
= 0; i
< length
; ++i
)
1228 current
[i
] = clname
[i
] == '/' ? '.' : clname
[i
];
1229 current
[length
] = '\0';
1231 /* We don't compute the hash slot here because the table might be
1232 modified by the recursion. In that case the slot could be
1234 if (htab_find (throw_hash
, current
))
1236 else if (htab_find (non_throw_hash
, current
))
1242 unsigned char *super
, *tmp
;
1243 int super_length
= -1;
1244 const char *classfile_name
= find_class ((char *) current
, strlen ((const char *) current
),
1247 if (! classfile_name
)
1249 error ("couldn't find class %s", current
);
1252 if (jcf_parse_preamble (&jcf
) != 0
1253 || jcf_parse_constant_pool (&jcf
) != 0
1254 || verify_constant_pool (&jcf
) > 0)
1256 error ("parse error while reading %s", classfile_name
);
1259 jcf_parse_class (&jcf
);
1261 tmp
= (unsigned char *) super_class_name (&jcf
, &super_length
);
1262 super
= ALLOC (super_length
+ 1);
1263 memcpy (super
, tmp
, super_length
);
1264 super
[super_length
] = '\0';
1266 result
= throwable_p (super
);
1267 slot
= htab_find_slot (result
? throw_hash
: non_throw_hash
,
1278 /* Print one piece of a signature. Returns pointer to next parseable
1279 character on success, NULL on error. */
1280 static const unsigned char *
1281 decode_signature_piece (FILE *stream
, const unsigned char *signature
,
1282 const unsigned char *limit
, int *need_space
)
1285 int array_depth
= 0;
1287 switch (signature
[0])
1290 /* More spaghetti. */
1293 for (signature
++; (signature
< limit
1294 && ISDIGIT (*signature
)); signature
++)
1299 ctype
= "jbyteArray";
1302 ctype
= "jcharArray";
1305 ctype
= "jdoubleArray";
1308 ctype
= "jfloatArray";
1311 ctype
= "jintArray";
1314 ctype
= "jshortArray";
1317 ctype
= "jlongArray";
1320 ctype
= "jbooleanArray";
1323 /* We have a nested array. */
1326 fputs ("JArray<", stream
);
1330 /* We have to generate a reference to JArray here, so that
1331 our output matches what the compiler does. */
1333 /* Space between `<' and `:' to avoid C++ digraphs. */
1335 fputs ("JArray< ::", stream
);
1336 while (signature
< limit
&& *signature
!= ';')
1338 int ch
= UTF8_GET (signature
, limit
);
1342 fputs ("::", stream
);
1344 jcf_print_char (stream
, ch
);
1348 fputs (" *> *", stream
);
1353 /* Unparseable signature. */
1357 /* If the previous iterations left us with something to print,
1358 print it. For JNI, we always print `jobjectArray' in the
1360 if (flag_jni
&& (ctype
== NULL
|| array_depth
> 0))
1362 ctype
= "jobjectArray";
1365 /* The `printit' case will advance SIGNATURE for us. If we
1366 don't go there, we must advance past the `;' ourselves. */
1374 /* This shouldn't happen. */
1377 case 'B': ctype
= "jbyte"; goto printit
;
1378 case 'C': ctype
= "jchar"; goto printit
;
1379 case 'D': ctype
= "jdouble"; goto printit
;
1380 case 'F': ctype
= "jfloat"; goto printit
;
1381 case 'I': ctype
= "jint"; goto printit
;
1382 case 'J': ctype
= "jlong"; goto printit
;
1383 case 'S': ctype
= "jshort"; goto printit
;
1384 case 'Z': ctype
= "jboolean"; goto printit
;
1385 case 'V': ctype
= "void"; goto printit
;
1389 /* We know about certain types and special-case their names. */
1390 if (! strncmp ((const char *) signature
, "Ljava/lang/String;",
1391 sizeof ("Ljava/lang/String;") -1))
1393 else if (! strncmp ((const char *) signature
, "Ljava/lang/Class;",
1394 sizeof ("Ljava/lang/Class;") - 1))
1396 /* Skip leading 'L' for throwable_p call. */
1397 else if (throwable_p (signature
+ 1))
1398 ctype
= "jthrowable";
1402 while (*signature
&& *signature
!= ';')
1407 /* Print a leading "::" so we look in the right namespace. */
1408 fputs ("::", stream
);
1410 while (*signature
&& *signature
!= ';')
1412 int ch
= UTF8_GET (signature
, limit
);
1414 fputs ("::", stream
);
1416 jcf_print_char (stream
, ch
);
1418 fputs (" *", stream
);
1419 if (*signature
== ';')
1425 jni_print_char (stream
, *signature
++);
1430 fputs (ctype
, stream
);
1436 while (array_depth
-- > 0)
1437 fputs ("> *", stream
);
1444 print_c_decl (FILE* stream
, JCF
* jcf
, int name_index
, int signature_index
,
1445 int is_init
, const char *name_override
, int flags
)
1447 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1449 fprintf (stream
, "<not a UTF8 constant>");
1454 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1455 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1456 const unsigned char *str
= str0
;
1457 const unsigned char *limit
= str
+ length
;
1459 int is_method
= str
[0] == '(';
1460 const unsigned char *next
;
1462 /* If printing a method, skip to the return signature and print
1463 that first. However, there is no return value if this is a
1465 if (is_method
&& ! is_init
)
1475 /* If printing a field or an ordinary method, then print the
1476 "return value" now. */
1477 if (! is_method
|| ! is_init
)
1479 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1482 error ("unparseable signature: '%s'", str0
);
1487 /* Force the alignment of the first data member. This is
1488 because the "new" C++ ABI changed the alignment of non-POD
1489 classes. gcj, however, still uses the "old" alignment. */
1490 if (is_first_data_member
&& ! (flags
& ACC_STATIC
) && ! is_method
)
1492 is_first_data_member
= 0;
1493 print_cxx_classname (out
, " __attribute__((aligned(__alignof__( ",
1494 jcf
, jcf
->super_class
, 1);
1495 fputs (" )))) ", stream
);
1498 /* Now print the name of the thing. */
1500 fputs (" ", stream
);
1501 print_full_cxx_name (stream
, jcf
, name_index
,
1502 signature_index
, is_init
, name_override
,
1507 /* Print the unqualified method name followed by the signature. */
1509 print_full_cxx_name (FILE* stream
, JCF
* jcf
, int name_index
,
1510 int signature_index
, int is_init
,
1511 const char *name_override
, int flags
)
1513 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1514 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1515 const unsigned char *str
= str0
;
1516 const unsigned char *limit
= str
+ length
;
1518 int is_method
= str
[0] == '(';
1519 const unsigned char *next
;
1522 fputs (name_override
, stream
);
1523 else if (name_index
)
1525 /* Declare constructors specially. */
1527 print_base_classname (stream
, jcf
, jcf
->this_class
);
1529 print_name (stream
, jcf
, name_index
);
1534 unsigned char *signature
= JPOOL_UTF_DATA (jcf
, signature_index
);
1535 int sig_len
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1536 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf
, name_index
),
1537 JPOOL_UTF_LENGTH (jcf
, name_index
),
1538 (const char *) signature
, sig_len
))
1540 /* If this method is overloaded by another native method,
1541 then include the argument information in the mangled
1543 unsigned char *limit
= signature
+ sig_len
;
1544 fputs ("__", stream
);
1545 while (signature
< limit
)
1547 int ch
= UTF8_GET (signature
, limit
);
1548 jni_print_char (stream
, ch
);
1560 /* Have a method or a constructor. Print signature pieces
1562 fputs (" (", stream
);
1566 /* In JNI mode, add extra arguments. */
1569 /* FIXME: it would be nice to know if we are printing a decl
1570 or a definition, and only print `env' for the latter. */
1571 fputs ("JNIEnv *env", stream
);
1573 fputs ((flags
& ACC_STATIC
) ? ", jclass" : ", jobject", stream
);
1576 fputs (", ", stream
);
1579 while (str
< limit
&& *str
!= ')')
1581 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1584 error ("unparseable signature: '%s'", str0
);
1588 if (next
< limit
&& *next
!= ')')
1589 fputs (", ", stream
);
1593 fputs (")", stream
);
1597 /* This is a helper for print_stub_or_jni. */
1599 print_name_for_stub_or_jni (FILE *stream
, JCF
*jcf
, int name_index
,
1600 int signature_index
, int is_init
,
1601 const char *name_override
, int flags
)
1603 const char *const prefix
= flag_jni
? "Java_" : "";
1604 print_cxx_classname (stream
, prefix
, jcf
, jcf
->this_class
, 1);
1605 fputs (flag_jni
? "_" : "::", stream
);
1606 print_full_cxx_name (stream
, jcf
, name_index
,
1607 signature_index
, is_init
, name_override
,
1612 print_stub_or_jni (FILE* stream
, JCF
* jcf
, int name_index
,
1613 int signature_index
, int is_init
,
1614 const char *name_override
, int flags
)
1616 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1618 fprintf (stream
, "<not a UTF8 constant>");
1623 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1624 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1625 const unsigned char *str
= str0
;
1626 const unsigned char *limit
= str
+ length
;
1628 int is_method
= str
[0] == '(';
1629 const unsigned char *next
;
1631 /* Don't print fields in the JNI case. */
1632 if (! is_method
&& flag_jni
)
1635 if (flag_jni
&& ! stubs
)
1636 fputs ("JNIEXPORT ", stream
);
1638 /* If printing a method, skip to the return signature and print
1639 that first. However, there is no return value if this is a
1641 if (is_method
&& ! is_init
)
1651 /* If printing a field or an ordinary method, then print the
1652 "return value" now. Note that a constructor can't be native,
1653 so we don't bother checking this in the JNI case. */
1654 if (! is_method
|| ! is_init
)
1656 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1659 error ("unparseable signature: '%s'", str0
);
1664 /* When printing a JNI header we need to respect the space. In
1665 other cases we're just going to insert a newline anyway. */
1666 fputs (need_space
&& ! stubs
? " " : "\n", stream
);
1668 if (flag_jni
&& ! stubs
)
1669 fputs ("JNICALL ", stream
);
1671 /* Now print the name of the thing. */
1672 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1673 signature_index
, is_init
, name_override
,
1676 /* Print the body. */
1680 fputs ("\n{\n (*env)->FatalError (env, \"", stream
);
1682 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream
);
1683 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1684 signature_index
, is_init
,
1687 fprintf (stream
, " not implemented\")%s;\n}\n\n",
1688 flag_jni
? "" : ")");
1694 print_mangled_classname (FILE *stream
, JCF
*jcf
, const char *prefix
, int index
)
1696 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1697 fputs (prefix
, stream
);
1698 jcf_print_utf8_replace (out
,
1699 JPOOL_UTF_DATA (jcf
, name_index
),
1700 JPOOL_UTF_LENGTH (jcf
, name_index
),
1704 /* Print PREFIX, then a class name in C++ format. If the name refers
1705 to an array, ignore it and don't print PREFIX. Returns 1 if
1706 something was printed, 0 otherwise. */
1708 print_cxx_classname (FILE *stream
, const char *prefix
,
1709 JCF
*jcf
, int index
, int add_scope
)
1711 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1713 const unsigned char *s
, *p
, *limit
;
1715 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1716 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1719 /* Explicitly omit arrays here. */
1721 c
= UTF8_GET (p
, limit
);
1725 fputs (prefix
, stream
);
1727 /* Print a leading "::" so we look in the right namespace. */
1728 if (! flag_jni
&& ! stubs
&& add_scope
)
1729 fputs ("::", stream
);
1733 c
= UTF8_GET (s
, limit
);
1735 fputs (flag_jni
? "_" : "::", stream
);
1737 jni_print_char (stream
, c
);
1743 int written_class_count
= 0;
1745 /* Return name of superclass. If LEN is not NULL, fill it with length
1747 static const unsigned char *
1748 super_class_name (JCF
*derived_jcf
, int *len
)
1750 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
1751 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
1752 const unsigned char *supername
=
1753 JPOOL_UTF_DATA (derived_jcf
, supername_index
);
1756 *len
= supername_length
;
1762 handle_inner_classes (int count
)
1766 if (out
&& ! flag_jni
&& ! stubs
&& count
> 0)
1767 fprintf (out
, "\n");
1769 for (i
= 0; i
< count
; ++i
)
1771 JCF_u2 inner_info_index
= JCF_readu2 (current_jcf
);
1773 /* There are a few more values here, but we don't care about
1774 them. The (void) cast is apparently the only way to avoid a
1776 (void) JCF_readu2 (current_jcf
);
1777 (void) JCF_readu2 (current_jcf
);
1778 (void) JCF_readu2 (current_jcf
);
1780 if (out
&& ! flag_jni
&& ! stubs
)
1782 print_mangled_classname (out
, current_jcf
, " friend class ",
1784 fprintf (out
, ";\n");
1791 /* We keep track of all the `#include's we generate, so we can avoid
1796 struct include
*next
;
1799 /* List of all includes. */
1800 static struct include
*all_includes
= NULL
;
1802 /* Generate a #include. */
1804 print_include (FILE *out
, const unsigned char *utf8
, int len
)
1806 struct include
*incl
;
1812 len
= strlen ((const char *) utf8
);
1814 for (incl
= all_includes
; incl
; incl
= incl
->next
)
1816 /* We check the length because we might have a proper prefix. */
1817 if (len
== (int) strlen (incl
->name
)
1818 && ! strncmp (incl
->name
, (const char *) utf8
, len
))
1822 incl
= xmalloc (sizeof (struct include
));
1823 incl
->name
= xmalloc (len
+ 1);
1824 strncpy (incl
->name
, (const char *) utf8
, len
);
1825 incl
->name
[len
] = '\0';
1826 incl
->next
= all_includes
;
1827 all_includes
= incl
;
1829 fputs ("#include <", out
);
1830 jcf_print_utf8_replace (out
, utf8
, len
,
1832 flag_jni
? '_' : '/');
1833 fputs (".h>\n", out
);
1838 /* This is used to represent part of a package or class name. */
1841 /* The text of this part of the name. */
1843 /* True if this represents a class. */
1845 /* Linked list of all classes and packages inside this one. */
1846 struct namelet
*subnamelets
;
1847 /* Pointer to next sibling. */
1848 struct namelet
*next
;
1851 static void add_namelet (const unsigned char *, const unsigned char *,
1853 static void print_namelet (FILE *, struct namelet
*, int);
1855 /* The special root namelet. */
1856 static struct namelet root
=
1864 /* This extracts the next name segment from the full UTF-8 encoded
1865 package or class name and links it into the tree. It does this
1868 add_namelet (const unsigned char *name
, const unsigned char *name_limit
,
1869 struct namelet
*parent
)
1871 const unsigned char *p
;
1872 struct namelet
*n
= NULL
, *np
;
1874 /* We want to skip the standard namespaces that we assume the
1875 runtime already knows about. We only do this at the top level,
1876 though, hence the check for `root'. */
1877 if (parent
== &root
)
1879 #define JAVALANG "java/lang/"
1880 #define JAVAIO "java/io/"
1881 #define JAVAUTIL "java/util/"
1882 if ((name_limit
- name
>= (int) sizeof (JAVALANG
) - 1
1883 && ! strncmp ((const char *) name
, JAVALANG
, sizeof (JAVALANG
) - 1))
1884 || (name_limit
- name
>= (int) sizeof (JAVAUTIL
) - 1
1885 && ! strncmp ((const char *) name
, JAVAUTIL
, sizeof (JAVAUTIL
) - 1))
1886 || (name_limit
- name
>= (int) sizeof (JAVAIO
) - 1
1887 && ! strncmp ((const char *) name
, JAVAIO
, sizeof (JAVAIO
) - 1)))
1891 for (p
= name
; p
< name_limit
&& *p
!= '/'; ++p
)
1894 /* Search for this name beneath the PARENT node. */
1895 for (np
= parent
->subnamelets
; np
!= NULL
; np
= np
->next
)
1897 /* We check the length because we might have a proper prefix. */
1898 if ((int) strlen (np
->name
) == p
- name
&&
1899 ! strncmp ((const char *) name
, np
->name
, p
- name
))
1908 n
= xmalloc (sizeof (struct namelet
));
1909 n
->name
= xmalloc (p
- name
+ 1);
1910 strncpy (n
->name
, (const char *) name
, p
- name
);
1911 n
->name
[p
- name
] = '\0';
1912 n
->is_class
= (p
== name_limit
);
1913 n
->subnamelets
= NULL
;
1914 n
->next
= parent
->subnamelets
;
1915 parent
->subnamelets
= n
;
1918 /* We recurse if there is more text, and if the trailing piece does
1919 not represent an inner class. */
1921 add_namelet (p
+ 1, name_limit
, n
);
1924 /* Print a single namelet. Destroys namelets while printing. */
1926 print_namelet (FILE *out
, struct namelet
*name
, int depth
)
1933 for (i
= 0; i
< depth
; ++i
)
1935 fprintf (out
, "%s %s", name
->is_class
? "class" : "namespace",
1937 if (name
->is_class
&& name
->subnamelets
== NULL
)
1943 for (i
= 0; i
< depth
; ++i
)
1949 c
= name
->subnamelets
;
1952 struct namelet
*next
= c
->next
;
1953 print_namelet (out
, c
, depth
+ 2);
1956 name
->subnamelets
= NULL
;
1962 for (i
= 0; i
< depth
; ++i
)
1965 /* Only print a `;' when printing a class. C++ is evil. */
1975 /* This is called to add some classes to the list of classes for which
1976 we need decls. The signature argument can be a function
1979 add_class_decl (FILE *out
, JCF
*jcf
, JCF_u2 signature
)
1981 const unsigned char *s
= JPOOL_UTF_DATA (jcf
, signature
);
1982 int len
= JPOOL_UTF_LENGTH (jcf
, signature
);
1985 for (i
= 0; i
< len
; ++i
)
1989 /* If we see an array, then we include the array header. */
1992 print_include (out
, (const unsigned char *) "gcj/array", -1);
1996 /* We're looking for `L<stuff>;' -- everything else is
2001 for (start
= ++i
; i
< len
&& s
[i
] != ';'; ++i
)
2004 add_namelet (&s
[start
], &s
[i
], &root
);
2008 /* Print declarations for all classes required by this class. Any
2009 class or package in the `java' package is assumed to be handled
2010 statically in libjava; we don't generate declarations for these.
2011 This makes the generated headers a bit easier to read. */
2013 print_class_decls (FILE *out
, JCF
*jcf
, int self
)
2015 /* Make sure to always add the current class to the list of things
2016 that should be declared. */
2017 int name_index
= JPOOL_USHORT1 (jcf
, self
);
2019 const unsigned char *s
;
2021 s
= JPOOL_UTF_DATA (jcf
, name_index
);
2022 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
2023 add_namelet (s
, s
+ len
, &root
);
2025 if (root
.subnamelets
)
2027 fputs ("extern \"Java\"\n{\n", out
);
2028 /* We use an initial offset of 0 because the root namelet
2029 doesn't cause anything to print. */
2030 print_namelet (out
, &root
, 0);
2031 fputs ("}\n\n", out
);
2038 process_file (JCF
*jcf
, FILE *out
)
2041 uint32 field_start
, method_end
, method_start
;
2047 if (jcf_parse_preamble (jcf
) != 0)
2049 error ("Not a valid Java .class file.");
2053 /* Parse and possibly print constant pool */
2054 code
= jcf_parse_constant_pool (jcf
);
2057 error ("error while parsing constant pool");
2060 code
= verify_constant_pool (jcf
);
2063 error ("error in constant pool entry #%d", code
);
2067 jcf_parse_class (jcf
);
2069 if (written_class_count
++ == 0 && out
)
2071 const char *cstart
, *cstart2
, *mode
, *cend
, *what
, *jflag
;
2086 mode
= " -*- c++ -*-";
2092 fprintf (out
, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2093 cstart
, mode
, cend
);
2096 fprintf (out
, "%s This file was created by `gcjh -stubs%s'.%s\n\
2098 %s This file is intended to give you a head start on implementing native\n\
2099 %s methods using %s.\n\
2100 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2101 %s overwrite any edits you have made to this file.%s\n\n",
2102 cstart
, jflag
, mode
,
2118 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
2119 fprintf (out
, "__\n");
2121 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
2122 fprintf (out
, "__\n\n");
2126 fprintf (out
, "#include <jni.h>\n\n");
2127 fprintf (out
, "#ifdef __cplusplus\n");
2128 fprintf (out
, "extern \"C\"\n");
2129 fprintf (out
, "{\n");
2130 fprintf (out
, "#endif\n");
2134 /* We do this to ensure that inline methods won't be
2135 `outlined' by g++. This works as long as method and
2136 fields are not added by the user. */
2137 fprintf (out
, "#pragma interface\n");
2139 if (jcf
->super_class
)
2142 const unsigned char *supername
=
2143 super_class_name (jcf
, &super_length
);
2146 print_include (out
, supername
, super_length
);
2152 /* Strip off the ".class" portion of the name when printing
2153 the include file name. */
2155 int i
, len
= strlen (jcf
->classname
);
2156 if (len
> 6 && ! strcmp (&jcf
->classname
[len
- 6], ".class"))
2158 /* Turn the class name into a file name. */
2159 name
= xmalloc (len
+ 1);
2160 for (i
= 0; i
< len
; ++i
)
2161 name
[i
] = jcf
->classname
[i
] == '.' ? '/' : jcf
->classname
[i
];
2163 print_include (out
, (const unsigned char *) name
, len
);
2168 print_include (out
, (const unsigned char *) "gcj/cni", -1);
2169 print_include (out
, (const unsigned char *) "java/lang/UnsupportedOperationException",
2175 /* We want to parse the methods first. But we need to find where
2176 they start. So first we skip the fields, then parse the methods.
2177 Then we parse the fields and skip the methods. This is ugly, but
2178 not too bad since we need two full passes to get class decl
2179 information anyway. */
2181 field_start
= JCF_TELL (jcf
);
2182 jcf_parse_fields (jcf
);
2184 method_start
= JCF_TELL (jcf
);
2186 jcf_parse_methods (jcf
);
2191 if (out
&& ! flag_jni
)
2194 print_class_decls (out
, jcf
, jcf
->this_class
);
2196 for (i
= 0; i
< prepend_count
; ++i
)
2197 fprintf (out
, "%s\n", prepend_specs
[i
]);
2198 if (prepend_count
> 0)
2203 if (! print_cxx_classname (out
, "class ", jcf
,
2204 jcf
->this_class
, 0))
2206 error ("class is of array type\n");
2209 if (jcf
->super_class
)
2211 if (! print_cxx_classname (out
, " : public ",
2212 jcf
, jcf
->super_class
, 1))
2214 error ("base class is of array type");
2219 fputs ("\n{\n", out
);
2223 /* Now go back for second pass over methods and fields. */
2224 is_first_data_member
= 1;
2226 JCF_SEEK (jcf
, method_start
);
2228 jcf_parse_methods (jcf
);
2229 method_end
= JCF_TELL (jcf
);
2232 JCF_SEEK (jcf
, field_start
);
2233 jcf_parse_fields (jcf
);
2234 JCF_SEEK (jcf
, method_end
);
2236 jcf_parse_final_attributes (jcf
);
2242 fprintf (out
, "\n#ifdef __cplusplus\n");
2243 fprintf (out
, "}\n");
2244 fprintf (out
, "#endif\n");
2248 /* Generate friend decl if we still must. */
2249 for (i
= 0; i
< friend_count
; ++i
)
2250 fprintf (out
, " friend %s\n", friend_specs
[i
]);
2252 /* Generate extra declarations. */
2255 for (i
= 0; i
< add_count
; ++i
)
2256 fprintf (out
, " %s\n", add_specs
[i
]);
2258 /* Generate an entry for the class object. */
2259 generate_access (out
, ACC_PUBLIC
);
2260 fprintf (out
, "\n static ::java::lang::Class class$;\n");
2264 if (jcf
->access_flags
& ACC_INTERFACE
)
2265 fputs (" __attribute__ ((java_interface))", out
);
2269 if (append_count
> 0)
2271 for (i
= 0; i
< append_count
; ++i
)
2272 fprintf (out
, "%s\n", append_specs
[i
]);
2275 print_mangled_classname (out
, jcf
,
2276 "\n#endif /* __", jcf
->this_class
);
2277 fprintf (out
, "__ */\n");
2283 /* This is used to mark options with no short value. */
2284 #define LONG_OPT(Num) ((Num) + 128)
2286 #define OPT_classpath LONG_OPT (0)
2287 #define OPT_CLASSPATH OPT_classpath
2288 #define OPT_bootclasspath LONG_OPT (1)
2289 #define OPT_extdirs LONG_OPT (2)
2290 #define OPT_HELP LONG_OPT (3)
2291 #define OPT_TEMP LONG_OPT (4)
2292 #define OPT_VERSION LONG_OPT (5)
2293 #define OPT_PREPEND LONG_OPT (6)
2294 #define OPT_FRIEND LONG_OPT (7)
2295 #define OPT_ADD LONG_OPT (8)
2296 #define OPT_APPEND LONG_OPT (9)
2297 #define OPT_M LONG_OPT (10)
2298 #define OPT_MM LONG_OPT (11)
2299 #define OPT_MG LONG_OPT (12)
2300 #define OPT_MD LONG_OPT (13)
2301 #define OPT_MMD LONG_OPT (14)
2303 static const struct option options
[] =
2305 { "classpath", required_argument
, NULL
, OPT_classpath
},
2306 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
2307 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
2308 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
2309 { "help", no_argument
, NULL
, OPT_HELP
},
2310 { "stubs", no_argument
, &stubs
, 1 },
2311 { "td", required_argument
, NULL
, OPT_TEMP
},
2312 { "verbose", no_argument
, NULL
, 'v' },
2313 { "version", no_argument
, NULL
, OPT_VERSION
},
2314 { "prepend", required_argument
, NULL
, OPT_PREPEND
},
2315 { "friend", required_argument
, NULL
, OPT_FRIEND
},
2316 { "add", required_argument
, NULL
, OPT_ADD
},
2317 { "append", required_argument
, NULL
, OPT_APPEND
},
2318 { "M", no_argument
, NULL
, OPT_M
},
2319 { "MM", no_argument
, NULL
, OPT_MM
},
2320 { "MG", no_argument
, NULL
, OPT_MG
},
2321 { "MD", no_argument
, NULL
, OPT_MD
},
2322 { "MMD", no_argument
, NULL
, OPT_MMD
},
2323 { "jni", no_argument
, &flag_jni
, 1 },
2324 { NULL
, no_argument
, NULL
, 0 }
2330 fprintf (stderr
, _("Try 'gcjh --help' for more information.\n"));
2337 printf (_("Usage: gcjh [OPTION]... CLASS...\n\n"));
2338 printf (_("Generate C++ header files from .class files\n\n"));
2339 printf (_(" -stubs Generate an implementation stub file\n"));
2340 printf (_(" -jni Generate a JNI header or stub\n"));
2342 printf (_(" -add TEXT Insert TEXT into class body\n"));
2343 printf (_(" -append TEXT Insert TEXT after class declaration\n"));
2344 printf (_(" -friend TEXT Insert TEXT as 'friend' declaration\n"));
2345 printf (_(" -prepend TEXT Insert TEXT before start of class\n"));
2347 printf (_(" --classpath PATH Set path to find .class files\n"));
2348 printf (_(" -IDIR Append directory to class path\n"));
2349 printf (_(" --bootclasspath PATH Override built-in class path\n"));
2350 printf (_(" --extdirs PATH Set extensions directory path\n"));
2351 printf (_(" -d DIRECTORY Set output directory name\n"));
2352 printf (_(" -o FILE Set output file name\n"));
2353 printf (_(" -td DIRECTORY Set temporary directory name\n"));
2355 printf (_(" --help Print this help, then exit\n"));
2356 printf (_(" --version Print version number, then exit\n"));
2357 printf (_(" -v, --verbose Print extra information while running\n"));
2359 printf (_(" -M Print all dependencies to stdout;\n"
2360 " suppress ordinary output\n"));
2361 printf (_(" -MM Print non-system dependencies to stdout;\n"
2362 " suppress ordinary output\n"));
2363 printf (_(" -MD Print all dependencies to stdout\n"));
2364 printf (_(" -MMD Print non-system dependencies to stdout\n"));
2365 /* We omit -MG until it is implemented. */
2367 printf (_("For bug reporting instructions, please see:\n"
2368 "%s.\n"), bug_report_url
);
2375 printf ("gcjh (GCC) %s\n\n", version_string
);
2376 printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
2377 printf (_("This is free software; see the source for copying conditions. There is NO\n"
2378 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
2383 main (int argc
, char** argv
)
2387 char *output_file
= NULL
;
2388 int emit_dependencies
= 0, suppress_output
= 0;
2391 gcc_init_libintl ();
2395 error ("no classes specified");
2401 /* We use getopt_long_only to allow single `-' long options. For
2402 some of our options this is more natural. */
2403 while ((opt
= getopt_long_only (argc
, argv
, "I:d:o:v", options
, NULL
)) != -1)
2408 /* Already handled. */
2412 output_file
= optarg
;
2416 output_directory
= optarg
;
2420 jcf_path_include_arg (optarg
);
2428 jcf_path_classpath_arg (optarg
);
2431 case OPT_bootclasspath
:
2432 jcf_path_bootclasspath_arg (optarg
);
2436 jcf_path_extdirs_arg (optarg
);
2444 temp_directory
= optarg
;
2452 if (prepend_count
== 0)
2453 prepend_specs
= ALLOC (argc
* sizeof (char*));
2454 prepend_specs
[prepend_count
++] = optarg
;
2458 if (friend_count
== 0)
2459 friend_specs
= ALLOC (argc
* sizeof (char*));
2460 friend_specs
[friend_count
++] = optarg
;
2465 add_specs
= ALLOC (argc
* sizeof (char*));
2466 add_specs
[add_count
++] = optarg
;
2470 if (append_count
== 0)
2471 append_specs
= ALLOC (argc
* sizeof (char*));
2472 append_specs
[append_count
++] = optarg
;
2476 emit_dependencies
= 1;
2477 suppress_output
= 1;
2478 jcf_dependency_init (1);
2482 emit_dependencies
= 1;
2483 suppress_output
= 1;
2484 jcf_dependency_init (0);
2488 error ("'-MG' option is unimplemented");
2492 emit_dependencies
= 1;
2493 jcf_dependency_init (1);
2497 emit_dependencies
= 1;
2498 jcf_dependency_init (0);
2509 error ("no classes specified");
2513 jcf_path_seal (verbose
);
2515 if (output_file
&& emit_dependencies
)
2517 error ("can't specify both -o and -MD");
2521 for (argi
= optind
; argi
< argc
; argi
++)
2523 char *classname
= argv
[argi
];
2524 char *current_output_file
;
2525 const char *classfile_name
;
2528 printf (_("Processing %s\n"), classname
);
2530 jcf_dependency_reset ();
2531 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 0);
2532 if (classfile_name
== NULL
)
2534 error ("%s: no such class", classname
);
2538 printf (_("Found in %s\n"), classfile_name
);
2541 if (strcmp (output_file
, "-") == 0)
2543 else if (out
== NULL
)
2545 out
= fopen (output_file
, "w");
2549 perror (output_file
);
2552 current_output_file
= output_file
;
2556 int dir_len
= strlen (output_directory
);
2557 int i
, classname_length
= strlen (classname
);
2558 current_output_file
= ALLOC (dir_len
+ classname_length
+ 5);
2559 strcpy (current_output_file
, output_directory
);
2560 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
2561 current_output_file
[dir_len
++] = '/';
2562 for (i
= 0; classname
[i
] != '\0'; i
++)
2564 char ch
= classname
[i
];
2567 if (flag_jni
&& ch
== '/')
2569 current_output_file
[dir_len
++] = ch
;
2571 if (emit_dependencies
)
2573 if (suppress_output
)
2575 jcf_dependency_set_dep_file ("-");
2580 /* We use `.hd' and not `.d' to avoid clashes with
2581 dependency tracking from straight compilation. */
2582 strcpy (current_output_file
+ dir_len
, ".hd");
2583 jcf_dependency_set_dep_file (current_output_file
);
2586 strcpy (current_output_file
+ dir_len
,
2587 stubs
? (flag_jni
? ".c" : ".cc") : ".h");
2588 jcf_dependency_set_target (current_output_file
);
2589 if (! suppress_output
)
2591 out
= fopen (current_output_file
, "w");
2594 perror (current_output_file
);
2599 free_method_name_list ();
2600 process_file (&jcf
, out
);
2602 if (current_output_file
!= output_file
)
2603 free (current_output_file
);
2604 jcf_dependency_write ();
2607 if (out
!= NULL
&& out
!= stdout
)