1 /* Program to write C++-suitable header files from a Java(TM) .class
2 file. This is similar to SUN's javah.
4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004
5 Free Software Foundation, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
24 Java and all Java-based marks are trademarks or registered trademarks
25 of Sun Microsystems, Inc. in the United States and other countries.
26 The Free Software Foundation is independent of Sun Microsystems, Inc. */
28 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
32 #include "coretypes.h"
39 #include "java-tree.h"
40 #include "java-opcodes.h"
49 /* The output file. */
52 /* Nonzero on failure. */
53 static int found_error = 0;
55 /* Nonzero if we're generating JNI output. */
58 /* When nonzero, warn when source file is newer than matching class
62 /* Directory to place resulting files in. Set by -d option. */
63 const char *output_directory = "";
65 /* Directory to place temporary file. Set by -td option. Currently unused. */
66 const char *temp_directory = "/tmp";
68 /* Number of friend functions we have to declare. */
69 static int friend_count;
71 /* A class can optionally have a `friend' function declared. If
72 non-NULL, this is that function. */
73 static char **friend_specs = NULL;
75 /* Number of lines we are prepending before the class. */
76 static int prepend_count;
78 /* We can prepend extra lines before the class's start. */
79 static char **prepend_specs = NULL;
81 /* Number of lines we are appending at the end of the class. */
84 /* We can append extra lines just before the class's end. */
85 static char **add_specs = NULL;
87 /* Number of lines we are appending after the class. */
88 static int append_count;
90 /* We can append extra lines after the class's end. */
91 static char **append_specs = NULL;
97 struct JCF *current_jcf;
99 /* This holds access information for the last field we examined. They
100 let us generate "private:", "public:", and "protected:" properly.
101 If 0 then we haven't previously examined any field. */
102 static JCF_u2 last_access;
104 /* Pass this macro the flags for a class and for a method. It will
105 return true if the method should be considered `final'. */
106 #define METHOD_IS_FINAL(Class, Method) \
107 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
109 /* Pass this macro the flags for a method. It will return true if the
111 #define METHOD_IS_NATIVE(Method) \
112 ((Method) & ACC_NATIVE)
114 /* We keep a linked list of all method names we have seen. This lets
115 us determine if a method name and a field name are in conflict. */
120 unsigned char *signature;
122 struct method_name *next;
125 /* List of method names we've seen. */
126 static struct method_name *method_name_list;
128 static void print_field_info (FILE*, JCF*, int, int, JCF_u2);
129 static void print_mangled_classname (FILE*, JCF*, const char*, int);
130 static int print_cxx_classname (FILE*, const char*, JCF*, int, int);
131 static void print_method_info (FILE*, JCF*, int, int, JCF_u2);
132 static void print_c_decl (FILE*, JCF*, int, int, int, const char *, int);
133 static void print_stub_or_jni (FILE*, JCF*, int, int, int, const char *, int);
134 static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int);
135 static void decompile_method (FILE*, JCF*, int);
136 static void add_class_decl (FILE*, JCF*, JCF_u2);
138 static void print_name (FILE *, JCF *, int);
139 static void print_base_classname (FILE *, JCF *, int);
140 static int utf8_cmp (const unsigned char *, int, const char *);
141 static char *cxx_keyword_subst (const unsigned char *, int);
142 static void generate_access (FILE *, JCF_u2);
143 static int name_is_method_p (const unsigned char *, int);
144 static char *get_field_name (JCF *, int, JCF_u2);
145 static void print_field_name (FILE *, JCF *, int, JCF_u2);
146 static const unsigned char *super_class_name (JCF *, int *);
147 static void print_include (FILE *, const unsigned char *, int);
148 static int gcjh_streq (const void *p1, const void *p2);
149 static int throwable_p (const unsigned char *signature);
150 static const unsigned char *
151 decode_signature_piece (FILE *, const unsigned char *,
152 const unsigned char *, int *);
153 static void print_class_decls (FILE *, JCF *, int);
154 static void error (const char *msgid, ...);
155 static void usage (void) ATTRIBUTE_NORETURN;
156 static void help (void) ATTRIBUTE_NORETURN;
157 static void version (void) ATTRIBUTE_NORETURN;
158 static int overloaded_jni_method_exists_p (const unsigned char *, int,
160 static void jni_print_char (FILE *, int);
161 static void jni_print_float (FILE *, jfloat);
162 static void jni_print_double (FILE *, jdouble);
163 static void decompile_return_statement (FILE *, JCF *, int, int, int);
165 static void handle_inner_classes (int);
167 JCF_u2 current_field_name;
168 JCF_u2 current_field_value;
169 JCF_u2 current_field_signature;
170 JCF_u2 current_field_flags;
172 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
173 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
174 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
176 /* We pass over fields twice. The first time we just note the types
177 of the fields and then the start of the methods. Then we go back
178 and parse the fields for real. This is ugly. */
179 static int field_pass;
180 /* Likewise we pass over methods twice. The first time we generate
181 class decl information; the second time we generate actual method
183 static int method_pass;
185 #define HANDLE_END_FIELD() \
188 if (out && ! stubs && ! flag_jni) \
189 print_field_info (out, jcf, current_field_name, \
190 current_field_signature, \
191 current_field_flags); \
193 else if (! stubs && ! flag_jni) \
194 add_class_decl (out, jcf, current_field_signature);
196 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
198 static int method_declared = 0;
199 static int method_access = 0;
200 static int method_printed = 0;
201 static int method_synthetic = 0;
202 static int method_signature = 0;
204 /* Set to 1 while the very first data member of a class is being handled. */
205 static int is_first_data_member = 0;
207 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
209 method_synthetic = 0; \
210 method_printed = 0; \
212 method_signature = SIGNATURE; \
213 if (ATTRIBUTE_COUNT) \
214 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
215 (const char *)"Synthetic", 9); \
216 /* If a synthetic methods have been declared, its attribute aren't \
217 worth reading (and triggering side-effects). We skip them an \
218 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
219 jcf_parse_one_method. */ \
220 if (method_synthetic) \
222 skip_attribute (jcf, ATTRIBUTE_COUNT); \
223 ATTRIBUTE_COUNT = 0; \
225 if (method_pass && !method_synthetic) \
228 print_method_info (out, jcf, NAME, SIGNATURE, \
231 else if (!method_synthetic) \
233 print_method_info (NULL, jcf, NAME, SIGNATURE, \
235 if (! stubs && ! flag_jni) \
236 add_class_decl (out, jcf, SIGNATURE); \
240 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
241 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
243 static int decompiled = 0;
244 #define HANDLE_END_METHOD() \
245 if (out && method_printed && !method_synthetic) \
246 fputs (decompiled || stubs ? "\n" : ";\n", out);
248 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
250 /* We're going to need {peek,skip}_attribute, enable their definition. */
251 #define NEED_PEEK_ATTRIBUTE
252 #define NEED_SKIP_ATTRIBUTE
254 #include "jcf-reader.c"
256 /* Print an error message and set found_error. */
258 error (const char *msgid, ...)
262 va_start (ap, msgid);
264 fprintf (stderr, "gcjh: ");
265 vfprintf (stderr, _(msgid), ap);
267 fprintf (stderr, "\n");
271 /* Print a single-precision float, suitable for parsing by g++. */
273 jni_print_float (FILE *stream, jfloat f)
275 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
276 work in data initializers. FIXME. */
277 if (JFLOAT_FINITE (f))
279 fputs (" = ", stream);
283 fprintf (stream, "0x1.%.6xp%+df",
284 ((unsigned int)f.mantissa) << 1,
285 f.exponent - JFLOAT_EXP_BIAS);
287 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
288 because the implicit leading 1 bit is no longer present. */
289 fprintf (stream, "0x0.%.6xp%+df",
290 ((unsigned int)f.mantissa) << 1,
291 f.exponent + 1 - JFLOAT_EXP_BIAS);
293 fputs (";\n", stream);
296 /* Print a double-precision float, suitable for parsing by g++. */
298 jni_print_double (FILE *stream, jdouble f)
300 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
301 work in data initializers. FIXME. */
302 if (JDOUBLE_FINITE (f))
304 fputs (" = ", stream);
308 fprintf (stream, "0x1.%.5x%.8xp%+d",
309 f.mantissa0, f.mantissa1,
310 f.exponent - JDOUBLE_EXP_BIAS);
312 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
313 because the implicit leading 1 bit is no longer present. */
314 fprintf (stream, "0x0.%.5x%.8xp%+d",
315 f.mantissa0, f.mantissa1,
316 f.exponent + 1 - JDOUBLE_EXP_BIAS);
318 fputs (";\n", stream);
321 /* Print a character, appropriately mangled for JNI. */
324 jni_print_char (FILE *stream, int ch)
327 jcf_print_char (stream, ch);
328 else if (ch == '(' || ch == ')')
333 fputs ("_1", stream);
335 fputs ("_2", stream);
337 fputs ("_3", stream);
340 else if (ISALNUM (ch))
344 /* "Unicode" character. */
345 fprintf (stream, "_0%04x", ch);
349 /* Print a name from the class data. If the index does not point to a
350 string, an error results. */
353 print_name (FILE* stream, JCF* jcf, int name_index)
355 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
357 fprintf (stream, "<not a UTF8 constant>");
361 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
362 JPOOL_UTF_LENGTH (jcf, name_index));
365 /* For JNI we must correctly quote each character. */
366 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
367 int length = JPOOL_UTF_LENGTH (jcf, name_index);
368 const unsigned char *limit = str + length;
371 int ch = UTF8_GET (str, limit);
374 fprintf (stream, "\\<invalid>");
377 jni_print_char (stream, ch);
382 /* Print base name of class. The base name is everything after the
386 print_base_classname (FILE *stream, JCF *jcf, int index)
388 int name_index = JPOOL_USHORT1 (jcf, index);
390 const unsigned char *s, *p, *limit;
392 s = JPOOL_UTF_DATA (jcf, name_index);
393 len = JPOOL_UTF_LENGTH (jcf, name_index);
398 int c = UTF8_GET (s, limit);
405 int ch = UTF8_GET (p, limit);
407 fputs ("::", stream);
409 jcf_print_char (stream, ch);
413 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
414 and 1 if STR is "greater" than NAME. */
417 utf8_cmp (const unsigned char *str, int length, const char *name)
419 const unsigned char *limit = str + length;
422 for (i = 0; name[i]; ++i)
424 int ch = UTF8_GET (str, limit);
429 return str == limit ? 0 : 1;
432 /* This is a sorted list of all C++ keywords. */
434 static const char *const cxx_keywords[] =
543 /* If NAME is the name of a C++ keyword, then return an override name.
544 This is a name that can be used in place of the keyword.
545 Otherwise, return NULL. The return value is malloc()d. */
548 cxx_keyword_subst (const unsigned char *str, int length)
550 int last = ARRAY_SIZE (cxx_keywords);
552 int mid = (last + first) / 2;
555 for (mid = (last + first) / 2;
557 old = mid, mid = (last + first) / 2)
559 int kwl = strlen (cxx_keywords[mid]);
560 int min_length = kwl > length ? length : kwl;
561 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
567 /* Skip all trailing `$'. */
568 for (i = min_length; i < length && str[i] == '$'; ++i)
570 /* We've only found a match if all the remaining characters
574 char *dup = xmalloc (2 + length - min_length + kwl);
575 strcpy (dup, cxx_keywords[mid]);
576 for (i = kwl; i < length + 1; ++i)
592 /* Generate an access control keyword based on FLAGS. */
595 generate_access (FILE *stream, JCF_u2 flags)
597 if ((flags & ACC_VISIBILITY) == last_access)
599 last_access = (flags & ACC_VISIBILITY);
604 fputs ("public: // actually package-private\n", stream);
607 fputs ("public:\n", stream);
610 fputs ("private:\n", stream);
613 fputs ("public: // actually protected\n", stream);
617 fprintf (stream, "#error unrecognized visibility %d\n",
618 (flags & ACC_VISIBILITY));
623 /* See if NAME is already the name of a method. */
625 name_is_method_p (const unsigned char *name, int length)
627 struct method_name *p;
629 for (p = method_name_list; p != NULL; p = p->next)
631 if (p->length == length && ! memcmp (p->name, name, length))
637 /* If there is already a method named NAME, whose signature is not
638 SIGNATURE, then return true. Otherwise return false. */
640 overloaded_jni_method_exists_p (const unsigned char *name, int length,
641 const char *signature, int sig_length)
643 struct method_name *p;
645 for (p = method_name_list; p != NULL; p = p->next)
647 if (p->length == length
648 && ! memcmp (p->name, name, length)
649 && (p->sig_length != sig_length
650 || memcmp (p->signature, signature, sig_length)))
656 /* Get name of a field. This handles renamings due to C++ clash. */
658 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
660 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
661 int length = JPOOL_UTF_LENGTH (jcf, name_index);
664 if (name_is_method_p (name, length))
666 /* This field name matches a method. So override the name with
667 a dummy name. This is yucky, but it isn't clear what else to
668 do. FIXME: if the field is static, then we'll be in real
670 if ((flags & ACC_STATIC))
672 error ("static field has same name as method");
676 override = xmalloc (length + 3);
677 memcpy (override, name, length);
678 strcpy (override + length, "__");
681 override = cxx_keyword_subst (name, length);
686 /* Print a field name. Convenience function for use with
689 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
691 char *override = get_field_name (jcf, name_index, flags);
695 fputs (override, stream);
699 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
700 JPOOL_UTF_LENGTH (jcf, name_index));
704 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
707 char *override = NULL;
709 generate_access (stream, flags);
710 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
712 fprintf (stream, "<not a UTF8 constant>");
718 if ((flags & ACC_STATIC))
719 fputs ("static ", out);
721 if ((flags & ACC_FINAL))
723 if (current_field_value > 0)
728 switch (JPOOL_TAG (jcf, current_field_value))
730 case CONSTANT_Integer:
733 int most_negative = 0;
734 fputs ("const jint ", out);
735 print_field_name (out, jcf, name_index, 0);
737 num = JPOOL_INT (jcf, current_field_value);
738 /* We single out the most negative number to print
739 specially. This avoids later warnings from g++. */
740 if (num == (jint) 0x80000000)
745 format_int (buffer, (jlong) num, 10);
746 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
752 int most_negative = 0;
753 fputs ("const jlong ", out);
754 print_field_name (out, jcf, name_index, 0);
756 num = JPOOL_LONG (jcf, current_field_value);
757 /* We single out the most negative number to print
758 specially.. This avoids later warnings from g++. */
759 if (num == (jlong) 0x8000000000000000LL)
764 format_int (buffer, num, 10);
765 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
770 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
771 fputs ("const jfloat ", out);
772 print_field_name (out, jcf, name_index, 0);
773 jni_print_float (out, fnum);
776 case CONSTANT_Double:
778 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
779 fputs ("const jdouble ", out);
780 print_field_name (out, jcf, name_index, 0);
781 jni_print_double (out, dnum);
785 /* We can't print this as a constant, but we can still
786 print something sensible. */
796 override = get_field_name (jcf, name_index, flags);
797 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
806 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
809 const unsigned char *str;
810 int length, is_init = 0;
811 char *override = NULL;
814 method_access = flags;
815 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
816 fprintf (stream, "<not a UTF8 constant>");
817 str = JPOOL_UTF_DATA (jcf, name_index);
818 length = JPOOL_UTF_LENGTH (jcf, name_index);
822 /* Ignore the internally generated method <clinit>. However,
823 treat <init> as a constructor. */
824 if (! utf8_cmp (str, length, "<init>"))
826 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
827 && ! (flags & ACC_STATIC))
829 /* FIXME: i18n bug here. Order of prints should not be
831 fprintf (stderr, _("ignored method `"));
832 jcf_print_utf8 (stderr, str, length);
833 fprintf (stderr, _("' marked virtual\n"));
841 /* During the first method pass, build a list of method names. This will
842 be used to determine if field names conflict with method names. */
845 struct method_name *nn;
847 nn = xmalloc (sizeof (struct method_name));
848 nn->name = xmalloc (length);
849 memcpy (nn->name, str, length);
851 nn->next = method_name_list;
852 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
853 nn->signature = xmalloc (nn->sig_length);
854 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
856 method_name_list = nn;
858 /* The rest of this function doesn't matter. */
862 /* We don't worry about overrides in JNI mode. */
865 /* We can't generate a method whose name is a C++ reserved word.
866 We can't just ignore the function, because that will cause
867 incorrect code to be generated if the function is virtual
868 (not only for calls to this function for for other functions
869 after it in the vtbl). So we give it a dummy name instead. */
870 override = cxx_keyword_subst (str, length);
873 if (! stubs && ! flag_jni)
877 generate_access (stream, flags);
880 if ((flags & ACC_STATIC))
881 fputs ("static ", out);
882 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
884 /* Don't print `virtual' if we have a constructor. */
886 fputs ("virtual ", out);
888 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
890 if ((flags & ACC_ABSTRACT))
897 if (METHOD_IS_NATIVE (flags))
900 print_stub_or_jni (out, jcf, name_index, sig_index,
901 is_init, override, flags);
909 /* A helper for the decompiler which prints a `return' statement where
910 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
911 identical, we emit a cast. We do this because the C++ compiler
912 doesn't know that a reference can be cast to the type of an
913 interface it implements. METHODTYPE is the index of the method's
914 signature. NAMEINDEX is the index of the field name; -1 for
915 `this'. OBJECTTYPE is the index of the object's type. */
917 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
918 int nameindex, int objecttype)
921 int obj_name_len, method_name_len;
922 const unsigned char *obj_data, *method_data;
924 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
925 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
927 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
928 method_data = JPOOL_UTF_DATA (jcf, methodtype);
930 /* Skip forward to return type part of method. */
931 while (*method_data != ')')
940 /* If we see an `L', skip it and the trailing `;'. */
941 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
944 method_name_len -= 2;
946 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
952 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
953 need a cast. Right now there is no way to determine if this is
955 if (method_name_len != obj_name_len)
960 for (i = 0; i < method_name_len; ++i)
962 if (method_data[i] != obj_data[i])
970 fputs (" { return ", out);
975 const unsigned char *limit;
977 fputs ("reinterpret_cast<", out);
979 while (*method_data == '[')
984 fputs ("JArray<", out);
987 /* Leading space to avoid C++ digraphs. */
990 /* If we see an `L', skip it and the trailing `;'. Only do this
991 if we've seen an array specification. If we don't have an
992 array then the `L' was stripped earlier. */
993 if (array_depth && method_data[0] == 'L'
994 && method_data[method_name_len - 1] == ';')
997 method_name_len -= 2;
1000 limit = method_data + method_name_len;
1001 while (method_data < limit)
1003 int ch = UTF8_GET (method_data, limit);
1007 jcf_print_char (out, ch);
1011 /* Close each array. */
1012 while (array_depth > 0)
1018 /* Close the cast. */
1022 if (nameindex == -1)
1023 fputs ("this", out);
1025 print_field_name (out, jcf, nameindex, 0);
1034 /* Try to decompile a method body. Right now we just try to handle a
1035 simple case that we can do. Expand as desired. */
1037 decompile_method (FILE *out, JCF *jcf, int code_len)
1039 const unsigned char *codes = jcf->read_ptr;
1041 uint16 name_and_type, name;
1043 /* If the method is synchronized, don't touch it. */
1044 if ((method_access & ACC_SYNCHRONIZED))
1048 && codes[0] == OPCODE_aload_0
1049 && codes[1] == OPCODE_getfield
1050 && (codes[4] == OPCODE_areturn
1051 || codes[4] == OPCODE_dreturn
1052 || codes[4] == OPCODE_freturn
1053 || codes[4] == OPCODE_ireturn
1054 || codes[4] == OPCODE_lreturn))
1056 /* Found code like `return FIELD'. */
1057 index = (codes[2] << 8) | codes[3];
1058 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1059 name_and_type = JPOOL_USHORT2 (jcf, index);
1060 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1061 name = JPOOL_USHORT1 (jcf, name_and_type);
1062 if (codes[4] == OPCODE_areturn)
1063 decompile_return_statement (out, jcf, method_signature,
1064 name, JPOOL_USHORT2 (jcf, name_and_type));
1067 fputs (" { return ", out);
1069 print_field_name (out, jcf, name, 0);
1074 else if (code_len == 2
1075 && codes[0] == OPCODE_aload_0
1076 && codes[1] == OPCODE_areturn
1077 /* We're going to generate `return this'. This only makes
1078 sense for non-static methods. */
1079 && ! (method_access & ACC_STATIC))
1081 decompile_return_statement (out, jcf, method_signature, -1,
1082 JPOOL_USHORT1 (jcf, jcf->this_class));
1085 else if (code_len == 1 && codes[0] == OPCODE_return)
1087 /* Found plain `return'. */
1088 fputs (" { }", out);
1091 else if (code_len == 2
1092 && codes[0] == OPCODE_aconst_null
1093 && codes[1] == OPCODE_areturn)
1095 /* Found `return null'. We don't want to depend on NULL being
1097 fputs (" { return 0; }", out);
1102 /* Like strcmp, but invert the return result for the hash table. This
1103 should probably be in hashtab.c to complement the existing string
1106 gcjh_streq (const void *p1, const void *p2)
1108 return ! strcmp ((char *) p1, (char *) p2);
1111 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1112 or 0 if not. CLNAME may be extracted from a signature, and can be
1113 terminated with either `;' or NULL. */
1115 throwable_p (const unsigned char *clname)
1118 unsigned char *current;
1122 /* We keep two hash tables of class names. In one we list all the
1123 classes which are subclasses of Throwable. In the other we will
1124 all other classes. We keep two tables to make the code a bit
1125 simpler; we don't have to have a structure mapping class name to
1126 a `throwable?' bit. */
1127 static htab_t throw_hash;
1128 static htab_t non_throw_hash;
1129 static int init_done = 0;
1136 /* Self-initializing. The cost of this really doesn't matter.
1137 We also don't care about freeing these, either. */
1138 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1140 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1143 /* Make sure the root classes show up in the tables. */
1144 str = xstrdup ("java.lang.Throwable");
1145 slot = htab_find_slot (throw_hash, str, INSERT);
1148 str = xstrdup ("java.lang.Object");
1149 slot = htab_find_slot (non_throw_hash, str, INSERT);
1155 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1157 current = ALLOC (length + 1);
1158 for (i = 0; i < length; ++i)
1159 current[i] = clname[i] == '/' ? '.' : clname[i];
1160 current[length] = '\0';
1162 /* We don't compute the hash slot here because the table might be
1163 modified by the recursion. In that case the slot could be
1165 if (htab_find (throw_hash, current))
1167 else if (htab_find (non_throw_hash, current))
1173 unsigned char *super, *tmp;
1174 int super_length = -1;
1175 const char *classfile_name = find_class (current, strlen (current),
1178 if (! classfile_name)
1180 error ("couldn't find class %s", current);
1183 if (jcf_parse_preamble (&jcf) != 0
1184 || jcf_parse_constant_pool (&jcf) != 0
1185 || verify_constant_pool (&jcf) > 0)
1187 error ("parse error while reading %s", classfile_name);
1190 jcf_parse_class (&jcf);
1192 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1193 super = ALLOC (super_length + 1);
1194 memcpy (super, tmp, super_length);
1195 super[super_length] = '\0';
1197 result = throwable_p (super);
1198 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1209 /* Print one piece of a signature. Returns pointer to next parseable
1210 character on success, NULL on error. */
1211 static const unsigned char *
1212 decode_signature_piece (FILE *stream, const unsigned char *signature,
1213 const unsigned char *limit, int *need_space)
1216 int array_depth = 0;
1218 switch (signature[0])
1221 /* More spaghetti. */
1224 for (signature++; (signature < limit
1225 && ISDIGIT (*signature)); signature++)
1230 ctype = "jbyteArray";
1233 ctype = "jcharArray";
1236 ctype = "jdoubleArray";
1239 ctype = "jfloatArray";
1242 ctype = "jintArray";
1245 ctype = "jshortArray";
1248 ctype = "jlongArray";
1251 ctype = "jbooleanArray";
1254 /* We have a nested array. */
1257 fputs ("JArray<", stream);
1261 /* We have to generate a reference to JArray here, so that
1262 our output matches what the compiler does. */
1264 /* Space between `<' and `:' to avoid C++ digraphs. */
1266 fputs ("JArray< ::", stream);
1267 while (signature < limit && *signature != ';')
1269 int ch = UTF8_GET (signature, limit);
1273 fputs ("::", stream);
1275 jcf_print_char (stream, ch);
1279 fputs (" *> *", stream);
1284 /* Unparseable signature. */
1288 /* If the previous iterations left us with something to print,
1289 print it. For JNI, we always print `jobjectArray' in the
1291 if (flag_jni && (ctype == NULL || array_depth > 0))
1293 ctype = "jobjectArray";
1296 /* The `printit' case will advance SIGNATURE for us. If we
1297 don't go there, we must advance past the `;' ourselves. */
1305 /* This shouldn't happen. */
1308 case 'B': ctype = "jbyte"; goto printit;
1309 case 'C': ctype = "jchar"; goto printit;
1310 case 'D': ctype = "jdouble"; goto printit;
1311 case 'F': ctype = "jfloat"; goto printit;
1312 case 'I': ctype = "jint"; goto printit;
1313 case 'J': ctype = "jlong"; goto printit;
1314 case 'S': ctype = "jshort"; goto printit;
1315 case 'Z': ctype = "jboolean"; goto printit;
1316 case 'V': ctype = "void"; goto printit;
1320 /* We know about certain types and special-case their names. */
1321 if (! strncmp (signature, "Ljava/lang/String;",
1322 sizeof ("Ljava/lang/String;") -1))
1324 else if (! strncmp (signature, "Ljava/lang/Class;",
1325 sizeof ("Ljava/lang/Class;") - 1))
1327 /* Skip leading 'L' for throwable_p call. */
1328 else if (throwable_p (signature + 1))
1329 ctype = "jthrowable";
1333 while (*signature && *signature != ';')
1338 /* Print a leading "::" so we look in the right namespace. */
1339 fputs ("::", stream);
1341 while (*signature && *signature != ';')
1343 int ch = UTF8_GET (signature, limit);
1345 fputs ("::", stream);
1347 jcf_print_char (stream, ch);
1349 fputs (" *", stream);
1350 if (*signature == ';')
1356 jni_print_char (stream, *signature++);
1361 fputs (ctype, stream);
1367 while (array_depth-- > 0)
1368 fputs ("> *", stream);
1375 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1376 int is_init, const char *name_override, int flags)
1378 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1380 fprintf (stream, "<not a UTF8 constant>");
1385 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1386 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1387 const unsigned char *str = str0;
1388 const unsigned char *limit = str + length;
1390 int is_method = str[0] == '(';
1391 const unsigned char *next;
1393 /* If printing a method, skip to the return signature and print
1394 that first. However, there is no return value if this is a
1396 if (is_method && ! is_init)
1406 /* If printing a field or an ordinary method, then print the
1407 "return value" now. */
1408 if (! is_method || ! is_init)
1410 next = decode_signature_piece (stream, str, limit, &need_space);
1413 error ("unparseable signature: `%s'", str0);
1418 /* Force the alignment of the first data member. This is
1419 because the "new" C++ ABI changed the alignemnt of non-POD
1420 classes. gcj, however, still uses the "old" alignment. */
1421 if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
1423 is_first_data_member = 0;
1424 print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1425 jcf, jcf->super_class, 1);
1426 fputs (" )))) ", stream);
1429 /* Now print the name of the thing. */
1431 fputs (" ", stream);
1432 print_full_cxx_name (stream, jcf, name_index,
1433 signature_index, is_init, name_override,
1438 /* Print the unqualified method name followed by the signature. */
1440 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1441 int signature_index, int is_init,
1442 const char *name_override, int flags)
1444 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1445 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1446 const unsigned char *str = str0;
1447 const unsigned char *limit = str + length;
1449 int is_method = str[0] == '(';
1450 const unsigned char *next;
1453 fputs (name_override, stream);
1454 else if (name_index)
1456 /* Declare constructors specially. */
1458 print_base_classname (stream, jcf, jcf->this_class);
1460 print_name (stream, jcf, name_index);
1465 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1466 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1467 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1468 JPOOL_UTF_LENGTH (jcf, name_index),
1469 signature, sig_len))
1471 /* If this method is overloaded by another native method,
1472 then include the argument information in the mangled
1474 unsigned char *limit = signature + sig_len;
1475 fputs ("__", stream);
1476 while (signature < limit)
1478 int ch = UTF8_GET (signature, limit);
1479 jni_print_char (stream, ch);
1491 /* Have a method or a constructor. Print signature pieces
1493 fputs (" (", stream);
1497 /* In JNI mode, add extra arguments. */
1500 /* FIXME: it would be nice to know if we are printing a decl
1501 or a definition, and only print `env' for the latter. */
1502 fputs ("JNIEnv *env", stream);
1504 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1507 fputs (", ", stream);
1510 while (str < limit && *str != ')')
1512 next = decode_signature_piece (stream, str, limit, &need_space);
1515 error ("unparseable signature: `%s'", str0);
1519 if (next < limit && *next != ')')
1520 fputs (", ", stream);
1524 fputs (")", stream);
1528 /* This is a helper for print_stub_or_jni. */
1530 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1531 int signature_index, int is_init,
1532 const char *name_override, int flags)
1534 const char *const prefix = flag_jni ? "Java_" : "";
1535 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1536 fputs (flag_jni ? "_" : "::", stream);
1537 print_full_cxx_name (stream, jcf, name_index,
1538 signature_index, is_init, name_override,
1543 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1544 int signature_index, int is_init,
1545 const char *name_override, int flags)
1547 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1549 fprintf (stream, "<not a UTF8 constant>");
1554 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1555 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1556 const unsigned char *str = str0;
1557 const unsigned char *limit = str + length;
1559 int is_method = str[0] == '(';
1560 const unsigned char *next;
1562 /* Don't print fields in the JNI case. */
1563 if (! is_method && flag_jni)
1566 if (flag_jni && ! stubs)
1567 fputs ("extern JNIEXPORT ", stream);
1569 /* If printing a method, skip to the return signature and print
1570 that first. However, there is no return value if this is a
1572 if (is_method && ! is_init)
1582 /* If printing a field or an ordinary method, then print the
1583 "return value" now. Note that a constructor can't be native,
1584 so we don't bother checking this in the JNI case. */
1585 if (! is_method || ! is_init)
1587 next = decode_signature_piece (stream, str, limit, &need_space);
1590 error ("unparseable signature: `%s'", str0);
1595 /* When printing a JNI header we need to respect the space. In
1596 other cases we're just going to insert a newline anyway. */
1597 fputs (need_space && ! stubs ? " " : "\n", stream);
1599 if (flag_jni && ! stubs)
1600 fputs ("JNICALL ", stream);
1602 /* Now print the name of the thing. */
1603 print_name_for_stub_or_jni (stream, jcf, name_index,
1604 signature_index, is_init, name_override,
1607 /* Print the body. */
1611 fputs ("\n{\n (*env)->FatalError (env, \"", stream);
1613 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1614 print_name_for_stub_or_jni (stream, jcf, name_index,
1615 signature_index, is_init,
1618 fprintf (stream, " not implemented\")%s;\n}\n\n",
1619 flag_jni ? "" : ")");
1625 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1627 int name_index = JPOOL_USHORT1 (jcf, index);
1628 fputs (prefix, stream);
1629 jcf_print_utf8_replace (out,
1630 JPOOL_UTF_DATA (jcf, name_index),
1631 JPOOL_UTF_LENGTH (jcf, name_index),
1635 /* Print PREFIX, then a class name in C++ format. If the name refers
1636 to an array, ignore it and don't print PREFIX. Returns 1 if
1637 something was printed, 0 otherwise. */
1639 print_cxx_classname (FILE *stream, const char *prefix,
1640 JCF *jcf, int index, int add_scope)
1642 int name_index = JPOOL_USHORT1 (jcf, index);
1644 const unsigned char *s, *p, *limit;
1646 s = JPOOL_UTF_DATA (jcf, name_index);
1647 len = JPOOL_UTF_LENGTH (jcf, name_index);
1650 /* Explicitly omit arrays here. */
1652 c = UTF8_GET (p, limit);
1656 fputs (prefix, stream);
1658 /* Print a leading "::" so we look in the right namespace. */
1659 if (! flag_jni && ! stubs && add_scope)
1660 fputs ("::", stream);
1664 c = UTF8_GET (s, limit);
1666 fputs (flag_jni ? "_" : "::", stream);
1668 jni_print_char (stream, c);
1674 int written_class_count = 0;
1676 /* Return name of superclass. If LEN is not NULL, fill it with length
1678 static const unsigned char *
1679 super_class_name (JCF *derived_jcf, int *len)
1681 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1682 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1683 const unsigned char *supername =
1684 JPOOL_UTF_DATA (derived_jcf, supername_index);
1687 *len = supername_length;
1693 handle_inner_classes (int count)
1697 if (out && ! flag_jni && ! stubs && count > 0)
1698 fprintf (out, "\n");
1700 for (i = 0; i < count; ++i)
1702 JCF_u2 inner_info_index = JCF_readu2 (current_jcf);
1704 /* There are a few more values here, but we don't care about
1705 them. The (void) cast is apparently the only way to avoid a
1707 (void) JCF_readu2 (current_jcf);
1708 (void) JCF_readu2 (current_jcf);
1709 (void) JCF_readu2 (current_jcf);
1711 if (out && ! flag_jni && ! stubs)
1713 print_mangled_classname (out, current_jcf, " friend class ",
1715 fprintf (out, ";\n");
1722 /* We keep track of all the `#include's we generate, so we can avoid
1727 struct include *next;
1730 /* List of all includes. */
1731 static struct include *all_includes = NULL;
1733 /* Generate a #include. */
1735 print_include (FILE *out, const unsigned char *utf8, int len)
1737 struct include *incl;
1743 len = strlen (utf8);
1745 for (incl = all_includes; incl; incl = incl->next)
1747 /* We check the length because we might have a proper prefix. */
1748 if (len == (int) strlen (incl->name)
1749 && ! strncmp (incl->name, utf8, len))
1753 incl = xmalloc (sizeof (struct include));
1754 incl->name = xmalloc (len + 1);
1755 strncpy (incl->name, utf8, len);
1756 incl->name[len] = '\0';
1757 incl->next = all_includes;
1758 all_includes = incl;
1760 fputs ("#include <", out);
1761 jcf_print_utf8_replace (out, utf8, len,
1763 flag_jni ? '_' : '/');
1764 fputs (".h>\n", out);
1769 /* This is used to represent part of a package or class name. */
1772 /* The text of this part of the name. */
1774 /* True if this represents a class. */
1776 /* Linked list of all classes and packages inside this one. */
1777 struct namelet *subnamelets;
1778 /* Pointer to next sibling. */
1779 struct namelet *next;
1782 static void add_namelet (const unsigned char *, const unsigned char *,
1784 static void print_namelet (FILE *, struct namelet *, int);
1786 /* The special root namelet. */
1787 static struct namelet root =
1795 /* This extracts the next name segment from the full UTF-8 encoded
1796 package or class name and links it into the tree. It does this
1799 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1800 struct namelet *parent)
1802 const unsigned char *p;
1803 struct namelet *n = NULL, *np;
1805 /* We want to skip the standard namespaces that we assume the
1806 runtime already knows about. We only do this at the top level,
1807 though, hence the check for `root'. */
1808 if (parent == &root)
1810 #define JAVALANG "java/lang/"
1811 #define JAVAIO "java/io/"
1812 #define JAVAUTIL "java/util/"
1813 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1814 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1815 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1816 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1817 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1818 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1822 for (p = name; p < name_limit && *p != '/'; ++p)
1825 /* Search for this name beneath the PARENT node. */
1826 for (np = parent->subnamelets; np != NULL; np = np->next)
1828 /* We check the length because we might have a proper prefix. */
1829 if ((int) strlen (np->name) == p - name &&
1830 ! strncmp (name, np->name, p - name))
1839 n = xmalloc (sizeof (struct namelet));
1840 n->name = xmalloc (p - name + 1);
1841 strncpy (n->name, name, p - name);
1842 n->name[p - name] = '\0';
1843 n->is_class = (p == name_limit);
1844 n->subnamelets = NULL;
1845 n->next = parent->subnamelets;
1846 parent->subnamelets = n;
1849 /* We recurse if there is more text, and if the trailing piece does
1850 not represent an inner class. */
1852 add_namelet (p + 1, name_limit, n);
1855 /* Print a single namelet. Destroys namelets while printing. */
1857 print_namelet (FILE *out, struct namelet *name, int depth)
1864 for (i = 0; i < depth; ++i)
1866 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1868 if (name->is_class && name->subnamelets == NULL)
1874 for (i = 0; i < depth; ++i)
1880 c = name->subnamelets;
1883 struct namelet *next = c->next;
1884 print_namelet (out, c, depth + 2);
1887 name->subnamelets = NULL;
1893 for (i = 0; i < depth; ++i)
1896 /* Only print a `;' when printing a class. C++ is evil. */
1906 /* This is called to add some classes to the list of classes for which
1907 we need decls. The signature argument can be a function
1910 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1912 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1913 int len = JPOOL_UTF_LENGTH (jcf, signature);
1916 for (i = 0; i < len; ++i)
1920 /* If we see an array, then we include the array header. */
1923 print_include (out, "gcj/array", -1);
1927 /* We're looking for `L<stuff>;' -- everything else is
1932 for (start = ++i; i < len && s[i] != ';'; ++i)
1935 add_namelet (&s[start], &s[i], &root);
1939 /* Print declarations for all classes required by this class. Any
1940 class or package in the `java' package is assumed to be handled
1941 statically in libjava; we don't generate declarations for these.
1942 This makes the generated headers a bit easier to read. */
1944 print_class_decls (FILE *out, JCF *jcf, int self)
1946 /* Make sure to always add the current class to the list of things
1947 that should be declared. */
1948 int name_index = JPOOL_USHORT1 (jcf, self);
1950 const unsigned char *s;
1952 s = JPOOL_UTF_DATA (jcf, name_index);
1953 len = JPOOL_UTF_LENGTH (jcf, name_index);
1954 add_namelet (s, s + len, &root);
1956 if (root.subnamelets)
1958 fputs ("extern \"Java\"\n{\n", out);
1959 /* We use an initial offset of 0 because the root namelet
1960 doesn't cause anything to print. */
1961 print_namelet (out, &root, 0);
1962 fputs ("}\n\n", out);
1969 process_file (JCF *jcf, FILE *out)
1972 uint32 field_start, method_end, method_start;
1978 if (jcf_parse_preamble (jcf) != 0)
1980 error ("Not a valid Java .class file.");
1984 /* Parse and possibly print constant pool */
1985 code = jcf_parse_constant_pool (jcf);
1988 error ("error while parsing constant pool");
1991 code = verify_constant_pool (jcf);
1994 error ("error in constant pool entry #%d", code);
1998 jcf_parse_class (jcf);
2000 if (written_class_count++ == 0 && out)
2002 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
2017 mode = " -*- c++ -*-";
2023 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2024 cstart, mode, cend);
2027 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2029 %s This file is intended to give you a head start on implementing native\n\
2030 %s methods using %s.\n\
2031 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2032 %s overwrite any edits you have made to this file.%s\n\n",
2033 cstart, jflag, mode,
2049 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2050 fprintf (out, "__\n");
2052 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2053 fprintf (out, "__\n\n");
2057 fprintf (out, "#include <jni.h>\n\n");
2058 fprintf (out, "#ifdef __cplusplus\n");
2059 fprintf (out, "extern \"C\"\n");
2060 fprintf (out, "{\n");
2061 fprintf (out, "#endif\n");
2065 /* We do this to ensure that inline methods won't be
2066 `outlined' by g++. This works as long as method and
2067 fields are not added by the user. */
2068 fprintf (out, "#pragma interface\n");
2070 if (jcf->super_class)
2073 const unsigned char *supername =
2074 super_class_name (jcf, &super_length);
2077 print_include (out, supername, super_length);
2083 /* Strip off the ".class" portion of the name when printing
2084 the include file name. */
2086 int i, len = strlen (jcf->classname);
2087 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2089 /* Turn the class name into a file name. */
2090 name = xmalloc (len + 1);
2091 for (i = 0; i < len; ++i)
2092 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2094 print_include (out, name, len);
2099 print_include (out, "gcj/cni", -1);
2100 print_include (out, "java/lang/UnsupportedOperationException",
2106 /* We want to parse the methods first. But we need to find where
2107 they start. So first we skip the fields, then parse the methods.
2108 Then we parse the fields and skip the methods. This is ugly, but
2109 not too bad since we need two full passes to get class decl
2110 information anyway. */
2112 field_start = JCF_TELL (jcf);
2113 jcf_parse_fields (jcf);
2115 method_start = JCF_TELL (jcf);
2117 jcf_parse_methods (jcf);
2122 if (out && ! flag_jni)
2125 print_class_decls (out, jcf, jcf->this_class);
2127 for (i = 0; i < prepend_count; ++i)
2128 fprintf (out, "%s\n", prepend_specs[i]);
2129 if (prepend_count > 0)
2134 if (! print_cxx_classname (out, "class ", jcf,
2135 jcf->this_class, 0))
2137 error ("class is of array type\n");
2140 if (jcf->super_class)
2142 if (! print_cxx_classname (out, " : public ",
2143 jcf, jcf->super_class, 1))
2145 error ("base class is of array type");
2150 fputs ("\n{\n", out);
2154 /* Now go back for second pass over methods and fields. */
2155 is_first_data_member = 1;
2157 JCF_SEEK (jcf, method_start);
2159 jcf_parse_methods (jcf);
2160 method_end = JCF_TELL (jcf);
2163 JCF_SEEK (jcf, field_start);
2164 jcf_parse_fields (jcf);
2165 JCF_SEEK (jcf, method_end);
2167 jcf_parse_final_attributes (jcf);
2173 fprintf (out, "\n#ifdef __cplusplus\n");
2174 fprintf (out, "}\n");
2175 fprintf (out, "#endif\n");
2179 /* Generate friend decl if we still must. */
2180 for (i = 0; i < friend_count; ++i)
2181 fprintf (out, " friend %s\n", friend_specs[i]);
2183 /* Generate extra declarations. */
2186 for (i = 0; i < add_count; ++i)
2187 fprintf (out, " %s\n", add_specs[i]);
2189 /* Generate an entry for the class object. */
2190 generate_access (out, ACC_PUBLIC);
2191 fprintf (out, "\n static ::java::lang::Class class$;\n");
2195 if (jcf->access_flags & ACC_INTERFACE)
2196 fputs (" __attribute__ ((java_interface))", out);
2200 if (append_count > 0)
2202 for (i = 0; i < append_count; ++i)
2203 fprintf (out, "%s\n", append_specs[i]);
2206 print_mangled_classname (out, jcf,
2207 "\n#endif /* __", jcf->this_class);
2208 fprintf (out, "__ */\n");
2214 /* This is used to mark options with no short value. */
2215 #define LONG_OPT(Num) ((Num) + 128)
2217 #define OPT_classpath LONG_OPT (0)
2218 #define OPT_CLASSPATH OPT_classpath
2219 #define OPT_bootclasspath LONG_OPT (1)
2220 #define OPT_extdirs LONG_OPT (2)
2221 #define OPT_HELP LONG_OPT (3)
2222 #define OPT_TEMP LONG_OPT (4)
2223 #define OPT_VERSION LONG_OPT (5)
2224 #define OPT_PREPEND LONG_OPT (6)
2225 #define OPT_FRIEND LONG_OPT (7)
2226 #define OPT_ADD LONG_OPT (8)
2227 #define OPT_APPEND LONG_OPT (9)
2228 #define OPT_M LONG_OPT (10)
2229 #define OPT_MM LONG_OPT (11)
2230 #define OPT_MG LONG_OPT (12)
2231 #define OPT_MD LONG_OPT (13)
2232 #define OPT_MMD LONG_OPT (14)
2234 static const struct option options[] =
2236 { "classpath", required_argument, NULL, OPT_classpath },
2237 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2238 { "extdirs", required_argument, NULL, OPT_extdirs },
2239 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2240 { "help", no_argument, NULL, OPT_HELP },
2241 { "stubs", no_argument, &stubs, 1 },
2242 { "td", required_argument, NULL, OPT_TEMP },
2243 { "verbose", no_argument, NULL, 'v' },
2244 { "version", no_argument, NULL, OPT_VERSION },
2245 { "prepend", required_argument, NULL, OPT_PREPEND },
2246 { "friend", required_argument, NULL, OPT_FRIEND },
2247 { "add", required_argument, NULL, OPT_ADD },
2248 { "append", required_argument, NULL, OPT_APPEND },
2249 { "M", no_argument, NULL, OPT_M },
2250 { "MM", no_argument, NULL, OPT_MM },
2251 { "MG", no_argument, NULL, OPT_MG },
2252 { "MD", no_argument, NULL, OPT_MD },
2253 { "MMD", no_argument, NULL, OPT_MMD },
2254 { "jni", no_argument, &flag_jni, 1 },
2255 { NULL, no_argument, NULL, 0 }
2261 fprintf (stderr, _("Try `gcjh --help' for more information.\n"));
2268 printf (_("Usage: gcjh [OPTION]... CLASS...\n\n"));
2269 printf (_("Generate C++ header files from .class files\n\n"));
2270 printf (_(" -stubs Generate an implementation stub file\n"));
2271 printf (_(" -jni Generate a JNI header or stub\n"));
2273 printf (_(" -add TEXT Insert TEXT into class body\n"));
2274 printf (_(" -append TEXT Insert TEXT after class declaration\n"));
2275 printf (_(" -friend TEXT Insert TEXT as `friend' declaration\n"));
2276 printf (_(" -prepend TEXT Insert TEXT before start of class\n"));
2278 printf (_(" --classpath PATH Set path to find .class files\n"));
2279 printf (_(" -IDIR Append directory to class path\n"));
2280 printf (_(" --bootclasspath PATH Override built-in class path\n"));
2281 printf (_(" --extdirs PATH Set extensions directory path\n"));
2282 printf (_(" -d DIRECTORY Set output directory name\n"));
2283 printf (_(" -o FILE Set output file name\n"));
2284 printf (_(" -td DIRECTORY Set temporary directory name\n"));
2286 printf (_(" --help Print this help, then exit\n"));
2287 printf (_(" --version Print version number, then exit\n"));
2288 printf (_(" -v, --verbose Print extra information while running\n"));
2290 printf (_(" -M Print all dependencies to stdout;\n"
2291 " suppress ordinary output\n"));
2292 printf (_(" -MM Print non-system dependencies to stdout;\n"
2293 " suppress ordinary output\n"));
2294 printf (_(" -MD Print all dependencies to stdout\n"));
2295 printf (_(" -MMD Print non-system dependencies to stdout\n"));
2296 /* We omit -MG until it is implemented. */
2298 printf (_("For bug reporting instructions, please see:\n"
2299 "%s.\n"), bug_report_url);
2306 printf ("gcjh (GCC) %s\n\n", version_string);
2307 printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
2308 printf (_("This is free software; see the source for copying conditions. There is NO\n"
2309 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
2314 main (int argc, char** argv)
2318 char *output_file = NULL;
2319 int emit_dependencies = 0, suppress_output = 0;
2322 gcc_init_libintl ();
2326 error ("no classes specified");
2332 /* We use getopt_long_only to allow single `-' long options. For
2333 some of our options this is more natural. */
2334 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2339 /* Already handled. */
2343 output_file = optarg;
2347 output_directory = optarg;
2351 jcf_path_include_arg (optarg);
2359 jcf_path_classpath_arg (optarg);
2362 case OPT_bootclasspath:
2363 jcf_path_bootclasspath_arg (optarg);
2367 jcf_path_extdirs_arg (optarg);
2375 temp_directory = optarg;
2383 if (prepend_count == 0)
2384 prepend_specs = ALLOC (argc * sizeof (char*));
2385 prepend_specs[prepend_count++] = optarg;
2389 if (friend_count == 0)
2390 friend_specs = ALLOC (argc * sizeof (char*));
2391 friend_specs[friend_count++] = optarg;
2396 add_specs = ALLOC (argc * sizeof (char*));
2397 add_specs[add_count++] = optarg;
2401 if (append_count == 0)
2402 append_specs = ALLOC (argc * sizeof (char*));
2403 append_specs[append_count++] = optarg;
2407 emit_dependencies = 1;
2408 suppress_output = 1;
2409 jcf_dependency_init (1);
2413 emit_dependencies = 1;
2414 suppress_output = 1;
2415 jcf_dependency_init (0);
2419 error ("`-MG' option is unimplemented");
2423 emit_dependencies = 1;
2424 jcf_dependency_init (1);
2428 emit_dependencies = 1;
2429 jcf_dependency_init (0);
2440 error ("no classes specified");
2444 jcf_path_seal (verbose);
2446 if (output_file && emit_dependencies)
2448 error ("can't specify both -o and -MD");
2452 for (argi = optind; argi < argc; argi++)
2454 char *classname = argv[argi];
2455 char *current_output_file;
2456 const char *classfile_name;
2459 printf (_("Processing %s\n"), classname);
2461 jcf_dependency_reset ();
2462 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2463 if (classfile_name == NULL)
2465 error ("%s: no such class", classname);
2469 printf (_("Found in %s\n"), classfile_name);
2472 if (strcmp (output_file, "-") == 0)
2474 else if (out == NULL)
2476 out = fopen (output_file, "w");
2480 perror (output_file);
2483 current_output_file = output_file;
2487 int dir_len = strlen (output_directory);
2488 int i, classname_length = strlen (classname);
2489 current_output_file = ALLOC (dir_len + classname_length + 5);
2490 strcpy (current_output_file, output_directory);
2491 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2492 current_output_file[dir_len++] = '/';
2493 for (i = 0; classname[i] != '\0'; i++)
2495 char ch = classname[i];
2498 if (flag_jni && ch == '/')
2500 current_output_file[dir_len++] = ch;
2502 if (emit_dependencies)
2504 if (suppress_output)
2506 jcf_dependency_set_dep_file ("-");
2511 /* We use `.hd' and not `.d' to avoid clashes with
2512 dependency tracking from straight compilation. */
2513 strcpy (current_output_file + dir_len, ".hd");
2514 jcf_dependency_set_dep_file (current_output_file);
2517 strcpy (current_output_file + dir_len,
2518 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2519 jcf_dependency_set_target (current_output_file);
2520 if (! suppress_output)
2522 out = fopen (current_output_file, "w");
2525 perror (current_output_file);
2530 process_file (&jcf, out);
2532 if (current_output_file != output_file)
2533 free (current_output_file);
2534 jcf_dependency_write ();
2537 if (out != NULL && out != stdout)