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. */
55 static int flag_jni
= 0;
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 JCF_u2 current_field_name
;
164 JCF_u2 current_field_value
;
165 JCF_u2 current_field_signature
;
166 JCF_u2 current_field_flags
;
168 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
169 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
170 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
172 /* We pass over fields twice. The first time we just note the types
173 of the fields and then the start of the methods. Then we go back
174 and parse the fields for real. This is ugly. */
175 static int field_pass
;
176 /* Likewise we pass over methods twice. The first time we generate
177 class decl information; the second time we generate actual method
179 static int method_pass
;
181 #define HANDLE_END_FIELD() \
184 if (out && ! stubs && ! flag_jni) \
185 print_field_info (out, jcf, current_field_name, \
186 current_field_signature, \
187 current_field_flags); \
189 else if (! stubs && ! flag_jni) \
190 add_class_decl (out, jcf, current_field_signature);
192 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
194 static int method_declared
= 0;
195 static int method_access
= 0;
196 static int method_printed
= 0;
197 static int method_synthetic
= 0;
198 static int method_signature
= 0;
200 /* Set to 1 while the very first data member of a class is being handled. */
201 static int is_first_data_member
= 0;
203 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
205 method_synthetic = 0; \
206 method_printed = 0; \
208 method_signature = SIGNATURE; \
209 if (ATTRIBUTE_COUNT) \
210 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
211 (const char *)"Synthetic", 9); \
212 /* If a synthetic methods have been declared, its attribute aren't \
213 worth reading (and triggering side-effects). We skip them an \
214 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
215 jcf_parse_one_method. */ \
216 if (method_synthetic) \
218 skip_attribute (jcf, ATTRIBUTE_COUNT); \
219 ATTRIBUTE_COUNT = 0; \
221 if (method_pass && !method_synthetic) \
224 print_method_info (out, jcf, NAME, SIGNATURE, \
227 else if (!method_synthetic) \
229 print_method_info (NULL, jcf, NAME, SIGNATURE, \
231 if (! stubs && ! flag_jni) \
232 add_class_decl (out, jcf, SIGNATURE); \
236 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
237 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
239 static int decompiled
= 0;
240 #define HANDLE_END_METHOD() \
241 if (out && method_printed && !method_synthetic) \
242 fputs (decompiled || stubs ? "\n" : ";\n", out);
244 /* We're going to need {peek,skip}_attribute, enable their definition. */
245 #define NEED_PEEK_ATTRIBUTE
246 #define NEED_SKIP_ATTRIBUTE
248 #include "jcf-reader.c"
250 /* Print a single-precision float, suitable for parsing by g++. */
252 jni_print_float (FILE *stream
, jfloat f
)
254 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
255 work in data initializers. FIXME. */
256 if (JFLOAT_FINITE (f
))
258 fputs (" = ", stream
);
262 fprintf (stream
, "0x1.%.6xp%+df",
263 ((unsigned int)f
.mantissa
) << 1,
264 f
.exponent
- JFLOAT_EXP_BIAS
);
266 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
267 because the implicit leading 1 bit is no longer present. */
268 fprintf (stream
, "0x0.%.6xp%+df",
269 ((unsigned int)f
.mantissa
) << 1,
270 f
.exponent
+ 1 - JFLOAT_EXP_BIAS
);
272 fputs (";\n", stream
);
275 /* Print a double-precision float, suitable for parsing by g++. */
277 jni_print_double (FILE *stream
, jdouble f
)
279 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
280 work in data initializers. FIXME. */
281 if (JDOUBLE_FINITE (f
))
283 fputs (" = ", stream
);
287 fprintf (stream
, "0x1.%.5x%.8xp%+d",
288 f
.mantissa0
, f
.mantissa1
,
289 f
.exponent
- JDOUBLE_EXP_BIAS
);
291 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
292 because the implicit leading 1 bit is no longer present. */
293 fprintf (stream
, "0x0.%.5x%.8xp%+d",
294 f
.mantissa0
, f
.mantissa1
,
295 f
.exponent
+ 1 - JDOUBLE_EXP_BIAS
);
297 fputs (";\n", stream
);
300 /* Print a character, appropriately mangled for JNI. */
303 jni_print_char (FILE *stream
, int ch
)
306 jcf_print_char (stream
, ch
);
307 else if (ch
== '(' || ch
== ')')
312 fputs ("_1", stream
);
314 fputs ("_2", stream
);
316 fputs ("_3", stream
);
319 else if (ISALNUM (ch
))
323 /* "Unicode" character. */
324 fprintf (stream
, "_0%04x", ch
);
328 /* Print a name from the class data. If the index does not point to a
329 string, an error results. */
332 print_name (FILE* stream
, JCF
* jcf
, int name_index
)
334 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
336 fprintf (stream
, "<not a UTF8 constant>");
340 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
341 JPOOL_UTF_LENGTH (jcf
, name_index
));
344 /* For JNI we must correctly quote each character. */
345 const unsigned char *str
= JPOOL_UTF_DATA (jcf
, name_index
);
346 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
347 const unsigned char *limit
= str
+ length
;
350 int ch
= UTF8_GET (str
, limit
);
353 fprintf (stream
, "\\<invalid>");
356 jni_print_char (stream
, ch
);
361 /* Print base name of class. The base name is everything after the
365 print_base_classname (FILE *stream
, JCF
*jcf
, int index
)
367 int name_index
= JPOOL_USHORT1 (jcf
, index
);
369 const unsigned char *s
, *p
, *limit
;
371 s
= JPOOL_UTF_DATA (jcf
, name_index
);
372 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
377 int c
= UTF8_GET (s
, limit
);
384 int ch
= UTF8_GET (p
, limit
);
386 fputs ("::", stream
);
388 jcf_print_char (stream
, ch
);
392 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
393 and 1 if STR is "greater" than NAME. */
396 utf8_cmp (const unsigned char *str
, int length
, const char *name
)
398 const unsigned char *limit
= str
+ length
;
401 for (i
= 0; name
[i
]; ++i
)
403 int ch
= UTF8_GET (str
, limit
);
408 return str
== limit
? 0 : 1;
411 /* This is a sorted list of all C++ keywords. */
413 static const char *const cxx_keywords
[] =
522 /* If NAME is the name of a C++ keyword, then return an override name.
523 This is a name that can be used in place of the keyword.
524 Otherwise, return NULL. The return value is malloc()d. */
527 cxx_keyword_subst (const unsigned char *str
, int length
)
529 int last
= ARRAY_SIZE (cxx_keywords
);
531 int mid
= (last
+ first
) / 2;
534 for (mid
= (last
+ first
) / 2;
536 old
= mid
, mid
= (last
+ first
) / 2)
538 int kwl
= strlen (cxx_keywords
[mid
]);
539 int min_length
= kwl
> length
? length
: kwl
;
540 int r
= utf8_cmp (str
, min_length
, cxx_keywords
[mid
]);
546 /* Skip all trailing `$'. */
547 for (i
= min_length
; i
< length
&& str
[i
] == '$'; ++i
)
549 /* We've only found a match if all the remaining characters
553 char *dup
= xmalloc (2 + length
- min_length
+ kwl
);
554 strcpy (dup
, cxx_keywords
[mid
]);
555 for (i
= kwl
; i
< length
+ 1; ++i
)
571 /* Generate an access control keyword based on FLAGS. */
574 generate_access (FILE *stream
, JCF_u2 flags
)
576 if ((flags
& ACC_VISIBILITY
) == last_access
)
578 last_access
= (flags
& ACC_VISIBILITY
);
583 fputs ("public: // actually package-private\n", stream
);
586 fputs ("public:\n", stream
);
589 fputs ("private:\n", stream
);
592 fputs ("public: // actually protected\n", stream
);
596 fprintf (stream
, "#error unrecognized visibility %d\n",
597 (flags
& ACC_VISIBILITY
));
602 /* See if NAME is already the name of a method. */
604 name_is_method_p (const unsigned char *name
, int length
)
606 struct method_name
*p
;
608 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
610 if (p
->length
== length
&& ! memcmp (p
->name
, name
, length
))
616 /* If there is already a method named NAME, whose signature is not
617 SIGNATURE, then return true. Otherwise return false. */
619 overloaded_jni_method_exists_p (const unsigned char *name
, int length
,
620 const char *signature
, int sig_length
)
622 struct method_name
*p
;
624 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
626 if (p
->length
== length
627 && ! memcmp (p
->name
, name
, length
)
628 && (p
->sig_length
!= sig_length
629 || memcmp (p
->signature
, signature
, sig_length
)))
635 /* Get name of a field. This handles renamings due to C++ clash. */
637 get_field_name (JCF
*jcf
, int name_index
, JCF_u2 flags
)
639 unsigned char *name
= JPOOL_UTF_DATA (jcf
, name_index
);
640 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
643 if (name_is_method_p (name
, length
))
645 /* This field name matches a method. So override the name with
646 a dummy name. This is yucky, but it isn't clear what else to
647 do. FIXME: if the field is static, then we'll be in real
649 if ((flags
& ACC_STATIC
))
651 fprintf (stderr
, "static field has same name as method\n");
656 override
= xmalloc (length
+ 3);
657 memcpy (override
, name
, length
);
658 strcpy (override
+ length
, "__");
661 override
= cxx_keyword_subst (name
, length
);
666 /* Print a field name. Convenience function for use with
669 print_field_name (FILE *stream
, JCF
*jcf
, int name_index
, JCF_u2 flags
)
671 char *override
= get_field_name (jcf
, name_index
, flags
);
675 fputs (override
, stream
);
679 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
680 JPOOL_UTF_LENGTH (jcf
, name_index
));
684 print_field_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
687 char *override
= NULL
;
689 generate_access (stream
, flags
);
690 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
692 fprintf (stream
, "<not a UTF8 constant>");
698 if ((flags
& ACC_STATIC
))
699 fputs ("static ", out
);
701 if ((flags
& ACC_FINAL
))
703 if (current_field_value
> 0)
708 switch (JPOOL_TAG (jcf
, current_field_value
))
710 case CONSTANT_Integer
:
713 int most_negative
= 0;
714 fputs ("const jint ", out
);
715 print_field_name (out
, jcf
, name_index
, 0);
717 num
= JPOOL_INT (jcf
, current_field_value
);
718 /* We single out the most negative number to print
719 specially. This avoids later warnings from g++. */
720 if (num
== (jint
) 0x80000000)
725 format_int (buffer
, (jlong
) num
, 10);
726 fprintf (out
, "%sL%s;\n", buffer
, most_negative
? " - 1" : "");
732 int most_negative
= 0;
733 fputs ("const jlong ", out
);
734 print_field_name (out
, jcf
, name_index
, 0);
736 num
= JPOOL_LONG (jcf
, current_field_value
);
737 /* We single out the most negative number to print
738 specially.. This avoids later warnings from g++. */
739 if (num
== (jlong
) 0x8000000000000000LL
)
744 format_int (buffer
, num
, 10);
745 fprintf (out
, "%sLL%s;\n", buffer
, most_negative
? " - 1" :"");
750 jfloat fnum
= JPOOL_FLOAT (jcf
, current_field_value
);
751 fputs ("const jfloat ", out
);
752 print_field_name (out
, jcf
, name_index
, 0);
753 jni_print_float (out
, fnum
);
756 case CONSTANT_Double
:
758 jdouble dnum
= JPOOL_DOUBLE (jcf
, current_field_value
);
759 fputs ("const jdouble ", out
);
760 print_field_name (out
, jcf
, name_index
, 0);
761 jni_print_double (out
, dnum
);
765 /* We can't print this as a constant, but we can still
766 print something sensible. */
776 override
= get_field_name (jcf
, name_index
, flags
);
777 print_c_decl (out
, jcf
, name_index
, sig_index
, 0, override
, flags
);
786 print_method_info (FILE *stream
, JCF
* jcf
, int name_index
, int sig_index
,
789 const unsigned char *str
;
790 int length
, is_init
= 0;
791 char *override
= NULL
;
794 method_access
= flags
;
795 if (stream
&& JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
796 fprintf (stream
, "<not a UTF8 constant>");
797 str
= JPOOL_UTF_DATA (jcf
, name_index
);
798 length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
802 /* Ignore the internally generated method <clinit>. However,
803 treat <init> as a constructor. */
804 if (! utf8_cmp (str
, length
, "<init>"))
806 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
)
807 && ! (flags
& ACC_STATIC
))
809 /* FIXME: i18n bug here. Order of prints should not be
811 fprintf (stderr
, "ignored method `");
812 jcf_print_utf8 (stderr
, str
, length
);
813 fprintf (stderr
, "' marked virtual\n");
821 /* During the first method pass, build a list of method names. This will
822 be used to determine if field names conflict with method names. */
825 struct method_name
*nn
;
827 nn
= xmalloc (sizeof (struct method_name
));
828 nn
->name
= xmalloc (length
);
829 memcpy (nn
->name
, str
, length
);
831 nn
->next
= method_name_list
;
832 nn
->sig_length
= JPOOL_UTF_LENGTH (jcf
, sig_index
);
833 nn
->signature
= xmalloc (nn
->sig_length
);
834 memcpy (nn
->signature
, JPOOL_UTF_DATA (jcf
, sig_index
),
836 method_name_list
= nn
;
838 /* The rest of this function doesn't matter. */
842 /* We don't worry about overrides in JNI mode. */
845 /* We can't generate a method whose name is a C++ reserved word.
846 We can't just ignore the function, because that will cause
847 incorrect code to be generated if the function is virtual
848 (not only for calls to this function for for other functions
849 after it in the vtbl). So we give it a dummy name instead. */
850 override
= cxx_keyword_subst (str
, length
);
853 if (! stubs
&& ! flag_jni
)
857 generate_access (stream
, flags
);
860 if ((flags
& ACC_STATIC
))
861 fputs ("static ", out
);
862 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
))
864 /* Don't print `virtual' if we have a constructor. */
866 fputs ("virtual ", out
);
868 print_c_decl (out
, jcf
, name_index
, sig_index
, is_init
, override
, flags
);
870 if ((flags
& ACC_ABSTRACT
))
877 if (METHOD_IS_NATIVE (flags
))
880 print_stub_or_jni (out
, jcf
, name_index
, sig_index
,
881 is_init
, override
, flags
);
889 /* A helper for the decompiler which prints a `return' statement where
890 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
891 identical, we emit a cast. We do this because the C++ compiler
892 doesn't know that a reference can be cast to the type of an
893 interface it implements. METHODTYPE is the index of the method's
894 signature. NAMEINDEX is the index of the field name; -1 for
895 `this'. OBJECTTYPE is the index of the object's type. */
897 decompile_return_statement (FILE *out
, JCF
*jcf
, int methodtype
,
898 int nameindex
, int objecttype
)
901 int obj_name_len
, method_name_len
;
902 const unsigned char *obj_data
, *method_data
;
904 obj_name_len
= JPOOL_UTF_LENGTH (jcf
, objecttype
);
905 obj_data
= JPOOL_UTF_DATA (jcf
, objecttype
);
907 method_name_len
= JPOOL_UTF_LENGTH (jcf
, methodtype
);
908 method_data
= JPOOL_UTF_DATA (jcf
, methodtype
);
910 /* Skip forward to return type part of method. */
911 while (*method_data
!= ')')
920 /* If we see an `L', skip it and the trailing `;'. */
921 if (method_data
[0] == 'L' && method_data
[method_name_len
- 1] == ';')
924 method_name_len
-= 2;
926 if (obj_data
[0] == 'L' && obj_data
[obj_name_len
- 1] == ';')
932 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
933 need a cast. Right now there is no way to determine if this is
935 if (method_name_len
!= obj_name_len
)
940 for (i
= 0; i
< method_name_len
; ++i
)
942 if (method_data
[i
] != obj_data
[i
])
950 fputs (" { return ", out
);
955 const unsigned char *limit
;
957 fputs ("reinterpret_cast<", out
);
959 while (*method_data
== '[')
964 fputs ("JArray<", out
);
967 /* Leading space to avoid C++ digraphs. */
970 /* If we see an `L', skip it and the trailing `;'. Only do this
971 if we've seen an array specification. If we don't have an
972 array then the `L' was stripped earlier. */
973 if (array_depth
&& method_data
[0] == 'L'
974 && method_data
[method_name_len
- 1] == ';')
977 method_name_len
-= 2;
980 limit
= method_data
+ method_name_len
;
981 while (method_data
< limit
)
983 int ch
= UTF8_GET (method_data
, limit
);
987 jcf_print_char (out
, ch
);
991 /* Close each array. */
992 while (array_depth
> 0)
998 /* Close the cast. */
1002 if (nameindex
== -1)
1003 fputs ("this", out
);
1005 print_field_name (out
, jcf
, nameindex
, 0);
1014 /* Try to decompile a method body. Right now we just try to handle a
1015 simple case that we can do. Expand as desired. */
1017 decompile_method (FILE *out
, JCF
*jcf
, int code_len
)
1019 const unsigned char *codes
= jcf
->read_ptr
;
1021 uint16 name_and_type
, name
;
1023 /* If the method is synchronized, don't touch it. */
1024 if ((method_access
& ACC_SYNCHRONIZED
))
1028 && codes
[0] == OPCODE_aload_0
1029 && codes
[1] == OPCODE_getfield
1030 && (codes
[4] == OPCODE_areturn
1031 || codes
[4] == OPCODE_dreturn
1032 || codes
[4] == OPCODE_freturn
1033 || codes
[4] == OPCODE_ireturn
1034 || codes
[4] == OPCODE_lreturn
))
1036 /* Found code like `return FIELD'. */
1037 index
= (codes
[2] << 8) | codes
[3];
1038 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1039 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
1040 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1041 name
= JPOOL_USHORT1 (jcf
, name_and_type
);
1042 if (codes
[4] == OPCODE_areturn
)
1043 decompile_return_statement (out
, jcf
, method_signature
,
1044 name
, JPOOL_USHORT2 (jcf
, name_and_type
));
1047 fputs (" { return ", out
);
1049 print_field_name (out
, jcf
, name
, 0);
1054 else if (code_len
== 2
1055 && codes
[0] == OPCODE_aload_0
1056 && codes
[1] == OPCODE_areturn
1057 /* We're going to generate `return this'. This only makes
1058 sense for non-static methods. */
1059 && ! (method_access
& ACC_STATIC
))
1061 decompile_return_statement (out
, jcf
, method_signature
, -1,
1062 JPOOL_USHORT1 (jcf
, jcf
->this_class
));
1065 else if (code_len
== 1 && codes
[0] == OPCODE_return
)
1067 /* Found plain `return'. */
1068 fputs (" { }", out
);
1071 else if (code_len
== 2
1072 && codes
[0] == OPCODE_aconst_null
1073 && codes
[1] == OPCODE_areturn
)
1075 /* Found `return null'. We don't want to depend on NULL being
1077 fputs (" { return 0; }", out
);
1082 /* Like strcmp, but invert the return result for the hash table. This
1083 should probably be in hashtab.c to complement the existing string
1086 gcjh_streq (const void *p1
, const void *p2
)
1088 return ! strcmp ((char *) p1
, (char *) p2
);
1091 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1092 or 0 if not. CLNAME may be extracted from a signature, and can be
1093 terminated with either `;' or NULL. */
1095 throwable_p (const unsigned char *clname
)
1098 unsigned char *current
;
1102 /* We keep two hash tables of class names. In one we list all the
1103 classes which are subclasses of Throwable. In the other we will
1104 all other classes. We keep two tables to make the code a bit
1105 simpler; we don't have to have a structure mapping class name to
1106 a `throwable?' bit. */
1107 static htab_t throw_hash
;
1108 static htab_t non_throw_hash
;
1109 static int init_done
= 0;
1116 /* Self-initializing. The cost of this really doesn't matter.
1117 We also don't care about freeing these, either. */
1118 throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1120 non_throw_hash
= htab_create (10, htab_hash_string
, gcjh_streq
,
1123 /* Make sure the root classes show up in the tables. */
1124 str
= xstrdup ("java.lang.Throwable");
1125 slot
= htab_find_slot (throw_hash
, str
, INSERT
);
1128 str
= xstrdup ("java.lang.Object");
1129 slot
= htab_find_slot (non_throw_hash
, str
, INSERT
);
1135 for (length
= 0; clname
[length
] != ';' && clname
[length
] != '\0'; ++length
)
1137 current
= ALLOC (length
+ 1);
1138 for (i
= 0; i
< length
; ++i
)
1139 current
[i
] = clname
[i
] == '/' ? '.' : clname
[i
];
1140 current
[length
] = '\0';
1142 /* We don't compute the hash slot here because the table might be
1143 modified by the recursion. In that case the slot could be
1145 if (htab_find (throw_hash
, current
))
1147 else if (htab_find (non_throw_hash
, current
))
1153 unsigned char *super
, *tmp
;
1154 int super_length
= -1;
1155 const char *classfile_name
= find_class (current
, strlen (current
),
1158 if (! classfile_name
)
1160 fprintf (stderr
, "couldn't find class %s\n", current
);
1164 if (jcf_parse_preamble (&jcf
) != 0
1165 || jcf_parse_constant_pool (&jcf
) != 0
1166 || verify_constant_pool (&jcf
) > 0)
1168 fprintf (stderr
, "parse error while reading %s\n", classfile_name
);
1172 jcf_parse_class (&jcf
);
1174 tmp
= (unsigned char *) super_class_name (&jcf
, &super_length
);
1175 super
= ALLOC (super_length
+ 1);
1176 memcpy (super
, tmp
, super_length
);
1177 super
[super_length
] = '\0';
1179 result
= throwable_p (super
);
1180 slot
= htab_find_slot (result
? throw_hash
: non_throw_hash
,
1191 /* Print one piece of a signature. Returns pointer to next parseable
1192 character on success, NULL on error. */
1193 static const unsigned char *
1194 decode_signature_piece (FILE *stream
, const unsigned char *signature
,
1195 const unsigned char *limit
, int *need_space
)
1198 int array_depth
= 0;
1200 switch (signature
[0])
1203 /* More spaghetti. */
1206 for (signature
++; (signature
< limit
1207 && ISDIGIT (*signature
)); signature
++)
1212 ctype
= "jbyteArray";
1215 ctype
= "jcharArray";
1218 ctype
= "jdoubleArray";
1221 ctype
= "jfloatArray";
1224 ctype
= "jintArray";
1227 ctype
= "jshortArray";
1230 ctype
= "jlongArray";
1233 ctype
= "jbooleanArray";
1236 /* We have a nested array. */
1239 fputs ("JArray<", stream
);
1243 /* We have to generate a reference to JArray here, so that
1244 our output matches what the compiler does. */
1246 /* Space between `<' and `:' to avoid C++ digraphs. */
1248 fputs ("JArray< ::", stream
);
1249 while (signature
< limit
&& *signature
!= ';')
1251 int ch
= UTF8_GET (signature
, limit
);
1255 fputs ("::", stream
);
1257 jcf_print_char (stream
, ch
);
1261 fputs (" *> *", stream
);
1266 /* Unparseable signature. */
1270 /* If the previous iterations left us with something to print,
1271 print it. For JNI, we always print `jobjectArray' in the
1273 if (flag_jni
&& (ctype
== NULL
|| array_depth
> 0))
1275 ctype
= "jobjectArray";
1278 /* The `printit' case will advance SIGNATURE for us. If we
1279 don't go there, we must advance past the `;' ourselves. */
1287 /* This shouldn't happen. */
1290 case 'B': ctype
= "jbyte"; goto printit
;
1291 case 'C': ctype
= "jchar"; goto printit
;
1292 case 'D': ctype
= "jdouble"; goto printit
;
1293 case 'F': ctype
= "jfloat"; goto printit
;
1294 case 'I': ctype
= "jint"; goto printit
;
1295 case 'J': ctype
= "jlong"; goto printit
;
1296 case 'S': ctype
= "jshort"; goto printit
;
1297 case 'Z': ctype
= "jboolean"; goto printit
;
1298 case 'V': ctype
= "void"; goto printit
;
1302 /* We know about certain types and special-case their names. */
1303 if (! strncmp (signature
, "Ljava/lang/String;",
1304 sizeof ("Ljava/lang/String;") -1))
1306 else if (! strncmp (signature
, "Ljava/lang/Class;",
1307 sizeof ("Ljava/lang/Class;") - 1))
1309 /* Skip leading 'L' for throwable_p call. */
1310 else if (throwable_p (signature
+ 1))
1311 ctype
= "jthrowable";
1315 while (*signature
&& *signature
!= ';')
1320 /* Print a leading "::" so we look in the right namespace. */
1321 fputs ("::", stream
);
1323 while (*signature
&& *signature
!= ';')
1325 int ch
= UTF8_GET (signature
, limit
);
1327 fputs ("::", stream
);
1329 jcf_print_char (stream
, ch
);
1331 fputs (" *", stream
);
1332 if (*signature
== ';')
1338 jni_print_char (stream
, *signature
++);
1343 fputs (ctype
, stream
);
1349 while (array_depth
-- > 0)
1350 fputs ("> *", stream
);
1357 print_c_decl (FILE* stream
, JCF
* jcf
, int name_index
, int signature_index
,
1358 int is_init
, const char *name_override
, int flags
)
1360 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1362 fprintf (stream
, "<not a UTF8 constant>");
1367 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1368 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1369 register const unsigned char *str
= str0
;
1370 const unsigned char *limit
= str
+ length
;
1372 int is_method
= str
[0] == '(';
1373 const unsigned char *next
;
1375 /* If printing a method, skip to the return signature and print
1376 that first. However, there is no return value if this is a
1378 if (is_method
&& ! is_init
)
1388 /* If printing a field or an ordinary method, then print the
1389 "return value" now. */
1390 if (! is_method
|| ! is_init
)
1392 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1395 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1401 /* Force the alignment of the first data member. This is
1402 because the "new" C++ ABI changed the alignemnt of non-POD
1403 classes. gcj, however, still uses the "old" alignment. */
1404 if (is_first_data_member
&& ! (flags
& ACC_STATIC
) && ! is_method
)
1406 is_first_data_member
= 0;
1407 print_cxx_classname (out
, " __attribute__((aligned(__alignof__( ",
1408 jcf
, jcf
->super_class
, 1);
1409 fputs (" )))) ", stream
);
1412 /* Now print the name of the thing. */
1414 fputs (" ", stream
);
1415 print_full_cxx_name (stream
, jcf
, name_index
,
1416 signature_index
, is_init
, name_override
,
1421 /* Print the unqualified method name followed by the signature. */
1423 print_full_cxx_name (FILE* stream
, JCF
* jcf
, int name_index
,
1424 int signature_index
, int is_init
,
1425 const char *name_override
, int flags
)
1427 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1428 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1429 register const unsigned char *str
= str0
;
1430 const unsigned char *limit
= str
+ length
;
1432 int is_method
= str
[0] == '(';
1433 const unsigned char *next
;
1436 fputs (name_override
, stream
);
1437 else if (name_index
)
1439 /* Declare constructors specially. */
1441 print_base_classname (stream
, jcf
, jcf
->this_class
);
1443 print_name (stream
, jcf
, name_index
);
1448 unsigned char *signature
= JPOOL_UTF_DATA (jcf
, signature_index
);
1449 int sig_len
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1450 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf
, name_index
),
1451 JPOOL_UTF_LENGTH (jcf
, name_index
),
1452 signature
, sig_len
))
1454 /* If this method is overloaded by another native method,
1455 then include the argument information in the mangled
1457 unsigned char *limit
= signature
+ sig_len
;
1458 fputs ("__", stream
);
1459 while (signature
< limit
)
1461 int ch
= UTF8_GET (signature
, limit
);
1462 jni_print_char (stream
, ch
);
1474 /* Have a method or a constructor. Print signature pieces
1476 fputs (" (", stream
);
1480 /* In JNI mode, add extra arguments. */
1483 /* FIXME: it would be nice to know if we are printing a decl
1484 or a definition, and only print `env' for the latter. */
1485 fputs ("JNIEnv *env", stream
);
1487 fputs ((flags
& ACC_STATIC
) ? ", jclass" : ", jobject", stream
);
1490 fputs (", ", stream
);
1493 while (str
< limit
&& *str
!= ')')
1495 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1498 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1503 if (next
< limit
&& *next
!= ')')
1504 fputs (", ", stream
);
1508 fputs (")", stream
);
1512 /* This is a helper for print_stub_or_jni. */
1514 print_name_for_stub_or_jni (FILE *stream
, JCF
*jcf
, int name_index
,
1515 int signature_index
, int is_init
,
1516 const char *name_override
, int flags
)
1518 const char *const prefix
= flag_jni
? "Java_" : "";
1519 print_cxx_classname (stream
, prefix
, jcf
, jcf
->this_class
, 1);
1520 fputs (flag_jni
? "_" : "::", stream
);
1521 print_full_cxx_name (stream
, jcf
, name_index
,
1522 signature_index
, is_init
, name_override
,
1527 print_stub_or_jni (FILE* stream
, JCF
* jcf
, int name_index
,
1528 int signature_index
, int is_init
,
1529 const char *name_override
, int flags
)
1531 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1533 fprintf (stream
, "<not a UTF8 constant>");
1538 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1539 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1540 register const unsigned char *str
= str0
;
1541 const unsigned char *limit
= str
+ length
;
1543 int is_method
= str
[0] == '(';
1544 const unsigned char *next
;
1546 /* Don't print fields in the JNI case. */
1547 if (! is_method
&& flag_jni
)
1550 if (flag_jni
&& ! stubs
)
1551 fputs ("extern JNIEXPORT ", stream
);
1553 /* If printing a method, skip to the return signature and print
1554 that first. However, there is no return value if this is a
1556 if (is_method
&& ! is_init
)
1566 /* If printing a field or an ordinary method, then print the
1567 "return value" now. Note that a constructor can't be native,
1568 so we don't bother checking this in the JNI case. */
1569 if (! is_method
|| ! is_init
)
1571 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1574 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1580 /* When printing a JNI header we need to respect the space. In
1581 other cases we're just going to insert a newline anyway. */
1582 fputs (need_space
&& ! stubs
? " " : "\n", stream
);
1584 if (flag_jni
&& ! stubs
)
1585 fputs ("JNICALL ", stream
);
1587 /* Now print the name of the thing. */
1588 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1589 signature_index
, is_init
, name_override
,
1592 /* Print the body. */
1596 fputs ("\n{\n (*env)->FatalError (\"", stream
);
1598 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream
);
1599 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1600 signature_index
, is_init
,
1603 fprintf (stream
, " not implemented\")%s;\n}\n\n",
1604 flag_jni
? "" : ")");
1610 print_mangled_classname (FILE *stream
, JCF
*jcf
, const char *prefix
, int index
)
1612 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1613 fputs (prefix
, stream
);
1614 jcf_print_utf8_replace (out
,
1615 JPOOL_UTF_DATA (jcf
, name_index
),
1616 JPOOL_UTF_LENGTH (jcf
, name_index
),
1620 /* Print PREFIX, then a class name in C++ format. If the name refers
1621 to an array, ignore it and don't print PREFIX. Returns 1 if
1622 something was printed, 0 otherwise. */
1624 print_cxx_classname (FILE *stream
, const char *prefix
,
1625 JCF
*jcf
, int index
, int add_scope
)
1627 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1629 const unsigned char *s
, *p
, *limit
;
1631 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1632 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1635 /* Explicitly omit arrays here. */
1637 c
= UTF8_GET (p
, limit
);
1641 fputs (prefix
, stream
);
1643 /* Print a leading "::" so we look in the right namespace. */
1644 if (! flag_jni
&& ! stubs
&& add_scope
)
1645 fputs ("::", stream
);
1649 c
= UTF8_GET (s
, limit
);
1651 fputs (flag_jni
? "_" : "::", stream
);
1653 jni_print_char (stream
, c
);
1659 int written_class_count
= 0;
1661 /* Return name of superclass. If LEN is not NULL, fill it with length
1663 static const unsigned char *
1664 super_class_name (JCF
*derived_jcf
, int *len
)
1666 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
1667 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
1668 const unsigned char *supername
=
1669 JPOOL_UTF_DATA (derived_jcf
, supername_index
);
1672 *len
= supername_length
;
1679 /* We keep track of all the `#include's we generate, so we can avoid
1684 struct include
*next
;
1687 /* List of all includes. */
1688 static struct include
*all_includes
= NULL
;
1690 /* Generate a #include. */
1692 print_include (FILE *out
, const unsigned char *utf8
, int len
)
1694 struct include
*incl
;
1700 len
= strlen (utf8
);
1702 for (incl
= all_includes
; incl
; incl
= incl
->next
)
1704 /* We check the length because we might have a proper prefix. */
1705 if (len
== (int) strlen (incl
->name
)
1706 && ! strncmp (incl
->name
, utf8
, len
))
1710 incl
= xmalloc (sizeof (struct include
));
1711 incl
->name
= xmalloc (len
+ 1);
1712 strncpy (incl
->name
, utf8
, len
);
1713 incl
->name
[len
] = '\0';
1714 incl
->next
= all_includes
;
1715 all_includes
= incl
;
1717 fputs ("#include <", out
);
1718 jcf_print_utf8_replace (out
, utf8
, len
,
1720 flag_jni
? '_' : '/');
1721 fputs (".h>\n", out
);
1726 /* This is used to represent part of a package or class name. */
1729 /* The text of this part of the name. */
1731 /* True if this represents a class. */
1733 /* Linked list of all classes and packages inside this one. */
1734 struct namelet
*subnamelets
;
1735 /* Pointer to next sibling. */
1736 struct namelet
*next
;
1739 static void add_namelet (const unsigned char *, const unsigned char *,
1741 static void print_namelet (FILE *, struct namelet
*, int);
1743 /* The special root namelet. */
1744 static struct namelet root
=
1752 /* This extracts the next name segment from the full UTF-8 encoded
1753 package or class name and links it into the tree. It does this
1756 add_namelet (const unsigned char *name
, const unsigned char *name_limit
,
1757 struct namelet
*parent
)
1759 const unsigned char *p
;
1760 struct namelet
*n
= NULL
, *np
;
1762 /* We want to skip the standard namespaces that we assume the
1763 runtime already knows about. We only do this at the top level,
1764 though, hence the check for `root'. */
1765 if (parent
== &root
)
1767 #define JAVALANG "java/lang/"
1768 #define JAVAIO "java/io/"
1769 #define JAVAUTIL "java/util/"
1770 if ((name_limit
- name
>= (int) sizeof (JAVALANG
) - 1
1771 && ! strncmp (name
, JAVALANG
, sizeof (JAVALANG
) - 1))
1772 || (name_limit
- name
>= (int) sizeof (JAVAUTIL
) - 1
1773 && ! strncmp (name
, JAVAUTIL
, sizeof (JAVAUTIL
) - 1))
1774 || (name_limit
- name
>= (int) sizeof (JAVAIO
) - 1
1775 && ! strncmp (name
, JAVAIO
, sizeof (JAVAIO
) - 1)))
1779 for (p
= name
; p
< name_limit
&& *p
!= '/'; ++p
)
1782 /* Search for this name beneath the PARENT node. */
1783 for (np
= parent
->subnamelets
; np
!= NULL
; np
= np
->next
)
1785 /* We check the length because we might have a proper prefix. */
1786 if ((int) strlen (np
->name
) == p
- name
&&
1787 ! strncmp (name
, np
->name
, p
- name
))
1796 n
= xmalloc (sizeof (struct namelet
));
1797 n
->name
= xmalloc (p
- name
+ 1);
1798 strncpy (n
->name
, name
, p
- name
);
1799 n
->name
[p
- name
] = '\0';
1800 n
->is_class
= (p
== name_limit
);
1801 n
->subnamelets
= NULL
;
1802 n
->next
= parent
->subnamelets
;
1803 parent
->subnamelets
= n
;
1806 /* We recurse if there is more text, and if the trailing piece does
1807 not represent an inner class. */
1809 add_namelet (p
+ 1, name_limit
, n
);
1812 /* Print a single namelet. Destroys namelets while printing. */
1814 print_namelet (FILE *out
, struct namelet
*name
, int depth
)
1821 for (i
= 0; i
< depth
; ++i
)
1823 fprintf (out
, "%s %s", name
->is_class
? "class" : "namespace",
1825 if (name
->is_class
&& name
->subnamelets
== NULL
)
1831 for (i
= 0; i
< depth
; ++i
)
1837 c
= name
->subnamelets
;
1840 struct namelet
*next
= c
->next
;
1841 print_namelet (out
, c
, depth
+ 2);
1844 name
->subnamelets
= NULL
;
1850 for (i
= 0; i
< depth
; ++i
)
1853 /* Only print a `;' when printing a class. C++ is evil. */
1863 /* This is called to add some classes to the list of classes for which
1864 we need decls. The signature argument can be a function
1867 add_class_decl (FILE *out
, JCF
*jcf
, JCF_u2 signature
)
1869 const unsigned char *s
= JPOOL_UTF_DATA (jcf
, signature
);
1870 int len
= JPOOL_UTF_LENGTH (jcf
, signature
);
1873 for (i
= 0; i
< len
; ++i
)
1877 /* If we see an array, then we include the array header. */
1880 print_include (out
, "gcj/array", -1);
1884 /* We're looking for `L<stuff>;' -- everything else is
1889 for (start
= ++i
; i
< len
&& s
[i
] != ';'; ++i
)
1892 add_namelet (&s
[start
], &s
[i
], &root
);
1896 /* Print declarations for all classes required by this class. Any
1897 class or package in the `java' package is assumed to be handled
1898 statically in libjava; we don't generate declarations for these.
1899 This makes the generated headers a bit easier to read. */
1901 print_class_decls (FILE *out
, JCF
*jcf
, int self
)
1903 /* Make sure to always add the current class to the list of things
1904 that should be declared. */
1905 int name_index
= JPOOL_USHORT1 (jcf
, self
);
1907 const unsigned char *s
;
1909 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1910 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1911 add_namelet (s
, s
+ len
, &root
);
1913 if (root
.subnamelets
)
1915 fputs ("extern \"Java\"\n{\n", out
);
1916 /* We use an initial offset of 0 because the root namelet
1917 doesn't cause anything to print. */
1918 print_namelet (out
, &root
, 0);
1919 fputs ("}\n\n", out
);
1926 process_file (JCF
*jcf
, FILE *out
)
1929 uint32 field_start
, method_end
, method_start
;
1935 if (jcf_parse_preamble (jcf
) != 0)
1937 fprintf (stderr
, "Not a valid Java .class file.\n");
1942 /* Parse and possibly print constant pool */
1943 code
= jcf_parse_constant_pool (jcf
);
1946 fprintf (stderr
, "error while parsing constant pool\n");
1950 code
= verify_constant_pool (jcf
);
1953 fprintf (stderr
, "error in constant pool entry #%d\n", code
);
1958 jcf_parse_class (jcf
);
1960 if (written_class_count
++ == 0 && out
)
1962 const char *cstart
, *cstart2
, *mode
, *cend
, *what
, *jflag
;
1977 mode
= " -*- c++ -*-";
1983 fprintf (out
, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1984 cstart
, mode
, cend
);
1987 fprintf (out
, "%s This file was created by `gcjh -stubs%s'.%s\n\
1989 %s This file is intended to give you a head start on implementing native\n\
1990 %s methods using %s.\n\
1991 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1992 %s overwrite any edits you have made to this file.%s\n\n",
1993 cstart
, jflag
, mode
,
2009 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
2010 fprintf (out
, "__\n");
2012 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
2013 fprintf (out
, "__\n\n");
2017 fprintf (out
, "#include <jni.h>\n\n");
2018 fprintf (out
, "#ifdef __cplusplus\n");
2019 fprintf (out
, "extern \"C\"\n");
2020 fprintf (out
, "{\n");
2021 fprintf (out
, "#endif\n");
2025 /* We do this to ensure that inline methods won't be
2026 `outlined' by g++. This works as long as method and
2027 fields are not added by the user. */
2028 fprintf (out
, "#pragma interface\n");
2030 if (jcf
->super_class
)
2033 const unsigned char *supername
=
2034 super_class_name (jcf
, &super_length
);
2037 print_include (out
, supername
, super_length
);
2043 /* Strip off the ".class" portion of the name when printing
2044 the include file name. */
2046 int i
, len
= strlen (jcf
->classname
);
2047 if (len
> 6 && ! strcmp (&jcf
->classname
[len
- 6], ".class"))
2049 /* Turn the class name into a file name. */
2050 name
= xmalloc (len
+ 1);
2051 for (i
= 0; i
< len
; ++i
)
2052 name
[i
] = jcf
->classname
[i
] == '.' ? '/' : jcf
->classname
[i
];
2054 print_include (out
, name
, len
);
2059 print_include (out
, "gcj/cni", -1);
2060 print_include (out
, "java/lang/UnsupportedOperationException",
2066 /* We want to parse the methods first. But we need to find where
2067 they start. So first we skip the fields, then parse the methods.
2068 Then we parse the fields and skip the methods. This is ugly, but
2069 not too bad since we need two full passes to get class decl
2070 information anyway. */
2072 field_start
= JCF_TELL (jcf
);
2073 jcf_parse_fields (jcf
);
2075 method_start
= JCF_TELL (jcf
);
2077 jcf_parse_methods (jcf
);
2082 if (out
&& ! flag_jni
)
2085 print_class_decls (out
, jcf
, jcf
->this_class
);
2087 for (i
= 0; i
< prepend_count
; ++i
)
2088 fprintf (out
, "%s\n", prepend_specs
[i
]);
2089 if (prepend_count
> 0)
2094 if (! print_cxx_classname (out
, "class ", jcf
,
2095 jcf
->this_class
, 0))
2097 fprintf (stderr
, "class is of array type\n");
2101 if (jcf
->super_class
)
2103 if (! print_cxx_classname (out
, " : public ",
2104 jcf
, jcf
->super_class
, 1))
2106 fprintf (stderr
, "base class is of array type\n");
2112 fputs ("\n{\n", out
);
2116 /* Now go back for second pass over methods and fields. */
2117 is_first_data_member
= 1;
2119 JCF_SEEK (jcf
, method_start
);
2121 jcf_parse_methods (jcf
);
2122 method_end
= JCF_TELL (jcf
);
2125 JCF_SEEK (jcf
, field_start
);
2126 jcf_parse_fields (jcf
);
2127 JCF_SEEK (jcf
, method_end
);
2129 jcf_parse_final_attributes (jcf
);
2135 fprintf (out
, "\n#ifdef __cplusplus\n");
2136 fprintf (out
, "}\n");
2137 fprintf (out
, "#endif\n");
2141 /* Generate friend decl if we still must. */
2142 for (i
= 0; i
< friend_count
; ++i
)
2143 fprintf (out
, " friend %s\n", friend_specs
[i
]);
2145 /* Generate extra declarations. */
2148 for (i
= 0; i
< add_count
; ++i
)
2149 fprintf (out
, " %s\n", add_specs
[i
]);
2151 /* Generate an entry for the class object. */
2152 generate_access (out
, ACC_PUBLIC
);
2153 fprintf (out
, "\n static ::java::lang::Class class$;\n");
2157 if (jcf
->access_flags
& ACC_INTERFACE
)
2158 fputs (" __attribute__ ((java_interface))", out
);
2162 if (append_count
> 0)
2164 for (i
= 0; i
< append_count
; ++i
)
2165 fprintf (out
, "%s\n", append_specs
[i
]);
2168 print_mangled_classname (out
, jcf
,
2169 "\n#endif /* __", jcf
->this_class
);
2170 fprintf (out
, "__ */\n");
2176 /* This is used to mark options with no short value. */
2177 #define LONG_OPT(Num) ((Num) + 128)
2179 #define OPT_classpath LONG_OPT (0)
2180 #define OPT_CLASSPATH OPT_classpath
2181 #define OPT_bootclasspath LONG_OPT (1)
2182 #define OPT_extdirs LONG_OPT (2)
2183 #define OPT_HELP LONG_OPT (3)
2184 #define OPT_TEMP LONG_OPT (4)
2185 #define OPT_VERSION LONG_OPT (5)
2186 #define OPT_PREPEND LONG_OPT (6)
2187 #define OPT_FRIEND LONG_OPT (7)
2188 #define OPT_ADD LONG_OPT (8)
2189 #define OPT_APPEND LONG_OPT (9)
2190 #define OPT_M LONG_OPT (10)
2191 #define OPT_MM LONG_OPT (11)
2192 #define OPT_MG LONG_OPT (12)
2193 #define OPT_MD LONG_OPT (13)
2194 #define OPT_MMD LONG_OPT (14)
2196 static const struct option options
[] =
2198 { "classpath", required_argument
, NULL
, OPT_classpath
},
2199 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
2200 { "extdirs", required_argument
, NULL
, OPT_extdirs
},
2201 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
2202 { "help", no_argument
, NULL
, OPT_HELP
},
2203 { "stubs", no_argument
, &stubs
, 1 },
2204 { "td", required_argument
, NULL
, OPT_TEMP
},
2205 { "verbose", no_argument
, NULL
, 'v' },
2206 { "version", no_argument
, NULL
, OPT_VERSION
},
2207 { "prepend", required_argument
, NULL
, OPT_PREPEND
},
2208 { "friend", required_argument
, NULL
, OPT_FRIEND
},
2209 { "add", required_argument
, NULL
, OPT_ADD
},
2210 { "append", required_argument
, NULL
, OPT_APPEND
},
2211 { "M", no_argument
, NULL
, OPT_M
},
2212 { "MM", no_argument
, NULL
, OPT_MM
},
2213 { "MG", no_argument
, NULL
, OPT_MG
},
2214 { "MD", no_argument
, NULL
, OPT_MD
},
2215 { "MMD", no_argument
, NULL
, OPT_MMD
},
2216 { "jni", no_argument
, &flag_jni
, 1 },
2217 { NULL
, no_argument
, NULL
, 0 }
2223 fprintf (stderr
, "Try `gcjh --help' for more information.\n");
2230 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2231 printf ("Generate C++ header files from .class files\n\n");
2232 printf (" -stubs Generate an implementation stub file\n");
2233 printf (" -jni Generate a JNI header or stub\n");
2235 printf (" -add TEXT Insert TEXT into class body\n");
2236 printf (" -append TEXT Insert TEXT after class declaration\n");
2237 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2238 printf (" -prepend TEXT Insert TEXT before start of class\n");
2240 printf (" --classpath PATH Set path to find .class files\n");
2241 printf (" -IDIR Append directory to class path\n");
2242 printf (" --bootclasspath PATH Override built-in class path\n");
2243 printf (" --extdirs PATH Set extensions directory path\n");
2244 printf (" -d DIRECTORY Set output directory name\n");
2245 printf (" -o FILE Set output file name\n");
2246 printf (" -td DIRECTORY Set temporary directory name\n");
2248 printf (" --help Print this help, then exit\n");
2249 printf (" --version Print version number, then exit\n");
2250 printf (" -v, --verbose Print extra information while running\n");
2252 printf (" -M Print all dependencies to stdout;\n");
2253 printf (" suppress ordinary output\n");
2254 printf (" -MM Print non-system dependencies to stdout;\n");
2255 printf (" suppress ordinary output\n");
2256 printf (" -MD Print all dependencies to stdout\n");
2257 printf (" -MMD Print non-system dependencies to stdout\n");
2258 /* We omit -MG until it is implemented. */
2260 printf ("For bug reporting instructions, please see:\n");
2261 printf ("%s.\n", bug_report_url
);
2268 printf ("gcjh (GCC) %s\n\n", version_string
);
2269 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2270 printf ("This is free software; see the source for copying conditions. There is NO\n");
2271 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2276 main (int argc
, char** argv
)
2280 char *output_file
= NULL
;
2281 int emit_dependencies
= 0, suppress_output
= 0;
2286 fprintf (stderr
, "gcjh: no classes specified\n");
2292 /* We use getopt_long_only to allow single `-' long options. For
2293 some of our options this is more natural. */
2294 while ((opt
= getopt_long_only (argc
, argv
, "I:d:o:v", options
, NULL
)) != -1)
2299 /* Already handled. */
2303 output_file
= optarg
;
2307 output_directory
= optarg
;
2311 jcf_path_include_arg (optarg
);
2319 jcf_path_classpath_arg (optarg
);
2322 case OPT_bootclasspath
:
2323 jcf_path_bootclasspath_arg (optarg
);
2327 jcf_path_extdirs_arg (optarg
);
2335 temp_directory
= optarg
;
2343 if (prepend_count
== 0)
2344 prepend_specs
= ALLOC (argc
* sizeof (char*));
2345 prepend_specs
[prepend_count
++] = optarg
;
2349 if (friend_count
== 0)
2350 friend_specs
= ALLOC (argc
* sizeof (char*));
2351 friend_specs
[friend_count
++] = optarg
;
2356 add_specs
= ALLOC (argc
* sizeof (char*));
2357 add_specs
[add_count
++] = optarg
;
2361 if (append_count
== 0)
2362 append_specs
= ALLOC (argc
* sizeof (char*));
2363 append_specs
[append_count
++] = optarg
;
2367 emit_dependencies
= 1;
2368 suppress_output
= 1;
2369 jcf_dependency_init (1);
2373 emit_dependencies
= 1;
2374 suppress_output
= 1;
2375 jcf_dependency_init (0);
2379 fprintf (stderr
, "gcjh: `-MG' option is unimplemented\n");
2383 emit_dependencies
= 1;
2384 jcf_dependency_init (1);
2388 emit_dependencies
= 1;
2389 jcf_dependency_init (0);
2400 fprintf (stderr
, "gcjh: no classes specified\n");
2404 jcf_path_seal (verbose
);
2406 if (output_file
&& emit_dependencies
)
2408 fprintf (stderr
, "gcjh: can't specify both -o and -MD\n");
2412 for (argi
= optind
; argi
< argc
; argi
++)
2414 char *classname
= argv
[argi
];
2415 char *current_output_file
;
2416 const char *classfile_name
;
2419 fprintf (stderr
, "Processing %s\n", classname
);
2421 jcf_dependency_reset ();
2422 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 0);
2423 if (classfile_name
== NULL
)
2425 fprintf (stderr
, "%s: no such class\n", classname
);
2429 fprintf (stderr
, "Found in %s\n", classfile_name
);
2432 if (strcmp (output_file
, "-") == 0)
2434 else if (out
== NULL
)
2436 out
= fopen (output_file
, "w");
2440 perror (output_file
);
2443 current_output_file
= output_file
;
2447 int dir_len
= strlen (output_directory
);
2448 int i
, classname_length
= strlen (classname
);
2449 current_output_file
= ALLOC (dir_len
+ classname_length
+ 5);
2450 strcpy (current_output_file
, output_directory
);
2451 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
2452 current_output_file
[dir_len
++] = '/';
2453 for (i
= 0; classname
[i
] != '\0'; i
++)
2455 char ch
= classname
[i
];
2458 if (flag_jni
&& ch
== '/')
2460 current_output_file
[dir_len
++] = ch
;
2462 if (emit_dependencies
)
2464 if (suppress_output
)
2466 jcf_dependency_set_dep_file ("-");
2471 /* We use `.hd' and not `.d' to avoid clashes with
2472 dependency tracking from straight compilation. */
2473 strcpy (current_output_file
+ dir_len
, ".hd");
2474 jcf_dependency_set_dep_file (current_output_file
);
2477 strcpy (current_output_file
+ dir_len
,
2478 stubs
? (flag_jni
? ".c" : ".cc") : ".h");
2479 jcf_dependency_set_target (current_output_file
);
2480 if (! suppress_output
)
2482 out
= fopen (current_output_file
, "w");
2485 perror (current_output_file
);
2490 process_file (&jcf
, out
);
2492 if (current_output_file
!= output_file
)
2493 free (current_output_file
);
2494 jcf_dependency_write ();
2497 if (out
!= NULL
&& out
!= stdout
)