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 (f)
263 /* We happen to know that F_NAN_MASK will match all NaN values, and
264 also positive and negative infinity. That's why we only need one
265 test here. See The Java Language Specification, section 20.9. */
266 return (u.i & F_NAN_MASK) != F_NAN_MASK;
269 /* Return 1 if D is not Inf or NaN. */
271 java_double_finite (d)
277 /* Now check for all NaNs. */
278 return (u.l & D_NAN_MASK) != D_NAN_MASK;
281 /* Print a character, appropriately mangled for JNI. */
284 jni_print_char (stream, ch)
289 jcf_print_char (stream, ch);
290 else if (ch == '(' || ch == ')')
295 fputs ("_1", stream);
297 fputs ("_2", stream);
299 fputs ("_3", stream);
302 else if (ISALNUM (ch))
306 /* "Unicode" character. */
307 fprintf (stream, "_0%04x", ch);
311 /* Print a name from the class data. If the index does not point to a
312 string, an error results. */
315 print_name (FILE* stream, JCF* jcf, int name_index)
317 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
319 fprintf (stream, "<not a UTF8 constant>");
323 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
324 JPOOL_UTF_LENGTH (jcf, name_index));
327 /* For JNI we must correctly quote each character. */
328 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
329 int length = JPOOL_UTF_LENGTH (jcf, name_index);
330 const unsigned char *limit = str + length;
333 int ch = UTF8_GET (str, limit);
336 fprintf (stream, "\\<invalid>");
339 jni_print_char (stream, ch);
344 /* Print base name of class. The base name is everything after the
348 print_base_classname (stream, jcf, index)
353 int name_index = JPOOL_USHORT1 (jcf, index);
355 const unsigned char *s, *p, *limit;
357 s = JPOOL_UTF_DATA (jcf, name_index);
358 len = JPOOL_UTF_LENGTH (jcf, name_index);
363 int c = UTF8_GET (s, limit);
370 int ch = UTF8_GET (p, limit);
372 fputs ("::", stream);
374 jcf_print_char (stream, ch);
378 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
379 and 1 if STR is "greater" than NAME. */
382 utf8_cmp (str, length, name)
383 const unsigned char *str;
387 const unsigned char *limit = str + length;
390 for (i = 0; name[i]; ++i)
392 int ch = UTF8_GET (str, limit);
397 return str == limit ? 0 : 1;
400 /* This is a sorted list of all C++ keywords. */
402 static const char *const cxx_keywords[] =
511 /* If NAME is the name of a C++ keyword, then return an override name.
512 This is a name that can be used in place of the keyword.
513 Otherwise, return NULL. The return value is malloc()d. */
516 cxx_keyword_subst (str, length)
517 const unsigned char *str;
520 int last = ARRAY_SIZE (cxx_keywords);
522 int mid = (last + first) / 2;
525 for (mid = (last + first) / 2;
527 old = mid, mid = (last + first) / 2)
529 int kwl = strlen (cxx_keywords[mid]);
530 int min_length = kwl > length ? length : kwl;
531 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
537 /* Skip all trailing `$'. */
538 for (i = min_length; i < length && str[i] == '$'; ++i)
540 /* We've only found a match if all the remaining characters
544 char *dup = xmalloc (2 + length - min_length + kwl);
545 strcpy (dup, cxx_keywords[mid]);
546 for (i = kwl; i < length + 1; ++i)
562 /* Generate an access control keyword based on FLAGS. */
565 generate_access (stream, flags)
569 if ((flags & ACC_VISIBILITY) == last_access)
571 last_access = (flags & ACC_VISIBILITY);
576 fputs ("public: // actually package-private\n", stream);
579 fputs ("public:\n", stream);
582 fputs ("private:\n", stream);
585 fputs ("public: // actually protected\n", stream);
589 fprintf (stream, "#error unrecognized visibility %d\n",
590 (flags & ACC_VISIBILITY));
595 /* See if NAME is already the name of a method. */
597 name_is_method_p (name, length)
598 const unsigned char *name;
601 struct method_name *p;
603 for (p = method_name_list; p != NULL; p = p->next)
605 if (p->length == length && ! memcmp (p->name, name, length))
611 /* If there is already a method named NAME, whose signature is not
612 SIGNATURE, then return true. Otherwise return false. */
614 overloaded_jni_method_exists_p (name, length, signature, sig_length)
615 const unsigned char *name;
617 const char *signature;
620 struct method_name *p;
622 for (p = method_name_list; p != NULL; p = p->next)
624 if (p->length == length
625 && ! memcmp (p->name, name, length)
626 && (p->sig_length != sig_length
627 || memcmp (p->signature, signature, sig_length)))
633 /* Get name of a field. This handles renamings due to C++ clash. */
635 get_field_name (jcf, name_index, flags)
640 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
641 int length = JPOOL_UTF_LENGTH (jcf, name_index);
644 if (name_is_method_p (name, length))
646 /* This field name matches a method. So override the name with
647 a dummy name. This is yucky, but it isn't clear what else to
648 do. FIXME: if the field is static, then we'll be in real
650 if ((flags & ACC_STATIC))
652 fprintf (stderr, "static field has same name as method\n");
657 override = xmalloc (length + 3);
658 memcpy (override, name, length);
659 strcpy (override + length, "__");
662 override = cxx_keyword_subst (name, length);
667 /* Print a field name. Convenience function for use with
670 print_field_name (stream, jcf, name_index, flags)
676 char *override = get_field_name (jcf, name_index, flags);
680 fputs (override, stream);
684 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
685 JPOOL_UTF_LENGTH (jcf, name_index));
689 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
692 char *override = NULL;
694 generate_access (stream, flags);
695 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
697 fprintf (stream, "<not a UTF8 constant>");
703 if ((flags & ACC_STATIC))
704 fputs ("static ", out);
706 if ((flags & ACC_FINAL))
708 if (current_field_value > 0)
713 switch (JPOOL_TAG (jcf, current_field_value))
715 case CONSTANT_Integer:
718 int most_negative = 0;
719 fputs ("const jint ", out);
720 print_field_name (out, jcf, name_index, 0);
722 num = JPOOL_INT (jcf, current_field_value);
723 /* We single out the most negative number to print
724 specially. This avoids later warnings from g++. */
725 if (num == (jint) 0x80000000)
730 format_int (buffer, (jlong) num, 10);
731 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
737 int most_negative = 0;
738 fputs ("const jlong ", out);
739 print_field_name (out, jcf, name_index, 0);
741 num = JPOOL_LONG (jcf, current_field_value);
742 /* We single out the most negative number to print
743 specially.. This avoids later warnings from g++. */
744 if (num == (jlong) 0x8000000000000000LL)
749 format_int (buffer, num, 10);
750 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
755 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
756 fputs ("const jfloat ", out);
757 print_field_name (out, jcf, name_index, 0);
758 if (! java_float_finite (fnum))
761 fprintf (out, " = %.10g;\n", fnum);
764 case CONSTANT_Double:
766 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
767 fputs ("const jdouble ", out);
768 print_field_name (out, jcf, name_index, 0);
769 if (! java_double_finite (dnum))
772 fprintf (out, " = %.17g;\n", dnum);
776 /* We can't print this as a constant, but we can still
777 print something sensible. */
787 override = get_field_name (jcf, name_index, flags);
788 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
797 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
800 const unsigned char *str;
801 int length, is_init = 0;
802 char *override = NULL;
805 method_access = flags;
806 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
807 fprintf (stream, "<not a UTF8 constant>");
808 str = JPOOL_UTF_DATA (jcf, name_index);
809 length = JPOOL_UTF_LENGTH (jcf, name_index);
813 /* Ignore the internally generated method <clinit>. However,
814 treat <init> as a constructor. */
815 if (! utf8_cmp (str, length, "<init>"))
817 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
818 && ! (flags & ACC_STATIC))
820 /* FIXME: i18n bug here. Order of prints should not be
822 fprintf (stderr, "ignored method `");
823 jcf_print_utf8 (stderr, str, length);
824 fprintf (stderr, "' marked virtual\n");
832 /* During the first method pass, build a list of method names. This will
833 be used to determine if field names conflict with method names. */
836 struct method_name *nn;
838 nn = xmalloc (sizeof (struct method_name));
839 nn->name = xmalloc (length);
840 memcpy (nn->name, str, length);
842 nn->next = method_name_list;
843 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
844 nn->signature = xmalloc (nn->sig_length);
845 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
847 method_name_list = nn;
849 /* The rest of this function doesn't matter. */
853 /* We don't worry about overrides in JNI mode. */
856 /* We can't generate a method whose name is a C++ reserved word.
857 We can't just ignore the function, because that will cause
858 incorrect code to be generated if the function is virtual
859 (not only for calls to this function for for other functions
860 after it in the vtbl). So we give it a dummy name instead. */
861 override = cxx_keyword_subst (str, length);
864 if (! stubs && ! flag_jni)
868 generate_access (stream, flags);
871 if ((flags & ACC_STATIC))
872 fputs ("static ", out);
873 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
875 /* Don't print `virtual' if we have a constructor. */
877 fputs ("virtual ", out);
879 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
881 if ((flags & ACC_ABSTRACT))
888 if (METHOD_IS_NATIVE (flags))
891 print_stub_or_jni (out, jcf, name_index, sig_index,
892 is_init, override, flags);
900 /* A helper for the decompiler which prints a `return' statement where
901 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
902 identical, we emit a cast. We do this because the C++ compiler
903 doesn't know that a reference can be cast to the type of an
904 interface it implements. METHODTYPE is the index of the method's
905 signature. NAMEINDEX is the index of the field name; -1 for
906 `this'. OBJECTTYPE is the index of the object's type. */
908 decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
911 int methodtype, nameindex, objecttype;
914 int obj_name_len, method_name_len;
915 const unsigned char *obj_data, *method_data;
917 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
918 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
920 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
921 method_data = JPOOL_UTF_DATA (jcf, methodtype);
923 /* Skip forward to return type part of method. */
924 while (*method_data != ')')
933 /* If we see an `L', skip it and the trailing `;'. */
934 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
937 method_name_len -= 2;
939 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
945 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
946 need a cast. Right now there is no way to determine if this is
948 if (method_name_len != obj_name_len)
953 for (i = 0; i < method_name_len; ++i)
955 if (method_data[i] != obj_data[i])
963 fputs (" { return ", out);
968 const unsigned char *limit;
970 fputs ("reinterpret_cast<", out);
972 while (*method_data == '[')
977 fputs ("JArray<", out);
980 /* Leading space to avoid C++ digraphs. */
983 /* If we see an `L', skip it and the trailing `;'. Only do this
984 if we've seen an array specification. If we don't have an
985 array then the `L' was stripped earlier. */
986 if (array_depth && method_data[0] == 'L'
987 && method_data[method_name_len - 1] == ';')
990 method_name_len -= 2;
993 limit = method_data + method_name_len;
994 while (method_data < limit)
996 int ch = UTF8_GET (method_data, limit);
1000 jcf_print_char (out, ch);
1004 /* Close each array. */
1005 while (array_depth > 0)
1011 /* Close the cast. */
1015 if (nameindex == -1)
1016 fputs ("this", out);
1018 print_field_name (out, jcf, nameindex, 0);
1027 /* Try to decompile a method body. Right now we just try to handle a
1028 simple case that we can do. Expand as desired. */
1030 decompile_method (out, jcf, code_len)
1035 const unsigned char *codes = jcf->read_ptr;
1037 uint16 name_and_type, name;
1039 /* If the method is synchronized, don't touch it. */
1040 if ((method_access & ACC_SYNCHRONIZED))
1044 && codes[0] == OPCODE_aload_0
1045 && codes[1] == OPCODE_getfield
1046 && (codes[4] == OPCODE_areturn
1047 || codes[4] == OPCODE_dreturn
1048 || codes[4] == OPCODE_freturn
1049 || codes[4] == OPCODE_ireturn
1050 || codes[4] == OPCODE_lreturn))
1052 /* Found code like `return FIELD'. */
1053 index = (codes[2] << 8) | codes[3];
1054 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1055 name_and_type = JPOOL_USHORT2 (jcf, index);
1056 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1057 name = JPOOL_USHORT1 (jcf, name_and_type);
1058 if (codes[4] == OPCODE_areturn)
1059 decompile_return_statement (out, jcf, method_signature,
1060 name, JPOOL_USHORT2 (jcf, name_and_type));
1063 fputs (" { return ", out);
1065 print_field_name (out, jcf, name, 0);
1070 else if (code_len == 2
1071 && codes[0] == OPCODE_aload_0
1072 && codes[1] == OPCODE_areturn
1073 /* We're going to generate `return this'. This only makes
1074 sense for non-static methods. */
1075 && ! (method_access & ACC_STATIC))
1077 decompile_return_statement (out, jcf, method_signature, -1,
1078 JPOOL_USHORT1 (jcf, jcf->this_class));
1081 else if (code_len == 1 && codes[0] == OPCODE_return)
1083 /* Found plain `return'. */
1084 fputs (" { }", out);
1087 else if (code_len == 2
1088 && codes[0] == OPCODE_aconst_null
1089 && codes[1] == OPCODE_areturn)
1091 /* Found `return null'. We don't want to depend on NULL being
1093 fputs (" { return 0; }", out);
1098 /* Like strcmp, but invert the return result for the hash table. This
1099 should probably be in hashtab.c to complement the existing string
1103 const void *p1, *p2;
1105 return ! strcmp ((char *) p1, (char *) p2);
1108 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1109 or 0 if not. CLNAME may be extracted from a signature, and can be
1110 terminated with either `;' or NULL. */
1112 throwable_p (clname)
1113 const unsigned char *clname;
1116 unsigned char *current;
1120 /* We keep two hash tables of class names. In one we list all the
1121 classes which are subclasses of Throwable. In the other we will
1122 all other classes. We keep two tables to make the code a bit
1123 simpler; we don't have to have a structure mapping class name to
1124 a `throwable?' bit. */
1125 static htab_t throw_hash;
1126 static htab_t non_throw_hash;
1127 static int init_done = 0;
1132 const unsigned char *str;
1134 /* Self-initializing. The cost of this really doesn't matter.
1135 We also don't care about freeing these, either. */
1136 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1138 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1141 /* Make sure the root classes show up in the tables. */
1142 str = xstrdup ("java.lang.Throwable");
1143 slot = htab_find_slot (throw_hash, str, INSERT);
1146 str = xstrdup ("java.lang.Object");
1147 slot = htab_find_slot (non_throw_hash, str, INSERT);
1153 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1155 current = ALLOC (length);
1156 for (i = 0; i < length; ++i)
1157 current[i] = clname[i] == '/' ? '.' : clname[i];
1158 current[length] = '\0';
1160 /* We don't compute the hash slot here because the table might be
1161 modified by the recursion. In that case the slot could be
1163 if (htab_find (throw_hash, current))
1165 else if (htab_find (non_throw_hash, current))
1171 unsigned char *super, *tmp;
1172 int super_length = -1;
1173 const char *classfile_name = find_class (current, strlen (current),
1176 if (! classfile_name)
1178 fprintf (stderr, "couldn't find class %s\n", current);
1182 if (jcf_parse_preamble (&jcf) != 0
1183 || jcf_parse_constant_pool (&jcf) != 0
1184 || verify_constant_pool (&jcf) > 0)
1186 fprintf (stderr, "parse error while reading %s\n", 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 (stream, signature, limit, need_space)
1214 const unsigned char *signature, *limit;
1218 int array_depth = 0;
1220 switch (signature[0])
1223 /* More spaghetti. */
1226 for (signature++; (signature < limit
1227 && ISDIGIT (*signature)); signature++)
1232 ctype = "jbyteArray";
1235 ctype = "jcharArray";
1238 ctype = "jdoubleArray";
1241 ctype = "jfloatArray";
1244 ctype = "jintArray";
1247 ctype = "jshortArray";
1250 ctype = "jlongArray";
1253 ctype = "jbooleanArray";
1256 /* We have a nested array. */
1259 fputs ("JArray<", stream);
1263 /* We have to generate a reference to JArray here, so that
1264 our output matches what the compiler does. */
1266 /* Space between `<' and `:' to avoid C++ digraphs. */
1268 fputs ("JArray< ::", stream);
1269 while (signature < limit && *signature != ';')
1271 int ch = UTF8_GET (signature, limit);
1275 fputs ("::", stream);
1277 jcf_print_char (stream, ch);
1281 fputs (" *> *", stream);
1286 /* Unparseable signature. */
1290 /* If the previous iterations left us with something to print,
1291 print it. For JNI, we always print `jobjectArray' in the
1293 if (flag_jni && (ctype == NULL || array_depth > 0))
1295 ctype = "jobjectArray";
1298 /* The `printit' case will advance SIGNATURE for us. If we
1299 don't go there, we must advance past the `;' ourselves. */
1307 /* This shouldn't happen. */
1310 case 'B': ctype = "jbyte"; goto printit;
1311 case 'C': ctype = "jchar"; goto printit;
1312 case 'D': ctype = "jdouble"; goto printit;
1313 case 'F': ctype = "jfloat"; goto printit;
1314 case 'I': ctype = "jint"; goto printit;
1315 case 'J': ctype = "jlong"; goto printit;
1316 case 'S': ctype = "jshort"; goto printit;
1317 case 'Z': ctype = "jboolean"; goto printit;
1318 case 'V': ctype = "void"; goto printit;
1322 /* We know about certain types and special-case their names. */
1323 if (! strncmp (signature, "Ljava/lang/String;",
1324 sizeof ("Ljava/lang/String;") -1))
1326 else if (! strncmp (signature, "Ljava/lang/Class;",
1327 sizeof ("Ljava/lang/Class;") - 1))
1329 /* Skip leading 'L' for throwable_p call. */
1330 else if (throwable_p (signature + 1))
1331 ctype = "jthrowable";
1335 while (*signature && *signature != ';')
1340 /* Print a leading "::" so we look in the right namespace. */
1341 fputs ("::", stream);
1343 while (*signature && *signature != ';')
1345 int ch = UTF8_GET (signature, limit);
1347 fputs ("::", stream);
1349 jcf_print_char (stream, ch);
1351 fputs (" *", stream);
1352 if (*signature == ';')
1358 jni_print_char (stream, *signature++);
1363 fputs (ctype, stream);
1369 while (array_depth-- > 0)
1370 fputs ("> *", stream);
1377 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1378 int is_init, const char *name_override, int flags)
1380 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1382 fprintf (stream, "<not a UTF8 constant>");
1387 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1388 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1389 register const unsigned char *str = str0;
1390 const unsigned char *limit = str + length;
1392 int is_method = str[0] == '(';
1393 const unsigned char *next;
1395 /* If printing a method, skip to the return signature and print
1396 that first. However, there is no return value if this is a
1398 if (is_method && ! is_init)
1408 /* If printing a field or an ordinary method, then print the
1409 "return value" now. */
1410 if (! is_method || ! is_init)
1412 next = decode_signature_piece (stream, str, limit, &need_space);
1415 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1421 /* Now print the name of the thing. */
1423 fputs (" ", stream);
1424 print_full_cxx_name (stream, jcf, name_index,
1425 signature_index, is_init, name_override,
1430 /* Print the unqualified method name followed by the signature. */
1432 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1433 int signature_index, int is_init,
1434 const char *name_override, int flags)
1436 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1437 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1438 register const unsigned char *str = str0;
1439 const unsigned char *limit = str + length;
1441 int is_method = str[0] == '(';
1442 const unsigned char *next;
1445 fputs (name_override, stream);
1446 else if (name_index)
1448 /* Declare constructors specially. */
1450 print_base_classname (stream, jcf, jcf->this_class);
1452 print_name (stream, jcf, name_index);
1457 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1458 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1459 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1460 JPOOL_UTF_LENGTH (jcf, name_index),
1461 signature, sig_len))
1463 /* If this method is overloaded by another native method,
1464 then include the argument information in the mangled
1466 unsigned char *limit = signature + sig_len;
1467 fputs ("__", stream);
1468 while (signature < limit)
1470 int ch = UTF8_GET (signature, limit);
1471 jni_print_char (stream, ch);
1483 /* Have a method or a constructor. Print signature pieces
1485 fputs (" (", stream);
1489 /* In JNI mode, add extra arguments. */
1492 /* FIXME: it would be nice to know if we are printing a decl
1493 or a definition, and only print `env' for the latter. */
1494 fputs ("JNIEnv *env", stream);
1496 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1499 fputs (", ", stream);
1502 while (str < limit && *str != ')')
1504 next = decode_signature_piece (stream, str, limit, &need_space);
1507 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1512 if (next < limit && *next != ')')
1513 fputs (", ", stream);
1517 fputs (")", stream);
1521 /* This is a helper for print_stub_or_jni. */
1523 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1524 int signature_index, int is_init,
1525 const char *name_override, int flags)
1527 const char *const prefix = flag_jni ? "Java_" : "";
1528 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1529 fputs (flag_jni ? "_" : "::", stream);
1530 print_full_cxx_name (stream, jcf, name_index,
1531 signature_index, is_init, name_override,
1536 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1537 int signature_index, int is_init,
1538 const char *name_override, int flags)
1540 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1542 fprintf (stream, "<not a UTF8 constant>");
1547 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1548 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1549 register const unsigned char *str = str0;
1550 const unsigned char *limit = str + length;
1552 int is_method = str[0] == '(';
1553 const unsigned char *next;
1555 /* Don't print fields in the JNI case. */
1556 if (! is_method && flag_jni)
1559 if (flag_jni && ! stubs)
1560 fputs ("extern JNIEXPORT ", stream);
1562 /* If printing a method, skip to the return signature and print
1563 that first. However, there is no return value if this is a
1565 if (is_method && ! is_init)
1575 /* If printing a field or an ordinary method, then print the
1576 "return value" now. Note that a constructor can't be native,
1577 so we don't bother checking this in the JNI case. */
1578 if (! is_method || ! is_init)
1580 next = decode_signature_piece (stream, str, limit, &need_space);
1583 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1589 /* When printing a JNI header we need to respect the space. In
1590 other cases we're just going to insert a newline anyway. */
1591 fputs (need_space && ! stubs ? " " : "\n", stream);
1593 if (flag_jni && ! stubs)
1594 fputs ("JNICALL ", stream);
1596 /* Now print the name of the thing. */
1597 print_name_for_stub_or_jni (stream, jcf, name_index,
1598 signature_index, is_init, name_override,
1601 /* Print the body. */
1605 fputs ("\n{\n (*env)->FatalError (\"", stream);
1607 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1608 print_name_for_stub_or_jni (stream, jcf, name_index,
1609 signature_index, is_init,
1612 fprintf (stream, " not implemented\")%s;\n}\n\n",
1613 flag_jni ? "" : ")");
1619 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1621 int name_index = JPOOL_USHORT1 (jcf, index);
1622 fputs (prefix, stream);
1623 jcf_print_utf8_replace (out,
1624 JPOOL_UTF_DATA (jcf, name_index),
1625 JPOOL_UTF_LENGTH (jcf, name_index),
1629 /* Print PREFIX, then a class name in C++ format. If the name refers
1630 to an array, ignore it and don't print PREFIX. Returns 1 if
1631 something was printed, 0 otherwise. */
1633 print_cxx_classname (stream, prefix, jcf, index, add_scope)
1640 int name_index = JPOOL_USHORT1 (jcf, index);
1642 const unsigned char *s, *p, *limit;
1644 s = JPOOL_UTF_DATA (jcf, name_index);
1645 len = JPOOL_UTF_LENGTH (jcf, name_index);
1648 /* Explicitly omit arrays here. */
1650 c = UTF8_GET (p, limit);
1654 fputs (prefix, stream);
1656 /* Print a leading "::" so we look in the right namespace. */
1657 if (! flag_jni && ! stubs && add_scope)
1658 fputs ("::", stream);
1662 c = UTF8_GET (s, limit);
1664 fputs (flag_jni ? "_" : "::", stream);
1666 jni_print_char (stream, c);
1672 int written_class_count = 0;
1674 /* Return name of superclass. If LEN is not NULL, fill it with length
1676 static const unsigned char *
1677 super_class_name (derived_jcf, 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;
1694 /* We keep track of all the `#include's we generate, so we can avoid
1699 struct include *next;
1702 /* List of all includes. */
1703 static struct include *all_includes = NULL;
1705 /* Generate a #include. */
1707 print_include (out, utf8, len)
1709 const unsigned char *utf8;
1712 struct include *incl;
1718 len = strlen (utf8);
1720 for (incl = all_includes; incl; incl = incl->next)
1722 /* We check the length because we might have a proper prefix. */
1723 if (len == (int) strlen (incl->name)
1724 && ! strncmp (incl->name, utf8, len))
1728 incl = xmalloc (sizeof (struct include));
1729 incl->name = xmalloc (len + 1);
1730 strncpy (incl->name, utf8, len);
1731 incl->name[len] = '\0';
1732 incl->next = all_includes;
1733 all_includes = incl;
1735 fputs ("#include <", out);
1736 jcf_print_utf8_replace (out, utf8, len,
1738 flag_jni ? '_' : '/');
1739 fputs (".h>\n", out);
1744 /* This is used to represent part of a package or class name. */
1747 /* The text of this part of the name. */
1749 /* True if this represents a class. */
1751 /* Linked list of all classes and packages inside this one. */
1752 struct namelet *subnamelets;
1753 /* Pointer to next sibling. */
1754 struct namelet *next;
1757 static void add_namelet (const unsigned char *, const unsigned char *,
1759 static void print_namelet (FILE *, struct namelet *, int);
1761 /* The special root namelet. */
1762 static struct namelet root =
1770 /* This extracts the next name segment from the full UTF-8 encoded
1771 package or class name and links it into the tree. It does this
1774 add_namelet (name, name_limit, parent)
1775 const unsigned char *name, *name_limit;
1776 struct namelet *parent;
1778 const unsigned char *p;
1779 struct namelet *n = NULL, *np;
1781 /* We want to skip the standard namespaces that we assume the
1782 runtime already knows about. We only do this at the top level,
1783 though, hence the check for `root'. */
1784 if (parent == &root)
1786 #define JAVALANG "java/lang/"
1787 #define JAVAIO "java/io/"
1788 #define JAVAUTIL "java/util/"
1789 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1790 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1791 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1792 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1793 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1794 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1798 for (p = name; p < name_limit && *p != '/'; ++p)
1801 /* Search for this name beneath the PARENT node. */
1802 for (np = parent->subnamelets; np != NULL; np = np->next)
1804 /* We check the length because we might have a proper prefix. */
1805 if ((int) strlen (np->name) == p - name &&
1806 ! strncmp (name, np->name, p - name))
1815 n = xmalloc (sizeof (struct namelet));
1816 n->name = xmalloc (p - name + 1);
1817 strncpy (n->name, name, p - name);
1818 n->name[p - name] = '\0';
1819 n->is_class = (p == name_limit);
1820 n->subnamelets = NULL;
1821 n->next = parent->subnamelets;
1822 parent->subnamelets = n;
1825 /* We recurse if there is more text, and if the trailing piece does
1826 not represent an inner class. */
1828 add_namelet (p + 1, name_limit, n);
1831 /* Print a single namelet. Destroys namelets while printing. */
1833 print_namelet (out, name, depth)
1835 struct namelet *name;
1843 for (i = 0; i < depth; ++i)
1845 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1847 if (name->is_class && name->subnamelets == NULL)
1853 for (i = 0; i < depth; ++i)
1859 c = name->subnamelets;
1862 struct namelet *next = c->next;
1863 print_namelet (out, c, depth + 2);
1866 name->subnamelets = NULL;
1872 for (i = 0; i < depth; ++i)
1875 /* Only print a `;' when printing a class. C++ is evil. */
1885 /* This is called to add some classes to the list of classes for which
1886 we need decls. The signature argument can be a function
1889 add_class_decl (out, jcf, signature)
1894 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1895 int len = JPOOL_UTF_LENGTH (jcf, signature);
1898 for (i = 0; i < len; ++i)
1902 /* If we see an array, then we include the array header. */
1905 print_include (out, "gcj/array", -1);
1909 /* We're looking for `L<stuff>;' -- everything else is
1914 for (start = ++i; i < len && s[i] != ';'; ++i)
1917 add_namelet (&s[start], &s[i], &root);
1921 /* Print declarations for all classes required by this class. Any
1922 class or package in the `java' package is assumed to be handled
1923 statically in libjava; we don't generate declarations for these.
1924 This makes the generated headers a bit easier to read. */
1926 print_class_decls (out, jcf, self)
1931 /* Make sure to always add the current class to the list of things
1932 that should be declared. */
1933 int name_index = JPOOL_USHORT1 (jcf, self);
1935 const unsigned char *s;
1937 s = JPOOL_UTF_DATA (jcf, name_index);
1938 len = JPOOL_UTF_LENGTH (jcf, name_index);
1939 add_namelet (s, s + len, &root);
1941 if (root.subnamelets)
1943 fputs ("extern \"Java\"\n{\n", out);
1944 /* We use an initial offset of 0 because the root namelet
1945 doesn't cause anything to print. */
1946 print_namelet (out, &root, 0);
1947 fputs ("}\n\n", out);
1954 process_file (JCF *jcf, FILE *out)
1957 uint32 field_start, method_end, method_start;
1963 if (jcf_parse_preamble (jcf) != 0)
1965 fprintf (stderr, "Not a valid Java .class file.\n");
1970 /* Parse and possibly print constant pool */
1971 code = jcf_parse_constant_pool (jcf);
1974 fprintf (stderr, "error while parsing constant pool\n");
1978 code = verify_constant_pool (jcf);
1981 fprintf (stderr, "error in constant pool entry #%d\n", code);
1986 jcf_parse_class (jcf);
1988 if (written_class_count++ == 0 && out)
1990 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
2005 mode = " -*- c++ -*-";
2011 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2012 cstart, mode, cend);
2015 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2017 %s This file is intended to give you a head start on implementing native\n\
2018 %s methods using %s.\n\
2019 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2020 %s overwrite any edits you have made to this file.%s\n\n",
2021 cstart, jflag, mode,
2037 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2038 fprintf (out, "__\n");
2040 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2041 fprintf (out, "__\n\n");
2045 fprintf (out, "#include <jni.h>\n\n");
2046 fprintf (out, "#ifdef __cplusplus\n");
2047 fprintf (out, "extern \"C\"\n");
2048 fprintf (out, "{\n");
2049 fprintf (out, "#endif\n");
2053 /* We do this to ensure that inline methods won't be
2054 `outlined' by g++. This works as long as method and
2055 fields are not added by the user. */
2056 fprintf (out, "#pragma interface\n");
2058 if (jcf->super_class)
2061 const unsigned char *supername =
2062 super_class_name (jcf, &super_length);
2065 print_include (out, supername, super_length);
2071 /* Strip off the ".class" portion of the name when printing
2072 the include file name. */
2074 int i, len = strlen (jcf->classname);
2075 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2077 /* Turn the class name into a file name. */
2078 name = xmalloc (len + 1);
2079 for (i = 0; i < len; ++i)
2080 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2082 print_include (out, name, len);
2087 print_include (out, "gcj/cni", -1);
2088 print_include (out, "java/lang/UnsupportedOperationException",
2094 /* We want to parse the methods first. But we need to find where
2095 they start. So first we skip the fields, then parse the methods.
2096 Then we parse the fields and skip the methods. This is ugly, but
2097 not too bad since we need two full passes to get class decl
2098 information anyway. */
2100 field_start = JCF_TELL (jcf);
2101 jcf_parse_fields (jcf);
2103 method_start = JCF_TELL (jcf);
2105 jcf_parse_methods (jcf);
2110 if (out && ! flag_jni)
2113 print_class_decls (out, jcf, jcf->this_class);
2115 for (i = 0; i < prepend_count; ++i)
2116 fprintf (out, "%s\n", prepend_specs[i]);
2117 if (prepend_count > 0)
2122 if (! print_cxx_classname (out, "class ", jcf,
2123 jcf->this_class, 0))
2125 fprintf (stderr, "class is of array type\n");
2129 if (jcf->super_class)
2131 if (! print_cxx_classname (out, " : public ",
2132 jcf, jcf->super_class, 1))
2134 fprintf (stderr, "base class is of array type\n");
2140 fputs ("\n{\n", out);
2144 /* Now go back for second pass over methods and fields. */
2145 JCF_SEEK (jcf, method_start);
2147 jcf_parse_methods (jcf);
2148 method_end = JCF_TELL (jcf);
2151 JCF_SEEK (jcf, field_start);
2152 jcf_parse_fields (jcf);
2153 JCF_SEEK (jcf, method_end);
2155 jcf_parse_final_attributes (jcf);
2161 fprintf (out, "\n#ifdef __cplusplus\n");
2162 fprintf (out, "}\n");
2163 fprintf (out, "#endif\n");
2167 /* Generate friend decl if we still must. */
2168 for (i = 0; i < friend_count; ++i)
2169 fprintf (out, " friend %s\n", friend_specs[i]);
2171 /* Generate extra declarations. */
2174 for (i = 0; i < add_count; ++i)
2175 fprintf (out, " %s\n", add_specs[i]);
2177 /* Generate an entry for the class object. */
2178 generate_access (out, ACC_PUBLIC);
2179 fprintf (out, "\n static ::java::lang::Class class$;\n");
2183 if (jcf->access_flags & ACC_INTERFACE)
2184 fputs (" __attribute__ ((java_interface))", out);
2188 if (append_count > 0)
2190 for (i = 0; i < append_count; ++i)
2191 fprintf (out, "%s\n", append_specs[i]);
2194 print_mangled_classname (out, jcf,
2195 "\n#endif /* __", jcf->this_class);
2196 fprintf (out, "__ */\n");
2202 /* This is used to mark options with no short value. */
2203 #define LONG_OPT(Num) ((Num) + 128)
2205 #define OPT_classpath LONG_OPT (0)
2206 #define OPT_CLASSPATH OPT_classpath
2207 #define OPT_bootclasspath LONG_OPT (1)
2208 #define OPT_extdirs LONG_OPT (2)
2209 #define OPT_HELP LONG_OPT (3)
2210 #define OPT_TEMP LONG_OPT (4)
2211 #define OPT_VERSION LONG_OPT (5)
2212 #define OPT_PREPEND LONG_OPT (6)
2213 #define OPT_FRIEND LONG_OPT (7)
2214 #define OPT_ADD LONG_OPT (8)
2215 #define OPT_APPEND LONG_OPT (9)
2216 #define OPT_M LONG_OPT (10)
2217 #define OPT_MM LONG_OPT (11)
2218 #define OPT_MG LONG_OPT (12)
2219 #define OPT_MD LONG_OPT (13)
2220 #define OPT_MMD LONG_OPT (14)
2222 static const struct option options[] =
2224 { "classpath", required_argument, NULL, OPT_classpath },
2225 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2226 { "extdirs", required_argument, NULL, OPT_extdirs },
2227 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2228 { "help", no_argument, NULL, OPT_HELP },
2229 { "stubs", no_argument, &stubs, 1 },
2230 { "td", required_argument, NULL, OPT_TEMP },
2231 { "verbose", no_argument, NULL, 'v' },
2232 { "version", no_argument, NULL, OPT_VERSION },
2233 { "prepend", required_argument, NULL, OPT_PREPEND },
2234 { "friend", required_argument, NULL, OPT_FRIEND },
2235 { "add", required_argument, NULL, OPT_ADD },
2236 { "append", required_argument, NULL, OPT_APPEND },
2237 { "M", no_argument, NULL, OPT_M },
2238 { "MM", no_argument, NULL, OPT_MM },
2239 { "MG", no_argument, NULL, OPT_MG },
2240 { "MD", no_argument, NULL, OPT_MD },
2241 { "MMD", no_argument, NULL, OPT_MMD },
2242 { "jni", no_argument, &flag_jni, 1 },
2243 { NULL, no_argument, NULL, 0 }
2249 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2256 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2257 printf ("Generate C++ header files from .class files\n\n");
2258 printf (" -stubs Generate an implementation stub file\n");
2259 printf (" -jni Generate a JNI header or stub\n");
2261 printf (" -add TEXT Insert TEXT into class body\n");
2262 printf (" -append TEXT Insert TEXT after class declaration\n");
2263 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2264 printf (" -prepend TEXT Insert TEXT before start of class\n");
2266 printf (" --classpath PATH Set path to find .class files\n");
2267 printf (" -IDIR Append directory to class path\n");
2268 printf (" --bootclasspath PATH Override built-in class path\n");
2269 printf (" --extdirs PATH Set extensions directory path\n");
2270 printf (" -d DIRECTORY Set output directory name\n");
2271 printf (" -o FILE Set output file name\n");
2272 printf (" -td DIRECTORY Set temporary directory name\n");
2274 printf (" --help Print this help, then exit\n");
2275 printf (" --version Print version number, then exit\n");
2276 printf (" -v, --verbose Print extra information while running\n");
2278 printf (" -M Print all dependencies to stdout;\n");
2279 printf (" suppress ordinary output\n");
2280 printf (" -MM Print non-system dependencies to stdout;\n");
2281 printf (" suppress ordinary output\n");
2282 printf (" -MD Print all dependencies to stdout\n");
2283 printf (" -MMD Print non-system dependencies to stdout\n");
2284 /* We omit -MG until it is implemented. */
2286 printf ("For bug reporting instructions, please see:\n");
2287 printf ("%s.\n", bug_report_url);
2294 printf ("gcjh (GCC) %s\n\n", version_string);
2295 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2296 printf ("This is free software; see the source for copying conditions. There is NO\n");
2297 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2302 main (int argc, char** argv)
2306 char *output_file = NULL;
2307 int emit_dependencies = 0, suppress_output = 0;
2312 fprintf (stderr, "gcjh: no classes specified\n");
2318 /* We use getopt_long_only to allow single `-' long options. For
2319 some of our options this is more natural. */
2320 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2325 /* Already handled. */
2329 output_file = optarg;
2333 output_directory = optarg;
2337 jcf_path_include_arg (optarg);
2345 jcf_path_classpath_arg (optarg);
2348 case OPT_bootclasspath:
2349 jcf_path_bootclasspath_arg (optarg);
2353 jcf_path_extdirs_arg (optarg);
2361 temp_directory = optarg;
2369 if (prepend_count == 0)
2370 prepend_specs = ALLOC (argc * sizeof (char*));
2371 prepend_specs[prepend_count++] = optarg;
2375 if (friend_count == 0)
2376 friend_specs = ALLOC (argc * sizeof (char*));
2377 friend_specs[friend_count++] = optarg;
2382 add_specs = ALLOC (argc * sizeof (char*));
2383 add_specs[add_count++] = optarg;
2387 if (append_count == 0)
2388 append_specs = ALLOC (argc * sizeof (char*));
2389 append_specs[append_count++] = optarg;
2393 emit_dependencies = 1;
2394 suppress_output = 1;
2395 jcf_dependency_init (1);
2399 emit_dependencies = 1;
2400 suppress_output = 1;
2401 jcf_dependency_init (0);
2405 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2409 emit_dependencies = 1;
2410 jcf_dependency_init (1);
2414 emit_dependencies = 1;
2415 jcf_dependency_init (0);
2426 fprintf (stderr, "gcjh: no classes specified\n");
2430 jcf_path_seal (verbose);
2432 if (output_file && emit_dependencies)
2434 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2438 for (argi = optind; argi < argc; argi++)
2440 char *classname = argv[argi];
2441 char *current_output_file;
2442 const char *classfile_name;
2445 fprintf (stderr, "Processing %s\n", classname);
2447 jcf_dependency_reset ();
2448 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2449 if (classfile_name == NULL)
2451 fprintf (stderr, "%s: no such class\n", classname);
2455 fprintf (stderr, "Found in %s\n", classfile_name);
2458 if (strcmp (output_file, "-") == 0)
2460 else if (out == NULL)
2462 out = fopen (output_file, "w");
2466 perror (output_file);
2469 current_output_file = output_file;
2473 int dir_len = strlen (output_directory);
2474 int i, classname_length = strlen (classname);
2475 current_output_file = ALLOC (dir_len + classname_length + 5);
2476 strcpy (current_output_file, output_directory);
2477 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2478 current_output_file[dir_len++] = '/';
2479 for (i = 0; classname[i] != '\0'; i++)
2481 char ch = classname[i];
2484 if (flag_jni && ch == '/')
2486 current_output_file[dir_len++] = ch;
2488 if (emit_dependencies)
2490 if (suppress_output)
2492 jcf_dependency_set_dep_file ("-");
2497 /* We use `.hd' and not `.d' to avoid clashes with
2498 dependency tracking from straight compilation. */
2499 strcpy (current_output_file + dir_len, ".hd");
2500 jcf_dependency_set_dep_file (current_output_file);
2503 strcpy (current_output_file + dir_len,
2504 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2505 jcf_dependency_set_target (current_output_file);
2506 if (! suppress_output)
2508 out = fopen (current_output_file, "w");
2511 perror (current_output_file);
2516 process_file (&jcf, out);
2518 if (current_output_file != output_file)
2519 free (current_output_file);
2520 jcf_dependency_write ();
2523 if (out != NULL && out != stdout)