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 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
34 #include "java-tree.h"
35 #include "java-opcodes.h"
41 /* The output file. */
44 /* Nonzero on failure. */
45 static int found_error = 0;
47 /* Nonzero if we're generating JNI output. */
48 static int flag_jni = 0;
50 /* When non zero, warn when source file is newer than matching class
54 /* Directory to place resulting files in. Set by -d option. */
55 const char *output_directory = "";
57 /* Directory to place temporary file. Set by -td option. Currently unused. */
58 const char *temp_directory = "/tmp";
60 /* Number of friend functions we have to declare. */
61 static int friend_count;
63 /* A class can optionally have a `friend' function declared. If
64 non-NULL, this is that function. */
65 static char **friend_specs = NULL;
67 /* Number of lines we are prepending before the class. */
68 static int prepend_count;
70 /* We can prepend extra lines before the class's start. */
71 static char **prepend_specs = NULL;
73 /* Number of lines we are appending at the end of the class. */
76 /* We can append extra lines just before the class's end. */
77 static char **add_specs = NULL;
79 /* Number of lines we are appending after the class. */
80 static int append_count;
82 /* We can append extra lines after the class's end. */
83 static char **append_specs = NULL;
89 struct JCF *current_jcf;
91 /* This holds access information for the last field we examined. They
92 let us generate "private:", "public:", and "protected:" properly.
93 If 0 then we haven't previously examined any field. */
94 static JCF_u2 last_access;
96 /* Pass this macro the flags for a class and for a method. It will
97 return true if the method should be considered `final'. */
98 #define METHOD_IS_FINAL(Class, Method) \
99 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
101 /* Pass this macro the flags for a method. It will return true if the
103 #define METHOD_IS_NATIVE(Method) \
104 ((Method) & ACC_NATIVE)
106 /* We keep a linked list of all method names we have seen. This lets
107 us determine if a method name and a field name are in conflict. */
112 unsigned char *signature;
114 struct method_name *next;
117 /* List of method names we've seen. */
118 static struct method_name *method_name_list;
120 static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
121 static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int));
122 static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int));
123 static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
124 static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *,
126 static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int,
128 static void print_full_cxx_name PARAMS ((FILE*, JCF*, int, int, int,
130 static void decompile_method PARAMS ((FILE*, JCF*, int));
131 static void add_class_decl PARAMS ((FILE*, JCF*, JCF_u2));
133 static int java_float_finite PARAMS ((jfloat));
134 static int java_double_finite PARAMS ((jdouble));
135 static void print_name PARAMS ((FILE *, JCF *, int));
136 static void print_base_classname PARAMS ((FILE *, JCF *, int));
137 static int utf8_cmp PARAMS ((const unsigned char *, int, const char *));
138 static char *cxx_keyword_subst PARAMS ((const unsigned char *, int));
139 static void generate_access PARAMS ((FILE *, JCF_u2));
140 static int name_is_method_p PARAMS ((const unsigned char *, int));
141 static char *get_field_name PARAMS ((JCF *, int, JCF_u2));
142 static void print_field_name PARAMS ((FILE *, JCF *, int, JCF_u2));
143 static const unsigned char *super_class_name PARAMS ((JCF *, int *));
144 static void print_include PARAMS ((FILE *, const unsigned char *, int));
145 static const unsigned char *decode_signature_piece
146 PARAMS ((FILE *, const unsigned char *, const unsigned char *, int *));
147 static void print_class_decls PARAMS ((FILE *, JCF *, int));
148 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
149 static void help PARAMS ((void)) ATTRIBUTE_NORETURN;
150 static void version PARAMS ((void)) ATTRIBUTE_NORETURN;
151 static int overloaded_jni_method_exists_p PARAMS ((const unsigned char *, int,
153 static void jni_print_char PARAMS ((FILE *, int));
154 static void decompile_return_statement PARAMS ((FILE *, JCF *, int, int, int));
156 JCF_u2 current_field_name;
157 JCF_u2 current_field_value;
158 JCF_u2 current_field_signature;
159 JCF_u2 current_field_flags;
161 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
162 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
163 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
165 /* We pass over fields twice. The first time we just note the types
166 of the fields and then the start of the methods. Then we go back
167 and parse the fields for real. This is ugly. */
168 static int field_pass;
169 /* Likewise we pass over methods twice. The first time we generate
170 class decl information; the second time we generate actual method
172 static int method_pass;
174 #define HANDLE_END_FIELD() \
177 if (out && ! stubs && ! flag_jni) \
178 print_field_info (out, jcf, current_field_name, \
179 current_field_signature, \
180 current_field_flags); \
182 else if (! stubs && ! flag_jni) \
183 add_class_decl (out, jcf, current_field_signature);
185 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
187 static int method_declared = 0;
188 static int method_access = 0;
189 static int method_printed = 0;
190 static int method_synthetic = 0;
191 static int method_signature = 0;
193 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
195 method_synthetic = 0; \
196 method_signature = SIGNATURE; \
197 if (ATTRIBUTE_COUNT) \
198 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
199 (const char *)"Synthetic", 9); \
200 /* If a synthetic methods have been declared, its attribute aren't \
201 worth reading (and triggering side-effects). We skip them an \
202 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
203 jcf_parse_one_method. */ \
204 if (method_synthetic) \
206 skip_attribute (jcf, ATTRIBUTE_COUNT); \
207 ATTRIBUTE_COUNT = 0; \
209 if (method_pass && !method_synthetic) \
211 decompiled = 0; method_printed = 0; \
213 print_method_info (out, jcf, NAME, SIGNATURE, \
216 else if (!method_synthetic) \
218 print_method_info (NULL, jcf, NAME, SIGNATURE, \
220 if (! stubs && ! flag_jni) \
221 add_class_decl (out, jcf, SIGNATURE); \
225 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
226 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
228 static int decompiled = 0;
229 #define HANDLE_END_METHOD() \
230 if (out && method_printed && !method_synthetic) \
231 fputs (decompiled || stubs ? "\n" : ";\n", out);
233 /* We're going to need {peek,skip}_attribute, enable their definition. */
234 #define NEED_PEEK_ATTRIBUTE
235 #define NEED_SKIP_ATTRIBUTE
237 #include "jcf-reader.c"
239 /* Some useful constants. */
240 #define F_NAN_MASK 0x7f800000
241 #if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN)
242 #define D_NAN_MASK 0x000000007ff00000LL
244 #define D_NAN_MASK 0x7ff0000000000000LL
247 /* Return 1 if F is not Inf or NaN. */
249 java_float_finite (f)
255 /* We happen to know that F_NAN_MASK will match all NaN values, and
256 also positive and negative infinity. That's why we only need one
257 test here. See The Java Language Specification, section 20.9. */
258 return (u.i & F_NAN_MASK) != F_NAN_MASK;
261 /* Return 1 if D is not Inf or NaN. */
263 java_double_finite (d)
269 /* Now check for all NaNs. */
270 return (u.l & D_NAN_MASK) != D_NAN_MASK;
273 /* Print a character, appropriately mangled for JNI. */
276 jni_print_char (stream, ch)
281 jcf_print_char (stream, ch);
282 else if (ch == '(' || ch == ')')
287 fputs ("_1", stream);
289 fputs ("_2", stream);
291 fputs ("_3", stream);
294 else if (ISALNUM (ch))
298 /* "Unicode" character. */
299 fprintf (stream, "_0%04x", ch);
303 /* Print a name from the class data. If the index does not point to a
304 string, an error results. */
307 DEFUN(print_name, (stream, jcf, name_index),
308 FILE* stream AND JCF* jcf AND int name_index)
310 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
312 fprintf (stream, "<not a UTF8 constant>");
316 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
317 JPOOL_UTF_LENGTH (jcf, name_index));
320 /* For JNI we must correctly quote each character. */
321 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
322 int length = JPOOL_UTF_LENGTH (jcf, name_index);
323 const unsigned char *limit = str + length;
326 int ch = UTF8_GET (str, limit);
329 fprintf (stream, "\\<invalid>");
332 jni_print_char (stream, ch);
337 /* Print base name of class. The base name is everything after the
341 print_base_classname (stream, jcf, 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 (str, length, name)
376 const unsigned char *str;
380 const unsigned char *limit = str + length;
383 for (i = 0; name[i]; ++i)
385 int ch = UTF8_GET (str, limit);
390 return str == limit ? 0 : 1;
393 /* This is a sorted list of all C++ keywords. */
395 static const char *const cxx_keywords[] =
504 /* If NAME is the name of a C++ keyword, then return an override name.
505 This is a name that can be used in place of the keyword.
506 Otherwise, return NULL. The return value is malloc()d. */
509 cxx_keyword_subst (str, length)
510 const unsigned char *str;
513 int last = ARRAY_SIZE (cxx_keywords);
515 int mid = (last + first) / 2;
518 for (mid = (last + first) / 2;
520 old = mid, mid = (last + first) / 2)
522 int kwl = strlen (cxx_keywords[mid]);
523 int min_length = kwl > length ? length : kwl;
524 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
530 /* Skip all trailing `$'. */
531 for (i = min_length; i < length && str[i] == '$'; ++i)
533 /* We've only found a match if all the remaining characters
537 char *dup = xmalloc (2 + length - min_length + kwl);
538 strcpy (dup, cxx_keywords[mid]);
539 for (i = kwl; i < length + 1; ++i)
555 /* Generate an access control keyword based on FLAGS. */
558 generate_access (stream, flags)
562 if ((flags & ACC_VISIBILITY) == last_access)
564 last_access = (flags & ACC_VISIBILITY);
569 fputs ("public: // actually package-private\n", stream);
572 fputs ("public:\n", stream);
575 fputs ("private:\n", stream);
578 fputs ("public: // actually protected\n", stream);
582 fprintf (stream, "#error unrecognized visibility %d\n",
583 (flags & ACC_VISIBILITY));
588 /* See if NAME is already the name of a method. */
590 name_is_method_p (name, length)
591 const unsigned char *name;
594 struct method_name *p;
596 for (p = method_name_list; p != NULL; p = p->next)
598 if (p->length == length && ! memcmp (p->name, name, length))
604 /* If there is already a method named NAME, whose signature is not
605 SIGNATURE, then return true. Otherwise return false. */
607 overloaded_jni_method_exists_p (name, length, signature, sig_length)
608 const unsigned char *name;
610 const char *signature;
613 struct method_name *p;
615 for (p = method_name_list; p != NULL; p = p->next)
617 if (p->length == length
618 && ! memcmp (p->name, name, length)
619 && (p->sig_length != sig_length
620 || memcmp (p->signature, signature, sig_length)))
626 /* Get name of a field. This handles renamings due to C++ clash. */
628 get_field_name (jcf, name_index, flags)
633 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
634 int length = JPOOL_UTF_LENGTH (jcf, name_index);
637 if (name_is_method_p (name, length))
639 /* This field name matches a method. So override the name with
640 a dummy name. This is yucky, but it isn't clear what else to
641 do. FIXME: if the field is static, then we'll be in real
643 if ((flags & ACC_STATIC))
645 fprintf (stderr, "static field has same name as method\n");
650 override = xmalloc (length + 3);
651 memcpy (override, name, length);
652 strcpy (override + length, "__");
655 override = cxx_keyword_subst (name, length);
660 /* Print a field name. Convenience function for use with
663 print_field_name (stream, jcf, name_index, flags)
669 char *override = get_field_name (jcf, name_index, flags);
673 fputs (override, stream);
677 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
678 JPOOL_UTF_LENGTH (jcf, name_index));
682 DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
683 FILE *stream AND JCF* jcf
684 AND int name_index AND int sig_index AND JCF_u2 flags)
686 char *override = NULL;
688 generate_access (stream, flags);
689 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
691 fprintf (stream, "<not a UTF8 constant>");
697 if ((flags & ACC_STATIC))
698 fputs ("static ", out);
700 if ((flags & ACC_FINAL))
702 if (current_field_value > 0)
707 switch (JPOOL_TAG (jcf, current_field_value))
709 case CONSTANT_Integer:
712 int most_negative = 0;
713 fputs ("const jint ", out);
714 print_field_name (out, jcf, name_index, 0);
716 num = JPOOL_INT (jcf, current_field_value);
717 /* We single out the most negative number to print
718 specially. This avoids later warnings from g++. */
719 if (num == (jint) 0x80000000)
724 format_int (buffer, (jlong) num, 10);
725 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
731 int most_negative = 0;
732 fputs ("const jlong ", out);
733 print_field_name (out, jcf, name_index, 0);
735 num = JPOOL_LONG (jcf, current_field_value);
736 /* We single out the most negative number to print
737 specially.. This avoids later warnings from g++. */
738 if (num == (jlong) 0x8000000000000000LL)
743 format_int (buffer, num, 10);
744 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
749 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
750 fputs ("const jfloat ", out);
751 print_field_name (out, jcf, name_index, 0);
752 if (! java_float_finite (fnum))
755 fprintf (out, " = %.10g;\n", fnum);
758 case CONSTANT_Double:
760 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
761 fputs ("const jdouble ", out);
762 print_field_name (out, jcf, name_index, 0);
763 if (! java_double_finite (dnum))
766 fprintf (out, " = %.17g;\n", dnum);
770 /* We can't print this as a constant, but we can still
771 print something sensible. */
781 override = get_field_name (jcf, name_index, flags);
782 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
791 DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
792 FILE *stream AND JCF* jcf
793 AND int name_index AND int sig_index AND JCF_u2 flags)
795 const unsigned char *str;
796 int length, is_init = 0;
797 char *override = NULL;
800 method_access = flags;
801 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
802 fprintf (stream, "<not a UTF8 constant>");
803 str = JPOOL_UTF_DATA (jcf, name_index);
804 length = JPOOL_UTF_LENGTH (jcf, name_index);
808 /* Ignore the internally generated method <clinit>. However,
809 treat <init> as a constructor. */
810 if (! utf8_cmp (str, length, "<init>"))
812 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
813 && ! (flags & ACC_STATIC))
815 /* FIXME: i18n bug here. Order of prints should not be
817 fprintf (stderr, "ignored method `");
818 jcf_print_utf8 (stderr, str, length);
819 fprintf (stderr, "' marked virtual\n");
827 /* During the first method pass, build a list of method names. This will
828 be used to determine if field names conflict with method names. */
831 struct method_name *nn;
833 nn = (struct method_name *) xmalloc (sizeof (struct method_name));
834 nn->name = (char *) xmalloc (length);
835 memcpy (nn->name, str, length);
837 nn->next = method_name_list;
838 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
839 nn->signature = (char *) xmalloc (nn->sig_length);
840 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
842 method_name_list = nn;
844 /* The rest of this function doesn't matter. */
848 /* We don't worry about overrides in JNI mode. */
851 /* We can't generate a method whose name is a C++ reserved word.
852 We can't just ignore the function, because that will cause
853 incorrect code to be generated if the function is virtual
854 (not only for calls to this function for for other functions
855 after it in the vtbl). So we give it a dummy name instead. */
856 override = cxx_keyword_subst (str, length);
859 if (! stubs && ! flag_jni)
863 generate_access (stream, flags);
866 if ((flags & ACC_STATIC))
867 fputs ("static ", out);
868 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
870 /* Don't print `virtual' if we have a constructor. */
872 fputs ("virtual ", out);
874 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
876 if ((flags & ACC_ABSTRACT))
883 if (METHOD_IS_NATIVE (flags))
886 print_stub_or_jni (out, jcf, name_index, sig_index,
887 is_init, override, flags);
895 /* A helper for the decompiler which prints a `return' statement where
896 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
897 identical, we emit a cast. We do this because the C++ compiler
898 doesn't know that a reference can be cast to the type of an
899 interface it implements. METHODTYPE is the index of the method's
900 signature. NAMEINDEX is the index of the field name; -1 for
901 `this'. OBJECTTYPE is the index of the object's type. */
903 decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
906 int methodtype, nameindex, objecttype;
909 int obj_name_len, method_name_len;
910 const unsigned char *obj_data, *method_data;
912 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
913 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
915 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
916 method_data = JPOOL_UTF_DATA (jcf, methodtype);
918 /* Skip forward to return type part of method. */
919 while (*method_data != ')')
928 /* If we see an `L', skip it and the trailing `;'. */
929 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
932 method_name_len -= 2;
934 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
940 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
941 need a cast. Right now there is no way to determine if this is
943 if (method_name_len != obj_name_len)
948 for (i = 0; i < method_name_len; ++i)
950 if (method_data[i] != obj_data[i])
958 fputs (" { return ", out);
963 const unsigned char *limit;
965 fputs ("reinterpret_cast<", out);
967 while (*method_data == '[')
972 fputs ("JArray<", out);
975 /* Leading space to avoid C++ digraphs. */
978 /* If we see an `L', skip it and the trailing `;'. Only do this
979 if we've seen an array specification. If we don't have an
980 array then the `L' was stripped earlier. */
981 if (array_depth && method_data[0] == 'L'
982 && method_data[method_name_len - 1] == ';')
985 method_name_len -= 2;
988 limit = method_data + method_name_len;
989 while (method_data < limit)
991 int ch = UTF8_GET (method_data, limit);
995 jcf_print_char (out, ch);
999 /* Close each array. */
1000 while (array_depth > 0)
1006 /* Close the cast. */
1010 if (nameindex == -1)
1011 fputs ("this", out);
1013 print_field_name (out, jcf, nameindex, 0);
1022 /* Try to decompile a method body. Right now we just try to handle a
1023 simple case that we can do. Expand as desired. */
1025 decompile_method (out, jcf, code_len)
1030 const unsigned char *codes = jcf->read_ptr;
1032 uint16 name_and_type, name;
1034 /* If the method is synchronized, don't touch it. */
1035 if ((method_access & ACC_SYNCHRONIZED))
1039 && codes[0] == OPCODE_aload_0
1040 && codes[1] == OPCODE_getfield
1041 && (codes[4] == OPCODE_areturn
1042 || codes[4] == OPCODE_dreturn
1043 || codes[4] == OPCODE_freturn
1044 || codes[4] == OPCODE_ireturn
1045 || codes[4] == OPCODE_lreturn))
1047 /* Found code like `return FIELD'. */
1048 index = (codes[2] << 8) | codes[3];
1049 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1050 name_and_type = JPOOL_USHORT2 (jcf, index);
1051 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1052 name = JPOOL_USHORT1 (jcf, name_and_type);
1053 if (codes[4] == OPCODE_areturn)
1054 decompile_return_statement (out, jcf, method_signature,
1055 name, JPOOL_USHORT2 (jcf, name_and_type));
1058 fputs (" { return ", out);
1060 print_field_name (out, jcf, name, 0);
1065 else if (code_len == 2
1066 && codes[0] == OPCODE_aload_0
1067 && codes[1] == OPCODE_areturn)
1069 decompile_return_statement (out, jcf, method_signature, -1,
1070 JPOOL_USHORT1 (jcf, jcf->this_class));
1073 else if (code_len == 1 && codes[0] == OPCODE_return)
1075 /* Found plain `return'. */
1076 fputs (" { }", out);
1079 else if (code_len == 2
1080 && codes[0] == OPCODE_aconst_null
1081 && codes[1] == OPCODE_areturn)
1083 /* Found `return null'. We don't want to depend on NULL being
1085 fputs (" { return 0; }", out);
1090 /* Print one piece of a signature. Returns pointer to next parseable
1091 character on success, NULL on error. */
1092 static const unsigned char *
1093 decode_signature_piece (stream, signature, limit, need_space)
1095 const unsigned char *signature, *limit;
1099 int array_depth = 0;
1101 switch (signature[0])
1104 /* More spaghetti. */
1107 for (signature++; (signature < limit
1108 && ISDIGIT (*signature)); signature++)
1113 ctype = "jbyteArray";
1116 ctype = "jcharArray";
1119 ctype = "jdoubleArray";
1122 ctype = "jfloatArray";
1125 ctype = "jintArray";
1128 ctype = "jshortArray";
1131 ctype = "jlongArray";
1134 ctype = "jbooleanArray";
1137 /* We have a nested array. */
1140 fputs ("JArray<", stream);
1144 /* We have to generate a reference to JArray here, so that
1145 our output matches what the compiler does. */
1147 /* Space between `<' and `:' to avoid C++ digraphs. */
1149 fputs ("JArray< ::", stream);
1150 while (signature < limit && *signature != ';')
1152 int ch = UTF8_GET (signature, limit);
1156 fputs ("::", stream);
1158 jcf_print_char (stream, ch);
1162 fputs (" *> *", stream);
1167 /* Unparseable signature. */
1171 /* If the previous iterations left us with something to print,
1172 print it. For JNI, we always print `jobjectArray' in the
1174 if (flag_jni && ctype == NULL)
1176 ctype = "jobjectArray";
1179 /* The `printit' case will advance SIGNATURE for us. If we
1180 don't go there, we must advance past the `;' ourselves. */
1188 /* This shouldn't happen. */
1191 case 'B': ctype = "jbyte"; goto printit;
1192 case 'C': ctype = "jchar"; goto printit;
1193 case 'D': ctype = "jdouble"; goto printit;
1194 case 'F': ctype = "jfloat"; goto printit;
1195 case 'I': ctype = "jint"; goto printit;
1196 case 'J': ctype = "jlong"; goto printit;
1197 case 'S': ctype = "jshort"; goto printit;
1198 case 'Z': ctype = "jboolean"; goto printit;
1199 case 'V': ctype = "void"; goto printit;
1203 /* We know about certain types and special-case their
1205 FIXME: something like java.lang.Exception should be
1206 printed as `jthrowable', because it is a subclass. This
1207 means that gcjh must read the entire hierarchy and
1209 if (! strncmp (signature, "Ljava/lang/String;",
1210 sizeof ("Ljava/lang/String;") -1))
1212 else if (! strncmp (signature, "Ljava/lang/Class;",
1213 sizeof ("Ljava/lang/Class;") - 1))
1215 else if (! strncmp (signature, "Ljava/lang/Throwable;",
1216 sizeof ("Ljava/lang/Throwable;") - 1))
1217 ctype = "jthrowable";
1218 else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;",
1219 sizeof ("Ljava/lang/ref/WeakReference;") - 1))
1224 while (*signature && *signature != ';')
1229 /* Print a leading "::" so we look in the right namespace. */
1230 fputs ("::", stream);
1232 while (*signature && *signature != ';')
1234 int ch = UTF8_GET (signature, limit);
1236 fputs ("::", stream);
1238 jcf_print_char (stream, ch);
1240 fputs (" *", stream);
1241 if (*signature == ';')
1247 jni_print_char (stream, *signature++);
1252 fputs (ctype, stream);
1258 while (array_depth-- > 0)
1259 fputs ("> *", stream);
1266 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
1267 name_override, flags),
1268 FILE* stream AND JCF* jcf
1269 AND int name_index AND int signature_index
1270 AND int is_init AND const char *name_override AND int flags)
1272 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1274 fprintf (stream, "<not a UTF8 constant>");
1279 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1280 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1281 register const unsigned char *str = str0;
1282 const unsigned char *limit = str + length;
1284 int is_method = str[0] == '(';
1285 const unsigned char *next;
1287 /* If printing a method, skip to the return signature and print
1288 that first. However, there is no return value if this is a
1290 if (is_method && ! is_init)
1300 /* If printing a field or an ordinary method, then print the
1301 "return value" now. */
1302 if (! is_method || ! is_init)
1304 next = decode_signature_piece (stream, str, limit, &need_space);
1307 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1313 /* Now print the name of the thing. */
1315 fputs (" ", stream);
1316 print_full_cxx_name (stream, jcf, name_index,
1317 signature_index, is_init, name_override,
1322 /* Print the unqualified method name followed by the signature. */
1324 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index,
1325 is_init, name_override, flags),
1326 FILE* stream AND JCF* jcf
1327 AND int name_index AND int signature_index AND int is_init
1328 AND const char *name_override AND int flags)
1330 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1331 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1332 register const unsigned char *str = str0;
1333 const unsigned char *limit = str + length;
1335 int is_method = str[0] == '(';
1336 const unsigned char *next;
1339 fputs (name_override, stream);
1340 else if (name_index)
1342 /* Declare constructors specially. */
1344 print_base_classname (stream, jcf, jcf->this_class);
1346 print_name (stream, jcf, name_index);
1351 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1352 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1353 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1354 JPOOL_UTF_LENGTH (jcf, name_index),
1355 signature, sig_len))
1357 /* If this method is overloaded by another native method,
1358 then include the argument information in the mangled
1360 unsigned char *limit = signature + sig_len;
1361 fputs ("__", stream);
1362 while (signature < limit)
1364 int ch = UTF8_GET (signature, limit);
1365 jni_print_char (stream, ch);
1377 /* Have a method or a constructor. Print signature pieces
1379 fputs (" (", stream);
1383 /* In JNI mode, add extra arguments. */
1386 /* FIXME: it would be nice to know if we are printing a decl
1387 or a definition, and only print `env' for the latter. */
1388 fputs ("JNIEnv *env", stream);
1390 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1393 fputs (", ", stream);
1396 while (str < limit && *str != ')')
1398 next = decode_signature_piece (stream, str, limit, &need_space);
1401 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1406 if (next < limit && *next != ')')
1407 fputs (", ", stream);
1411 fputs (")", stream);
1415 /* This is a helper for print_stub_or_jni. */
1417 DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index,
1418 is_init, name_override, flags),
1419 FILE *stream AND JCF *jcf
1420 AND int name_index AND int signature_index
1421 AND int is_init AND const char *name_override AND int flags)
1423 const char *const prefix = flag_jni ? "Java_" : "";
1424 print_cxx_classname (stream, prefix, jcf, jcf->this_class);
1425 fputs (flag_jni ? "_" : "::", stream);
1426 print_full_cxx_name (stream, jcf, name_index,
1427 signature_index, is_init, name_override,
1432 DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init,
1433 name_override, flags),
1434 FILE* stream AND JCF* jcf
1435 AND int name_index AND int signature_index
1436 AND int is_init AND const char *name_override AND int flags)
1438 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1440 fprintf (stream, "<not a UTF8 constant>");
1445 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1446 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1447 register const unsigned char *str = str0;
1448 const unsigned char *limit = str + length;
1450 int is_method = str[0] == '(';
1451 const unsigned char *next;
1453 /* Don't print fields in the JNI case. */
1454 if (! is_method && flag_jni)
1457 if (flag_jni && ! stubs)
1458 fputs ("extern ", stream);
1460 /* If printing a method, skip to the return signature and print
1461 that first. However, there is no return value if this is a
1463 if (is_method && ! is_init)
1473 /* If printing a field or an ordinary method, then print the
1474 "return value" now. Note that a constructor can't be native,
1475 so we don't bother checking this in the JNI case. */
1476 if (! is_method || ! is_init)
1478 next = decode_signature_piece (stream, str, limit, &need_space);
1481 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1487 /* When printing a JNI header we need to respect the space. In
1488 other cases we're just going to insert a newline anyway. */
1489 fputs (need_space && ! stubs ? " " : "\n", stream);
1491 /* Now print the name of the thing. */
1492 print_name_for_stub_or_jni (stream, jcf, name_index,
1493 signature_index, is_init, name_override,
1496 /* Print the body. */
1500 fputs ("\n{\n (*env)->FatalError (\"", stream);
1502 fputs ("\n{\n JvFail (\"", stream);
1503 print_name_for_stub_or_jni (stream, jcf, name_index,
1504 signature_index, is_init,
1507 fputs (" not implemented\");\n}\n\n", stream);
1513 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
1514 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
1516 int name_index = JPOOL_USHORT1 (jcf, index);
1517 fputs (prefix, stream);
1518 jcf_print_utf8_replace (out,
1519 JPOOL_UTF_DATA (jcf, name_index),
1520 JPOOL_UTF_LENGTH (jcf, name_index),
1524 /* Print PREFIX, then a class name in C++ format. If the name refers
1525 to an array, ignore it and don't print PREFIX. Returns 1 if
1526 something was printed, 0 otherwise. */
1528 print_cxx_classname (stream, prefix, jcf, index)
1534 int name_index = JPOOL_USHORT1 (jcf, index);
1536 const unsigned char *s, *p, *limit;
1538 s = JPOOL_UTF_DATA (jcf, name_index);
1539 len = JPOOL_UTF_LENGTH (jcf, name_index);
1542 /* Explicitly omit arrays here. */
1544 c = UTF8_GET (p, limit);
1548 fputs (prefix, stream);
1550 /* Print a leading "::" so we look in the right namespace. */
1551 if (! flag_jni && ! stubs)
1552 fputs ("::", stream);
1556 c = UTF8_GET (s, limit);
1558 fputs (flag_jni ? "_" : "::", stream);
1560 jni_print_char (stream, c);
1566 int written_class_count = 0;
1568 /* Return name of superclass. If LEN is not NULL, fill it with length
1570 static const unsigned char *
1571 super_class_name (derived_jcf, len)
1575 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1576 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1577 const unsigned char *supername =
1578 JPOOL_UTF_DATA (derived_jcf, supername_index);
1581 *len = supername_length;
1588 /* We keep track of all the `#include's we generate, so we can avoid
1593 struct include *next;
1596 /* List of all includes. */
1597 static struct include *all_includes = NULL;
1599 /* Generate a #include. */
1601 print_include (out, utf8, len)
1603 const unsigned char *utf8;
1606 struct include *incl;
1612 len = strlen (utf8);
1614 for (incl = all_includes; incl; incl = incl->next)
1616 /* We check the length because we might have a proper prefix. */
1617 if (len == (int) strlen (incl->name)
1618 && ! strncmp (incl->name, utf8, len))
1622 incl = (struct include *) xmalloc (sizeof (struct include));
1623 incl->name = xmalloc (len + 1);
1624 strncpy (incl->name, utf8, len);
1625 incl->name[len] = '\0';
1626 incl->next = all_includes;
1627 all_includes = incl;
1629 fputs ("#include <", out);
1630 jcf_print_utf8_replace (out, utf8, len,
1632 flag_jni ? '_' : '/');
1633 fputs (".h>\n", out);
1638 /* This is used to represent part of a package or class name. */
1641 /* The text of this part of the name. */
1643 /* True if this represents a class. */
1645 /* Linked list of all classes and packages inside this one. */
1646 struct namelet *subnamelets;
1647 /* Pointer to next sibling. */
1648 struct namelet *next;
1651 static void add_namelet PARAMS ((const unsigned char *,
1652 const unsigned char *, struct namelet *));
1653 static void print_namelet PARAMS ((FILE *, struct namelet *, int));
1655 /* The special root namelet. */
1656 static struct namelet root =
1664 /* This extracts the next name segment from the full UTF-8 encoded
1665 package or class name and links it into the tree. It does this
1668 add_namelet (name, name_limit, parent)
1669 const unsigned char *name, *name_limit;
1670 struct namelet *parent;
1672 const unsigned char *p;
1673 struct namelet *n = NULL, *np;
1675 /* We want to skip the standard namespaces that we assume the
1676 runtime already knows about. We only do this at the top level,
1677 though, hence the check for `root'. */
1678 if (parent == &root)
1680 #define JAVALANG "java/lang/"
1681 #define JAVAIO "java/io/"
1682 #define JAVAUTIL "java/util/"
1683 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1684 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1685 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1686 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1687 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1688 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1692 for (p = name; p < name_limit && *p != '/'; ++p)
1695 /* Search for this name beneath the PARENT node. */
1696 for (np = parent->subnamelets; np != NULL; np = np->next)
1698 /* We check the length because we might have a proper prefix. */
1699 if ((int) strlen (np->name) == p - name &&
1700 ! strncmp (name, np->name, p - name))
1709 n = (struct namelet *) xmalloc (sizeof (struct namelet));
1710 n->name = xmalloc (p - name + 1);
1711 strncpy (n->name, name, p - name);
1712 n->name[p - name] = '\0';
1713 n->is_class = (p == name_limit);
1714 n->subnamelets = NULL;
1715 n->next = parent->subnamelets;
1716 parent->subnamelets = n;
1719 /* We recurse if there is more text, and if the trailing piece does
1720 not represent an inner class. */
1722 add_namelet (p + 1, name_limit, n);
1725 /* Print a single namelet. Destroys namelets while printing. */
1727 print_namelet (out, name, depth)
1729 struct namelet *name;
1737 for (i = 0; i < depth; ++i)
1739 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1741 if (name->is_class && name->subnamelets == NULL)
1747 for (i = 0; i < depth; ++i)
1753 c = name->subnamelets;
1756 struct namelet *next = c->next;
1757 print_namelet (out, c, depth + 2);
1765 for (i = 0; i < depth; ++i)
1768 /* Only print a `;' when printing a class. C++ is evil. */
1778 /* This is called to add some classes to the list of classes for which
1779 we need decls. The signature argument can be a function
1782 add_class_decl (out, jcf, signature)
1787 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1788 int len = JPOOL_UTF_LENGTH (jcf, signature);
1791 for (i = 0; i < len; ++i)
1795 /* If we see an array, then we include the array header. */
1798 print_include (out, "gcj/array", -1);
1802 /* We're looking for `L<stuff>;' -- everything else is
1807 for (start = ++i; i < len && s[i] != ';'; ++i)
1810 add_namelet (&s[start], &s[i], &root);
1814 /* Print declarations for all classes required by this class. Any
1815 class or package in the `java' package is assumed to be handled
1816 statically in libjava; we don't generate declarations for these.
1817 This makes the generated headers a bit easier to read. */
1819 print_class_decls (out, jcf, self)
1824 /* Make sure to always add the current class to the list of things
1825 that should be declared. */
1826 int name_index = JPOOL_USHORT1 (jcf, self);
1828 const unsigned char *s;
1830 s = JPOOL_UTF_DATA (jcf, name_index);
1831 len = JPOOL_UTF_LENGTH (jcf, name_index);
1832 add_namelet (s, s + len, &root);
1834 if (root.subnamelets)
1836 fputs ("extern \"Java\"\n{\n", out);
1837 /* We use an initial offset of 0 because the root namelet
1838 doesn't cause anything to print. */
1839 print_namelet (out, &root, 0);
1840 fputs ("};\n\n", out);
1847 DEFUN(process_file, (jcf, out),
1848 JCF *jcf AND FILE *out)
1851 uint32 field_start, method_end, method_start;
1857 if (jcf_parse_preamble (jcf) != 0)
1859 fprintf (stderr, "Not a valid Java .class file.\n");
1864 /* Parse and possibly print constant pool */
1865 code = jcf_parse_constant_pool (jcf);
1868 fprintf (stderr, "error while parsing constant pool\n");
1872 code = verify_constant_pool (jcf);
1875 fprintf (stderr, "error in constant pool entry #%d\n", code);
1880 jcf_parse_class (jcf);
1882 if (written_class_count++ == 0 && out)
1884 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1899 mode = " -*- c++ -*-";
1905 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1906 cstart, mode, cend);
1909 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1911 %s This file is intended to give you a head start on implementing native\n\
1912 %s methods using %s.\n\
1913 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1914 %s overwrite any edits you have made to this file.%s\n\n",
1915 cstart, jflag, mode,
1931 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1932 fprintf (out, "__\n");
1934 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1935 fprintf (out, "__\n\n");
1939 fprintf (out, "#include <jni.h>\n\n");
1940 fprintf (out, "#ifdef __cplusplus\n");
1941 fprintf (out, "extern \"C\"\n");
1942 fprintf (out, "{\n");
1943 fprintf (out, "#endif\n");
1947 /* We do this to ensure that inline methods won't be
1948 `outlined' by g++. This works as long as method and
1949 fields are not added by the user. */
1950 fprintf (out, "#pragma interface\n");
1952 if (jcf->super_class)
1955 const unsigned char *supername =
1956 super_class_name (jcf, &super_length);
1959 print_include (out, supername, super_length);
1965 /* Strip off the ".class" portion of the name when printing
1966 the include file name. */
1967 int len = strlen (jcf->classname);
1968 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
1970 print_include (out, jcf->classname, len);
1972 print_include (out, "gcj/cni", -1);
1976 /* We want to parse the methods first. But we need to find where
1977 they start. So first we skip the fields, then parse the methods.
1978 Then we parse the fields and skip the methods. This is ugly, but
1979 not too bad since we need two full passes to get class decl
1980 information anyway. */
1982 field_start = JCF_TELL (jcf);
1983 jcf_parse_fields (jcf);
1985 method_start = JCF_TELL (jcf);
1987 jcf_parse_methods (jcf);
1992 if (out && ! flag_jni)
1995 print_class_decls (out, jcf, jcf->this_class);
1997 for (i = 0; i < prepend_count; ++i)
1998 fprintf (out, "%s\n", prepend_specs[i]);
1999 if (prepend_count > 0)
2004 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
2006 fprintf (stderr, "class is of array type\n");
2010 if (jcf->super_class)
2012 if (! print_cxx_classname (out, " : public ",
2013 jcf, jcf->super_class))
2015 fprintf (stderr, "base class is of array type\n");
2021 fputs ("\n{\n", out);
2025 /* Now go back for second pass over methods and fields. */
2026 JCF_SEEK (jcf, method_start);
2028 jcf_parse_methods (jcf);
2029 method_end = JCF_TELL (jcf);
2032 JCF_SEEK (jcf, field_start);
2033 jcf_parse_fields (jcf);
2034 JCF_SEEK (jcf, method_end);
2036 jcf_parse_final_attributes (jcf);
2042 fprintf (out, "\n#ifdef __cplusplus\n");
2043 fprintf (out, "}\n");
2044 fprintf (out, "#endif\n");
2048 /* Generate friend decl if we still must. */
2049 for (i = 0; i < friend_count; ++i)
2050 fprintf (out, " friend %s\n", friend_specs[i]);
2052 /* Generate extra declarations. */
2055 for (i = 0; i < add_count; ++i)
2056 fprintf (out, " %s\n", add_specs[i]);
2058 /* Generate an entry for the class object. */
2059 generate_access (out, ACC_PUBLIC);
2060 fprintf (out, "\n static ::java::lang::Class class$;\n");
2064 if (jcf->access_flags & ACC_INTERFACE)
2065 fputs (" __attribute__ ((java_interface))", out);
2069 if (append_count > 0)
2071 for (i = 0; i < append_count; ++i)
2072 fprintf (out, "%s\n", append_specs[i]);
2075 print_mangled_classname (out, jcf,
2076 "\n#endif /* __", jcf->this_class);
2077 fprintf (out, "__ */\n");
2083 /* This is used to mark options with no short value. */
2084 #define LONG_OPT(Num) ((Num) + 128)
2086 #define OPT_classpath LONG_OPT (0)
2087 #define OPT_CLASSPATH LONG_OPT (1)
2088 #define OPT_HELP LONG_OPT (2)
2089 #define OPT_TEMP LONG_OPT (3)
2090 #define OPT_VERSION LONG_OPT (4)
2091 #define OPT_PREPEND LONG_OPT (5)
2092 #define OPT_FRIEND LONG_OPT (6)
2093 #define OPT_ADD LONG_OPT (7)
2094 #define OPT_APPEND LONG_OPT (8)
2095 #define OPT_M LONG_OPT (9)
2096 #define OPT_MM LONG_OPT (10)
2097 #define OPT_MG LONG_OPT (11)
2098 #define OPT_MD LONG_OPT (12)
2099 #define OPT_MMD LONG_OPT (13)
2101 static struct option options[] =
2103 { "classpath", required_argument, NULL, OPT_classpath },
2104 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2105 { "help", no_argument, NULL, OPT_HELP },
2106 { "stubs", no_argument, &stubs, 1 },
2107 { "td", required_argument, NULL, OPT_TEMP },
2108 { "verbose", no_argument, NULL, 'v' },
2109 { "version", no_argument, NULL, OPT_VERSION },
2110 { "prepend", required_argument, NULL, OPT_PREPEND },
2111 { "friend", required_argument, NULL, OPT_FRIEND },
2112 { "add", required_argument, NULL, OPT_ADD },
2113 { "append", required_argument, NULL, OPT_APPEND },
2114 { "M", no_argument, NULL, OPT_M },
2115 { "MM", no_argument, NULL, OPT_MM },
2116 { "MG", no_argument, NULL, OPT_MG },
2117 { "MD", no_argument, NULL, OPT_MD },
2118 { "MMD", no_argument, NULL, OPT_MMD },
2119 { "jni", no_argument, &flag_jni, 1 },
2120 { NULL, no_argument, NULL, 0 }
2126 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2133 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2134 printf ("Generate C++ header files from .class files\n\n");
2135 printf (" -stubs Generate an implementation stub file\n");
2136 printf (" -jni Generate a JNI header or stub\n");
2138 printf (" -add TEXT Insert TEXT into class body\n");
2139 printf (" -append TEXT Insert TEXT after class declaration\n");
2140 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2141 printf (" -prepend TEXT Insert TEXT before start of class\n");
2143 printf (" --classpath PATH Set path to find .class files\n");
2144 printf (" --CLASSPATH PATH Set path to find .class files\n");
2145 printf (" -IDIR Append directory to class path\n");
2146 printf (" -d DIRECTORY Set output directory name\n");
2147 printf (" -o FILE Set output file name\n");
2148 printf (" -td DIRECTORY Set temporary directory name\n");
2150 printf (" --help Print this help, then exit\n");
2151 printf (" --version Print version number, then exit\n");
2152 printf (" -v, --verbose Print extra information while running\n");
2154 printf (" -M Print all dependencies to stdout;\n");
2155 printf (" suppress ordinary output\n");
2156 printf (" -MM Print non-system dependencies to stdout;\n");
2157 printf (" suppress ordinary output\n");
2158 printf (" -MD Print all dependencies to stdout\n");
2159 printf (" -MMD Print non-system dependencies to stdout\n");
2160 /* We omit -MG until it is implemented. */
2162 printf ("For bug reporting instructions, please see:\n");
2163 printf ("%s.\n", GCCBUGURL);
2170 printf ("gcjh (%s)\n\n", version_string);
2171 printf ("Copyright (C) 2001 Free Software Foundation, Inc.\n");
2172 printf ("This is free software; see the source for copying conditions. There is NO\n");
2173 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2178 DEFUN(main, (argc, argv),
2179 int argc AND char** argv)
2183 char *output_file = NULL;
2184 int emit_dependencies = 0, suppress_output = 0;
2189 fprintf (stderr, "gcjh: no classes specified\n");
2195 /* We use getopt_long_only to allow single `-' long options. For
2196 some of our options this is more natural. */
2197 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2202 /* Already handled. */
2206 output_file = optarg;
2210 output_directory = optarg;
2214 jcf_path_include_arg (optarg);
2222 jcf_path_classpath_arg (optarg);
2226 jcf_path_CLASSPATH_arg (optarg);
2234 temp_directory = optarg;
2242 if (prepend_count == 0)
2243 prepend_specs = (char**) ALLOC (argc * sizeof (char*));
2244 prepend_specs[prepend_count++] = optarg;
2248 if (friend_count == 0)
2249 friend_specs = (char**) ALLOC (argc * sizeof (char*));
2250 friend_specs[friend_count++] = optarg;
2255 add_specs = (char**) ALLOC (argc * sizeof (char*));
2256 add_specs[add_count++] = optarg;
2260 if (append_count == 0)
2261 append_specs = (char**) ALLOC (argc * sizeof (char*));
2262 append_specs[append_count++] = optarg;
2266 emit_dependencies = 1;
2267 suppress_output = 1;
2268 jcf_dependency_init (1);
2272 emit_dependencies = 1;
2273 suppress_output = 1;
2274 jcf_dependency_init (0);
2278 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2282 emit_dependencies = 1;
2283 jcf_dependency_init (1);
2287 emit_dependencies = 1;
2288 jcf_dependency_init (0);
2299 fprintf (stderr, "gcjh: no classes specified\n");
2303 jcf_path_seal (verbose);
2305 if (output_file && emit_dependencies)
2307 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2311 for (argi = optind; argi < argc; argi++)
2313 char *classname = argv[argi];
2314 char *current_output_file;
2315 const char *classfile_name;
2318 fprintf (stderr, "Processing %s\n", classname);
2320 jcf_dependency_reset ();
2321 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2322 if (classfile_name == NULL)
2324 fprintf (stderr, "%s: no such class\n", classname);
2328 fprintf (stderr, "Found in %s\n", classfile_name);
2331 if (strcmp (output_file, "-") == 0)
2333 else if (out == NULL)
2335 out = fopen (output_file, "w");
2339 perror (output_file);
2342 current_output_file = output_file;
2346 int dir_len = strlen (output_directory);
2347 int i, classname_length = strlen (classname);
2348 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2349 strcpy (current_output_file, output_directory);
2350 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2351 current_output_file[dir_len++] = '/';
2352 for (i = 0; classname[i] != '\0'; i++)
2354 char ch = classname[i];
2357 if (flag_jni && ch == '/')
2359 current_output_file[dir_len++] = ch;
2361 if (emit_dependencies)
2363 if (suppress_output)
2365 jcf_dependency_set_dep_file ("-");
2370 /* We use `.hd' and not `.d' to avoid clashes with
2371 dependency tracking from straight compilation. */
2372 strcpy (current_output_file + dir_len, ".hd");
2373 jcf_dependency_set_dep_file (current_output_file);
2376 strcpy (current_output_file + dir_len,
2377 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2378 jcf_dependency_set_target (current_output_file);
2379 if (! suppress_output)
2381 out = fopen (current_output_file, "w");
2384 perror (current_output_file);
2389 process_file (&jcf, out);
2391 if (current_output_file != output_file)
2392 free (current_output_file);
2393 jcf_dependency_write ();
2396 if (out != NULL && out != stdout)