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 int java_float_finite (jfloat);
138 static int java_double_finite (jdouble);
139 static void print_name (FILE *, JCF *, int);
140 static void print_base_classname (FILE *, JCF *, int);
141 static int utf8_cmp (const unsigned char *, int, const char *);
142 static char *cxx_keyword_subst (const unsigned char *, int);
143 static void generate_access (FILE *, JCF_u2);
144 static int name_is_method_p (const unsigned char *, int);
145 static char *get_field_name (JCF *, int, JCF_u2);
146 static void print_field_name (FILE *, JCF *, int, JCF_u2);
147 static const unsigned char *super_class_name (JCF *, int *);
148 static void print_include (FILE *, const unsigned char *, int);
149 static int gcjh_streq (const void *p1, const void *p2);
150 static int throwable_p (const unsigned char *signature);
151 static const unsigned char *
152 decode_signature_piece (FILE *, const unsigned char *,
153 const unsigned char *, int *);
154 static void print_class_decls (FILE *, JCF *, int);
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 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 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
202 method_synthetic = 0; \
203 method_printed = 0; \
205 method_signature = SIGNATURE; \
206 if (ATTRIBUTE_COUNT) \
207 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
208 (const char *)"Synthetic", 9); \
209 /* If a synthetic methods have been declared, its attribute aren't \
210 worth reading (and triggering side-effects). We skip them an \
211 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
212 jcf_parse_one_method. */ \
213 if (method_synthetic) \
215 skip_attribute (jcf, ATTRIBUTE_COUNT); \
216 ATTRIBUTE_COUNT = 0; \
218 if (method_pass && !method_synthetic) \
221 print_method_info (out, jcf, NAME, SIGNATURE, \
224 else if (!method_synthetic) \
226 print_method_info (NULL, jcf, NAME, SIGNATURE, \
228 if (! stubs && ! flag_jni) \
229 add_class_decl (out, jcf, SIGNATURE); \
233 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
234 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
236 static int decompiled = 0;
237 #define HANDLE_END_METHOD() \
238 if (out && method_printed && !method_synthetic) \
239 fputs (decompiled || stubs ? "\n" : ";\n", out);
241 /* We're going to need {peek,skip}_attribute, enable their definition. */
242 #define NEED_PEEK_ATTRIBUTE
243 #define NEED_SKIP_ATTRIBUTE
245 #include "jcf-reader.c"
247 /* Some useful constants. */
248 #define F_NAN_MASK 0x7f800000
249 #if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN)
250 #define D_NAN_MASK 0x000000007ff00000LL
252 #define D_NAN_MASK 0x7ff0000000000000LL
255 /* Return 1 if F is not Inf or NaN. */
257 java_float_finite (jfloat f)
262 /* We happen to know that F_NAN_MASK will match all NaN values, and
263 also positive and negative infinity. That's why we only need one
264 test here. See The Java Language Specification, section 20.9. */
265 return (u.i & F_NAN_MASK) != F_NAN_MASK;
268 /* Return 1 if D is not Inf or NaN. */
270 java_double_finite (jdouble d)
275 /* Now check for all NaNs. */
276 return (u.l & D_NAN_MASK) != D_NAN_MASK;
279 /* Print a character, appropriately mangled for JNI. */
282 jni_print_char (FILE *stream, int ch)
285 jcf_print_char (stream, ch);
286 else if (ch == '(' || ch == ')')
291 fputs ("_1", stream);
293 fputs ("_2", stream);
295 fputs ("_3", stream);
298 else if (ISALNUM (ch))
302 /* "Unicode" character. */
303 fprintf (stream, "_0%04x", ch);
307 /* Print a name from the class data. If the index does not point to a
308 string, an error results. */
311 print_name (FILE* stream, JCF* jcf, int name_index)
313 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
315 fprintf (stream, "<not a UTF8 constant>");
319 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
320 JPOOL_UTF_LENGTH (jcf, name_index));
323 /* For JNI we must correctly quote each character. */
324 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
325 int length = JPOOL_UTF_LENGTH (jcf, name_index);
326 const unsigned char *limit = str + length;
329 int ch = UTF8_GET (str, limit);
332 fprintf (stream, "\\<invalid>");
335 jni_print_char (stream, ch);
340 /* Print base name of class. The base name is everything after the
344 print_base_classname (FILE *stream, JCF *jcf, int index)
346 int name_index = JPOOL_USHORT1 (jcf, index);
348 const unsigned char *s, *p, *limit;
350 s = JPOOL_UTF_DATA (jcf, name_index);
351 len = JPOOL_UTF_LENGTH (jcf, name_index);
356 int c = UTF8_GET (s, limit);
363 int ch = UTF8_GET (p, limit);
365 fputs ("::", stream);
367 jcf_print_char (stream, ch);
371 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
372 and 1 if STR is "greater" than NAME. */
375 utf8_cmp (const unsigned char *str, int length, const char *name)
377 const unsigned char *limit = str + length;
380 for (i = 0; name[i]; ++i)
382 int ch = UTF8_GET (str, limit);
387 return str == limit ? 0 : 1;
390 /* This is a sorted list of all C++ keywords. */
392 static const char *const cxx_keywords[] =
501 /* If NAME is the name of a C++ keyword, then return an override name.
502 This is a name that can be used in place of the keyword.
503 Otherwise, return NULL. The return value is malloc()d. */
506 cxx_keyword_subst (const unsigned char *str, int length)
508 int last = ARRAY_SIZE (cxx_keywords);
510 int mid = (last + first) / 2;
513 for (mid = (last + first) / 2;
515 old = mid, mid = (last + first) / 2)
517 int kwl = strlen (cxx_keywords[mid]);
518 int min_length = kwl > length ? length : kwl;
519 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
525 /* Skip all trailing `$'. */
526 for (i = min_length; i < length && str[i] == '$'; ++i)
528 /* We've only found a match if all the remaining characters
532 char *dup = xmalloc (2 + length - min_length + kwl);
533 strcpy (dup, cxx_keywords[mid]);
534 for (i = kwl; i < length + 1; ++i)
550 /* Generate an access control keyword based on FLAGS. */
553 generate_access (FILE *stream, JCF_u2 flags)
555 if ((flags & ACC_VISIBILITY) == last_access)
557 last_access = (flags & ACC_VISIBILITY);
562 fputs ("public: // actually package-private\n", stream);
565 fputs ("public:\n", stream);
568 fputs ("private:\n", stream);
571 fputs ("public: // actually protected\n", stream);
575 fprintf (stream, "#error unrecognized visibility %d\n",
576 (flags & ACC_VISIBILITY));
581 /* See if NAME is already the name of a method. */
583 name_is_method_p (const unsigned char *name, int length)
585 struct method_name *p;
587 for (p = method_name_list; p != NULL; p = p->next)
589 if (p->length == length && ! memcmp (p->name, name, length))
595 /* If there is already a method named NAME, whose signature is not
596 SIGNATURE, then return true. Otherwise return false. */
598 overloaded_jni_method_exists_p (const unsigned char *name, int length,
599 const char *signature, int sig_length)
601 struct method_name *p;
603 for (p = method_name_list; p != NULL; p = p->next)
605 if (p->length == length
606 && ! memcmp (p->name, name, length)
607 && (p->sig_length != sig_length
608 || memcmp (p->signature, signature, sig_length)))
614 /* Get name of a field. This handles renamings due to C++ clash. */
616 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
618 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
619 int length = JPOOL_UTF_LENGTH (jcf, name_index);
622 if (name_is_method_p (name, length))
624 /* This field name matches a method. So override the name with
625 a dummy name. This is yucky, but it isn't clear what else to
626 do. FIXME: if the field is static, then we'll be in real
628 if ((flags & ACC_STATIC))
630 fprintf (stderr, "static field has same name as method\n");
635 override = xmalloc (length + 3);
636 memcpy (override, name, length);
637 strcpy (override + length, "__");
640 override = cxx_keyword_subst (name, length);
645 /* Print a field name. Convenience function for use with
648 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
650 char *override = get_field_name (jcf, name_index, flags);
654 fputs (override, stream);
658 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
659 JPOOL_UTF_LENGTH (jcf, name_index));
663 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
666 char *override = NULL;
668 generate_access (stream, flags);
669 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
671 fprintf (stream, "<not a UTF8 constant>");
677 if ((flags & ACC_STATIC))
678 fputs ("static ", out);
680 if ((flags & ACC_FINAL))
682 if (current_field_value > 0)
687 switch (JPOOL_TAG (jcf, current_field_value))
689 case CONSTANT_Integer:
692 int most_negative = 0;
693 fputs ("const jint ", out);
694 print_field_name (out, jcf, name_index, 0);
696 num = JPOOL_INT (jcf, current_field_value);
697 /* We single out the most negative number to print
698 specially. This avoids later warnings from g++. */
699 if (num == (jint) 0x80000000)
704 format_int (buffer, (jlong) num, 10);
705 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
711 int most_negative = 0;
712 fputs ("const jlong ", out);
713 print_field_name (out, jcf, name_index, 0);
715 num = JPOOL_LONG (jcf, current_field_value);
716 /* We single out the most negative number to print
717 specially.. This avoids later warnings from g++. */
718 if (num == (jlong) 0x8000000000000000LL)
723 format_int (buffer, num, 10);
724 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
729 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
730 fputs ("const jfloat ", out);
731 print_field_name (out, jcf, name_index, 0);
732 if (! java_float_finite (fnum))
735 fprintf (out, " = %.10g;\n", fnum);
738 case CONSTANT_Double:
740 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
741 fputs ("const jdouble ", out);
742 print_field_name (out, jcf, name_index, 0);
743 if (! java_double_finite (dnum))
746 fprintf (out, " = %.17g;\n", dnum);
750 /* We can't print this as a constant, but we can still
751 print something sensible. */
761 override = get_field_name (jcf, name_index, flags);
762 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
771 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
774 const unsigned char *str;
775 int length, is_init = 0;
776 char *override = NULL;
779 method_access = flags;
780 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
781 fprintf (stream, "<not a UTF8 constant>");
782 str = JPOOL_UTF_DATA (jcf, name_index);
783 length = JPOOL_UTF_LENGTH (jcf, name_index);
787 /* Ignore the internally generated method <clinit>. However,
788 treat <init> as a constructor. */
789 if (! utf8_cmp (str, length, "<init>"))
791 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
792 && ! (flags & ACC_STATIC))
794 /* FIXME: i18n bug here. Order of prints should not be
796 fprintf (stderr, "ignored method `");
797 jcf_print_utf8 (stderr, str, length);
798 fprintf (stderr, "' marked virtual\n");
806 /* During the first method pass, build a list of method names. This will
807 be used to determine if field names conflict with method names. */
810 struct method_name *nn;
812 nn = xmalloc (sizeof (struct method_name));
813 nn->name = xmalloc (length);
814 memcpy (nn->name, str, length);
816 nn->next = method_name_list;
817 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
818 nn->signature = xmalloc (nn->sig_length);
819 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
821 method_name_list = nn;
823 /* The rest of this function doesn't matter. */
827 /* We don't worry about overrides in JNI mode. */
830 /* We can't generate a method whose name is a C++ reserved word.
831 We can't just ignore the function, because that will cause
832 incorrect code to be generated if the function is virtual
833 (not only for calls to this function for for other functions
834 after it in the vtbl). So we give it a dummy name instead. */
835 override = cxx_keyword_subst (str, length);
838 if (! stubs && ! flag_jni)
842 generate_access (stream, flags);
845 if ((flags & ACC_STATIC))
846 fputs ("static ", out);
847 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
849 /* Don't print `virtual' if we have a constructor. */
851 fputs ("virtual ", out);
853 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
855 if ((flags & ACC_ABSTRACT))
862 if (METHOD_IS_NATIVE (flags))
865 print_stub_or_jni (out, jcf, name_index, sig_index,
866 is_init, override, flags);
874 /* A helper for the decompiler which prints a `return' statement where
875 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
876 identical, we emit a cast. We do this because the C++ compiler
877 doesn't know that a reference can be cast to the type of an
878 interface it implements. METHODTYPE is the index of the method's
879 signature. NAMEINDEX is the index of the field name; -1 for
880 `this'. OBJECTTYPE is the index of the object's type. */
882 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
883 int nameindex, int objecttype)
886 int obj_name_len, method_name_len;
887 const unsigned char *obj_data, *method_data;
889 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
890 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
892 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
893 method_data = JPOOL_UTF_DATA (jcf, methodtype);
895 /* Skip forward to return type part of method. */
896 while (*method_data != ')')
905 /* If we see an `L', skip it and the trailing `;'. */
906 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
909 method_name_len -= 2;
911 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
917 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
918 need a cast. Right now there is no way to determine if this is
920 if (method_name_len != obj_name_len)
925 for (i = 0; i < method_name_len; ++i)
927 if (method_data[i] != obj_data[i])
935 fputs (" { return ", out);
940 const unsigned char *limit;
942 fputs ("reinterpret_cast<", out);
944 while (*method_data == '[')
949 fputs ("JArray<", out);
952 /* Leading space to avoid C++ digraphs. */
955 /* If we see an `L', skip it and the trailing `;'. Only do this
956 if we've seen an array specification. If we don't have an
957 array then the `L' was stripped earlier. */
958 if (array_depth && method_data[0] == 'L'
959 && method_data[method_name_len - 1] == ';')
962 method_name_len -= 2;
965 limit = method_data + method_name_len;
966 while (method_data < limit)
968 int ch = UTF8_GET (method_data, limit);
972 jcf_print_char (out, ch);
976 /* Close each array. */
977 while (array_depth > 0)
983 /* Close the cast. */
990 print_field_name (out, jcf, nameindex, 0);
999 /* Try to decompile a method body. Right now we just try to handle a
1000 simple case that we can do. Expand as desired. */
1002 decompile_method (FILE *out, JCF *jcf, int code_len)
1004 const unsigned char *codes = jcf->read_ptr;
1006 uint16 name_and_type, name;
1008 /* If the method is synchronized, don't touch it. */
1009 if ((method_access & ACC_SYNCHRONIZED))
1013 && codes[0] == OPCODE_aload_0
1014 && codes[1] == OPCODE_getfield
1015 && (codes[4] == OPCODE_areturn
1016 || codes[4] == OPCODE_dreturn
1017 || codes[4] == OPCODE_freturn
1018 || codes[4] == OPCODE_ireturn
1019 || codes[4] == OPCODE_lreturn))
1021 /* Found code like `return FIELD'. */
1022 index = (codes[2] << 8) | codes[3];
1023 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1024 name_and_type = JPOOL_USHORT2 (jcf, index);
1025 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1026 name = JPOOL_USHORT1 (jcf, name_and_type);
1027 if (codes[4] == OPCODE_areturn)
1028 decompile_return_statement (out, jcf, method_signature,
1029 name, JPOOL_USHORT2 (jcf, name_and_type));
1032 fputs (" { return ", out);
1034 print_field_name (out, jcf, name, 0);
1039 else if (code_len == 2
1040 && codes[0] == OPCODE_aload_0
1041 && codes[1] == OPCODE_areturn
1042 /* We're going to generate `return this'. This only makes
1043 sense for non-static methods. */
1044 && ! (method_access & ACC_STATIC))
1046 decompile_return_statement (out, jcf, method_signature, -1,
1047 JPOOL_USHORT1 (jcf, jcf->this_class));
1050 else if (code_len == 1 && codes[0] == OPCODE_return)
1052 /* Found plain `return'. */
1053 fputs (" { }", out);
1056 else if (code_len == 2
1057 && codes[0] == OPCODE_aconst_null
1058 && codes[1] == OPCODE_areturn)
1060 /* Found `return null'. We don't want to depend on NULL being
1062 fputs (" { return 0; }", out);
1067 /* Like strcmp, but invert the return result for the hash table. This
1068 should probably be in hashtab.c to complement the existing string
1071 gcjh_streq (const void *p1, const void *p2)
1073 return ! strcmp ((char *) p1, (char *) p2);
1076 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1077 or 0 if not. CLNAME may be extracted from a signature, and can be
1078 terminated with either `;' or NULL. */
1080 throwable_p (const unsigned char *clname)
1083 unsigned char *current;
1087 /* We keep two hash tables of class names. In one we list all the
1088 classes which are subclasses of Throwable. In the other we will
1089 all other classes. We keep two tables to make the code a bit
1090 simpler; we don't have to have a structure mapping class name to
1091 a `throwable?' bit. */
1092 static htab_t throw_hash;
1093 static htab_t non_throw_hash;
1094 static int init_done = 0;
1101 /* Self-initializing. The cost of this really doesn't matter.
1102 We also don't care about freeing these, either. */
1103 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1105 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1108 /* Make sure the root classes show up in the tables. */
1109 str = xstrdup ("java.lang.Throwable");
1110 slot = htab_find_slot (throw_hash, str, INSERT);
1113 str = xstrdup ("java.lang.Object");
1114 slot = htab_find_slot (non_throw_hash, str, INSERT);
1120 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1122 current = ALLOC (length + 1);
1123 for (i = 0; i < length; ++i)
1124 current[i] = clname[i] == '/' ? '.' : clname[i];
1125 current[length] = '\0';
1127 /* We don't compute the hash slot here because the table might be
1128 modified by the recursion. In that case the slot could be
1130 if (htab_find (throw_hash, current))
1132 else if (htab_find (non_throw_hash, current))
1138 unsigned char *super, *tmp;
1139 int super_length = -1;
1140 const char *classfile_name = find_class (current, strlen (current),
1143 if (! classfile_name)
1145 fprintf (stderr, "couldn't find class %s\n", current);
1149 if (jcf_parse_preamble (&jcf) != 0
1150 || jcf_parse_constant_pool (&jcf) != 0
1151 || verify_constant_pool (&jcf) > 0)
1153 fprintf (stderr, "parse error while reading %s\n", classfile_name);
1157 jcf_parse_class (&jcf);
1159 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1160 super = ALLOC (super_length + 1);
1161 memcpy (super, tmp, super_length);
1162 super[super_length] = '\0';
1164 result = throwable_p (super);
1165 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1176 /* Print one piece of a signature. Returns pointer to next parseable
1177 character on success, NULL on error. */
1178 static const unsigned char *
1179 decode_signature_piece (FILE *stream, const unsigned char *signature,
1180 const unsigned char *limit, int *need_space)
1183 int array_depth = 0;
1185 switch (signature[0])
1188 /* More spaghetti. */
1191 for (signature++; (signature < limit
1192 && ISDIGIT (*signature)); signature++)
1197 ctype = "jbyteArray";
1200 ctype = "jcharArray";
1203 ctype = "jdoubleArray";
1206 ctype = "jfloatArray";
1209 ctype = "jintArray";
1212 ctype = "jshortArray";
1215 ctype = "jlongArray";
1218 ctype = "jbooleanArray";
1221 /* We have a nested array. */
1224 fputs ("JArray<", stream);
1228 /* We have to generate a reference to JArray here, so that
1229 our output matches what the compiler does. */
1231 /* Space between `<' and `:' to avoid C++ digraphs. */
1233 fputs ("JArray< ::", stream);
1234 while (signature < limit && *signature != ';')
1236 int ch = UTF8_GET (signature, limit);
1240 fputs ("::", stream);
1242 jcf_print_char (stream, ch);
1246 fputs (" *> *", stream);
1251 /* Unparseable signature. */
1255 /* If the previous iterations left us with something to print,
1256 print it. For JNI, we always print `jobjectArray' in the
1258 if (flag_jni && (ctype == NULL || array_depth > 0))
1260 ctype = "jobjectArray";
1263 /* The `printit' case will advance SIGNATURE for us. If we
1264 don't go there, we must advance past the `;' ourselves. */
1272 /* This shouldn't happen. */
1275 case 'B': ctype = "jbyte"; goto printit;
1276 case 'C': ctype = "jchar"; goto printit;
1277 case 'D': ctype = "jdouble"; goto printit;
1278 case 'F': ctype = "jfloat"; goto printit;
1279 case 'I': ctype = "jint"; goto printit;
1280 case 'J': ctype = "jlong"; goto printit;
1281 case 'S': ctype = "jshort"; goto printit;
1282 case 'Z': ctype = "jboolean"; goto printit;
1283 case 'V': ctype = "void"; goto printit;
1287 /* We know about certain types and special-case their names. */
1288 if (! strncmp (signature, "Ljava/lang/String;",
1289 sizeof ("Ljava/lang/String;") -1))
1291 else if (! strncmp (signature, "Ljava/lang/Class;",
1292 sizeof ("Ljava/lang/Class;") - 1))
1294 /* Skip leading 'L' for throwable_p call. */
1295 else if (throwable_p (signature + 1))
1296 ctype = "jthrowable";
1300 while (*signature && *signature != ';')
1305 /* Print a leading "::" so we look in the right namespace. */
1306 fputs ("::", stream);
1308 while (*signature && *signature != ';')
1310 int ch = UTF8_GET (signature, limit);
1312 fputs ("::", stream);
1314 jcf_print_char (stream, ch);
1316 fputs (" *", stream);
1317 if (*signature == ';')
1323 jni_print_char (stream, *signature++);
1328 fputs (ctype, stream);
1334 while (array_depth-- > 0)
1335 fputs ("> *", stream);
1342 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1343 int is_init, const char *name_override, int flags)
1345 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1347 fprintf (stream, "<not a UTF8 constant>");
1352 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1353 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1354 register const unsigned char *str = str0;
1355 const unsigned char *limit = str + length;
1357 int is_method = str[0] == '(';
1358 const unsigned char *next;
1360 /* If printing a method, skip to the return signature and print
1361 that first. However, there is no return value if this is a
1363 if (is_method && ! is_init)
1373 /* If printing a field or an ordinary method, then print the
1374 "return value" now. */
1375 if (! is_method || ! is_init)
1377 next = decode_signature_piece (stream, str, limit, &need_space);
1380 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1386 /* Now print the name of the thing. */
1388 fputs (" ", stream);
1389 print_full_cxx_name (stream, jcf, name_index,
1390 signature_index, is_init, name_override,
1395 /* Print the unqualified method name followed by the signature. */
1397 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1398 int signature_index, int is_init,
1399 const char *name_override, int flags)
1401 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1402 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1403 register const unsigned char *str = str0;
1404 const unsigned char *limit = str + length;
1406 int is_method = str[0] == '(';
1407 const unsigned char *next;
1410 fputs (name_override, stream);
1411 else if (name_index)
1413 /* Declare constructors specially. */
1415 print_base_classname (stream, jcf, jcf->this_class);
1417 print_name (stream, jcf, name_index);
1422 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1423 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1424 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1425 JPOOL_UTF_LENGTH (jcf, name_index),
1426 signature, sig_len))
1428 /* If this method is overloaded by another native method,
1429 then include the argument information in the mangled
1431 unsigned char *limit = signature + sig_len;
1432 fputs ("__", stream);
1433 while (signature < limit)
1435 int ch = UTF8_GET (signature, limit);
1436 jni_print_char (stream, ch);
1448 /* Have a method or a constructor. Print signature pieces
1450 fputs (" (", stream);
1454 /* In JNI mode, add extra arguments. */
1457 /* FIXME: it would be nice to know if we are printing a decl
1458 or a definition, and only print `env' for the latter. */
1459 fputs ("JNIEnv *env", stream);
1461 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1464 fputs (", ", stream);
1467 while (str < limit && *str != ')')
1469 next = decode_signature_piece (stream, str, limit, &need_space);
1472 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1477 if (next < limit && *next != ')')
1478 fputs (", ", stream);
1482 fputs (")", stream);
1486 /* This is a helper for print_stub_or_jni. */
1488 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1489 int signature_index, int is_init,
1490 const char *name_override, int flags)
1492 const char *const prefix = flag_jni ? "Java_" : "";
1493 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1494 fputs (flag_jni ? "_" : "::", stream);
1495 print_full_cxx_name (stream, jcf, name_index,
1496 signature_index, is_init, name_override,
1501 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1502 int signature_index, int is_init,
1503 const char *name_override, int flags)
1505 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1507 fprintf (stream, "<not a UTF8 constant>");
1512 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1513 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1514 register const unsigned char *str = str0;
1515 const unsigned char *limit = str + length;
1517 int is_method = str[0] == '(';
1518 const unsigned char *next;
1520 /* Don't print fields in the JNI case. */
1521 if (! is_method && flag_jni)
1524 if (flag_jni && ! stubs)
1525 fputs ("extern JNIEXPORT ", stream);
1527 /* If printing a method, skip to the return signature and print
1528 that first. However, there is no return value if this is a
1530 if (is_method && ! is_init)
1540 /* If printing a field or an ordinary method, then print the
1541 "return value" now. Note that a constructor can't be native,
1542 so we don't bother checking this in the JNI case. */
1543 if (! is_method || ! is_init)
1545 next = decode_signature_piece (stream, str, limit, &need_space);
1548 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1554 /* When printing a JNI header we need to respect the space. In
1555 other cases we're just going to insert a newline anyway. */
1556 fputs (need_space && ! stubs ? " " : "\n", stream);
1558 if (flag_jni && ! stubs)
1559 fputs ("JNICALL ", stream);
1561 /* Now print the name of the thing. */
1562 print_name_for_stub_or_jni (stream, jcf, name_index,
1563 signature_index, is_init, name_override,
1566 /* Print the body. */
1570 fputs ("\n{\n (*env)->FatalError (\"", stream);
1572 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1573 print_name_for_stub_or_jni (stream, jcf, name_index,
1574 signature_index, is_init,
1577 fprintf (stream, " not implemented\")%s;\n}\n\n",
1578 flag_jni ? "" : ")");
1584 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1586 int name_index = JPOOL_USHORT1 (jcf, index);
1587 fputs (prefix, stream);
1588 jcf_print_utf8_replace (out,
1589 JPOOL_UTF_DATA (jcf, name_index),
1590 JPOOL_UTF_LENGTH (jcf, name_index),
1594 /* Print PREFIX, then a class name in C++ format. If the name refers
1595 to an array, ignore it and don't print PREFIX. Returns 1 if
1596 something was printed, 0 otherwise. */
1598 print_cxx_classname (FILE *stream, const char *prefix,
1599 JCF *jcf, int index, int add_scope)
1601 int name_index = JPOOL_USHORT1 (jcf, index);
1603 const unsigned char *s, *p, *limit;
1605 s = JPOOL_UTF_DATA (jcf, name_index);
1606 len = JPOOL_UTF_LENGTH (jcf, name_index);
1609 /* Explicitly omit arrays here. */
1611 c = UTF8_GET (p, limit);
1615 fputs (prefix, stream);
1617 /* Print a leading "::" so we look in the right namespace. */
1618 if (! flag_jni && ! stubs && add_scope)
1619 fputs ("::", stream);
1623 c = UTF8_GET (s, limit);
1625 fputs (flag_jni ? "_" : "::", stream);
1627 jni_print_char (stream, c);
1633 int written_class_count = 0;
1635 /* Return name of superclass. If LEN is not NULL, fill it with length
1637 static const unsigned char *
1638 super_class_name (JCF *derived_jcf, int *len)
1640 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1641 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1642 const unsigned char *supername =
1643 JPOOL_UTF_DATA (derived_jcf, supername_index);
1646 *len = supername_length;
1653 /* We keep track of all the `#include's we generate, so we can avoid
1658 struct include *next;
1661 /* List of all includes. */
1662 static struct include *all_includes = NULL;
1664 /* Generate a #include. */
1666 print_include (FILE *out, const unsigned char *utf8, int len)
1668 struct include *incl;
1674 len = strlen (utf8);
1676 for (incl = all_includes; incl; incl = incl->next)
1678 /* We check the length because we might have a proper prefix. */
1679 if (len == (int) strlen (incl->name)
1680 && ! strncmp (incl->name, utf8, len))
1684 incl = xmalloc (sizeof (struct include));
1685 incl->name = xmalloc (len + 1);
1686 strncpy (incl->name, utf8, len);
1687 incl->name[len] = '\0';
1688 incl->next = all_includes;
1689 all_includes = incl;
1691 fputs ("#include <", out);
1692 jcf_print_utf8_replace (out, utf8, len,
1694 flag_jni ? '_' : '/');
1695 fputs (".h>\n", out);
1700 /* This is used to represent part of a package or class name. */
1703 /* The text of this part of the name. */
1705 /* True if this represents a class. */
1707 /* Linked list of all classes and packages inside this one. */
1708 struct namelet *subnamelets;
1709 /* Pointer to next sibling. */
1710 struct namelet *next;
1713 static void add_namelet (const unsigned char *, const unsigned char *,
1715 static void print_namelet (FILE *, struct namelet *, int);
1717 /* The special root namelet. */
1718 static struct namelet root =
1726 /* This extracts the next name segment from the full UTF-8 encoded
1727 package or class name and links it into the tree. It does this
1730 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1731 struct namelet *parent)
1733 const unsigned char *p;
1734 struct namelet *n = NULL, *np;
1736 /* We want to skip the standard namespaces that we assume the
1737 runtime already knows about. We only do this at the top level,
1738 though, hence the check for `root'. */
1739 if (parent == &root)
1741 #define JAVALANG "java/lang/"
1742 #define JAVAIO "java/io/"
1743 #define JAVAUTIL "java/util/"
1744 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1745 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1746 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1747 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1748 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1749 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1753 for (p = name; p < name_limit && *p != '/'; ++p)
1756 /* Search for this name beneath the PARENT node. */
1757 for (np = parent->subnamelets; np != NULL; np = np->next)
1759 /* We check the length because we might have a proper prefix. */
1760 if ((int) strlen (np->name) == p - name &&
1761 ! strncmp (name, np->name, p - name))
1770 n = xmalloc (sizeof (struct namelet));
1771 n->name = xmalloc (p - name + 1);
1772 strncpy (n->name, name, p - name);
1773 n->name[p - name] = '\0';
1774 n->is_class = (p == name_limit);
1775 n->subnamelets = NULL;
1776 n->next = parent->subnamelets;
1777 parent->subnamelets = n;
1780 /* We recurse if there is more text, and if the trailing piece does
1781 not represent an inner class. */
1783 add_namelet (p + 1, name_limit, n);
1786 /* Print a single namelet. Destroys namelets while printing. */
1788 print_namelet (FILE *out, struct namelet *name, int depth)
1795 for (i = 0; i < depth; ++i)
1797 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1799 if (name->is_class && name->subnamelets == NULL)
1805 for (i = 0; i < depth; ++i)
1811 c = name->subnamelets;
1814 struct namelet *next = c->next;
1815 print_namelet (out, c, depth + 2);
1818 name->subnamelets = NULL;
1824 for (i = 0; i < depth; ++i)
1827 /* Only print a `;' when printing a class. C++ is evil. */
1837 /* This is called to add some classes to the list of classes for which
1838 we need decls. The signature argument can be a function
1841 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1843 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1844 int len = JPOOL_UTF_LENGTH (jcf, signature);
1847 for (i = 0; i < len; ++i)
1851 /* If we see an array, then we include the array header. */
1854 print_include (out, "gcj/array", -1);
1858 /* We're looking for `L<stuff>;' -- everything else is
1863 for (start = ++i; i < len && s[i] != ';'; ++i)
1866 add_namelet (&s[start], &s[i], &root);
1870 /* Print declarations for all classes required by this class. Any
1871 class or package in the `java' package is assumed to be handled
1872 statically in libjava; we don't generate declarations for these.
1873 This makes the generated headers a bit easier to read. */
1875 print_class_decls (FILE *out, JCF *jcf, int self)
1877 /* Make sure to always add the current class to the list of things
1878 that should be declared. */
1879 int name_index = JPOOL_USHORT1 (jcf, self);
1881 const unsigned char *s;
1883 s = JPOOL_UTF_DATA (jcf, name_index);
1884 len = JPOOL_UTF_LENGTH (jcf, name_index);
1885 add_namelet (s, s + len, &root);
1887 if (root.subnamelets)
1889 fputs ("extern \"Java\"\n{\n", out);
1890 /* We use an initial offset of 0 because the root namelet
1891 doesn't cause anything to print. */
1892 print_namelet (out, &root, 0);
1893 fputs ("}\n\n", out);
1900 process_file (JCF *jcf, FILE *out)
1903 uint32 field_start, method_end, method_start;
1909 if (jcf_parse_preamble (jcf) != 0)
1911 fprintf (stderr, "Not a valid Java .class file.\n");
1916 /* Parse and possibly print constant pool */
1917 code = jcf_parse_constant_pool (jcf);
1920 fprintf (stderr, "error while parsing constant pool\n");
1924 code = verify_constant_pool (jcf);
1927 fprintf (stderr, "error in constant pool entry #%d\n", code);
1932 jcf_parse_class (jcf);
1934 if (written_class_count++ == 0 && out)
1936 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1951 mode = " -*- c++ -*-";
1957 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1958 cstart, mode, cend);
1961 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1963 %s This file is intended to give you a head start on implementing native\n\
1964 %s methods using %s.\n\
1965 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1966 %s overwrite any edits you have made to this file.%s\n\n",
1967 cstart, jflag, mode,
1983 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1984 fprintf (out, "__\n");
1986 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1987 fprintf (out, "__\n\n");
1991 fprintf (out, "#include <jni.h>\n\n");
1992 fprintf (out, "#ifdef __cplusplus\n");
1993 fprintf (out, "extern \"C\"\n");
1994 fprintf (out, "{\n");
1995 fprintf (out, "#endif\n");
1999 /* We do this to ensure that inline methods won't be
2000 `outlined' by g++. This works as long as method and
2001 fields are not added by the user. */
2002 fprintf (out, "#pragma interface\n");
2004 if (jcf->super_class)
2007 const unsigned char *supername =
2008 super_class_name (jcf, &super_length);
2011 print_include (out, supername, super_length);
2017 /* Strip off the ".class" portion of the name when printing
2018 the include file name. */
2020 int i, len = strlen (jcf->classname);
2021 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2023 /* Turn the class name into a file name. */
2024 name = xmalloc (len + 1);
2025 for (i = 0; i < len; ++i)
2026 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2028 print_include (out, name, len);
2033 print_include (out, "gcj/cni", -1);
2034 print_include (out, "java/lang/UnsupportedOperationException",
2040 /* We want to parse the methods first. But we need to find where
2041 they start. So first we skip the fields, then parse the methods.
2042 Then we parse the fields and skip the methods. This is ugly, but
2043 not too bad since we need two full passes to get class decl
2044 information anyway. */
2046 field_start = JCF_TELL (jcf);
2047 jcf_parse_fields (jcf);
2049 method_start = JCF_TELL (jcf);
2051 jcf_parse_methods (jcf);
2056 if (out && ! flag_jni)
2059 print_class_decls (out, jcf, jcf->this_class);
2061 for (i = 0; i < prepend_count; ++i)
2062 fprintf (out, "%s\n", prepend_specs[i]);
2063 if (prepend_count > 0)
2068 if (! print_cxx_classname (out, "class ", jcf,
2069 jcf->this_class, 0))
2071 fprintf (stderr, "class is of array type\n");
2075 if (jcf->super_class)
2077 if (! print_cxx_classname (out, " : public ",
2078 jcf, jcf->super_class, 1))
2080 fprintf (stderr, "base class is of array type\n");
2086 fputs ("\n{\n", out);
2090 /* Now go back for second pass over methods and fields. */
2091 JCF_SEEK (jcf, method_start);
2093 jcf_parse_methods (jcf);
2094 method_end = JCF_TELL (jcf);
2097 JCF_SEEK (jcf, field_start);
2098 jcf_parse_fields (jcf);
2099 JCF_SEEK (jcf, method_end);
2101 jcf_parse_final_attributes (jcf);
2107 fprintf (out, "\n#ifdef __cplusplus\n");
2108 fprintf (out, "}\n");
2109 fprintf (out, "#endif\n");
2113 /* Generate friend decl if we still must. */
2114 for (i = 0; i < friend_count; ++i)
2115 fprintf (out, " friend %s\n", friend_specs[i]);
2117 /* Generate extra declarations. */
2120 for (i = 0; i < add_count; ++i)
2121 fprintf (out, " %s\n", add_specs[i]);
2123 /* Generate an entry for the class object. */
2124 generate_access (out, ACC_PUBLIC);
2125 fprintf (out, "\n static ::java::lang::Class class$;\n");
2129 if (jcf->access_flags & ACC_INTERFACE)
2130 fputs (" __attribute__ ((java_interface))", out);
2134 if (append_count > 0)
2136 for (i = 0; i < append_count; ++i)
2137 fprintf (out, "%s\n", append_specs[i]);
2140 print_mangled_classname (out, jcf,
2141 "\n#endif /* __", jcf->this_class);
2142 fprintf (out, "__ */\n");
2148 /* This is used to mark options with no short value. */
2149 #define LONG_OPT(Num) ((Num) + 128)
2151 #define OPT_classpath LONG_OPT (0)
2152 #define OPT_CLASSPATH OPT_classpath
2153 #define OPT_bootclasspath LONG_OPT (1)
2154 #define OPT_extdirs LONG_OPT (2)
2155 #define OPT_HELP LONG_OPT (3)
2156 #define OPT_TEMP LONG_OPT (4)
2157 #define OPT_VERSION LONG_OPT (5)
2158 #define OPT_PREPEND LONG_OPT (6)
2159 #define OPT_FRIEND LONG_OPT (7)
2160 #define OPT_ADD LONG_OPT (8)
2161 #define OPT_APPEND LONG_OPT (9)
2162 #define OPT_M LONG_OPT (10)
2163 #define OPT_MM LONG_OPT (11)
2164 #define OPT_MG LONG_OPT (12)
2165 #define OPT_MD LONG_OPT (13)
2166 #define OPT_MMD LONG_OPT (14)
2168 static const struct option options[] =
2170 { "classpath", required_argument, NULL, OPT_classpath },
2171 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2172 { "extdirs", required_argument, NULL, OPT_extdirs },
2173 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2174 { "help", no_argument, NULL, OPT_HELP },
2175 { "stubs", no_argument, &stubs, 1 },
2176 { "td", required_argument, NULL, OPT_TEMP },
2177 { "verbose", no_argument, NULL, 'v' },
2178 { "version", no_argument, NULL, OPT_VERSION },
2179 { "prepend", required_argument, NULL, OPT_PREPEND },
2180 { "friend", required_argument, NULL, OPT_FRIEND },
2181 { "add", required_argument, NULL, OPT_ADD },
2182 { "append", required_argument, NULL, OPT_APPEND },
2183 { "M", no_argument, NULL, OPT_M },
2184 { "MM", no_argument, NULL, OPT_MM },
2185 { "MG", no_argument, NULL, OPT_MG },
2186 { "MD", no_argument, NULL, OPT_MD },
2187 { "MMD", no_argument, NULL, OPT_MMD },
2188 { "jni", no_argument, &flag_jni, 1 },
2189 { NULL, no_argument, NULL, 0 }
2195 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2202 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2203 printf ("Generate C++ header files from .class files\n\n");
2204 printf (" -stubs Generate an implementation stub file\n");
2205 printf (" -jni Generate a JNI header or stub\n");
2207 printf (" -add TEXT Insert TEXT into class body\n");
2208 printf (" -append TEXT Insert TEXT after class declaration\n");
2209 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2210 printf (" -prepend TEXT Insert TEXT before start of class\n");
2212 printf (" --classpath PATH Set path to find .class files\n");
2213 printf (" -IDIR Append directory to class path\n");
2214 printf (" --bootclasspath PATH Override built-in class path\n");
2215 printf (" --extdirs PATH Set extensions directory path\n");
2216 printf (" -d DIRECTORY Set output directory name\n");
2217 printf (" -o FILE Set output file name\n");
2218 printf (" -td DIRECTORY Set temporary directory name\n");
2220 printf (" --help Print this help, then exit\n");
2221 printf (" --version Print version number, then exit\n");
2222 printf (" -v, --verbose Print extra information while running\n");
2224 printf (" -M Print all dependencies to stdout;\n");
2225 printf (" suppress ordinary output\n");
2226 printf (" -MM Print non-system dependencies to stdout;\n");
2227 printf (" suppress ordinary output\n");
2228 printf (" -MD Print all dependencies to stdout\n");
2229 printf (" -MMD Print non-system dependencies to stdout\n");
2230 /* We omit -MG until it is implemented. */
2232 printf ("For bug reporting instructions, please see:\n");
2233 printf ("%s.\n", bug_report_url);
2240 printf ("gcjh (GCC) %s\n\n", version_string);
2241 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2242 printf ("This is free software; see the source for copying conditions. There is NO\n");
2243 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2248 main (int argc, char** argv)
2252 char *output_file = NULL;
2253 int emit_dependencies = 0, suppress_output = 0;
2258 fprintf (stderr, "gcjh: no classes specified\n");
2264 /* We use getopt_long_only to allow single `-' long options. For
2265 some of our options this is more natural. */
2266 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2271 /* Already handled. */
2275 output_file = optarg;
2279 output_directory = optarg;
2283 jcf_path_include_arg (optarg);
2291 jcf_path_classpath_arg (optarg);
2294 case OPT_bootclasspath:
2295 jcf_path_bootclasspath_arg (optarg);
2299 jcf_path_extdirs_arg (optarg);
2307 temp_directory = optarg;
2315 if (prepend_count == 0)
2316 prepend_specs = ALLOC (argc * sizeof (char*));
2317 prepend_specs[prepend_count++] = optarg;
2321 if (friend_count == 0)
2322 friend_specs = ALLOC (argc * sizeof (char*));
2323 friend_specs[friend_count++] = optarg;
2328 add_specs = ALLOC (argc * sizeof (char*));
2329 add_specs[add_count++] = optarg;
2333 if (append_count == 0)
2334 append_specs = ALLOC (argc * sizeof (char*));
2335 append_specs[append_count++] = optarg;
2339 emit_dependencies = 1;
2340 suppress_output = 1;
2341 jcf_dependency_init (1);
2345 emit_dependencies = 1;
2346 suppress_output = 1;
2347 jcf_dependency_init (0);
2351 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2355 emit_dependencies = 1;
2356 jcf_dependency_init (1);
2360 emit_dependencies = 1;
2361 jcf_dependency_init (0);
2372 fprintf (stderr, "gcjh: no classes specified\n");
2376 jcf_path_seal (verbose);
2378 if (output_file && emit_dependencies)
2380 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2384 for (argi = optind; argi < argc; argi++)
2386 char *classname = argv[argi];
2387 char *current_output_file;
2388 const char *classfile_name;
2391 fprintf (stderr, "Processing %s\n", classname);
2393 jcf_dependency_reset ();
2394 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2395 if (classfile_name == NULL)
2397 fprintf (stderr, "%s: no such class\n", classname);
2401 fprintf (stderr, "Found in %s\n", classfile_name);
2404 if (strcmp (output_file, "-") == 0)
2406 else if (out == NULL)
2408 out = fopen (output_file, "w");
2412 perror (output_file);
2415 current_output_file = output_file;
2419 int dir_len = strlen (output_directory);
2420 int i, classname_length = strlen (classname);
2421 current_output_file = ALLOC (dir_len + classname_length + 5);
2422 strcpy (current_output_file, output_directory);
2423 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2424 current_output_file[dir_len++] = '/';
2425 for (i = 0; classname[i] != '\0'; i++)
2427 char ch = classname[i];
2430 if (flag_jni && ch == '/')
2432 current_output_file[dir_len++] = ch;
2434 if (emit_dependencies)
2436 if (suppress_output)
2438 jcf_dependency_set_dep_file ("-");
2443 /* We use `.hd' and not `.d' to avoid clashes with
2444 dependency tracking from straight compilation. */
2445 strcpy (current_output_file + dir_len, ".hd");
2446 jcf_dependency_set_dep_file (current_output_file);
2449 strcpy (current_output_file + dir_len,
2450 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2451 jcf_dependency_set_target (current_output_file);
2452 if (! suppress_output)
2454 out = fopen (current_output_file, "w");
2457 perror (current_output_file);
2462 process_file (&jcf, out);
2464 if (current_output_file != output_file)
2465 free (current_output_file);
2466 jcf_dependency_write ();
2469 if (out != NULL && out != stdout)