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_printed = 0; \
198 method_signature = SIGNATURE; \
199 if (ATTRIBUTE_COUNT) \
200 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
201 (const char *)"Synthetic", 9); \
202 /* If a synthetic methods have been declared, its attribute aren't \
203 worth reading (and triggering side-effects). We skip them an \
204 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
205 jcf_parse_one_method. */ \
206 if (method_synthetic) \
208 skip_attribute (jcf, ATTRIBUTE_COUNT); \
209 ATTRIBUTE_COUNT = 0; \
211 if (method_pass && !method_synthetic) \
214 print_method_info (out, jcf, NAME, SIGNATURE, \
217 else if (!method_synthetic) \
219 print_method_info (NULL, jcf, NAME, SIGNATURE, \
221 if (! stubs && ! flag_jni) \
222 add_class_decl (out, jcf, SIGNATURE); \
226 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
227 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
229 static int decompiled = 0;
230 #define HANDLE_END_METHOD() \
231 if (out && method_printed && !method_synthetic) \
232 fputs (decompiled || stubs ? "\n" : ";\n", out);
234 /* We're going to need {peek,skip}_attribute, enable their definition. */
235 #define NEED_PEEK_ATTRIBUTE
236 #define NEED_SKIP_ATTRIBUTE
238 #include "jcf-reader.c"
240 /* Some useful constants. */
241 #define F_NAN_MASK 0x7f800000
242 #if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN)
243 #define D_NAN_MASK 0x000000007ff00000LL
245 #define D_NAN_MASK 0x7ff0000000000000LL
248 /* Return 1 if F is not Inf or NaN. */
250 java_float_finite (f)
256 /* We happen to know that F_NAN_MASK will match all NaN values, and
257 also positive and negative infinity. That's why we only need one
258 test here. See The Java Language Specification, section 20.9. */
259 return (u.i & F_NAN_MASK) != F_NAN_MASK;
262 /* Return 1 if D is not Inf or NaN. */
264 java_double_finite (d)
270 /* Now check for all NaNs. */
271 return (u.l & D_NAN_MASK) != D_NAN_MASK;
274 /* Print a character, appropriately mangled for JNI. */
277 jni_print_char (stream, ch)
282 jcf_print_char (stream, ch);
283 else if (ch == '(' || ch == ')')
288 fputs ("_1", stream);
290 fputs ("_2", stream);
292 fputs ("_3", stream);
295 else if (ISALNUM (ch))
299 /* "Unicode" character. */
300 fprintf (stream, "_0%04x", ch);
304 /* Print a name from the class data. If the index does not point to a
305 string, an error results. */
308 DEFUN(print_name, (stream, jcf, name_index),
309 FILE* stream AND JCF* jcf AND int name_index)
311 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
313 fprintf (stream, "<not a UTF8 constant>");
317 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
318 JPOOL_UTF_LENGTH (jcf, name_index));
321 /* For JNI we must correctly quote each character. */
322 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
323 int length = JPOOL_UTF_LENGTH (jcf, name_index);
324 const unsigned char *limit = str + length;
327 int ch = UTF8_GET (str, limit);
330 fprintf (stream, "\\<invalid>");
333 jni_print_char (stream, ch);
338 /* Print base name of class. The base name is everything after the
342 print_base_classname (stream, jcf, index)
347 int name_index = JPOOL_USHORT1 (jcf, index);
349 const unsigned char *s, *p, *limit;
351 s = JPOOL_UTF_DATA (jcf, name_index);
352 len = JPOOL_UTF_LENGTH (jcf, name_index);
357 int c = UTF8_GET (s, limit);
364 int ch = UTF8_GET (p, limit);
366 fputs ("::", stream);
368 jcf_print_char (stream, ch);
372 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
373 and 1 if STR is "greater" than NAME. */
376 utf8_cmp (str, length, name)
377 const unsigned char *str;
381 const unsigned char *limit = str + length;
384 for (i = 0; name[i]; ++i)
386 int ch = UTF8_GET (str, limit);
391 return str == limit ? 0 : 1;
394 /* This is a sorted list of all C++ keywords. */
396 static const char *const cxx_keywords[] =
505 /* If NAME is the name of a C++ keyword, then return an override name.
506 This is a name that can be used in place of the keyword.
507 Otherwise, return NULL. The return value is malloc()d. */
510 cxx_keyword_subst (str, length)
511 const unsigned char *str;
514 int last = ARRAY_SIZE (cxx_keywords);
516 int mid = (last + first) / 2;
519 for (mid = (last + first) / 2;
521 old = mid, mid = (last + first) / 2)
523 int kwl = strlen (cxx_keywords[mid]);
524 int min_length = kwl > length ? length : kwl;
525 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
531 /* Skip all trailing `$'. */
532 for (i = min_length; i < length && str[i] == '$'; ++i)
534 /* We've only found a match if all the remaining characters
538 char *dup = xmalloc (2 + length - min_length + kwl);
539 strcpy (dup, cxx_keywords[mid]);
540 for (i = kwl; i < length + 1; ++i)
556 /* Generate an access control keyword based on FLAGS. */
559 generate_access (stream, flags)
563 if ((flags & ACC_VISIBILITY) == last_access)
565 last_access = (flags & ACC_VISIBILITY);
570 fputs ("public: // actually package-private\n", stream);
573 fputs ("public:\n", stream);
576 fputs ("private:\n", stream);
579 fputs ("public: // actually protected\n", stream);
583 fprintf (stream, "#error unrecognized visibility %d\n",
584 (flags & ACC_VISIBILITY));
589 /* See if NAME is already the name of a method. */
591 name_is_method_p (name, length)
592 const unsigned char *name;
595 struct method_name *p;
597 for (p = method_name_list; p != NULL; p = p->next)
599 if (p->length == length && ! memcmp (p->name, name, length))
605 /* If there is already a method named NAME, whose signature is not
606 SIGNATURE, then return true. Otherwise return false. */
608 overloaded_jni_method_exists_p (name, length, signature, sig_length)
609 const unsigned char *name;
611 const char *signature;
614 struct method_name *p;
616 for (p = method_name_list; p != NULL; p = p->next)
618 if (p->length == length
619 && ! memcmp (p->name, name, length)
620 && (p->sig_length != sig_length
621 || memcmp (p->signature, signature, sig_length)))
627 /* Get name of a field. This handles renamings due to C++ clash. */
629 get_field_name (jcf, name_index, flags)
634 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
635 int length = JPOOL_UTF_LENGTH (jcf, name_index);
638 if (name_is_method_p (name, length))
640 /* This field name matches a method. So override the name with
641 a dummy name. This is yucky, but it isn't clear what else to
642 do. FIXME: if the field is static, then we'll be in real
644 if ((flags & ACC_STATIC))
646 fprintf (stderr, "static field has same name as method\n");
651 override = xmalloc (length + 3);
652 memcpy (override, name, length);
653 strcpy (override + length, "__");
656 override = cxx_keyword_subst (name, length);
661 /* Print a field name. Convenience function for use with
664 print_field_name (stream, jcf, name_index, flags)
670 char *override = get_field_name (jcf, name_index, flags);
674 fputs (override, stream);
678 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
679 JPOOL_UTF_LENGTH (jcf, name_index));
683 DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
684 FILE *stream AND JCF* jcf
685 AND int name_index AND int sig_index AND JCF_u2 flags)
687 char *override = NULL;
689 generate_access (stream, flags);
690 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
692 fprintf (stream, "<not a UTF8 constant>");
698 if ((flags & ACC_STATIC))
699 fputs ("static ", out);
701 if ((flags & ACC_FINAL))
703 if (current_field_value > 0)
708 switch (JPOOL_TAG (jcf, current_field_value))
710 case CONSTANT_Integer:
713 int most_negative = 0;
714 fputs ("const jint ", out);
715 print_field_name (out, jcf, name_index, 0);
717 num = JPOOL_INT (jcf, current_field_value);
718 /* We single out the most negative number to print
719 specially. This avoids later warnings from g++. */
720 if (num == (jint) 0x80000000)
725 format_int (buffer, (jlong) num, 10);
726 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
732 int most_negative = 0;
733 fputs ("const jlong ", out);
734 print_field_name (out, jcf, name_index, 0);
736 num = JPOOL_LONG (jcf, current_field_value);
737 /* We single out the most negative number to print
738 specially.. This avoids later warnings from g++. */
739 if (num == (jlong) 0x8000000000000000LL)
744 format_int (buffer, num, 10);
745 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
750 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
751 fputs ("const jfloat ", out);
752 print_field_name (out, jcf, name_index, 0);
753 if (! java_float_finite (fnum))
756 fprintf (out, " = %.10g;\n", fnum);
759 case CONSTANT_Double:
761 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
762 fputs ("const jdouble ", out);
763 print_field_name (out, jcf, name_index, 0);
764 if (! java_double_finite (dnum))
767 fprintf (out, " = %.17g;\n", dnum);
771 /* We can't print this as a constant, but we can still
772 print something sensible. */
782 override = get_field_name (jcf, name_index, flags);
783 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
792 DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
793 FILE *stream AND JCF* jcf
794 AND int name_index AND int sig_index AND JCF_u2 flags)
796 const unsigned char *str;
797 int length, is_init = 0;
798 char *override = NULL;
801 method_access = flags;
802 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
803 fprintf (stream, "<not a UTF8 constant>");
804 str = JPOOL_UTF_DATA (jcf, name_index);
805 length = JPOOL_UTF_LENGTH (jcf, name_index);
809 /* Ignore the internally generated method <clinit>. However,
810 treat <init> as a constructor. */
811 if (! utf8_cmp (str, length, "<init>"))
813 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
814 && ! (flags & ACC_STATIC))
816 /* FIXME: i18n bug here. Order of prints should not be
818 fprintf (stderr, "ignored method `");
819 jcf_print_utf8 (stderr, str, length);
820 fprintf (stderr, "' marked virtual\n");
828 /* During the first method pass, build a list of method names. This will
829 be used to determine if field names conflict with method names. */
832 struct method_name *nn;
834 nn = (struct method_name *) xmalloc (sizeof (struct method_name));
835 nn->name = (char *) xmalloc (length);
836 memcpy (nn->name, str, length);
838 nn->next = method_name_list;
839 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
840 nn->signature = (char *) xmalloc (nn->sig_length);
841 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
843 method_name_list = nn;
845 /* The rest of this function doesn't matter. */
849 /* We don't worry about overrides in JNI mode. */
852 /* We can't generate a method whose name is a C++ reserved word.
853 We can't just ignore the function, because that will cause
854 incorrect code to be generated if the function is virtual
855 (not only for calls to this function for for other functions
856 after it in the vtbl). So we give it a dummy name instead. */
857 override = cxx_keyword_subst (str, length);
860 if (! stubs && ! flag_jni)
864 generate_access (stream, flags);
867 if ((flags & ACC_STATIC))
868 fputs ("static ", out);
869 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
871 /* Don't print `virtual' if we have a constructor. */
873 fputs ("virtual ", out);
875 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
877 if ((flags & ACC_ABSTRACT))
884 if (METHOD_IS_NATIVE (flags))
887 print_stub_or_jni (out, jcf, name_index, sig_index,
888 is_init, override, flags);
896 /* A helper for the decompiler which prints a `return' statement where
897 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
898 identical, we emit a cast. We do this because the C++ compiler
899 doesn't know that a reference can be cast to the type of an
900 interface it implements. METHODTYPE is the index of the method's
901 signature. NAMEINDEX is the index of the field name; -1 for
902 `this'. OBJECTTYPE is the index of the object's type. */
904 decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
907 int methodtype, nameindex, objecttype;
910 int obj_name_len, method_name_len;
911 const unsigned char *obj_data, *method_data;
913 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
914 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
916 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
917 method_data = JPOOL_UTF_DATA (jcf, methodtype);
919 /* Skip forward to return type part of method. */
920 while (*method_data != ')')
929 /* If we see an `L', skip it and the trailing `;'. */
930 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
933 method_name_len -= 2;
935 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
941 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
942 need a cast. Right now there is no way to determine if this is
944 if (method_name_len != obj_name_len)
949 for (i = 0; i < method_name_len; ++i)
951 if (method_data[i] != obj_data[i])
959 fputs (" { return ", out);
964 const unsigned char *limit;
966 fputs ("reinterpret_cast<", out);
968 while (*method_data == '[')
973 fputs ("JArray<", out);
976 /* Leading space to avoid C++ digraphs. */
979 /* If we see an `L', skip it and the trailing `;'. Only do this
980 if we've seen an array specification. If we don't have an
981 array then the `L' was stripped earlier. */
982 if (array_depth && method_data[0] == 'L'
983 && method_data[method_name_len - 1] == ';')
986 method_name_len -= 2;
989 limit = method_data + method_name_len;
990 while (method_data < limit)
992 int ch = UTF8_GET (method_data, limit);
996 jcf_print_char (out, ch);
1000 /* Close each array. */
1001 while (array_depth > 0)
1007 /* Close the cast. */
1011 if (nameindex == -1)
1012 fputs ("this", out);
1014 print_field_name (out, jcf, nameindex, 0);
1023 /* Try to decompile a method body. Right now we just try to handle a
1024 simple case that we can do. Expand as desired. */
1026 decompile_method (out, jcf, code_len)
1031 const unsigned char *codes = jcf->read_ptr;
1033 uint16 name_and_type, name;
1035 /* If the method is synchronized, don't touch it. */
1036 if ((method_access & ACC_SYNCHRONIZED))
1040 && codes[0] == OPCODE_aload_0
1041 && codes[1] == OPCODE_getfield
1042 && (codes[4] == OPCODE_areturn
1043 || codes[4] == OPCODE_dreturn
1044 || codes[4] == OPCODE_freturn
1045 || codes[4] == OPCODE_ireturn
1046 || codes[4] == OPCODE_lreturn))
1048 /* Found code like `return FIELD'. */
1049 index = (codes[2] << 8) | codes[3];
1050 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1051 name_and_type = JPOOL_USHORT2 (jcf, index);
1052 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1053 name = JPOOL_USHORT1 (jcf, name_and_type);
1054 if (codes[4] == OPCODE_areturn)
1055 decompile_return_statement (out, jcf, method_signature,
1056 name, JPOOL_USHORT2 (jcf, name_and_type));
1059 fputs (" { return ", out);
1061 print_field_name (out, jcf, name, 0);
1066 else if (code_len == 2
1067 && codes[0] == OPCODE_aload_0
1068 && codes[1] == OPCODE_areturn)
1070 decompile_return_statement (out, jcf, method_signature, -1,
1071 JPOOL_USHORT1 (jcf, jcf->this_class));
1074 else if (code_len == 1 && codes[0] == OPCODE_return)
1076 /* Found plain `return'. */
1077 fputs (" { }", out);
1080 else if (code_len == 2
1081 && codes[0] == OPCODE_aconst_null
1082 && codes[1] == OPCODE_areturn)
1084 /* Found `return null'. We don't want to depend on NULL being
1086 fputs (" { return 0; }", out);
1091 /* Print one piece of a signature. Returns pointer to next parseable
1092 character on success, NULL on error. */
1093 static const unsigned char *
1094 decode_signature_piece (stream, signature, limit, need_space)
1096 const unsigned char *signature, *limit;
1100 int array_depth = 0;
1102 switch (signature[0])
1105 /* More spaghetti. */
1108 for (signature++; (signature < limit
1109 && ISDIGIT (*signature)); signature++)
1114 ctype = "jbyteArray";
1117 ctype = "jcharArray";
1120 ctype = "jdoubleArray";
1123 ctype = "jfloatArray";
1126 ctype = "jintArray";
1129 ctype = "jshortArray";
1132 ctype = "jlongArray";
1135 ctype = "jbooleanArray";
1138 /* We have a nested array. */
1141 fputs ("JArray<", stream);
1145 /* We have to generate a reference to JArray here, so that
1146 our output matches what the compiler does. */
1148 /* Space between `<' and `:' to avoid C++ digraphs. */
1150 fputs ("JArray< ::", stream);
1151 while (signature < limit && *signature != ';')
1153 int ch = UTF8_GET (signature, limit);
1157 fputs ("::", stream);
1159 jcf_print_char (stream, ch);
1163 fputs (" *> *", stream);
1168 /* Unparseable signature. */
1172 /* If the previous iterations left us with something to print,
1173 print it. For JNI, we always print `jobjectArray' in the
1175 if (flag_jni && ctype == NULL)
1177 ctype = "jobjectArray";
1180 /* The `printit' case will advance SIGNATURE for us. If we
1181 don't go there, we must advance past the `;' ourselves. */
1189 /* This shouldn't happen. */
1192 case 'B': ctype = "jbyte"; goto printit;
1193 case 'C': ctype = "jchar"; goto printit;
1194 case 'D': ctype = "jdouble"; goto printit;
1195 case 'F': ctype = "jfloat"; goto printit;
1196 case 'I': ctype = "jint"; goto printit;
1197 case 'J': ctype = "jlong"; goto printit;
1198 case 'S': ctype = "jshort"; goto printit;
1199 case 'Z': ctype = "jboolean"; goto printit;
1200 case 'V': ctype = "void"; goto printit;
1204 /* We know about certain types and special-case their
1206 FIXME: something like java.lang.Exception should be
1207 printed as `jthrowable', because it is a subclass. This
1208 means that gcjh must read the entire hierarchy and
1210 if (! strncmp (signature, "Ljava/lang/String;",
1211 sizeof ("Ljava/lang/String;") -1))
1213 else if (! strncmp (signature, "Ljava/lang/Class;",
1214 sizeof ("Ljava/lang/Class;") - 1))
1216 else if (! strncmp (signature, "Ljava/lang/Throwable;",
1217 sizeof ("Ljava/lang/Throwable;") - 1))
1218 ctype = "jthrowable";
1219 else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;",
1220 sizeof ("Ljava/lang/ref/WeakReference;") - 1))
1225 while (*signature && *signature != ';')
1230 /* Print a leading "::" so we look in the right namespace. */
1231 fputs ("::", stream);
1233 while (*signature && *signature != ';')
1235 int ch = UTF8_GET (signature, limit);
1237 fputs ("::", stream);
1239 jcf_print_char (stream, ch);
1241 fputs (" *", stream);
1242 if (*signature == ';')
1248 jni_print_char (stream, *signature++);
1253 fputs (ctype, stream);
1259 while (array_depth-- > 0)
1260 fputs ("> *", stream);
1267 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
1268 name_override, flags),
1269 FILE* stream AND JCF* jcf
1270 AND int name_index AND int signature_index
1271 AND int is_init AND const char *name_override AND int flags)
1273 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1275 fprintf (stream, "<not a UTF8 constant>");
1280 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1281 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1282 register const unsigned char *str = str0;
1283 const unsigned char *limit = str + length;
1285 int is_method = str[0] == '(';
1286 const unsigned char *next;
1288 /* If printing a method, skip to the return signature and print
1289 that first. However, there is no return value if this is a
1291 if (is_method && ! is_init)
1301 /* If printing a field or an ordinary method, then print the
1302 "return value" now. */
1303 if (! is_method || ! is_init)
1305 next = decode_signature_piece (stream, str, limit, &need_space);
1308 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1314 /* Now print the name of the thing. */
1316 fputs (" ", stream);
1317 print_full_cxx_name (stream, jcf, name_index,
1318 signature_index, is_init, name_override,
1323 /* Print the unqualified method name followed by the signature. */
1325 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index,
1326 is_init, name_override, flags),
1327 FILE* stream AND JCF* jcf
1328 AND int name_index AND int signature_index AND int is_init
1329 AND const char *name_override AND int flags)
1331 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1332 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1333 register const unsigned char *str = str0;
1334 const unsigned char *limit = str + length;
1336 int is_method = str[0] == '(';
1337 const unsigned char *next;
1340 fputs (name_override, stream);
1341 else if (name_index)
1343 /* Declare constructors specially. */
1345 print_base_classname (stream, jcf, jcf->this_class);
1347 print_name (stream, jcf, name_index);
1352 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1353 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1354 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1355 JPOOL_UTF_LENGTH (jcf, name_index),
1356 signature, sig_len))
1358 /* If this method is overloaded by another native method,
1359 then include the argument information in the mangled
1361 unsigned char *limit = signature + sig_len;
1362 fputs ("__", stream);
1363 while (signature < limit)
1365 int ch = UTF8_GET (signature, limit);
1366 jni_print_char (stream, ch);
1378 /* Have a method or a constructor. Print signature pieces
1380 fputs (" (", stream);
1384 /* In JNI mode, add extra arguments. */
1387 /* FIXME: it would be nice to know if we are printing a decl
1388 or a definition, and only print `env' for the latter. */
1389 fputs ("JNIEnv *env", stream);
1391 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1394 fputs (", ", stream);
1397 while (str < limit && *str != ')')
1399 next = decode_signature_piece (stream, str, limit, &need_space);
1402 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1407 if (next < limit && *next != ')')
1408 fputs (", ", stream);
1412 fputs (")", stream);
1416 /* This is a helper for print_stub_or_jni. */
1418 DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index,
1419 is_init, name_override, flags),
1420 FILE *stream AND JCF *jcf
1421 AND int name_index AND int signature_index
1422 AND int is_init AND const char *name_override AND int flags)
1424 const char *const prefix = flag_jni ? "Java_" : "";
1425 print_cxx_classname (stream, prefix, jcf, jcf->this_class);
1426 fputs (flag_jni ? "_" : "::", stream);
1427 print_full_cxx_name (stream, jcf, name_index,
1428 signature_index, is_init, name_override,
1433 DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init,
1434 name_override, flags),
1435 FILE* stream AND JCF* jcf
1436 AND int name_index AND int signature_index
1437 AND int is_init AND const char *name_override AND int flags)
1439 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1441 fprintf (stream, "<not a UTF8 constant>");
1446 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1447 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1448 register const unsigned char *str = str0;
1449 const unsigned char *limit = str + length;
1451 int is_method = str[0] == '(';
1452 const unsigned char *next;
1454 /* Don't print fields in the JNI case. */
1455 if (! is_method && flag_jni)
1458 if (flag_jni && ! stubs)
1459 fputs ("extern ", stream);
1461 /* If printing a method, skip to the return signature and print
1462 that first. However, there is no return value if this is a
1464 if (is_method && ! is_init)
1474 /* If printing a field or an ordinary method, then print the
1475 "return value" now. Note that a constructor can't be native,
1476 so we don't bother checking this in the JNI case. */
1477 if (! is_method || ! is_init)
1479 next = decode_signature_piece (stream, str, limit, &need_space);
1482 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1488 /* When printing a JNI header we need to respect the space. In
1489 other cases we're just going to insert a newline anyway. */
1490 fputs (need_space && ! stubs ? " " : "\n", stream);
1492 /* Now print the name of the thing. */
1493 print_name_for_stub_or_jni (stream, jcf, name_index,
1494 signature_index, is_init, name_override,
1497 /* Print the body. */
1501 fputs ("\n{\n (*env)->FatalError (\"", stream);
1503 fputs ("\n{\n JvFail (\"", stream);
1504 print_name_for_stub_or_jni (stream, jcf, name_index,
1505 signature_index, is_init,
1508 fputs (" not implemented\");\n}\n\n", stream);
1514 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
1515 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
1517 int name_index = JPOOL_USHORT1 (jcf, index);
1518 fputs (prefix, stream);
1519 jcf_print_utf8_replace (out,
1520 JPOOL_UTF_DATA (jcf, name_index),
1521 JPOOL_UTF_LENGTH (jcf, name_index),
1525 /* Print PREFIX, then a class name in C++ format. If the name refers
1526 to an array, ignore it and don't print PREFIX. Returns 1 if
1527 something was printed, 0 otherwise. */
1529 print_cxx_classname (stream, prefix, jcf, index)
1535 int name_index = JPOOL_USHORT1 (jcf, index);
1537 const unsigned char *s, *p, *limit;
1539 s = JPOOL_UTF_DATA (jcf, name_index);
1540 len = JPOOL_UTF_LENGTH (jcf, name_index);
1543 /* Explicitly omit arrays here. */
1545 c = UTF8_GET (p, limit);
1549 fputs (prefix, stream);
1551 /* Print a leading "::" so we look in the right namespace. */
1552 if (! flag_jni && ! stubs)
1553 fputs ("::", stream);
1557 c = UTF8_GET (s, limit);
1559 fputs (flag_jni ? "_" : "::", stream);
1561 jni_print_char (stream, c);
1567 int written_class_count = 0;
1569 /* Return name of superclass. If LEN is not NULL, fill it with length
1571 static const unsigned char *
1572 super_class_name (derived_jcf, len)
1576 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1577 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1578 const unsigned char *supername =
1579 JPOOL_UTF_DATA (derived_jcf, supername_index);
1582 *len = supername_length;
1589 /* We keep track of all the `#include's we generate, so we can avoid
1594 struct include *next;
1597 /* List of all includes. */
1598 static struct include *all_includes = NULL;
1600 /* Generate a #include. */
1602 print_include (out, utf8, len)
1604 const unsigned char *utf8;
1607 struct include *incl;
1613 len = strlen (utf8);
1615 for (incl = all_includes; incl; incl = incl->next)
1617 /* We check the length because we might have a proper prefix. */
1618 if (len == (int) strlen (incl->name)
1619 && ! strncmp (incl->name, utf8, len))
1623 incl = (struct include *) xmalloc (sizeof (struct include));
1624 incl->name = xmalloc (len + 1);
1625 strncpy (incl->name, utf8, len);
1626 incl->name[len] = '\0';
1627 incl->next = all_includes;
1628 all_includes = incl;
1630 fputs ("#include <", out);
1631 jcf_print_utf8_replace (out, utf8, len,
1633 flag_jni ? '_' : '/');
1634 fputs (".h>\n", out);
1639 /* This is used to represent part of a package or class name. */
1642 /* The text of this part of the name. */
1644 /* True if this represents a class. */
1646 /* Linked list of all classes and packages inside this one. */
1647 struct namelet *subnamelets;
1648 /* Pointer to next sibling. */
1649 struct namelet *next;
1652 static void add_namelet PARAMS ((const unsigned char *,
1653 const unsigned char *, struct namelet *));
1654 static void print_namelet PARAMS ((FILE *, struct namelet *, int));
1656 /* The special root namelet. */
1657 static struct namelet root =
1665 /* This extracts the next name segment from the full UTF-8 encoded
1666 package or class name and links it into the tree. It does this
1669 add_namelet (name, name_limit, parent)
1670 const unsigned char *name, *name_limit;
1671 struct namelet *parent;
1673 const unsigned char *p;
1674 struct namelet *n = NULL, *np;
1676 /* We want to skip the standard namespaces that we assume the
1677 runtime already knows about. We only do this at the top level,
1678 though, hence the check for `root'. */
1679 if (parent == &root)
1681 #define JAVALANG "java/lang/"
1682 #define JAVAIO "java/io/"
1683 #define JAVAUTIL "java/util/"
1684 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1685 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1686 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1687 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1688 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1689 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1693 for (p = name; p < name_limit && *p != '/'; ++p)
1696 /* Search for this name beneath the PARENT node. */
1697 for (np = parent->subnamelets; np != NULL; np = np->next)
1699 /* We check the length because we might have a proper prefix. */
1700 if ((int) strlen (np->name) == p - name &&
1701 ! strncmp (name, np->name, p - name))
1710 n = (struct namelet *) xmalloc (sizeof (struct namelet));
1711 n->name = xmalloc (p - name + 1);
1712 strncpy (n->name, name, p - name);
1713 n->name[p - name] = '\0';
1714 n->is_class = (p == name_limit);
1715 n->subnamelets = NULL;
1716 n->next = parent->subnamelets;
1717 parent->subnamelets = n;
1720 /* We recurse if there is more text, and if the trailing piece does
1721 not represent an inner class. */
1723 add_namelet (p + 1, name_limit, n);
1726 /* Print a single namelet. Destroys namelets while printing. */
1728 print_namelet (out, name, depth)
1730 struct namelet *name;
1738 for (i = 0; i < depth; ++i)
1740 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1742 if (name->is_class && name->subnamelets == NULL)
1748 for (i = 0; i < depth; ++i)
1754 c = name->subnamelets;
1757 struct namelet *next = c->next;
1758 print_namelet (out, c, depth + 2);
1761 name->subnamelets = NULL;
1767 for (i = 0; i < depth; ++i)
1770 /* Only print a `;' when printing a class. C++ is evil. */
1780 /* This is called to add some classes to the list of classes for which
1781 we need decls. The signature argument can be a function
1784 add_class_decl (out, jcf, signature)
1789 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1790 int len = JPOOL_UTF_LENGTH (jcf, signature);
1793 for (i = 0; i < len; ++i)
1797 /* If we see an array, then we include the array header. */
1800 print_include (out, "gcj/array", -1);
1804 /* We're looking for `L<stuff>;' -- everything else is
1809 for (start = ++i; i < len && s[i] != ';'; ++i)
1812 add_namelet (&s[start], &s[i], &root);
1816 /* Print declarations for all classes required by this class. Any
1817 class or package in the `java' package is assumed to be handled
1818 statically in libjava; we don't generate declarations for these.
1819 This makes the generated headers a bit easier to read. */
1821 print_class_decls (out, jcf, self)
1826 /* Make sure to always add the current class to the list of things
1827 that should be declared. */
1828 int name_index = JPOOL_USHORT1 (jcf, self);
1830 const unsigned char *s;
1832 s = JPOOL_UTF_DATA (jcf, name_index);
1833 len = JPOOL_UTF_LENGTH (jcf, name_index);
1834 add_namelet (s, s + len, &root);
1836 if (root.subnamelets)
1838 fputs ("extern \"Java\"\n{\n", out);
1839 /* We use an initial offset of 0 because the root namelet
1840 doesn't cause anything to print. */
1841 print_namelet (out, &root, 0);
1842 fputs ("};\n\n", out);
1849 DEFUN(process_file, (jcf, out),
1850 JCF *jcf AND FILE *out)
1853 uint32 field_start, method_end, method_start;
1859 if (jcf_parse_preamble (jcf) != 0)
1861 fprintf (stderr, "Not a valid Java .class file.\n");
1866 /* Parse and possibly print constant pool */
1867 code = jcf_parse_constant_pool (jcf);
1870 fprintf (stderr, "error while parsing constant pool\n");
1874 code = verify_constant_pool (jcf);
1877 fprintf (stderr, "error in constant pool entry #%d\n", code);
1882 jcf_parse_class (jcf);
1884 if (written_class_count++ == 0 && out)
1886 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1901 mode = " -*- c++ -*-";
1907 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1908 cstart, mode, cend);
1911 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
1913 %s This file is intended to give you a head start on implementing native\n\
1914 %s methods using %s.\n\
1915 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1916 %s overwrite any edits you have made to this file.%s\n\n",
1917 cstart, jflag, mode,
1933 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1934 fprintf (out, "__\n");
1936 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1937 fprintf (out, "__\n\n");
1941 fprintf (out, "#include <jni.h>\n\n");
1942 fprintf (out, "#ifdef __cplusplus\n");
1943 fprintf (out, "extern \"C\"\n");
1944 fprintf (out, "{\n");
1945 fprintf (out, "#endif\n");
1949 /* We do this to ensure that inline methods won't be
1950 `outlined' by g++. This works as long as method and
1951 fields are not added by the user. */
1952 fprintf (out, "#pragma interface\n");
1954 if (jcf->super_class)
1957 const unsigned char *supername =
1958 super_class_name (jcf, &super_length);
1961 print_include (out, supername, super_length);
1967 /* Strip off the ".class" portion of the name when printing
1968 the include file name. */
1969 int len = strlen (jcf->classname);
1970 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
1972 print_include (out, jcf->classname, len);
1974 print_include (out, "gcj/cni", -1);
1978 /* We want to parse the methods first. But we need to find where
1979 they start. So first we skip the fields, then parse the methods.
1980 Then we parse the fields and skip the methods. This is ugly, but
1981 not too bad since we need two full passes to get class decl
1982 information anyway. */
1984 field_start = JCF_TELL (jcf);
1985 jcf_parse_fields (jcf);
1987 method_start = JCF_TELL (jcf);
1989 jcf_parse_methods (jcf);
1994 if (out && ! flag_jni)
1997 print_class_decls (out, jcf, jcf->this_class);
1999 for (i = 0; i < prepend_count; ++i)
2000 fprintf (out, "%s\n", prepend_specs[i]);
2001 if (prepend_count > 0)
2006 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
2008 fprintf (stderr, "class is of array type\n");
2012 if (jcf->super_class)
2014 if (! print_cxx_classname (out, " : public ",
2015 jcf, jcf->super_class))
2017 fprintf (stderr, "base class is of array type\n");
2023 fputs ("\n{\n", out);
2027 /* Now go back for second pass over methods and fields. */
2028 JCF_SEEK (jcf, method_start);
2030 jcf_parse_methods (jcf);
2031 method_end = JCF_TELL (jcf);
2034 JCF_SEEK (jcf, field_start);
2035 jcf_parse_fields (jcf);
2036 JCF_SEEK (jcf, method_end);
2038 jcf_parse_final_attributes (jcf);
2044 fprintf (out, "\n#ifdef __cplusplus\n");
2045 fprintf (out, "}\n");
2046 fprintf (out, "#endif\n");
2050 /* Generate friend decl if we still must. */
2051 for (i = 0; i < friend_count; ++i)
2052 fprintf (out, " friend %s\n", friend_specs[i]);
2054 /* Generate extra declarations. */
2057 for (i = 0; i < add_count; ++i)
2058 fprintf (out, " %s\n", add_specs[i]);
2060 /* Generate an entry for the class object. */
2061 generate_access (out, ACC_PUBLIC);
2062 fprintf (out, "\n static ::java::lang::Class class$;\n");
2066 if (jcf->access_flags & ACC_INTERFACE)
2067 fputs (" __attribute__ ((java_interface))", out);
2071 if (append_count > 0)
2073 for (i = 0; i < append_count; ++i)
2074 fprintf (out, "%s\n", append_specs[i]);
2077 print_mangled_classname (out, jcf,
2078 "\n#endif /* __", jcf->this_class);
2079 fprintf (out, "__ */\n");
2085 /* This is used to mark options with no short value. */
2086 #define LONG_OPT(Num) ((Num) + 128)
2088 #define OPT_classpath LONG_OPT (0)
2089 #define OPT_CLASSPATH LONG_OPT (1)
2090 #define OPT_HELP LONG_OPT (2)
2091 #define OPT_TEMP LONG_OPT (3)
2092 #define OPT_VERSION LONG_OPT (4)
2093 #define OPT_PREPEND LONG_OPT (5)
2094 #define OPT_FRIEND LONG_OPT (6)
2095 #define OPT_ADD LONG_OPT (7)
2096 #define OPT_APPEND LONG_OPT (8)
2097 #define OPT_M LONG_OPT (9)
2098 #define OPT_MM LONG_OPT (10)
2099 #define OPT_MG LONG_OPT (11)
2100 #define OPT_MD LONG_OPT (12)
2101 #define OPT_MMD LONG_OPT (13)
2103 static struct option options[] =
2105 { "classpath", required_argument, NULL, OPT_classpath },
2106 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2107 { "help", no_argument, NULL, OPT_HELP },
2108 { "stubs", no_argument, &stubs, 1 },
2109 { "td", required_argument, NULL, OPT_TEMP },
2110 { "verbose", no_argument, NULL, 'v' },
2111 { "version", no_argument, NULL, OPT_VERSION },
2112 { "prepend", required_argument, NULL, OPT_PREPEND },
2113 { "friend", required_argument, NULL, OPT_FRIEND },
2114 { "add", required_argument, NULL, OPT_ADD },
2115 { "append", required_argument, NULL, OPT_APPEND },
2116 { "M", no_argument, NULL, OPT_M },
2117 { "MM", no_argument, NULL, OPT_MM },
2118 { "MG", no_argument, NULL, OPT_MG },
2119 { "MD", no_argument, NULL, OPT_MD },
2120 { "MMD", no_argument, NULL, OPT_MMD },
2121 { "jni", no_argument, &flag_jni, 1 },
2122 { NULL, no_argument, NULL, 0 }
2128 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2135 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2136 printf ("Generate C++ header files from .class files\n\n");
2137 printf (" -stubs Generate an implementation stub file\n");
2138 printf (" -jni Generate a JNI header or stub\n");
2140 printf (" -add TEXT Insert TEXT into class body\n");
2141 printf (" -append TEXT Insert TEXT after class declaration\n");
2142 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2143 printf (" -prepend TEXT Insert TEXT before start of class\n");
2145 printf (" --classpath PATH Set path to find .class files\n");
2146 printf (" --CLASSPATH PATH Set path to find .class files\n");
2147 printf (" -IDIR Append directory to class path\n");
2148 printf (" -d DIRECTORY Set output directory name\n");
2149 printf (" -o FILE Set output file name\n");
2150 printf (" -td DIRECTORY Set temporary directory name\n");
2152 printf (" --help Print this help, then exit\n");
2153 printf (" --version Print version number, then exit\n");
2154 printf (" -v, --verbose Print extra information while running\n");
2156 printf (" -M Print all dependencies to stdout;\n");
2157 printf (" suppress ordinary output\n");
2158 printf (" -MM Print non-system dependencies to stdout;\n");
2159 printf (" suppress ordinary output\n");
2160 printf (" -MD Print all dependencies to stdout\n");
2161 printf (" -MMD Print non-system dependencies to stdout\n");
2162 /* We omit -MG until it is implemented. */
2164 printf ("For bug reporting instructions, please see:\n");
2165 printf ("%s.\n", GCCBUGURL);
2172 printf ("gcjh (%s)\n\n", version_string);
2173 printf ("Copyright (C) 2001 Free Software Foundation, Inc.\n");
2174 printf ("This is free software; see the source for copying conditions. There is NO\n");
2175 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2180 DEFUN(main, (argc, argv),
2181 int argc AND char** argv)
2185 char *output_file = NULL;
2186 int emit_dependencies = 0, suppress_output = 0;
2191 fprintf (stderr, "gcjh: no classes specified\n");
2197 /* We use getopt_long_only to allow single `-' long options. For
2198 some of our options this is more natural. */
2199 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2204 /* Already handled. */
2208 output_file = optarg;
2212 output_directory = optarg;
2216 jcf_path_include_arg (optarg);
2224 jcf_path_classpath_arg (optarg);
2228 jcf_path_CLASSPATH_arg (optarg);
2236 temp_directory = optarg;
2244 if (prepend_count == 0)
2245 prepend_specs = (char**) ALLOC (argc * sizeof (char*));
2246 prepend_specs[prepend_count++] = optarg;
2250 if (friend_count == 0)
2251 friend_specs = (char**) ALLOC (argc * sizeof (char*));
2252 friend_specs[friend_count++] = optarg;
2257 add_specs = (char**) ALLOC (argc * sizeof (char*));
2258 add_specs[add_count++] = optarg;
2262 if (append_count == 0)
2263 append_specs = (char**) ALLOC (argc * sizeof (char*));
2264 append_specs[append_count++] = optarg;
2268 emit_dependencies = 1;
2269 suppress_output = 1;
2270 jcf_dependency_init (1);
2274 emit_dependencies = 1;
2275 suppress_output = 1;
2276 jcf_dependency_init (0);
2280 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2284 emit_dependencies = 1;
2285 jcf_dependency_init (1);
2289 emit_dependencies = 1;
2290 jcf_dependency_init (0);
2301 fprintf (stderr, "gcjh: no classes specified\n");
2305 jcf_path_seal (verbose);
2307 if (output_file && emit_dependencies)
2309 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2313 for (argi = optind; argi < argc; argi++)
2315 char *classname = argv[argi];
2316 char *current_output_file;
2317 const char *classfile_name;
2320 fprintf (stderr, "Processing %s\n", classname);
2322 jcf_dependency_reset ();
2323 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2324 if (classfile_name == NULL)
2326 fprintf (stderr, "%s: no such class\n", classname);
2330 fprintf (stderr, "Found in %s\n", classfile_name);
2333 if (strcmp (output_file, "-") == 0)
2335 else if (out == NULL)
2337 out = fopen (output_file, "w");
2341 perror (output_file);
2344 current_output_file = output_file;
2348 int dir_len = strlen (output_directory);
2349 int i, classname_length = strlen (classname);
2350 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2351 strcpy (current_output_file, output_directory);
2352 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2353 current_output_file[dir_len++] = '/';
2354 for (i = 0; classname[i] != '\0'; i++)
2356 char ch = classname[i];
2359 if (flag_jni && ch == '/')
2361 current_output_file[dir_len++] = ch;
2363 if (emit_dependencies)
2365 if (suppress_output)
2367 jcf_dependency_set_dep_file ("-");
2372 /* We use `.hd' and not `.d' to avoid clashes with
2373 dependency tracking from straight compilation. */
2374 strcpy (current_output_file + dir_len, ".hd");
2375 jcf_dependency_set_dep_file (current_output_file);
2378 strcpy (current_output_file + dir_len,
2379 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2380 jcf_dependency_set_target (current_output_file);
2381 if (! suppress_output)
2383 out = fopen (current_output_file, "w");
2386 perror (current_output_file);
2391 process_file (&jcf, out);
2393 if (current_output_file != output_file)
2394 free (current_output_file);
2395 jcf_dependency_write ();
2398 if (out != NULL && out != stdout)