1 /* Program to write C++-suitable header files from a Java(TM) .class
2 file. This is similar to SUN's javah.
4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003
5 Free Software Foundation, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
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"
39 #include "java-tree.h"
40 #include "java-opcodes.h"
48 /* The output file. */
51 /* Nonzero on failure. */
52 static int found_error
= 0;
54 /* Nonzero if we're generating JNI output. */
57 /* When nonzero, warn when source file is newer than matching class
61 /* Directory to place resulting files in. Set by -d option. */
62 const char *output_directory
= "";
64 /* Directory to place temporary file. Set by -td option. Currently unused. */
65 const char *temp_directory
= "/tmp";
67 /* Number of friend functions we have to declare. */
68 static int friend_count
;
70 /* A class can optionally have a `friend' function declared. If
71 non-NULL, this is that function. */
72 static char **friend_specs
= NULL
;
74 /* Number of lines we are prepending before the class. */
75 static int prepend_count
;
77 /* We can prepend extra lines before the class's start. */
78 static char **prepend_specs
= NULL
;
80 /* Number of lines we are appending at the end of the class. */
83 /* We can append extra lines just before the class's end. */
84 static char **add_specs
= NULL
;
86 /* Number of lines we are appending after the class. */
87 static int append_count
;
89 /* We can append extra lines after the class's end. */
90 static char **append_specs
= NULL
;
96 struct JCF
*current_jcf
;
98 /* This holds access information for the last field we examined. They
99 let us generate "private:", "public:", and "protected:" properly.
100 If 0 then we haven't previously examined any field. */
101 static JCF_u2 last_access
;
103 /* Pass this macro the flags for a class and for a method. It will
104 return true if the method should be considered `final'. */
105 #define METHOD_IS_FINAL(Class, Method) \
106 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
108 /* Pass this macro the flags for a method. It will return true if the
110 #define METHOD_IS_NATIVE(Method) \
111 ((Method) & ACC_NATIVE)
113 /* We keep a linked list of all method names we have seen. This lets
114 us determine if a method name and a field name are in conflict. */
119 unsigned char *signature
;
121 struct method_name
*next
;
124 /* List of method names we've seen. */
125 static struct method_name
*method_name_list
;
127 static void print_field_info (FILE*, JCF
*, int, int, JCF_u2
);
128 static void print_mangled_classname (FILE*, JCF
*, const char*, int);
129 static int print_cxx_classname (FILE*, const char*, JCF
*, int, int);
130 static void print_method_info (FILE*, JCF
*, int, int, JCF_u2
);
131 static void print_c_decl (FILE*, JCF
*, int, int, int, const char *, int);
132 static void print_stub_or_jni (FILE*, JCF
*, int, int, int, const char *, int);
133 static void print_full_cxx_name (FILE*, JCF
*, int, int, int, const char *, int);
134 static void decompile_method (FILE*, JCF
*, int);
135 static void add_class_decl (FILE*, JCF
*, JCF_u2
);
137 static void print_name (FILE *, JCF
*, int);
138 static void print_base_classname (FILE *, JCF
*, int);
139 static int utf8_cmp (const unsigned char *, int, const char *);
140 static char *cxx_keyword_subst (const unsigned char *, int);
141 static void generate_access (FILE *, JCF_u2
);
142 static int name_is_method_p (const unsigned char *, int);
143 static char *get_field_name (JCF
*, int, JCF_u2
);
144 static void print_field_name (FILE *, JCF
*, int, JCF_u2
);
145 static const unsigned char *super_class_name (JCF
*, int *);
146 static void print_include (FILE *, const unsigned char *, int);
147 static int gcjh_streq (const void *p1
, const void *p2
);
148 static int throwable_p (const unsigned char *signature
);
149 static const unsigned char *
150 decode_signature_piece (FILE *, const unsigned char *,
151 const unsigned char *, int *);
152 static void print_class_decls (FILE *, JCF
*, int);
153 static void usage (void) ATTRIBUTE_NORETURN
;
154 static void help (void) ATTRIBUTE_NORETURN
;
155 static void version (void) ATTRIBUTE_NORETURN
;
156 static int overloaded_jni_method_exists_p (const unsigned char *, int,
158 static void jni_print_char (FILE *, int);
159 static void jni_print_float (FILE *, jfloat
);
160 static void jni_print_double (FILE *, jdouble
);
161 static void decompile_return_statement (FILE *, JCF
*, int, int, int);
163 static void handle_inner_classes (int);
165 JCF_u2 current_field_name
;
166 JCF_u2 current_field_value
;
167 JCF_u2 current_field_signature
;
168 JCF_u2 current_field_flags
;
170 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
171 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
172 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
174 /* We pass over fields twice. The first time we just note the types
175 of the fields and then the start of the methods. Then we go back
176 and parse the fields for real. This is ugly. */
177 static int field_pass
;
178 /* Likewise we pass over methods twice. The first time we generate
179 class decl information; the second time we generate actual method
181 static int method_pass
;
183 #define HANDLE_END_FIELD() \
186 if (out && ! stubs && ! flag_jni) \
187 print_field_info (out, jcf, current_field_name, \
188 current_field_signature, \
189 current_field_flags); \
191 else if (! stubs && ! flag_jni) \
192 add_class_decl (out, jcf, current_field_signature);
194 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
196 static int method_declared
= 0;
197 static int method_access
= 0;
198 static int method_printed
= 0;
199 static int method_synthetic
= 0;
200 static int method_signature
= 0;
202 /* Set to 1 while the very first data member of a class is being handled. */
203 static int is_first_data_member
= 0;
205 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
207 method_synthetic = 0; \
208 method_printed = 0; \
210 method_signature = SIGNATURE; \
211 if (ATTRIBUTE_COUNT) \
212 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
213 (const char *)"Synthetic", 9); \
214 /* If a synthetic methods have been declared, its attribute aren't \
215 worth reading (and triggering side-effects). We skip them an \
216 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
217 jcf_parse_one_method. */ \
218 if (method_synthetic) \
220 skip_attribute (jcf, ATTRIBUTE_COUNT); \
221 ATTRIBUTE_COUNT = 0; \
223 if (method_pass && !method_synthetic) \
226 print_method_info (out, jcf, NAME, SIGNATURE, \
229 else if (!method_synthetic) \
231 print_method_info (NULL, jcf, NAME, SIGNATURE, \
233 if (! stubs && ! flag_jni) \
234 add_class_decl (out, jcf, SIGNATURE); \
238 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
239 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
241 static int decompiled
= 0;
242 #define HANDLE_END_METHOD() \
243 if (out && method_printed && !method_synthetic) \
244 fputs (decompiled || stubs ? "\n" : ";\n", out);
246 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
248 /* We're going to need {peek,skip}_attribute, enable their definition. */
249 #define NEED_PEEK_ATTRIBUTE
250 #define NEED_SKIP_ATTRIBUTE
252 #include "jcf-reader.c"
254 /* Print a single-precision float, suitable for parsing by g++. */
256 jni_print_float (FILE *stream
, jfloat f
)
258 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
259 work in data initializers. FIXME. */
260 if (JFLOAT_FINITE (f
))
262 fputs (" = ", stream
);
266 fprintf (stream
, "0x1.%.6xp%+df",
267 ((unsigned int)f
.mantissa
) << 1,
268 f
.exponent
- JFLOAT_EXP_BIAS
);
270 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
271 because the implicit leading 1 bit is no longer present. */
272 fprintf (stream
, "0x0.%.6xp%+df",
273 ((unsigned int)f
.mantissa
) << 1,
274 f
.exponent
+ 1 - JFLOAT_EXP_BIAS
);
276 fputs (";\n", stream
);
279 /* Print a double-precision float, suitable for parsing by g++. */
281 jni_print_double (FILE *stream
, jdouble f
)
283 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
284 work in data initializers. FIXME. */
285 if (JDOUBLE_FINITE (f
))
287 fputs (" = ", stream
);
291 fprintf (stream
, "0x1.%.5x%.8xp%+d",
292 f
.mantissa0
, f
.mantissa1
,
293 f
.exponent
- JDOUBLE_EXP_BIAS
);
295 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
296 because the implicit leading 1 bit is no longer present. */
297 fprintf (stream
, "0x0.%.5x%.8xp%+d",
298 f
.mantissa0
, f
.mantissa1
,
299 f
.exponent
+ 1 - JDOUBLE_EXP_BIAS
);
301 fputs (";\n", stream
);
304 /* Print a character, appropriately mangled for JNI. */
307 jni_print_char (FILE *stream
, int ch
)
310 jcf_print_char (stream
, ch
);
311 else if (ch
== '(' || ch
== ')')
316 fputs ("_1", stream
);
318 fputs ("_2", stream
);
320 fputs ("_3", stream
);
323 else if (ISALNUM (ch
))
327 /* "Unicode" character. */
328 fprintf (stream
, "_0%04x", ch
);
332 /* Print a name from the class data. If the index does not point to a
333 string, an error results. */
336 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
338 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
340 fprintf (stream
, "<not a UTF8 constant>");
344 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
345 JPOOL_UTF_LENGTH (jcf
, name_index
));
348 /* For JNI we must correctly quote each character. */
349 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, name_index
);
350 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
351 const unsigned char *limit
= str
+ length
;
354 int ch
= UTF8_GET (str
, limit
);
357 fprintf (stream
, "\\<invalid>");
360 jni_print_char (stream
, ch
);
365 /* Print base name of class. The base name is everything after the
369 print_base_classname (FILE *stream
, JCF
*jcf
, int index
)
371 int name_index
= JPOOL_USHORT1 (jcf
, index
);
373 const unsigned char *s
, *p
, *limit
;
375 s
= JPOOL_UTF_DATA (jcf
, name_index
);
376 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
381 int c
= UTF8_GET (s
, limit
);
388 int ch
= UTF8_GET (p
, limit
);
390 fputs ("::", stream
);
392 jcf_print_char (stream
, ch
);
396 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
397 and 1 if STR is "greater" than NAME. */
400 utf8_cmp (const unsigned char *str
, int length
, const char *name
)
402 const unsigned char *limit
= str
+ length
;
405 for (i
= 0; name
[i
]; ++i
)
407 int ch
= UTF8_GET (str
, limit
);
412 return str
== limit
? 0 : 1;
415 /* This is a sorted list of all C++ keywords. */
417 static const char *const cxx_keywords
[] =
526 /* If NAME is the name of a C++ keyword, then return an override name.
527 This is a name that can be used in place of the keyword.
528 Otherwise, return NULL. The return value is malloc()d. */
531 cxx_keyword_subst (const unsigned char *str
, int length
)
533 int last
= ARRAY_SIZE (cxx_keywords
);
535 int mid
= (last
+ first
) / 2;
538 for (mid
= (last
+ first
) / 2;
540 old
= mid
, mid
= (last
+ first
) / 2)
542 int kwl
= strlen (cxx_keywords
[mid
]);
543 int min_length
= kwl
> length
? length
: kwl
;
544 int r
= utf8_cmp (str
, min_length
, cxx_keywords
[mid
]);
550 /* Skip all trailing `$'. */
551 for (i
= min_length
; i
< length
&& str
[i
] == '$'; ++i
)
553 /* We've only found a match if all the remaining characters
557 char *dup
= xmalloc (2 + length
- min_length
+ kwl
);
558 strcpy (dup
, cxx_keywords
[mid
]);
559 for (i
= kwl
; i
< length
+ 1; ++i
)
575 /* Generate an access control keyword based on FLAGS. */
578 generate_access (FILE *stream
, JCF_u2 flags
)
580 if ((flags
& ACC_VISIBILITY
) == last_access
)
582 last_access
= (flags
& ACC_VISIBILITY
);
587 fputs ("public: // actually package-private\n", stream
);
590 fputs ("public:\n", stream
);
593 fputs ("private:\n", stream
);
596 fputs ("public: // actually protected\n", stream
);
600 fprintf (stream
, "#error unrecognized visibility %d\n",
601 (flags
& ACC_VISIBILITY
));
606 /* See if NAME is already the name of a method. */
608 name_is_method_p (const unsigned char *name
, int length
)
610 struct method_name
*p
;
612 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
614 if (p
->length
== length
&& ! memcmp (p
->name
, name
, length
))
620 /* If there is already a method named NAME, whose signature is not
621 SIGNATURE, then return true. Otherwise return false. */
623 overloaded_jni_method_exists_p (const unsigned char *name
, int length
,
624 const char *signature
, int sig_length
)
626 struct method_name
*p
;
628 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
630 if (p
->length
== length
631 && ! memcmp (p
->name
, name
, length
)
632 && (p
->sig_length
!= sig_length
633 || memcmp (p
->signature
, signature
, sig_length
)))
639 /* Get name of a field. This handles renamings due to C++ clash. */
641 get_field_name (JCF
*jcf
, int name_index
, JCF_u2 flags
)
643 unsigned char *name
= JPOOL_UTF_DATA (jcf
, name_index
);
644 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
647 if (name_is_method_p (name
, length
))
649 /* This field name matches a method. So override the name with
650 a dummy name. This is yucky, but it isn't clear what else to
651 do. FIXME: if the field is static, then we'll be in real
653 if ((flags
& ACC_STATIC
))
655 fprintf (stderr
, "static field has same name as method\n");
660 override
= xmalloc (length
+ 3);
661 memcpy (override
, name
, length
);
662 strcpy (override
+ length
, "__");
665 override
= cxx_keyword_subst (name
, length
);
670 /* Print a field name. Convenience function for use with
673 print_field_name (FILE *stream
, JCF
*jcf
, int name_index
, JCF_u2 flags
)
675 char *override
= get_field_name (jcf
, name_index
, flags
);
679 fputs (override
, stream
);
683 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
684 JPOOL_UTF_LENGTH (jcf
, name_index
));
688 print_field_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
691 char *override
= NULL
;
693 generate_access (stream
, flags
);
694 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
696 fprintf (stream
, "<not a UTF8 constant>");
702 if ((flags
& ACC_STATIC
))
703 fputs ("static ", out
);
705 if ((flags
& ACC_FINAL
))
707 if (current_field_value
> 0)
712 switch (JPOOL_TAG (jcf
, current_field_value
))
714 case CONSTANT_Integer
:
717 int most_negative
= 0;
718 fputs ("const jint ", out
);
719 print_field_name (out
, jcf
, name_index
, 0);
721 num
= JPOOL_INT (jcf
, current_field_value
);
722 /* We single out the most negative number to print
723 specially. This avoids later warnings from g++. */
724 if (num
== (jint
) 0x80000000)
729 format_int (buffer
, (jlong
) num
, 10);
730 fprintf (out
, "%sL%s;\n", buffer
, most_negative
? " - 1" : "");
736 int most_negative
= 0;
737 fputs ("const jlong ", out
);
738 print_field_name (out
, jcf
, name_index
, 0);
740 num
= JPOOL_LONG (jcf
, current_field_value
);
741 /* We single out the most negative number to print
742 specially.. This avoids later warnings from g++. */
743 if (num
== (jlong
) 0x8000000000000000LL
)
748 format_int (buffer
, num
, 10);
749 fprintf (out
, "%sLL%s;\n", buffer
, most_negative
? " - 1" :"");
754 jfloat fnum
= JPOOL_FLOAT (jcf
, current_field_value
);
755 fputs ("const jfloat ", out
);
756 print_field_name (out
, jcf
, name_index
, 0);
757 jni_print_float (out
, fnum
);
760 case CONSTANT_Double
:
762 jdouble dnum
= JPOOL_DOUBLE (jcf
, current_field_value
);
763 fputs ("const jdouble ", out
);
764 print_field_name (out
, jcf
, name_index
, 0);
765 jni_print_double (out
, dnum
);
769 /* We can't print this as a constant, but we can still
770 print something sensible. */
780 override
= get_field_name (jcf
, name_index
, flags
);
781 print_c_decl (out
, jcf
, name_index
, sig_index
, 0, override
, flags
);
790 print_method_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
793 const unsigned char *str
;
794 int length
, is_init
= 0;
795 char *override
= NULL
;
798 method_access
= flags
;
799 if (stream
&& JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
800 fprintf (stream
, "<not a UTF8 constant>");
801 str
= JPOOL_UTF_DATA (jcf
, name_index
);
802 length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
806 /* Ignore the internally generated method <clinit>. However,
807 treat <init> as a constructor. */
808 if (! utf8_cmp (str
, length
, "<init>"))
810 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
)
811 && ! (flags
& ACC_STATIC
))
813 /* FIXME: i18n bug here. Order of prints should not be
815 fprintf (stderr
, "ignored method `");
816 jcf_print_utf8 (stderr
, str
, length
);
817 fprintf (stderr
, "' marked virtual\n");
825 /* During the first method pass, build a list of method names. This will
826 be used to determine if field names conflict with method names. */
829 struct method_name
*nn
;
831 nn
= xmalloc (sizeof (struct method_name
));
832 nn
->name
= xmalloc (length
);
833 memcpy (nn
->name
, str
, length
);
835 nn
->next
= method_name_list
;
836 nn
->sig_length
= JPOOL_UTF_LENGTH (jcf
, sig_index
);
837 nn
->signature
= xmalloc (nn
->sig_length
);
838 memcpy (nn
->signature
, JPOOL_UTF_DATA (jcf
, sig_index
),
840 method_name_list
= nn
;
842 /* The rest of this function doesn't matter. */
846 /* We don't worry about overrides in JNI mode. */
849 /* We can't generate a method whose name is a C++ reserved word.
850 We can't just ignore the function, because that will cause
851 incorrect code to be generated if the function is virtual
852 (not only for calls to this function for for other functions
853 after it in the vtbl). So we give it a dummy name instead. */
854 override
= cxx_keyword_subst (str
, length
);
857 if (! stubs
&& ! flag_jni
)
861 generate_access (stream
, flags
);
864 if ((flags
& ACC_STATIC
))
865 fputs ("static ", out
);
866 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
))
868 /* Don't print `virtual' if we have a constructor. */
870 fputs ("virtual ", out
);
872 print_c_decl (out
, jcf
, name_index
, sig_index
, is_init
, override
, flags
);
874 if ((flags
& ACC_ABSTRACT
))
881 if (METHOD_IS_NATIVE (flags
))
884 print_stub_or_jni (out
, jcf
, name_index
, sig_index
,
885 is_init
, override
, flags
);
893 /* A helper for the decompiler which prints a `return' statement where
894 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
895 identical, we emit a cast. We do this because the C++ compiler
896 doesn't know that a reference can be cast to the type of an
897 interface it implements. METHODTYPE is the index of the method's
898 signature. NAMEINDEX is the index of the field name; -1 for
899 `this'. OBJECTTYPE is the index of the object's type. */
901 decompile_return_statement (FILE *out
, JCF
*jcf
, int methodtype
,
902 int nameindex
, int objecttype
)
905 int obj_name_len
, method_name_len
;
906 const unsigned char *obj_data
, *method_data
;
908 obj_name_len
= JPOOL_UTF_LENGTH (jcf
, objecttype
);
909 obj_data
= JPOOL_UTF_DATA (jcf
, objecttype
);
911 method_name_len
= JPOOL_UTF_LENGTH (jcf
, methodtype
);
912 method_data
= JPOOL_UTF_DATA (jcf
, methodtype
);
914 /* Skip forward to return type part of method. */
915 while (*method_data
!= ')')
924 /* If we see an `L', skip it and the trailing `;'. */
925 if (method_data
[0] == 'L' && method_data
[method_name_len
- 1] == ';')
928 method_name_len
-= 2;
930 if (obj_data
[0] == 'L' && obj_data
[obj_name_len
- 1] == ';')
936 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
937 need a cast. Right now there is no way to determine if this is
939 if (method_name_len
!= obj_name_len
)
944 for (i
= 0; i
< method_name_len
; ++i
)
946 if (method_data
[i
] != obj_data
[i
])
954 fputs (" { return ", out
);
959 const unsigned char *limit
;
961 fputs ("reinterpret_cast<", out
);
963 while (*method_data
== '[')
968 fputs ("JArray<", out
);
971 /* Leading space to avoid C++ digraphs. */
974 /* If we see an `L', skip it and the trailing `;'. Only do this
975 if we've seen an array specification. If we don't have an
976 array then the `L' was stripped earlier. */
977 if (array_depth
&& method_data
[0] == 'L'
978 && method_data
[method_name_len
- 1] == ';')
981 method_name_len
-= 2;
984 limit
= method_data
+ method_name_len
;
985 while (method_data
< limit
)
987 int ch
= UTF8_GET (method_data
, limit
);
991 jcf_print_char (out
, ch
);
995 /* Close each array. */
996 while (array_depth
> 0)
1002 /* Close the cast. */
1006 if (nameindex
== -1)
1007 fputs ("this", out
);
1009 print_field_name (out
, jcf
, nameindex
, 0);
1018 /* Try to decompile a method body. Right now we just try to handle a
1019 simple case that we can do. Expand as desired. */
1021 decompile_method (FILE *out
, JCF
*jcf
, int code_len
)
1023 const unsigned char *codes
= jcf
->read_ptr
;
1025 uint16 name_and_type
, name
;
1027 /* If the method is synchronized, don't touch it. */
1028 if ((method_access
& ACC_SYNCHRONIZED
))
1032 && codes
[0] == OPCODE_aload_0
1033 && codes
[1] == OPCODE_getfield
1034 && (codes
[4] == OPCODE_areturn
1035 || codes
[4] == OPCODE_dreturn
1036 || codes
[4] == OPCODE_freturn
1037 || codes
[4] == OPCODE_ireturn
1038 || codes
[4] == OPCODE_lreturn
))
1040 /* Found code like `return FIELD'. */
1041 index
= (codes
[2] << 8) | codes
[3];
1042 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1043 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
1044 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1045 name
= JPOOL_USHORT1 (jcf
, name_and_type
);
1046 if (codes
[4] == OPCODE_areturn
)
1047 decompile_return_statement (out
, jcf
, method_signature
,
1048 name
, JPOOL_USHORT2 (jcf
, name_and_type
));
1051 fputs (" { return ", out
);
1053 print_field_name (out
, jcf
, name
, 0);
1058 else if (code_len
== 2
1059 && codes
[0] == OPCODE_aload_0
1060 && codes
[1] == OPCODE_areturn
1061 /* We're going to generate `return this'. This only makes
1062 sense for non-static methods. */
1063 && ! (method_access
& ACC_STATIC
))
1065 decompile_return_statement (out
, jcf
, method_signature
, -1,
1066 JPOOL_USHORT1 (jcf
, jcf
->this_class
));
1069 else if (code_len
== 1 && codes
[0] == OPCODE_return
)
1071 /* Found plain `return'. */
1072 fputs (" { }", out
);
1075 else if (code_len
== 2
1076 && codes
[0] == OPCODE_aconst_null
1077 && codes
[1] == OPCODE_areturn
)
1079 /* Found `return null'. We don't want to depend on NULL being
1081 fputs (" { return 0; }", out
);
1086 /* Like strcmp, but invert the return result for the hash table. This
1087 should probably be in hashtab.c to complement the existing string
1090 gcjh_streq (const void *p1
, const void *p2
)
1092 return ! strcmp ((char *) p1
, (char *) p2
);
1095 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1096 or 0 if not. CLNAME may be extracted from a signature, and can be
1097 terminated with either `;' or NULL. */
1099 throwable_p (const unsigned char *clname
)
1102 unsigned char *current
;
1106 /* We keep two hash tables of class names. In one we list all the
1107 classes which are subclasses of Throwable. In the other we will
1108 all other classes. We keep two tables to make the code a bit
1109 simpler; we don't have to have a structure mapping class name to
1110 a `throwable?' bit. */
1111 static htab_t throw_hash
;
1112 static htab_t non_throw_hash
;
1113 static int init_done
= 0;
1120 /* Self-initializing. The cost of this really doesn't matter.
1121 We also don't care about freeing these, either. */
1122 throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1124 non_throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1127 /* Make sure the root classes show up in the tables. */
1128 str
= xstrdup ("java.lang.Throwable");
1129 slot
= htab_find_slot (throw_hash
, str
, INSERT
);
1132 str
= xstrdup ("java.lang.Object");
1133 slot
= htab_find_slot (non_throw_hash
, str
, INSERT
);
1139 for (length
= 0; clname
[length
] != ';' && clname
[length
] != '\0'; ++length
)
1141 current
= ALLOC (length
+ 1);
1142 for (i
= 0; i
< length
; ++i
)
1143 current
[i
] = clname
[i
] == '/' ? '.' : clname
[i
];
1144 current
[length
] = '\0';
1146 /* We don't compute the hash slot here because the table might be
1147 modified by the recursion. In that case the slot could be
1149 if (htab_find (throw_hash
, current
))
1151 else if (htab_find (non_throw_hash
, current
))
1157 unsigned char *super
, *tmp
;
1158 int super_length
= -1;
1159 const char *classfile_name
= find_class (current
, strlen (current
),
1162 if (! classfile_name
)
1164 fprintf (stderr
, "couldn't find class %s\n", current
);
1168 if (jcf_parse_preamble (&jcf
) != 0
1169 || jcf_parse_constant_pool (&jcf
) != 0
1170 || verify_constant_pool (&jcf
) > 0)
1172 fprintf (stderr
, "parse error while reading %s\n", classfile_name
);
1176 jcf_parse_class (&jcf
);
1178 tmp
= (unsigned char *) super_class_name (&jcf
, &super_length
);
1179 super
= ALLOC (super_length
+ 1);
1180 memcpy (super
, tmp
, super_length
);
1181 super
[super_length
] = '\0';
1183 result
= throwable_p (super
);
1184 slot
= htab_find_slot (result
? throw_hash
: non_throw_hash
,
1195 /* Print one piece of a signature. Returns pointer to next parseable
1196 character on success, NULL on error. */
1197 static const unsigned char *
1198 decode_signature_piece (FILE *stream
, const unsigned char *signature
,
1199 const unsigned char *limit
, int *need_space
)
1202 int array_depth
= 0;
1204 switch (signature
[0])
1207 /* More spaghetti. */
1210 for (signature
++; (signature
< limit
1211 && ISDIGIT (*signature
)); signature
++)
1216 ctype
= "jbyteArray";
1219 ctype
= "jcharArray";
1222 ctype
= "jdoubleArray";
1225 ctype
= "jfloatArray";
1228 ctype
= "jintArray";
1231 ctype
= "jshortArray";
1234 ctype
= "jlongArray";
1237 ctype
= "jbooleanArray";
1240 /* We have a nested array. */
1243 fputs ("JArray<", stream
);
1247 /* We have to generate a reference to JArray here, so that
1248 our output matches what the compiler does. */
1250 /* Space between `<' and `:' to avoid C++ digraphs. */
1252 fputs ("JArray< ::", stream
);
1253 while (signature
< limit
&& *signature
!= ';')
1255 int ch
= UTF8_GET (signature
, limit
);
1259 fputs ("::", stream
);
1261 jcf_print_char (stream
, ch
);
1265 fputs (" *> *", stream
);
1270 /* Unparseable signature. */
1274 /* If the previous iterations left us with something to print,
1275 print it. For JNI, we always print `jobjectArray' in the
1277 if (flag_jni
&& (ctype
== NULL
|| array_depth
> 0))
1279 ctype
= "jobjectArray";
1282 /* The `printit' case will advance SIGNATURE for us. If we
1283 don't go there, we must advance past the `;' ourselves. */
1291 /* This shouldn't happen. */
1294 case 'B': ctype
= "jbyte"; goto printit
;
1295 case 'C': ctype
= "jchar"; goto printit
;
1296 case 'D': ctype
= "jdouble"; goto printit
;
1297 case 'F': ctype
= "jfloat"; goto printit
;
1298 case 'I': ctype
= "jint"; goto printit
;
1299 case 'J': ctype
= "jlong"; goto printit
;
1300 case 'S': ctype
= "jshort"; goto printit
;
1301 case 'Z': ctype
= "jboolean"; goto printit
;
1302 case 'V': ctype
= "void"; goto printit
;
1306 /* We know about certain types and special-case their names. */
1307 if (! strncmp (signature
, "Ljava/lang/String;",
1308 sizeof ("Ljava/lang/String;") -1))
1310 else if (! strncmp (signature
, "Ljava/lang/Class;",
1311 sizeof ("Ljava/lang/Class;") - 1))
1313 /* Skip leading 'L' for throwable_p call. */
1314 else if (throwable_p (signature
+ 1))
1315 ctype
= "jthrowable";
1319 while (*signature
&& *signature
!= ';')
1324 /* Print a leading "::" so we look in the right namespace. */
1325 fputs ("::", stream
);
1327 while (*signature
&& *signature
!= ';')
1329 int ch
= UTF8_GET (signature
, limit
);
1331 fputs ("::", stream
);
1333 jcf_print_char (stream
, ch
);
1335 fputs (" *", stream
);
1336 if (*signature
== ';')
1342 jni_print_char (stream
, *signature
++);
1347 fputs (ctype
, stream
);
1353 while (array_depth
-- > 0)
1354 fputs ("> *", stream
);
1361 print_c_decl (FILE* stream
, JCF
* jcf
, int name_index
, int signature_index
,
1362 int is_init
, const char *name_override
, int flags
)
1364 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1366 fprintf (stream
, "<not a UTF8 constant>");
1371 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1372 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1373 const unsigned char *str
= str0
;
1374 const unsigned char *limit
= str
+ length
;
1376 int is_method
= str
[0] == '(';
1377 const unsigned char *next
;
1379 /* If printing a method, skip to the return signature and print
1380 that first. However, there is no return value if this is a
1382 if (is_method
&& ! is_init
)
1392 /* If printing a field or an ordinary method, then print the
1393 "return value" now. */
1394 if (! is_method
|| ! is_init
)
1396 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1399 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1405 /* Force the alignment of the first data member. This is
1406 because the "new" C++ ABI changed the alignemnt of non-POD
1407 classes. gcj, however, still uses the "old" alignment. */
1408 if (is_first_data_member
&& ! (flags
& ACC_STATIC
) && ! is_method
)
1410 is_first_data_member
= 0;
1411 print_cxx_classname (out
, " __attribute__((aligned(__alignof__( ",
1412 jcf
, jcf
->super_class
, 1);
1413 fputs (" )))) ", stream
);
1416 /* Now print the name of the thing. */
1418 fputs (" ", stream
);
1419 print_full_cxx_name (stream
, jcf
, name_index
,
1420 signature_index
, is_init
, name_override
,
1425 /* Print the unqualified method name followed by the signature. */
1427 print_full_cxx_name (FILE* stream
, JCF
* jcf
, int name_index
,
1428 int signature_index
, int is_init
,
1429 const char *name_override
, int flags
)
1431 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1432 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1433 const unsigned char *str
= str0
;
1434 const unsigned char *limit
= str
+ length
;
1436 int is_method
= str
[0] == '(';
1437 const unsigned char *next
;
1440 fputs (name_override
, stream
);
1441 else if (name_index
)
1443 /* Declare constructors specially. */
1445 print_base_classname (stream
, jcf
, jcf
->this_class
);
1447 print_name (stream
, jcf
, name_index
);
1452 unsigned char *signature
= JPOOL_UTF_DATA (jcf
, signature_index
);
1453 int sig_len
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1454 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf
, name_index
),
1455 JPOOL_UTF_LENGTH (jcf
, name_index
),
1456 signature
, sig_len
))
1458 /* If this method is overloaded by another native method,
1459 then include the argument information in the mangled
1461 unsigned char *limit
= signature
+ sig_len
;
1462 fputs ("__", stream
);
1463 while (signature
< limit
)
1465 int ch
= UTF8_GET (signature
, limit
);
1466 jni_print_char (stream
, ch
);
1478 /* Have a method or a constructor. Print signature pieces
1480 fputs (" (", stream
);
1484 /* In JNI mode, add extra arguments. */
1487 /* FIXME: it would be nice to know if we are printing a decl
1488 or a definition, and only print `env' for the latter. */
1489 fputs ("JNIEnv *env", stream
);
1491 fputs ((flags
& ACC_STATIC
) ? ", jclass" : ", jobject", stream
);
1494 fputs (", ", stream
);
1497 while (str
< limit
&& *str
!= ')')
1499 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1502 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1507 if (next
< limit
&& *next
!= ')')
1508 fputs (", ", stream
);
1512 fputs (")", stream
);
1516 /* This is a helper for print_stub_or_jni. */
1518 print_name_for_stub_or_jni (FILE *stream
, JCF
*jcf
, int name_index
,
1519 int signature_index
, int is_init
,
1520 const char *name_override
, int flags
)
1522 const char *const prefix
= flag_jni
? "Java_" : "";
1523 print_cxx_classname (stream
, prefix
, jcf
, jcf
->this_class
, 1);
1524 fputs (flag_jni
? "_" : "::", stream
);
1525 print_full_cxx_name (stream
, jcf
, name_index
,
1526 signature_index
, is_init
, name_override
,
1531 print_stub_or_jni (FILE* stream
, JCF
* jcf
, int name_index
,
1532 int signature_index
, int is_init
,
1533 const char *name_override
, int flags
)
1535 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1537 fprintf (stream
, "<not a UTF8 constant>");
1542 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1543 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1544 const unsigned char *str
= str0
;
1545 const unsigned char *limit
= str
+ length
;
1547 int is_method
= str
[0] == '(';
1548 const unsigned char *next
;
1550 /* Don't print fields in the JNI case. */
1551 if (! is_method
&& flag_jni
)
1554 if (flag_jni
&& ! stubs
)
1555 fputs ("extern JNIEXPORT ", stream
);
1557 /* If printing a method, skip to the return signature and print
1558 that first. However, there is no return value if this is a
1560 if (is_method
&& ! is_init
)
1570 /* If printing a field or an ordinary method, then print the
1571 "return value" now. Note that a constructor can't be native,
1572 so we don't bother checking this in the JNI case. */
1573 if (! is_method
|| ! is_init
)
1575 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1578 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1584 /* When printing a JNI header we need to respect the space. In
1585 other cases we're just going to insert a newline anyway. */
1586 fputs (need_space
&& ! stubs
? " " : "\n", stream
);
1588 if (flag_jni
&& ! stubs
)
1589 fputs ("JNICALL ", stream
);
1591 /* Now print the name of the thing. */
1592 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1593 signature_index
, is_init
, name_override
,
1596 /* Print the body. */
1600 fputs ("\n{\n (*env)->FatalError (env, \"", stream
);
1602 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream
);
1603 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1604 signature_index
, is_init
,
1607 fprintf (stream
, " not implemented\")%s;\n}\n\n",
1608 flag_jni
? "" : ")");
1614 print_mangled_classname (FILE *stream
, JCF
*jcf
, const char *prefix
, int index
)
1616 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1617 fputs (prefix
, stream
);
1618 jcf_print_utf8_replace (out
,
1619 JPOOL_UTF_DATA (jcf
, name_index
),
1620 JPOOL_UTF_LENGTH (jcf
, name_index
),
1624 /* Print PREFIX, then a class name in C++ format. If the name refers
1625 to an array, ignore it and don't print PREFIX. Returns 1 if
1626 something was printed, 0 otherwise. */
1628 print_cxx_classname (FILE *stream
, const char *prefix
,
1629 JCF
*jcf
, int index
, int add_scope
)
1631 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1633 const unsigned char *s
, *p
, *limit
;
1635 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1636 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1639 /* Explicitly omit arrays here. */
1641 c
= UTF8_GET (p
, limit
);
1645 fputs (prefix
, stream
);
1647 /* Print a leading "::" so we look in the right namespace. */
1648 if (! flag_jni
&& ! stubs
&& add_scope
)
1649 fputs ("::", stream
);
1653 c
= UTF8_GET (s
, limit
);
1655 fputs (flag_jni
? "_" : "::", stream
);
1657 jni_print_char (stream
, c
);
1663 int written_class_count
= 0;
1665 /* Return name of superclass. If LEN is not NULL, fill it with length
1667 static const unsigned char *
1668 super_class_name (JCF
*derived_jcf
, int *len
)
1670 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
1671 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
1672 const unsigned char *supername
=
1673 JPOOL_UTF_DATA (derived_jcf
, supername_index
);
1676 *len
= supername_length
;
1682 handle_inner_classes (int count
)
1686 if (out
&& ! flag_jni
&& ! stubs
&& count
> 0)
1687 fprintf (out
, "\n");
1689 for (i
= 0; i
< count
; ++i
)
1691 JCF_u2 inner_info_index
= JCF_readu2 (current_jcf
);
1693 /* There are a few more values here, but we don't care about
1694 them. The (void) cast is apparently the only way to avoid a
1696 (void) JCF_readu2 (current_jcf
);
1697 (void) JCF_readu2 (current_jcf
);
1698 (void) JCF_readu2 (current_jcf
);
1700 if (out
&& ! flag_jni
&& ! stubs
)
1702 print_mangled_classname (out
, current_jcf
, " friend class ",
1704 fprintf (out
, ";\n");
1711 /* We keep track of all the `#include's we generate, so we can avoid
1716 struct include
*next
;
1719 /* List of all includes. */
1720 static struct include
*all_includes
= NULL
;
1722 /* Generate a #include. */
1724 print_include (FILE *out
, const unsigned char *utf8
, int len
)
1726 struct include
*incl
;
1732 len
= strlen (utf8
);
1734 for (incl
= all_includes
; incl
; incl
= incl
->next
)
1736 /* We check the length because we might have a proper prefix. */
1737 if (len
== (int) strlen (incl
->name
)
1738 && ! strncmp (incl
->name
, utf8
, len
))
1742 incl
= xmalloc (sizeof (struct include
));
1743 incl
->name
= xmalloc (len
+ 1);
1744 strncpy (incl
->name
, utf8
, len
);
1745 incl
->name
[len
] = '\0';
1746 incl
->next
= all_includes
;
1747 all_includes
= incl
;
1749 fputs ("#include <", out
);
1750 jcf_print_utf8_replace (out
, utf8
, len
,
1752 flag_jni
? '_' : '/');
1753 fputs (".h>\n", out
);
1758 /* This is used to represent part of a package or class name. */
1761 /* The text of this part of the name. */
1763 /* True if this represents a class. */
1765 /* Linked list of all classes and packages inside this one. */
1766 struct namelet
*subnamelets
;
1767 /* Pointer to next sibling. */
1768 struct namelet
*next
;
1771 static void add_namelet (const unsigned char *, const unsigned char *,
1773 static void print_namelet (FILE *, struct namelet
*, int);
1775 /* The special root namelet. */
1776 static struct namelet root
=
1784 /* This extracts the next name segment from the full UTF-8 encoded
1785 package or class name and links it into the tree. It does this
1788 add_namelet (const unsigned char *name
, const unsigned char *name_limit
,
1789 struct namelet
*parent
)
1791 const unsigned char *p
;
1792 struct namelet
*n
= NULL
, *np
;
1794 /* We want to skip the standard namespaces that we assume the
1795 runtime already knows about. We only do this at the top level,
1796 though, hence the check for `root'. */
1797 if (parent
== &root
)
1799 #define JAVALANG "java/lang/"
1800 #define JAVAIO "java/io/"
1801 #define JAVAUTIL "java/util/"
1802 if ((name_limit
- name
>= (int) sizeof (JAVALANG
) - 1
1803 && ! strncmp (name
, JAVALANG
, sizeof (JAVALANG
) - 1))
1804 || (name_limit
- name
>= (int) sizeof (JAVAUTIL
) - 1
1805 && ! strncmp (name
, JAVAUTIL
, sizeof (JAVAUTIL
) - 1))
1806 || (name_limit
- name
>= (int) sizeof (JAVAIO
) - 1
1807 && ! strncmp (name
, JAVAIO
, sizeof (JAVAIO
) - 1)))
1811 for (p
= name
; p
< name_limit
&& *p
!= '/'; ++p
)
1814 /* Search for this name beneath the PARENT node. */
1815 for (np
= parent
->subnamelets
; np
!= NULL
; np
= np
->next
)
1817 /* We check the length because we might have a proper prefix. */
1818 if ((int) strlen (np
->name
) == p
- name
&&
1819 ! strncmp (name
, np
->name
, p
- name
))
1828 n
= xmalloc (sizeof (struct namelet
));
1829 n
->name
= xmalloc (p
- name
+ 1);
1830 strncpy (n
->name
, name
, p
- name
);
1831 n
->name
[p
- name
] = '\0';
1832 n
->is_class
= (p
== name_limit
);
1833 n
->subnamelets
= NULL
;
1834 n
->next
= parent
->subnamelets
;
1835 parent
->subnamelets
= n
;
1838 /* We recurse if there is more text, and if the trailing piece does
1839 not represent an inner class. */
1841 add_namelet (p
+ 1, name_limit
, n
);
1844 /* Print a single namelet. Destroys namelets while printing. */
1846 print_namelet (FILE *out
, struct namelet
*name
, int depth
)
1853 for (i
= 0; i
< depth
; ++i
)
1855 fprintf (out
, "%s %s", name
->is_class
? "class" : "namespace",
1857 if (name
->is_class
&& name
->subnamelets
== NULL
)
1863 for (i
= 0; i
< depth
; ++i
)
1869 c
= name
->subnamelets
;
1872 struct namelet
*next
= c
->next
;
1873 print_namelet (out
, c
, depth
+ 2);
1876 name
->subnamelets
= NULL
;
1882 for (i
= 0; i
< depth
; ++i
)
1885 /* Only print a `;' when printing a class. C++ is evil. */
1895 /* This is called to add some classes to the list of classes for which
1896 we need decls. The signature argument can be a function
1899 add_class_decl (FILE *out
, JCF
*jcf
, JCF_u2 signature
)
1901 const unsigned char *s
= JPOOL_UTF_DATA (jcf
, signature
);
1902 int len
= JPOOL_UTF_LENGTH (jcf
, signature
);
1905 for (i
= 0; i
< len
; ++i
)
1909 /* If we see an array, then we include the array header. */
1912 print_include (out
, "gcj/array", -1);
1916 /* We're looking for `L<stuff>;' -- everything else is
1921 for (start
= ++i
; i
< len
&& s
[i
] != ';'; ++i
)
1924 add_namelet (&s
[start
], &s
[i
], &root
);
1928 /* Print declarations for all classes required by this class. Any
1929 class or package in the `java' package is assumed to be handled
1930 statically in libjava; we don't generate declarations for these.
1931 This makes the generated headers a bit easier to read. */
1933 print_class_decls (FILE *out
, JCF
*jcf
, int self
)
1935 /* Make sure to always add the current class to the list of things
1936 that should be declared. */
1937 int name_index
= JPOOL_USHORT1 (jcf
, self
);
1939 const unsigned char *s
;
1941 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1942 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1943 add_namelet (s
, s
+ len
, &root
);
1945 if (root
.subnamelets
)
1947 fputs ("extern \"Java\"\n{\n", out
);
1948 /* We use an initial offset of 0 because the root namelet
1949 doesn't cause anything to print. */
1950 print_namelet (out
, &root
, 0);
1951 fputs ("}\n\n", out
);
1958 process_file (JCF
*jcf
, FILE *out
)
1961 uint32 field_start
, method_end
, method_start
;
1967 if (jcf_parse_preamble (jcf
) != 0)
1969 fprintf (stderr
, "Not a valid Java .class file.\n");
1974 /* Parse and possibly print constant pool */
1975 code
= jcf_parse_constant_pool (jcf
);
1978 fprintf (stderr
, "error while parsing constant pool\n");
1982 code
= verify_constant_pool (jcf
);
1985 fprintf (stderr
, "error in constant pool entry #%d\n", code
);
1990 jcf_parse_class (jcf
);
1992 if (written_class_count
++ == 0 && out
)
1994 const char *cstart
, *cstart2
, *mode
, *cend
, *what
, *jflag
;
2009 mode
= " -*- c++ -*-";
2015 fprintf (out
, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2016 cstart
, mode
, cend
);
2019 fprintf (out
, "%s This file was created by `gcjh -stubs%s'.%s\n\
2021 %s This file is intended to give you a head start on implementing native\n\
2022 %s methods using %s.\n\
2023 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2024 %s overwrite any edits you have made to this file.%s\n\n",
2025 cstart
, jflag
, mode
,
2041 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
2042 fprintf (out
, "__\n");
2044 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
2045 fprintf (out
, "__\n\n");
2049 fprintf (out
, "#include <jni.h>\n\n");
2050 fprintf (out
, "#ifdef __cplusplus\n");
2051 fprintf (out
, "extern \"C\"\n");
2052 fprintf (out
, "{\n");
2053 fprintf (out
, "#endif\n");
2057 /* We do this to ensure that inline methods won't be
2058 `outlined' by g++. This works as long as method and
2059 fields are not added by the user. */
2060 fprintf (out
, "#pragma interface\n");
2062 if (jcf
->super_class
)
2065 const unsigned char *supername
=
2066 super_class_name (jcf
, &super_length
);
2069 print_include (out
, supername
, super_length
);
2075 /* Strip off the ".class" portion of the name when printing
2076 the include file name. */
2078 int i
, len
= strlen (jcf
->classname
);
2079 if (len
> 6 && ! strcmp (&jcf
->classname
[len
- 6], ".class"))
2081 /* Turn the class name into a file name. */
2082 name
= xmalloc (len
+ 1);
2083 for (i
= 0; i
< len
; ++i
)
2084 name
[i
] = jcf
->classname
[i
] == '.' ? '/' : jcf
->classname
[i
];
2086 print_include (out
, name
, len
);
2091 print_include (out
, "gcj/cni", -1);
2092 print_include (out
, "java/lang/UnsupportedOperationException",
2098 /* We want to parse the methods first. But we need to find where
2099 they start. So first we skip the fields, then parse the methods.
2100 Then we parse the fields and skip the methods. This is ugly, but
2101 not too bad since we need two full passes to get class decl
2102 information anyway. */
2104 field_start
= JCF_TELL (jcf
);
2105 jcf_parse_fields (jcf
);
2107 method_start
= JCF_TELL (jcf
);
2109 jcf_parse_methods (jcf
);
2114 if (out
&& ! flag_jni
)
2117 print_class_decls (out
, jcf
, jcf
->this_class
);
2119 for (i
= 0; i
< prepend_count
; ++i
)
2120 fprintf (out
, "%s\n", prepend_specs
[i
]);
2121 if (prepend_count
> 0)
2126 if (! print_cxx_classname (out
, "class ", jcf
,
2127 jcf
->this_class
, 0))
2129 fprintf (stderr
, "class is of array type\n");
2133 if (jcf
->super_class
)
2135 if (! print_cxx_classname (out
, " : public ",
2136 jcf
, jcf
->super_class
, 1))
2138 fprintf (stderr
, "base class is of array type\n");
2144 fputs ("\n{\n", out
);
2148 /* Now go back for second pass over methods and fields. */
2149 is_first_data_member
= 1;
2151 JCF_SEEK (jcf
, method_start
);
2153 jcf_parse_methods (jcf
);
2154 method_end
= JCF_TELL (jcf
);
2157 JCF_SEEK (jcf
, field_start
);
2158 jcf_parse_fields (jcf
);
2159 JCF_SEEK (jcf
, method_end
);
2161 jcf_parse_final_attributes (jcf
);
2167 fprintf (out
, "\n#ifdef __cplusplus\n");
2168 fprintf (out
, "}\n");
2169 fprintf (out
, "#endif\n");
2173 /* Generate friend decl if we still must. */
2174 for (i
= 0; i
< friend_count
; ++i
)
2175 fprintf (out
, " friend %s\n", friend_specs
[i
]);
2177 /* Generate extra declarations. */
2180 for (i
= 0; i
< add_count
; ++i
)
2181 fprintf (out
, " %s\n", add_specs
[i
]);
2183 /* Generate an entry for the class object. */
2184 generate_access (out
, ACC_PUBLIC
);
2185 fprintf (out
, "\n static ::java::lang::Class class$;\n");
2189 if (jcf
->access_flags
& ACC_INTERFACE
)
2190 fputs (" __attribute__ ((java_interface))", out
);
2194 if (append_count
> 0)
2196 for (i
= 0; i
< append_count
; ++i
)
2197 fprintf (out
, "%s\n", append_specs
[i
]);
2200 print_mangled_classname (out
, jcf
,
2201 "\n#endif /* __", jcf
->this_class
);
2202 fprintf (out
, "__ */\n");
2208 /* This is used to mark options with no short value. */
2209 #define LONG_OPT(Num) ((Num) + 128)
2211 #define OPT_classpath LONG_OPT (0)
2212 #define OPT_CLASSPATH OPT_classpath
2213 #define OPT_bootclasspath LONG_OPT (1)
2214 #define OPT_extdirs LONG_OPT (2)
2215 #define OPT_HELP LONG_OPT (3)
2216 #define OPT_TEMP LONG_OPT (4)
2217 #define OPT_VERSION LONG_OPT (5)
2218 #define OPT_PREPEND LONG_OPT (6)
2219 #define OPT_FRIEND LONG_OPT (7)
2220 #define OPT_ADD LONG_OPT (8)
2221 #define OPT_APPEND LONG_OPT (9)
2222 #define OPT_M LONG_OPT (10)
2223 #define OPT_MM LONG_OPT (11)
2224 #define OPT_MG LONG_OPT (12)
2225 #define OPT_MD LONG_OPT (13)
2226 #define OPT_MMD LONG_OPT (14)
2228 static const struct option options
[] =
2230 { "classpath", required_argument
, NULL
, OPT_classpath
},
2231 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
2232 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
2233 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
2234 { "help", no_argument
, NULL
, OPT_HELP
},
2235 { "stubs", no_argument
, &stubs
, 1 },
2236 { "td", required_argument
, NULL
, OPT_TEMP
},
2237 { "verbose", no_argument
, NULL
, 'v' },
2238 { "version", no_argument
, NULL
, OPT_VERSION
},
2239 { "prepend", required_argument
, NULL
, OPT_PREPEND
},
2240 { "friend", required_argument
, NULL
, OPT_FRIEND
},
2241 { "add", required_argument
, NULL
, OPT_ADD
},
2242 { "append", required_argument
, NULL
, OPT_APPEND
},
2243 { "M", no_argument
, NULL
, OPT_M
},
2244 { "MM", no_argument
, NULL
, OPT_MM
},
2245 { "MG", no_argument
, NULL
, OPT_MG
},
2246 { "MD", no_argument
, NULL
, OPT_MD
},
2247 { "MMD", no_argument
, NULL
, OPT_MMD
},
2248 { "jni", no_argument
, &flag_jni
, 1 },
2249 { NULL
, no_argument
, NULL
, 0 }
2255 fprintf (stderr
, "Try `gcjh --help' for more information.\n");
2262 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2263 printf ("Generate C++ header files from .class files\n\n");
2264 printf (" -stubs Generate an implementation stub file\n");
2265 printf (" -jni Generate a JNI header or stub\n");
2267 printf (" -add TEXT Insert TEXT into class body\n");
2268 printf (" -append TEXT Insert TEXT after class declaration\n");
2269 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2270 printf (" -prepend TEXT Insert TEXT before start of class\n");
2272 printf (" --classpath PATH Set path to find .class files\n");
2273 printf (" -IDIR Append directory to class path\n");
2274 printf (" --bootclasspath PATH Override built-in class path\n");
2275 printf (" --extdirs PATH Set extensions directory path\n");
2276 printf (" -d DIRECTORY Set output directory name\n");
2277 printf (" -o FILE Set output file name\n");
2278 printf (" -td DIRECTORY Set temporary directory name\n");
2280 printf (" --help Print this help, then exit\n");
2281 printf (" --version Print version number, then exit\n");
2282 printf (" -v, --verbose Print extra information while running\n");
2284 printf (" -M Print all dependencies to stdout;\n");
2285 printf (" suppress ordinary output\n");
2286 printf (" -MM Print non-system dependencies to stdout;\n");
2287 printf (" suppress ordinary output\n");
2288 printf (" -MD Print all dependencies to stdout\n");
2289 printf (" -MMD Print non-system dependencies to stdout\n");
2290 /* We omit -MG until it is implemented. */
2292 printf ("For bug reporting instructions, please see:\n");
2293 printf ("%s.\n", bug_report_url
);
2300 printf ("gcjh (GCC) %s\n\n", version_string
);
2301 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2302 printf ("This is free software; see the source for copying conditions. There is NO\n");
2303 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2308 main (int argc
, char** argv
)
2312 char *output_file
= NULL
;
2313 int emit_dependencies
= 0, suppress_output
= 0;
2318 fprintf (stderr
, "gcjh: no classes specified\n");
2324 /* We use getopt_long_only to allow single `-' long options. For
2325 some of our options this is more natural. */
2326 while ((opt
= getopt_long_only (argc
, argv
, "I:d:o:v", options
, NULL
)) != -1)
2331 /* Already handled. */
2335 output_file
= optarg
;
2339 output_directory
= optarg
;
2343 jcf_path_include_arg (optarg
);
2351 jcf_path_classpath_arg (optarg
);
2354 case OPT_bootclasspath
:
2355 jcf_path_bootclasspath_arg (optarg
);
2359 jcf_path_extdirs_arg (optarg
);
2367 temp_directory
= optarg
;
2375 if (prepend_count
== 0)
2376 prepend_specs
= ALLOC (argc
* sizeof (char*));
2377 prepend_specs
[prepend_count
++] = optarg
;
2381 if (friend_count
== 0)
2382 friend_specs
= ALLOC (argc
* sizeof (char*));
2383 friend_specs
[friend_count
++] = optarg
;
2388 add_specs
= ALLOC (argc
* sizeof (char*));
2389 add_specs
[add_count
++] = optarg
;
2393 if (append_count
== 0)
2394 append_specs
= ALLOC (argc
* sizeof (char*));
2395 append_specs
[append_count
++] = optarg
;
2399 emit_dependencies
= 1;
2400 suppress_output
= 1;
2401 jcf_dependency_init (1);
2405 emit_dependencies
= 1;
2406 suppress_output
= 1;
2407 jcf_dependency_init (0);
2411 fprintf (stderr
, "gcjh: `-MG' option is unimplemented\n");
2415 emit_dependencies
= 1;
2416 jcf_dependency_init (1);
2420 emit_dependencies
= 1;
2421 jcf_dependency_init (0);
2432 fprintf (stderr
, "gcjh: no classes specified\n");
2436 jcf_path_seal (verbose
);
2438 if (output_file
&& emit_dependencies
)
2440 fprintf (stderr
, "gcjh: can't specify both -o and -MD\n");
2444 for (argi
= optind
; argi
< argc
; argi
++)
2446 char *classname
= argv
[argi
];
2447 char *current_output_file
;
2448 const char *classfile_name
;
2451 fprintf (stderr
, "Processing %s\n", classname
);
2453 jcf_dependency_reset ();
2454 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 0);
2455 if (classfile_name
== NULL
)
2457 fprintf (stderr
, "%s: no such class\n", classname
);
2461 fprintf (stderr
, "Found in %s\n", classfile_name
);
2464 if (strcmp (output_file
, "-") == 0)
2466 else if (out
== NULL
)
2468 out
= fopen (output_file
, "w");
2472 perror (output_file
);
2475 current_output_file
= output_file
;
2479 int dir_len
= strlen (output_directory
);
2480 int i
, classname_length
= strlen (classname
);
2481 current_output_file
= ALLOC (dir_len
+ classname_length
+ 5);
2482 strcpy (current_output_file
, output_directory
);
2483 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
2484 current_output_file
[dir_len
++] = '/';
2485 for (i
= 0; classname
[i
] != '\0'; i
++)
2487 char ch
= classname
[i
];
2490 if (flag_jni
&& ch
== '/')
2492 current_output_file
[dir_len
++] = ch
;
2494 if (emit_dependencies
)
2496 if (suppress_output
)
2498 jcf_dependency_set_dep_file ("-");
2503 /* We use `.hd' and not `.d' to avoid clashes with
2504 dependency tracking from straight compilation. */
2505 strcpy (current_output_file
+ dir_len
, ".hd");
2506 jcf_dependency_set_dep_file (current_output_file
);
2509 strcpy (current_output_file
+ dir_len
,
2510 stubs
? (flag_jni
? ".c" : ".cc") : ".h");
2511 jcf_dependency_set_target (current_output_file
);
2512 if (! suppress_output
)
2514 out
= fopen (current_output_file
, "w");
2517 perror (current_output_file
);
2522 process_file (&jcf
, out
);
2524 if (current_output_file
!= output_file
)
2525 free (current_output_file
);
2526 jcf_dependency_write ();
2529 if (out
!= NULL
&& out
!= stdout
)