1 /* Program to write C++-suitable header files from a Java(TM) .class
2 file. This is similar to SUN's javah.
4 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002 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"
42 /* The output file. */
45 /* Nonzero on failure. */
46 static int found_error = 0;
48 /* Nonzero if we're generating JNI output. */
49 static int flag_jni = 0;
51 /* When non zero, warn when source file is newer than matching class
55 /* Directory to place resulting files in. Set by -d option. */
56 const char *output_directory = "";
58 /* Directory to place temporary file. Set by -td option. Currently unused. */
59 const char *temp_directory = "/tmp";
61 /* Number of friend functions we have to declare. */
62 static int friend_count;
64 /* A class can optionally have a `friend' function declared. If
65 non-NULL, this is that function. */
66 static char **friend_specs = NULL;
68 /* Number of lines we are prepending before the class. */
69 static int prepend_count;
71 /* We can prepend extra lines before the class's start. */
72 static char **prepend_specs = NULL;
74 /* Number of lines we are appending at the end of the class. */
77 /* We can append extra lines just before the class's end. */
78 static char **add_specs = NULL;
80 /* Number of lines we are appending after the class. */
81 static int append_count;
83 /* We can append extra lines after the class's end. */
84 static char **append_specs = NULL;
90 struct JCF *current_jcf;
92 /* This holds access information for the last field we examined. They
93 let us generate "private:", "public:", and "protected:" properly.
94 If 0 then we haven't previously examined any field. */
95 static JCF_u2 last_access;
97 /* Pass this macro the flags for a class and for a method. It will
98 return true if the method should be considered `final'. */
99 #define METHOD_IS_FINAL(Class, Method) \
100 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
102 /* Pass this macro the flags for a method. It will return true if the
104 #define METHOD_IS_NATIVE(Method) \
105 ((Method) & ACC_NATIVE)
107 /* We keep a linked list of all method names we have seen. This lets
108 us determine if a method name and a field name are in conflict. */
113 unsigned char *signature;
115 struct method_name *next;
118 /* List of method names we've seen. */
119 static struct method_name *method_name_list;
121 static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
122 static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int));
123 static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int));
124 static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2));
125 static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *,
127 static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int,
129 static void print_full_cxx_name PARAMS ((FILE*, JCF*, int, int, int,
131 static void decompile_method PARAMS ((FILE*, JCF*, int));
132 static void add_class_decl PARAMS ((FILE*, JCF*, JCF_u2));
134 static int java_float_finite PARAMS ((jfloat));
135 static int java_double_finite PARAMS ((jdouble));
136 static void print_name PARAMS ((FILE *, JCF *, int));
137 static void print_base_classname PARAMS ((FILE *, JCF *, int));
138 static int utf8_cmp PARAMS ((const unsigned char *, int, const char *));
139 static char *cxx_keyword_subst PARAMS ((const unsigned char *, int));
140 static void generate_access PARAMS ((FILE *, JCF_u2));
141 static int name_is_method_p PARAMS ((const unsigned char *, int));
142 static char *get_field_name PARAMS ((JCF *, int, JCF_u2));
143 static void print_field_name PARAMS ((FILE *, JCF *, int, JCF_u2));
144 static const unsigned char *super_class_name PARAMS ((JCF *, int *));
145 static void print_include PARAMS ((FILE *, const unsigned char *, int));
146 static int gcjh_streq PARAMS ((const void *p1, const void *p2));
147 static int throwable_p PARAMS ((const unsigned char *signature));
148 static const unsigned char *decode_signature_piece
149 PARAMS ((FILE *, const unsigned char *, const unsigned char *, int *));
150 static void print_class_decls PARAMS ((FILE *, JCF *, int));
151 static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
152 static void help PARAMS ((void)) ATTRIBUTE_NORETURN;
153 static void version PARAMS ((void)) ATTRIBUTE_NORETURN;
154 static int overloaded_jni_method_exists_p PARAMS ((const unsigned char *, int,
156 static void jni_print_char PARAMS ((FILE *, int));
157 static void decompile_return_statement PARAMS ((FILE *, JCF *, int, int, int));
159 JCF_u2 current_field_name;
160 JCF_u2 current_field_value;
161 JCF_u2 current_field_signature;
162 JCF_u2 current_field_flags;
164 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
165 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
166 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
168 /* We pass over fields twice. The first time we just note the types
169 of the fields and then the start of the methods. Then we go back
170 and parse the fields for real. This is ugly. */
171 static int field_pass;
172 /* Likewise we pass over methods twice. The first time we generate
173 class decl information; the second time we generate actual method
175 static int method_pass;
177 #define HANDLE_END_FIELD() \
180 if (out && ! stubs && ! flag_jni) \
181 print_field_info (out, jcf, current_field_name, \
182 current_field_signature, \
183 current_field_flags); \
185 else if (! stubs && ! flag_jni) \
186 add_class_decl (out, jcf, current_field_signature);
188 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
190 static int method_declared = 0;
191 static int method_access = 0;
192 static int method_printed = 0;
193 static int method_synthetic = 0;
194 static int method_signature = 0;
196 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
198 method_synthetic = 0; \
199 method_printed = 0; \
201 method_signature = SIGNATURE; \
202 if (ATTRIBUTE_COUNT) \
203 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
204 (const char *)"Synthetic", 9); \
205 /* If a synthetic methods have been declared, its attribute aren't \
206 worth reading (and triggering side-effects). We skip them an \
207 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
208 jcf_parse_one_method. */ \
209 if (method_synthetic) \
211 skip_attribute (jcf, ATTRIBUTE_COUNT); \
212 ATTRIBUTE_COUNT = 0; \
214 if (method_pass && !method_synthetic) \
217 print_method_info (out, jcf, NAME, SIGNATURE, \
220 else if (!method_synthetic) \
222 print_method_info (NULL, jcf, NAME, SIGNATURE, \
224 if (! stubs && ! flag_jni) \
225 add_class_decl (out, jcf, SIGNATURE); \
229 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
230 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
232 static int decompiled = 0;
233 #define HANDLE_END_METHOD() \
234 if (out && method_printed && !method_synthetic) \
235 fputs (decompiled || stubs ? "\n" : ";\n", out);
237 /* We're going to need {peek,skip}_attribute, enable their definition. */
238 #define NEED_PEEK_ATTRIBUTE
239 #define NEED_SKIP_ATTRIBUTE
241 #include "jcf-reader.c"
243 /* Some useful constants. */
244 #define F_NAN_MASK 0x7f800000
245 #if (1 == HOST_FLOAT_WORDS_BIG_ENDIAN) && ! defined (HOST_WORDS_BIG_ENDIAN)
246 #define D_NAN_MASK 0x000000007ff00000LL
248 #define D_NAN_MASK 0x7ff0000000000000LL
251 /* Return 1 if F is not Inf or NaN. */
253 java_float_finite (f)
259 /* We happen to know that F_NAN_MASK will match all NaN values, and
260 also positive and negative infinity. That's why we only need one
261 test here. See The Java Language Specification, section 20.9. */
262 return (u.i & F_NAN_MASK) != F_NAN_MASK;
265 /* Return 1 if D is not Inf or NaN. */
267 java_double_finite (d)
273 /* Now check for all NaNs. */
274 return (u.l & D_NAN_MASK) != D_NAN_MASK;
277 /* Print a character, appropriately mangled for JNI. */
280 jni_print_char (stream, ch)
285 jcf_print_char (stream, ch);
286 else if (ch == '(' || ch == ')')
291 fputs ("_1", stream);
293 fputs ("_2", stream);
295 fputs ("_3", stream);
298 else if (ISALNUM (ch))
302 /* "Unicode" character. */
303 fprintf (stream, "_0%04x", ch);
307 /* Print a name from the class data. If the index does not point to a
308 string, an error results. */
311 DEFUN(print_name, (stream, jcf, name_index),
312 FILE* stream AND JCF* jcf AND int name_index)
314 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
316 fprintf (stream, "<not a UTF8 constant>");
320 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
321 JPOOL_UTF_LENGTH (jcf, name_index));
324 /* For JNI we must correctly quote each character. */
325 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
326 int length = JPOOL_UTF_LENGTH (jcf, name_index);
327 const unsigned char *limit = str + length;
330 int ch = UTF8_GET (str, limit);
333 fprintf (stream, "\\<invalid>");
336 jni_print_char (stream, ch);
341 /* Print base name of class. The base name is everything after the
345 print_base_classname (stream, jcf, index)
350 int name_index = JPOOL_USHORT1 (jcf, index);
352 const unsigned char *s, *p, *limit;
354 s = JPOOL_UTF_DATA (jcf, name_index);
355 len = JPOOL_UTF_LENGTH (jcf, name_index);
360 int c = UTF8_GET (s, limit);
367 int ch = UTF8_GET (p, limit);
369 fputs ("::", stream);
371 jcf_print_char (stream, ch);
375 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
376 and 1 if STR is "greater" than NAME. */
379 utf8_cmp (str, length, name)
380 const unsigned char *str;
384 const unsigned char *limit = str + length;
387 for (i = 0; name[i]; ++i)
389 int ch = UTF8_GET (str, limit);
394 return str == limit ? 0 : 1;
397 /* This is a sorted list of all C++ keywords. */
399 static const char *const cxx_keywords[] =
508 /* If NAME is the name of a C++ keyword, then return an override name.
509 This is a name that can be used in place of the keyword.
510 Otherwise, return NULL. The return value is malloc()d. */
513 cxx_keyword_subst (str, length)
514 const unsigned char *str;
517 int last = ARRAY_SIZE (cxx_keywords);
519 int mid = (last + first) / 2;
522 for (mid = (last + first) / 2;
524 old = mid, mid = (last + first) / 2)
526 int kwl = strlen (cxx_keywords[mid]);
527 int min_length = kwl > length ? length : kwl;
528 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
534 /* Skip all trailing `$'. */
535 for (i = min_length; i < length && str[i] == '$'; ++i)
537 /* We've only found a match if all the remaining characters
541 char *dup = xmalloc (2 + length - min_length + kwl);
542 strcpy (dup, cxx_keywords[mid]);
543 for (i = kwl; i < length + 1; ++i)
559 /* Generate an access control keyword based on FLAGS. */
562 generate_access (stream, flags)
566 if ((flags & ACC_VISIBILITY) == last_access)
568 last_access = (flags & ACC_VISIBILITY);
573 fputs ("public: // actually package-private\n", stream);
576 fputs ("public:\n", stream);
579 fputs ("private:\n", stream);
582 fputs ("public: // actually protected\n", stream);
586 fprintf (stream, "#error unrecognized visibility %d\n",
587 (flags & ACC_VISIBILITY));
592 /* See if NAME is already the name of a method. */
594 name_is_method_p (name, length)
595 const unsigned char *name;
598 struct method_name *p;
600 for (p = method_name_list; p != NULL; p = p->next)
602 if (p->length == length && ! memcmp (p->name, name, length))
608 /* If there is already a method named NAME, whose signature is not
609 SIGNATURE, then return true. Otherwise return false. */
611 overloaded_jni_method_exists_p (name, length, signature, sig_length)
612 const unsigned char *name;
614 const char *signature;
617 struct method_name *p;
619 for (p = method_name_list; p != NULL; p = p->next)
621 if (p->length == length
622 && ! memcmp (p->name, name, length)
623 && (p->sig_length != sig_length
624 || memcmp (p->signature, signature, sig_length)))
630 /* Get name of a field. This handles renamings due to C++ clash. */
632 get_field_name (jcf, name_index, flags)
637 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
638 int length = JPOOL_UTF_LENGTH (jcf, name_index);
641 if (name_is_method_p (name, length))
643 /* This field name matches a method. So override the name with
644 a dummy name. This is yucky, but it isn't clear what else to
645 do. FIXME: if the field is static, then we'll be in real
647 if ((flags & ACC_STATIC))
649 fprintf (stderr, "static field has same name as method\n");
654 override = xmalloc (length + 3);
655 memcpy (override, name, length);
656 strcpy (override + length, "__");
659 override = cxx_keyword_subst (name, length);
664 /* Print a field name. Convenience function for use with
667 print_field_name (stream, jcf, name_index, flags)
673 char *override = get_field_name (jcf, name_index, flags);
677 fputs (override, stream);
681 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
682 JPOOL_UTF_LENGTH (jcf, name_index));
686 DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
687 FILE *stream AND JCF* jcf
688 AND int name_index AND int sig_index AND JCF_u2 flags)
690 char *override = NULL;
692 generate_access (stream, flags);
693 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
695 fprintf (stream, "<not a UTF8 constant>");
701 if ((flags & ACC_STATIC))
702 fputs ("static ", out);
704 if ((flags & ACC_FINAL))
706 if (current_field_value > 0)
711 switch (JPOOL_TAG (jcf, current_field_value))
713 case CONSTANT_Integer:
716 int most_negative = 0;
717 fputs ("const jint ", out);
718 print_field_name (out, jcf, name_index, 0);
720 num = JPOOL_INT (jcf, current_field_value);
721 /* We single out the most negative number to print
722 specially. This avoids later warnings from g++. */
723 if (num == (jint) 0x80000000)
728 format_int (buffer, (jlong) num, 10);
729 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
735 int most_negative = 0;
736 fputs ("const jlong ", out);
737 print_field_name (out, jcf, name_index, 0);
739 num = JPOOL_LONG (jcf, current_field_value);
740 /* We single out the most negative number to print
741 specially.. This avoids later warnings from g++. */
742 if (num == (jlong) 0x8000000000000000LL)
747 format_int (buffer, num, 10);
748 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
753 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
754 fputs ("const jfloat ", out);
755 print_field_name (out, jcf, name_index, 0);
756 if (! java_float_finite (fnum))
759 fprintf (out, " = %.10g;\n", fnum);
762 case CONSTANT_Double:
764 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
765 fputs ("const jdouble ", out);
766 print_field_name (out, jcf, name_index, 0);
767 if (! java_double_finite (dnum))
770 fprintf (out, " = %.17g;\n", dnum);
774 /* We can't print this as a constant, but we can still
775 print something sensible. */
785 override = get_field_name (jcf, name_index, flags);
786 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
795 DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
796 FILE *stream AND JCF* jcf
797 AND int name_index AND int sig_index AND JCF_u2 flags)
799 const unsigned char *str;
800 int length, is_init = 0;
801 char *override = NULL;
804 method_access = flags;
805 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
806 fprintf (stream, "<not a UTF8 constant>");
807 str = JPOOL_UTF_DATA (jcf, name_index);
808 length = JPOOL_UTF_LENGTH (jcf, name_index);
812 /* Ignore the internally generated method <clinit>. However,
813 treat <init> as a constructor. */
814 if (! utf8_cmp (str, length, "<init>"))
816 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
817 && ! (flags & ACC_STATIC))
819 /* FIXME: i18n bug here. Order of prints should not be
821 fprintf (stderr, "ignored method `");
822 jcf_print_utf8 (stderr, str, length);
823 fprintf (stderr, "' marked virtual\n");
831 /* During the first method pass, build a list of method names. This will
832 be used to determine if field names conflict with method names. */
835 struct method_name *nn;
837 nn = (struct method_name *) xmalloc (sizeof (struct method_name));
838 nn->name = (char *) xmalloc (length);
839 memcpy (nn->name, str, length);
841 nn->next = method_name_list;
842 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
843 nn->signature = (char *) xmalloc (nn->sig_length);
844 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
846 method_name_list = nn;
848 /* The rest of this function doesn't matter. */
852 /* We don't worry about overrides in JNI mode. */
855 /* We can't generate a method whose name is a C++ reserved word.
856 We can't just ignore the function, because that will cause
857 incorrect code to be generated if the function is virtual
858 (not only for calls to this function for for other functions
859 after it in the vtbl). So we give it a dummy name instead. */
860 override = cxx_keyword_subst (str, length);
863 if (! stubs && ! flag_jni)
867 generate_access (stream, flags);
870 if ((flags & ACC_STATIC))
871 fputs ("static ", out);
872 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
874 /* Don't print `virtual' if we have a constructor. */
876 fputs ("virtual ", out);
878 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
880 if ((flags & ACC_ABSTRACT))
887 if (METHOD_IS_NATIVE (flags))
890 print_stub_or_jni (out, jcf, name_index, sig_index,
891 is_init, override, flags);
899 /* A helper for the decompiler which prints a `return' statement where
900 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
901 identical, we emit a cast. We do this because the C++ compiler
902 doesn't know that a reference can be cast to the type of an
903 interface it implements. METHODTYPE is the index of the method's
904 signature. NAMEINDEX is the index of the field name; -1 for
905 `this'. OBJECTTYPE is the index of the object's type. */
907 decompile_return_statement (out, jcf, methodtype, nameindex, objecttype)
910 int methodtype, nameindex, objecttype;
913 int obj_name_len, method_name_len;
914 const unsigned char *obj_data, *method_data;
916 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
917 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
919 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
920 method_data = JPOOL_UTF_DATA (jcf, methodtype);
922 /* Skip forward to return type part of method. */
923 while (*method_data != ')')
932 /* If we see an `L', skip it and the trailing `;'. */
933 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
936 method_name_len -= 2;
938 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
944 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
945 need a cast. Right now there is no way to determine if this is
947 if (method_name_len != obj_name_len)
952 for (i = 0; i < method_name_len; ++i)
954 if (method_data[i] != obj_data[i])
962 fputs (" { return ", out);
967 const unsigned char *limit;
969 fputs ("reinterpret_cast<", out);
971 while (*method_data == '[')
976 fputs ("JArray<", out);
979 /* Leading space to avoid C++ digraphs. */
982 /* If we see an `L', skip it and the trailing `;'. Only do this
983 if we've seen an array specification. If we don't have an
984 array then the `L' was stripped earlier. */
985 if (array_depth && method_data[0] == 'L'
986 && method_data[method_name_len - 1] == ';')
989 method_name_len -= 2;
992 limit = method_data + method_name_len;
993 while (method_data < limit)
995 int ch = UTF8_GET (method_data, limit);
999 jcf_print_char (out, ch);
1003 /* Close each array. */
1004 while (array_depth > 0)
1010 /* Close the cast. */
1014 if (nameindex == -1)
1015 fputs ("this", out);
1017 print_field_name (out, jcf, nameindex, 0);
1026 /* Try to decompile a method body. Right now we just try to handle a
1027 simple case that we can do. Expand as desired. */
1029 decompile_method (out, jcf, code_len)
1034 const unsigned char *codes = jcf->read_ptr;
1036 uint16 name_and_type, name;
1038 /* If the method is synchronized, don't touch it. */
1039 if ((method_access & ACC_SYNCHRONIZED))
1043 && codes[0] == OPCODE_aload_0
1044 && codes[1] == OPCODE_getfield
1045 && (codes[4] == OPCODE_areturn
1046 || codes[4] == OPCODE_dreturn
1047 || codes[4] == OPCODE_freturn
1048 || codes[4] == OPCODE_ireturn
1049 || codes[4] == OPCODE_lreturn))
1051 /* Found code like `return FIELD'. */
1052 index = (codes[2] << 8) | codes[3];
1053 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1054 name_and_type = JPOOL_USHORT2 (jcf, index);
1055 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1056 name = JPOOL_USHORT1 (jcf, name_and_type);
1057 if (codes[4] == OPCODE_areturn)
1058 decompile_return_statement (out, jcf, method_signature,
1059 name, JPOOL_USHORT2 (jcf, name_and_type));
1062 fputs (" { return ", out);
1064 print_field_name (out, jcf, name, 0);
1069 else if (code_len == 2
1070 && codes[0] == OPCODE_aload_0
1071 && codes[1] == OPCODE_areturn
1072 /* We're going to generate `return this'. This only makes
1073 sense for non-static methods. */
1074 && ! (method_access & ACC_STATIC))
1076 decompile_return_statement (out, jcf, method_signature, -1,
1077 JPOOL_USHORT1 (jcf, jcf->this_class));
1080 else if (code_len == 1 && codes[0] == OPCODE_return)
1082 /* Found plain `return'. */
1083 fputs (" { }", out);
1086 else if (code_len == 2
1087 && codes[0] == OPCODE_aconst_null
1088 && codes[1] == OPCODE_areturn)
1090 /* Found `return null'. We don't want to depend on NULL being
1092 fputs (" { return 0; }", out);
1097 /* Like strcmp, but invert the return result for the hash table. This
1098 should probably be in hashtab.c to complement the existing string
1102 const void *p1, *p2;
1104 return ! strcmp ((char *) p1, (char *) p2);
1107 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1108 or 0 if not. CLNAME may be extracted from a signature, and can be
1109 terminated with either `;' or NULL. */
1111 throwable_p (clname)
1112 const unsigned char *clname;
1115 unsigned char *current;
1119 /* We keep two hash tables of class names. In one we list all the
1120 classes which are subclasses of Throwable. In the other we will
1121 all other classes. We keep two tables to make the code a bit
1122 simpler; we don't have to have a structure mapping class name to
1123 a `throwable?' bit. */
1124 static htab_t throw_hash;
1125 static htab_t non_throw_hash;
1126 static int init_done = 0;
1131 const unsigned char *str;
1133 /* Self-initializing. The cost of this really doesn't matter.
1134 We also don't care about freeing these, either. */
1135 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1137 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1140 /* Make sure the root classes show up in the tables. */
1141 str = xstrdup ("java.lang.Throwable");
1142 slot = htab_find_slot (throw_hash, str, INSERT);
1145 str = xstrdup ("java.lang.Object");
1146 slot = htab_find_slot (non_throw_hash, str, INSERT);
1152 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1154 current = (unsigned char *) ALLOC (length);
1155 for (i = 0; i < length; ++i)
1156 current[i] = clname[i] == '/' ? '.' : clname[i];
1157 current[length] = '\0';
1159 /* We don't compute the hash slot here because the table might be
1160 modified by the recursion. In that case the slot could be
1162 if (htab_find (throw_hash, current))
1164 else if (htab_find (non_throw_hash, current))
1170 unsigned char *super, *tmp;
1171 int super_length = -1;
1172 const char *classfile_name = find_class (current, strlen (current),
1175 if (! classfile_name)
1177 fprintf (stderr, "couldn't find class %s\n", current);
1181 if (jcf_parse_preamble (&jcf) != 0
1182 || jcf_parse_constant_pool (&jcf) != 0
1183 || verify_constant_pool (&jcf) > 0)
1185 fprintf (stderr, "parse error while reading %s\n", classfile_name);
1189 jcf_parse_class (&jcf);
1191 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1192 super = (unsigned char *) ALLOC (super_length + 1);
1193 memcpy (super, tmp, super_length);
1194 super[super_length] = '\0';
1196 result = throwable_p (super);
1197 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1208 /* Print one piece of a signature. Returns pointer to next parseable
1209 character on success, NULL on error. */
1210 static const unsigned char *
1211 decode_signature_piece (stream, signature, limit, need_space)
1213 const unsigned char *signature, *limit;
1217 int array_depth = 0;
1219 switch (signature[0])
1222 /* More spaghetti. */
1225 for (signature++; (signature < limit
1226 && ISDIGIT (*signature)); signature++)
1231 ctype = "jbyteArray";
1234 ctype = "jcharArray";
1237 ctype = "jdoubleArray";
1240 ctype = "jfloatArray";
1243 ctype = "jintArray";
1246 ctype = "jshortArray";
1249 ctype = "jlongArray";
1252 ctype = "jbooleanArray";
1255 /* We have a nested array. */
1258 fputs ("JArray<", stream);
1262 /* We have to generate a reference to JArray here, so that
1263 our output matches what the compiler does. */
1265 /* Space between `<' and `:' to avoid C++ digraphs. */
1267 fputs ("JArray< ::", stream);
1268 while (signature < limit && *signature != ';')
1270 int ch = UTF8_GET (signature, limit);
1274 fputs ("::", stream);
1276 jcf_print_char (stream, ch);
1280 fputs (" *> *", stream);
1285 /* Unparseable signature. */
1289 /* If the previous iterations left us with something to print,
1290 print it. For JNI, we always print `jobjectArray' in the
1292 if (flag_jni && ctype == NULL)
1294 ctype = "jobjectArray";
1297 /* The `printit' case will advance SIGNATURE for us. If we
1298 don't go there, we must advance past the `;' ourselves. */
1306 /* This shouldn't happen. */
1309 case 'B': ctype = "jbyte"; goto printit;
1310 case 'C': ctype = "jchar"; goto printit;
1311 case 'D': ctype = "jdouble"; goto printit;
1312 case 'F': ctype = "jfloat"; goto printit;
1313 case 'I': ctype = "jint"; goto printit;
1314 case 'J': ctype = "jlong"; goto printit;
1315 case 'S': ctype = "jshort"; goto printit;
1316 case 'Z': ctype = "jboolean"; goto printit;
1317 case 'V': ctype = "void"; goto printit;
1321 /* We know about certain types and special-case their names. */
1322 if (! strncmp (signature, "Ljava/lang/String;",
1323 sizeof ("Ljava/lang/String;") -1))
1325 else if (! strncmp (signature, "Ljava/lang/Class;",
1326 sizeof ("Ljava/lang/Class;") - 1))
1328 /* Skip leading 'L' for throwable_p call. */
1329 else if (throwable_p (signature + 1))
1330 ctype = "jthrowable";
1334 while (*signature && *signature != ';')
1339 /* Print a leading "::" so we look in the right namespace. */
1340 fputs ("::", stream);
1342 while (*signature && *signature != ';')
1344 int ch = UTF8_GET (signature, limit);
1346 fputs ("::", stream);
1348 jcf_print_char (stream, ch);
1350 fputs (" *", stream);
1351 if (*signature == ';')
1357 jni_print_char (stream, *signature++);
1362 fputs (ctype, stream);
1368 while (array_depth-- > 0)
1369 fputs ("> *", stream);
1376 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
1377 name_override, flags),
1378 FILE* stream AND JCF* jcf
1379 AND int name_index AND int signature_index
1380 AND int is_init AND const char *name_override AND int flags)
1382 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1384 fprintf (stream, "<not a UTF8 constant>");
1389 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1390 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1391 register const unsigned char *str = str0;
1392 const unsigned char *limit = str + length;
1394 int is_method = str[0] == '(';
1395 const unsigned char *next;
1397 /* If printing a method, skip to the return signature and print
1398 that first. However, there is no return value if this is a
1400 if (is_method && ! is_init)
1410 /* If printing a field or an ordinary method, then print the
1411 "return value" now. */
1412 if (! is_method || ! is_init)
1414 next = decode_signature_piece (stream, str, limit, &need_space);
1417 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1423 /* Now print the name of the thing. */
1425 fputs (" ", stream);
1426 print_full_cxx_name (stream, jcf, name_index,
1427 signature_index, is_init, name_override,
1432 /* Print the unqualified method name followed by the signature. */
1434 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index,
1435 is_init, name_override, flags),
1436 FILE* stream AND JCF* jcf
1437 AND int name_index AND int signature_index AND int is_init
1438 AND const char *name_override AND int flags)
1440 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1441 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1442 register const unsigned char *str = str0;
1443 const unsigned char *limit = str + length;
1445 int is_method = str[0] == '(';
1446 const unsigned char *next;
1449 fputs (name_override, stream);
1450 else if (name_index)
1452 /* Declare constructors specially. */
1454 print_base_classname (stream, jcf, jcf->this_class);
1456 print_name (stream, jcf, name_index);
1461 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1462 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1463 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1464 JPOOL_UTF_LENGTH (jcf, name_index),
1465 signature, sig_len))
1467 /* If this method is overloaded by another native method,
1468 then include the argument information in the mangled
1470 unsigned char *limit = signature + sig_len;
1471 fputs ("__", stream);
1472 while (signature < limit)
1474 int ch = UTF8_GET (signature, limit);
1475 jni_print_char (stream, ch);
1487 /* Have a method or a constructor. Print signature pieces
1489 fputs (" (", stream);
1493 /* In JNI mode, add extra arguments. */
1496 /* FIXME: it would be nice to know if we are printing a decl
1497 or a definition, and only print `env' for the latter. */
1498 fputs ("JNIEnv *env", stream);
1500 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1503 fputs (", ", stream);
1506 while (str < limit && *str != ')')
1508 next = decode_signature_piece (stream, str, limit, &need_space);
1511 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1516 if (next < limit && *next != ')')
1517 fputs (", ", stream);
1521 fputs (")", stream);
1525 /* This is a helper for print_stub_or_jni. */
1527 DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index,
1528 is_init, name_override, flags),
1529 FILE *stream AND JCF *jcf
1530 AND int name_index AND int signature_index
1531 AND int is_init AND const char *name_override AND int flags)
1533 const char *const prefix = flag_jni ? "Java_" : "";
1534 print_cxx_classname (stream, prefix, jcf, jcf->this_class);
1535 fputs (flag_jni ? "_" : "::", stream);
1536 print_full_cxx_name (stream, jcf, name_index,
1537 signature_index, is_init, name_override,
1542 DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init,
1543 name_override, flags),
1544 FILE* stream AND JCF* jcf
1545 AND int name_index AND int signature_index
1546 AND int is_init AND const char *name_override AND int flags)
1548 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1550 fprintf (stream, "<not a UTF8 constant>");
1555 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1556 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1557 register const unsigned char *str = str0;
1558 const unsigned char *limit = str + length;
1560 int is_method = str[0] == '(';
1561 const unsigned char *next;
1563 /* Don't print fields in the JNI case. */
1564 if (! is_method && flag_jni)
1567 if (flag_jni && ! stubs)
1568 fputs ("extern ", stream);
1570 /* If printing a method, skip to the return signature and print
1571 that first. However, there is no return value if this is a
1573 if (is_method && ! is_init)
1583 /* If printing a field or an ordinary method, then print the
1584 "return value" now. Note that a constructor can't be native,
1585 so we don't bother checking this in the JNI case. */
1586 if (! is_method || ! is_init)
1588 next = decode_signature_piece (stream, str, limit, &need_space);
1591 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1597 /* When printing a JNI header we need to respect the space. In
1598 other cases we're just going to insert a newline anyway. */
1599 fputs (need_space && ! stubs ? " " : "\n", stream);
1601 /* Now print the name of the thing. */
1602 print_name_for_stub_or_jni (stream, jcf, name_index,
1603 signature_index, is_init, name_override,
1606 /* Print the body. */
1610 fputs ("\n{\n (*env)->FatalError (\"", stream);
1612 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1613 print_name_for_stub_or_jni (stream, jcf, name_index,
1614 signature_index, is_init,
1617 fprintf (stream, " not implemented\")%s;\n}\n\n",
1618 flag_jni ? "" : ")");
1624 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
1625 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
1627 int name_index = JPOOL_USHORT1 (jcf, index);
1628 fputs (prefix, stream);
1629 jcf_print_utf8_replace (out,
1630 JPOOL_UTF_DATA (jcf, name_index),
1631 JPOOL_UTF_LENGTH (jcf, name_index),
1635 /* Print PREFIX, then a class name in C++ format. If the name refers
1636 to an array, ignore it and don't print PREFIX. Returns 1 if
1637 something was printed, 0 otherwise. */
1639 print_cxx_classname (stream, prefix, jcf, index)
1645 int name_index = JPOOL_USHORT1 (jcf, index);
1647 const unsigned char *s, *p, *limit;
1649 s = JPOOL_UTF_DATA (jcf, name_index);
1650 len = JPOOL_UTF_LENGTH (jcf, name_index);
1653 /* Explicitly omit arrays here. */
1655 c = UTF8_GET (p, limit);
1659 fputs (prefix, stream);
1661 /* Print a leading "::" so we look in the right namespace. */
1662 if (! flag_jni && ! stubs)
1663 fputs ("::", stream);
1667 c = UTF8_GET (s, limit);
1669 fputs (flag_jni ? "_" : "::", stream);
1671 jni_print_char (stream, c);
1677 int written_class_count = 0;
1679 /* Return name of superclass. If LEN is not NULL, fill it with length
1681 static const unsigned char *
1682 super_class_name (derived_jcf, len)
1686 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1687 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1688 const unsigned char *supername =
1689 JPOOL_UTF_DATA (derived_jcf, supername_index);
1692 *len = supername_length;
1699 /* We keep track of all the `#include's we generate, so we can avoid
1704 struct include *next;
1707 /* List of all includes. */
1708 static struct include *all_includes = NULL;
1710 /* Generate a #include. */
1712 print_include (out, utf8, len)
1714 const unsigned char *utf8;
1717 struct include *incl;
1723 len = strlen (utf8);
1725 for (incl = all_includes; incl; incl = incl->next)
1727 /* We check the length because we might have a proper prefix. */
1728 if (len == (int) strlen (incl->name)
1729 && ! strncmp (incl->name, utf8, len))
1733 incl = (struct include *) xmalloc (sizeof (struct include));
1734 incl->name = xmalloc (len + 1);
1735 strncpy (incl->name, utf8, len);
1736 incl->name[len] = '\0';
1737 incl->next = all_includes;
1738 all_includes = incl;
1740 fputs ("#include <", out);
1741 jcf_print_utf8_replace (out, utf8, len,
1743 flag_jni ? '_' : '/');
1744 fputs (".h>\n", out);
1749 /* This is used to represent part of a package or class name. */
1752 /* The text of this part of the name. */
1754 /* True if this represents a class. */
1756 /* Linked list of all classes and packages inside this one. */
1757 struct namelet *subnamelets;
1758 /* Pointer to next sibling. */
1759 struct namelet *next;
1762 static void add_namelet PARAMS ((const unsigned char *,
1763 const unsigned char *, struct namelet *));
1764 static void print_namelet PARAMS ((FILE *, struct namelet *, int));
1766 /* The special root namelet. */
1767 static struct namelet root =
1775 /* This extracts the next name segment from the full UTF-8 encoded
1776 package or class name and links it into the tree. It does this
1779 add_namelet (name, name_limit, parent)
1780 const unsigned char *name, *name_limit;
1781 struct namelet *parent;
1783 const unsigned char *p;
1784 struct namelet *n = NULL, *np;
1786 /* We want to skip the standard namespaces that we assume the
1787 runtime already knows about. We only do this at the top level,
1788 though, hence the check for `root'. */
1789 if (parent == &root)
1791 #define JAVALANG "java/lang/"
1792 #define JAVAIO "java/io/"
1793 #define JAVAUTIL "java/util/"
1794 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1795 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1796 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1797 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1798 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1799 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1803 for (p = name; p < name_limit && *p != '/'; ++p)
1806 /* Search for this name beneath the PARENT node. */
1807 for (np = parent->subnamelets; np != NULL; np = np->next)
1809 /* We check the length because we might have a proper prefix. */
1810 if ((int) strlen (np->name) == p - name &&
1811 ! strncmp (name, np->name, p - name))
1820 n = (struct namelet *) xmalloc (sizeof (struct namelet));
1821 n->name = xmalloc (p - name + 1);
1822 strncpy (n->name, name, p - name);
1823 n->name[p - name] = '\0';
1824 n->is_class = (p == name_limit);
1825 n->subnamelets = NULL;
1826 n->next = parent->subnamelets;
1827 parent->subnamelets = n;
1830 /* We recurse if there is more text, and if the trailing piece does
1831 not represent an inner class. */
1833 add_namelet (p + 1, name_limit, n);
1836 /* Print a single namelet. Destroys namelets while printing. */
1838 print_namelet (out, name, depth)
1840 struct namelet *name;
1848 for (i = 0; i < depth; ++i)
1850 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1852 if (name->is_class && name->subnamelets == NULL)
1858 for (i = 0; i < depth; ++i)
1864 c = name->subnamelets;
1867 struct namelet *next = c->next;
1868 print_namelet (out, c, depth + 2);
1871 name->subnamelets = NULL;
1877 for (i = 0; i < depth; ++i)
1880 /* Only print a `;' when printing a class. C++ is evil. */
1890 /* This is called to add some classes to the list of classes for which
1891 we need decls. The signature argument can be a function
1894 add_class_decl (out, jcf, signature)
1899 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1900 int len = JPOOL_UTF_LENGTH (jcf, signature);
1903 for (i = 0; i < len; ++i)
1907 /* If we see an array, then we include the array header. */
1910 print_include (out, "gcj/array", -1);
1914 /* We're looking for `L<stuff>;' -- everything else is
1919 for (start = ++i; i < len && s[i] != ';'; ++i)
1922 add_namelet (&s[start], &s[i], &root);
1926 /* Print declarations for all classes required by this class. Any
1927 class or package in the `java' package is assumed to be handled
1928 statically in libjava; we don't generate declarations for these.
1929 This makes the generated headers a bit easier to read. */
1931 print_class_decls (out, jcf, self)
1936 /* Make sure to always add the current class to the list of things
1937 that should be declared. */
1938 int name_index = JPOOL_USHORT1 (jcf, self);
1940 const unsigned char *s;
1942 s = JPOOL_UTF_DATA (jcf, name_index);
1943 len = JPOOL_UTF_LENGTH (jcf, name_index);
1944 add_namelet (s, s + len, &root);
1946 if (root.subnamelets)
1948 fputs ("extern \"Java\"\n{\n", out);
1949 /* We use an initial offset of 0 because the root namelet
1950 doesn't cause anything to print. */
1951 print_namelet (out, &root, 0);
1952 fputs ("};\n\n", out);
1959 DEFUN(process_file, (jcf, out),
1960 JCF *jcf AND FILE *out)
1963 uint32 field_start, method_end, method_start;
1969 if (jcf_parse_preamble (jcf) != 0)
1971 fprintf (stderr, "Not a valid Java .class file.\n");
1976 /* Parse and possibly print constant pool */
1977 code = jcf_parse_constant_pool (jcf);
1980 fprintf (stderr, "error while parsing constant pool\n");
1984 code = verify_constant_pool (jcf);
1987 fprintf (stderr, "error in constant pool entry #%d\n", code);
1992 jcf_parse_class (jcf);
1994 if (written_class_count++ == 0 && out)
1996 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
2011 mode = " -*- c++ -*-";
2017 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2018 cstart, mode, cend);
2021 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2023 %s This file is intended to give you a head start on implementing native\n\
2024 %s methods using %s.\n\
2025 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2026 %s overwrite any edits you have made to this file.%s\n\n",
2027 cstart, jflag, mode,
2043 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2044 fprintf (out, "__\n");
2046 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2047 fprintf (out, "__\n\n");
2051 fprintf (out, "#include <jni.h>\n\n");
2052 fprintf (out, "#ifdef __cplusplus\n");
2053 fprintf (out, "extern \"C\"\n");
2054 fprintf (out, "{\n");
2055 fprintf (out, "#endif\n");
2059 /* We do this to ensure that inline methods won't be
2060 `outlined' by g++. This works as long as method and
2061 fields are not added by the user. */
2062 fprintf (out, "#pragma interface\n");
2064 if (jcf->super_class)
2067 const unsigned char *supername =
2068 super_class_name (jcf, &super_length);
2071 print_include (out, supername, super_length);
2077 /* Strip off the ".class" portion of the name when printing
2078 the include file name. */
2080 int i, len = strlen (jcf->classname);
2081 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2083 /* Turn the class name into a file name. */
2084 name = xmalloc (len + 1);
2085 for (i = 0; i < len; ++i)
2086 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2088 print_include (out, name, len);
2093 print_include (out, "gcj/cni", -1);
2094 print_include (out, "java/lang/UnsupportedOperationException",
2100 /* We want to parse the methods first. But we need to find where
2101 they start. So first we skip the fields, then parse the methods.
2102 Then we parse the fields and skip the methods. This is ugly, but
2103 not too bad since we need two full passes to get class decl
2104 information anyway. */
2106 field_start = JCF_TELL (jcf);
2107 jcf_parse_fields (jcf);
2109 method_start = JCF_TELL (jcf);
2111 jcf_parse_methods (jcf);
2116 if (out && ! flag_jni)
2119 print_class_decls (out, jcf, jcf->this_class);
2121 for (i = 0; i < prepend_count; ++i)
2122 fprintf (out, "%s\n", prepend_specs[i]);
2123 if (prepend_count > 0)
2128 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
2130 fprintf (stderr, "class is of array type\n");
2134 if (jcf->super_class)
2136 if (! print_cxx_classname (out, " : public ",
2137 jcf, jcf->super_class))
2139 fprintf (stderr, "base class is of array type\n");
2145 fputs ("\n{\n", out);
2149 /* Now go back for second pass over methods and fields. */
2150 JCF_SEEK (jcf, method_start);
2152 jcf_parse_methods (jcf);
2153 method_end = JCF_TELL (jcf);
2156 JCF_SEEK (jcf, field_start);
2157 jcf_parse_fields (jcf);
2158 JCF_SEEK (jcf, method_end);
2160 jcf_parse_final_attributes (jcf);
2166 fprintf (out, "\n#ifdef __cplusplus\n");
2167 fprintf (out, "}\n");
2168 fprintf (out, "#endif\n");
2172 /* Generate friend decl if we still must. */
2173 for (i = 0; i < friend_count; ++i)
2174 fprintf (out, " friend %s\n", friend_specs[i]);
2176 /* Generate extra declarations. */
2179 for (i = 0; i < add_count; ++i)
2180 fprintf (out, " %s\n", add_specs[i]);
2182 /* Generate an entry for the class object. */
2183 generate_access (out, ACC_PUBLIC);
2184 fprintf (out, "\n static ::java::lang::Class class$;\n");
2188 if (jcf->access_flags & ACC_INTERFACE)
2189 fputs (" __attribute__ ((java_interface))", out);
2193 if (append_count > 0)
2195 for (i = 0; i < append_count; ++i)
2196 fprintf (out, "%s\n", append_specs[i]);
2199 print_mangled_classname (out, jcf,
2200 "\n#endif /* __", jcf->this_class);
2201 fprintf (out, "__ */\n");
2207 /* This is used to mark options with no short value. */
2208 #define LONG_OPT(Num) ((Num) + 128)
2210 #define OPT_classpath LONG_OPT (0)
2211 #define OPT_CLASSPATH OPT_classpath
2212 #define OPT_bootclasspath LONG_OPT (1)
2213 #define OPT_extdirs LONG_OPT (2)
2214 #define OPT_HELP LONG_OPT (3)
2215 #define OPT_TEMP LONG_OPT (4)
2216 #define OPT_VERSION LONG_OPT (5)
2217 #define OPT_PREPEND LONG_OPT (6)
2218 #define OPT_FRIEND LONG_OPT (7)
2219 #define OPT_ADD LONG_OPT (8)
2220 #define OPT_APPEND LONG_OPT (9)
2221 #define OPT_M LONG_OPT (10)
2222 #define OPT_MM LONG_OPT (11)
2223 #define OPT_MG LONG_OPT (12)
2224 #define OPT_MD LONG_OPT (13)
2225 #define OPT_MMD LONG_OPT (14)
2227 static const struct option options[] =
2229 { "classpath", required_argument, NULL, OPT_classpath },
2230 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2231 { "extdirs", required_argument, NULL, OPT_extdirs },
2232 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2233 { "help", no_argument, NULL, OPT_HELP },
2234 { "stubs", no_argument, &stubs, 1 },
2235 { "td", required_argument, NULL, OPT_TEMP },
2236 { "verbose", no_argument, NULL, 'v' },
2237 { "version", no_argument, NULL, OPT_VERSION },
2238 { "prepend", required_argument, NULL, OPT_PREPEND },
2239 { "friend", required_argument, NULL, OPT_FRIEND },
2240 { "add", required_argument, NULL, OPT_ADD },
2241 { "append", required_argument, NULL, OPT_APPEND },
2242 { "M", no_argument, NULL, OPT_M },
2243 { "MM", no_argument, NULL, OPT_MM },
2244 { "MG", no_argument, NULL, OPT_MG },
2245 { "MD", no_argument, NULL, OPT_MD },
2246 { "MMD", no_argument, NULL, OPT_MMD },
2247 { "jni", no_argument, &flag_jni, 1 },
2248 { NULL, no_argument, NULL, 0 }
2254 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2261 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2262 printf ("Generate C++ header files from .class files\n\n");
2263 printf (" -stubs Generate an implementation stub file\n");
2264 printf (" -jni Generate a JNI header or stub\n");
2266 printf (" -add TEXT Insert TEXT into class body\n");
2267 printf (" -append TEXT Insert TEXT after class declaration\n");
2268 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2269 printf (" -prepend TEXT Insert TEXT before start of class\n");
2271 printf (" --classpath PATH Set path to find .class files\n");
2272 printf (" -IDIR Append directory to class path\n");
2273 printf (" --bootclasspath PATH Override built-in class path\n");
2274 printf (" --extdirs PATH Set extensions directory path\n");
2275 printf (" -d DIRECTORY Set output directory name\n");
2276 printf (" -o FILE Set output file name\n");
2277 printf (" -td DIRECTORY Set temporary directory name\n");
2279 printf (" --help Print this help, then exit\n");
2280 printf (" --version Print version number, then exit\n");
2281 printf (" -v, --verbose Print extra information while running\n");
2283 printf (" -M Print all dependencies to stdout;\n");
2284 printf (" suppress ordinary output\n");
2285 printf (" -MM Print non-system dependencies to stdout;\n");
2286 printf (" suppress ordinary output\n");
2287 printf (" -MD Print all dependencies to stdout\n");
2288 printf (" -MMD Print non-system dependencies to stdout\n");
2289 /* We omit -MG until it is implemented. */
2291 printf ("For bug reporting instructions, please see:\n");
2292 printf ("%s.\n", GCCBUGURL);
2299 printf ("gcjh (GCC) %s\n\n", version_string);
2300 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2301 printf ("This is free software; see the source for copying conditions. There is NO\n");
2302 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2307 DEFUN(main, (argc, argv),
2308 int argc AND char** argv)
2312 char *output_file = NULL;
2313 int emit_dependencies = 0, suppress_output = 0;
2318 fprintf (stderr, "gcjh: no classes specified\n");
2324 /* We use getopt_long_only to allow single `-' long options. For
2325 some of our options this is more natural. */
2326 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2331 /* Already handled. */
2335 output_file = optarg;
2339 output_directory = optarg;
2343 jcf_path_include_arg (optarg);
2351 jcf_path_classpath_arg (optarg);
2354 case OPT_bootclasspath:
2355 jcf_path_bootclasspath_arg (optarg);
2359 jcf_path_extdirs_arg (optarg);
2367 temp_directory = optarg;
2375 if (prepend_count == 0)
2376 prepend_specs = (char**) ALLOC (argc * sizeof (char*));
2377 prepend_specs[prepend_count++] = optarg;
2381 if (friend_count == 0)
2382 friend_specs = (char**) ALLOC (argc * sizeof (char*));
2383 friend_specs[friend_count++] = optarg;
2388 add_specs = (char**) ALLOC (argc * sizeof (char*));
2389 add_specs[add_count++] = optarg;
2393 if (append_count == 0)
2394 append_specs = (char**) ALLOC (argc * sizeof (char*));
2395 append_specs[append_count++] = optarg;
2399 emit_dependencies = 1;
2400 suppress_output = 1;
2401 jcf_dependency_init (1);
2405 emit_dependencies = 1;
2406 suppress_output = 1;
2407 jcf_dependency_init (0);
2411 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2415 emit_dependencies = 1;
2416 jcf_dependency_init (1);
2420 emit_dependencies = 1;
2421 jcf_dependency_init (0);
2432 fprintf (stderr, "gcjh: no classes specified\n");
2436 jcf_path_seal (verbose);
2438 if (output_file && emit_dependencies)
2440 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2444 for (argi = optind; argi < argc; argi++)
2446 char *classname = argv[argi];
2447 char *current_output_file;
2448 const char *classfile_name;
2451 fprintf (stderr, "Processing %s\n", classname);
2453 jcf_dependency_reset ();
2454 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2455 if (classfile_name == NULL)
2457 fprintf (stderr, "%s: no such class\n", classname);
2461 fprintf (stderr, "Found in %s\n", classfile_name);
2464 if (strcmp (output_file, "-") == 0)
2466 else if (out == NULL)
2468 out = fopen (output_file, "w");
2472 perror (output_file);
2475 current_output_file = output_file;
2479 int dir_len = strlen (output_directory);
2480 int i, classname_length = strlen (classname);
2481 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
2482 strcpy (current_output_file, output_directory);
2483 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2484 current_output_file[dir_len++] = '/';
2485 for (i = 0; classname[i] != '\0'; i++)
2487 char ch = classname[i];
2490 if (flag_jni && ch == '/')
2492 current_output_file[dir_len++] = ch;
2494 if (emit_dependencies)
2496 if (suppress_output)
2498 jcf_dependency_set_dep_file ("-");
2503 /* We use `.hd' and not `.d' to avoid clashes with
2504 dependency tracking from straight compilation. */
2505 strcpy (current_output_file + dir_len, ".hd");
2506 jcf_dependency_set_dep_file (current_output_file);
2509 strcpy (current_output_file + dir_len,
2510 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2511 jcf_dependency_set_target (current_output_file);
2512 if (! suppress_output)
2514 out = fopen (current_output_file, "w");
2517 perror (current_output_file);
2522 process_file (&jcf, out);
2524 if (current_output_file != output_file)
2525 free (current_output_file);
2526 jcf_dependency_write ();
2529 if (out != NULL && out != stdout)