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"
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
1069 /* We're going to generate `return this'. This only makes
1070 sense for non-static methods. */
1071 && ! (method_access
& ACC_STATIC
))
1073 decompile_return_statement (out
, jcf
, method_signature
, -1,
1074 JPOOL_USHORT1 (jcf
, jcf
->this_class
));
1077 else if (code_len
== 1 && codes
[0] == OPCODE_return
)
1079 /* Found plain `return'. */
1080 fputs (" { }", out
);
1083 else if (code_len
== 2
1084 && codes
[0] == OPCODE_aconst_null
1085 && codes
[1] == OPCODE_areturn
)
1087 /* Found `return null'. We don't want to depend on NULL being
1089 fputs (" { return 0; }", out
);
1094 /* Print one piece of a signature. Returns pointer to next parseable
1095 character on success, NULL on error. */
1096 static const unsigned char *
1097 decode_signature_piece (stream
, signature
, limit
, need_space
)
1099 const unsigned char *signature
, *limit
;
1103 int array_depth
= 0;
1105 switch (signature
[0])
1108 /* More spaghetti. */
1111 for (signature
++; (signature
< limit
1112 && ISDIGIT (*signature
)); signature
++)
1117 ctype
= "jbyteArray";
1120 ctype
= "jcharArray";
1123 ctype
= "jdoubleArray";
1126 ctype
= "jfloatArray";
1129 ctype
= "jintArray";
1132 ctype
= "jshortArray";
1135 ctype
= "jlongArray";
1138 ctype
= "jbooleanArray";
1141 /* We have a nested array. */
1144 fputs ("JArray<", stream
);
1148 /* We have to generate a reference to JArray here, so that
1149 our output matches what the compiler does. */
1151 /* Space between `<' and `:' to avoid C++ digraphs. */
1153 fputs ("JArray< ::", stream
);
1154 while (signature
< limit
&& *signature
!= ';')
1156 int ch
= UTF8_GET (signature
, limit
);
1160 fputs ("::", stream
);
1162 jcf_print_char (stream
, ch
);
1166 fputs (" *> *", stream
);
1171 /* Unparseable signature. */
1175 /* If the previous iterations left us with something to print,
1176 print it. For JNI, we always print `jobjectArray' in the
1178 if (flag_jni
&& ctype
== NULL
)
1180 ctype
= "jobjectArray";
1183 /* The `printit' case will advance SIGNATURE for us. If we
1184 don't go there, we must advance past the `;' ourselves. */
1192 /* This shouldn't happen. */
1195 case 'B': ctype
= "jbyte"; goto printit
;
1196 case 'C': ctype
= "jchar"; goto printit
;
1197 case 'D': ctype
= "jdouble"; goto printit
;
1198 case 'F': ctype
= "jfloat"; goto printit
;
1199 case 'I': ctype
= "jint"; goto printit
;
1200 case 'J': ctype
= "jlong"; goto printit
;
1201 case 'S': ctype
= "jshort"; goto printit
;
1202 case 'Z': ctype
= "jboolean"; goto printit
;
1203 case 'V': ctype
= "void"; goto printit
;
1207 /* We know about certain types and special-case their
1209 FIXME: something like java.lang.Exception should be
1210 printed as `jthrowable', because it is a subclass. This
1211 means that gcjh must read the entire hierarchy and
1213 if (! strncmp (signature
, "Ljava/lang/String;",
1214 sizeof ("Ljava/lang/String;") -1))
1216 else if (! strncmp (signature
, "Ljava/lang/Class;",
1217 sizeof ("Ljava/lang/Class;") - 1))
1219 else if (! strncmp (signature
, "Ljava/lang/Throwable;",
1220 sizeof ("Ljava/lang/Throwable;") - 1))
1221 ctype
= "jthrowable";
1222 else if (! strncmp (signature
, "Ljava/lang/ref/WeakReference;",
1223 sizeof ("Ljava/lang/ref/WeakReference;") - 1))
1228 while (*signature
&& *signature
!= ';')
1233 /* Print a leading "::" so we look in the right namespace. */
1234 fputs ("::", stream
);
1236 while (*signature
&& *signature
!= ';')
1238 int ch
= UTF8_GET (signature
, limit
);
1240 fputs ("::", stream
);
1242 jcf_print_char (stream
, ch
);
1244 fputs (" *", stream
);
1245 if (*signature
== ';')
1251 jni_print_char (stream
, *signature
++);
1256 fputs (ctype
, stream
);
1262 while (array_depth
-- > 0)
1263 fputs ("> *", stream
);
1270 DEFUN(print_c_decl
, (stream
, jcf
, name_index
, signature_index
, is_init
,
1271 name_override
, flags
),
1272 FILE* stream AND JCF
* jcf
1273 AND
int name_index AND
int signature_index
1274 AND
int is_init AND
const char *name_override AND
int flags
)
1276 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1278 fprintf (stream
, "<not a UTF8 constant>");
1283 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1284 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1285 register const unsigned char *str
= str0
;
1286 const unsigned char *limit
= str
+ length
;
1288 int is_method
= str
[0] == '(';
1289 const unsigned char *next
;
1291 /* If printing a method, skip to the return signature and print
1292 that first. However, there is no return value if this is a
1294 if (is_method
&& ! is_init
)
1304 /* If printing a field or an ordinary method, then print the
1305 "return value" now. */
1306 if (! is_method
|| ! is_init
)
1308 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1311 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1317 /* Now print the name of the thing. */
1319 fputs (" ", stream
);
1320 print_full_cxx_name (stream
, jcf
, name_index
,
1321 signature_index
, is_init
, name_override
,
1326 /* Print the unqualified method name followed by the signature. */
1328 DEFUN(print_full_cxx_name
, (stream
, jcf
, name_index
, signature_index
,
1329 is_init
, name_override
, flags
),
1330 FILE* stream AND JCF
* jcf
1331 AND
int name_index AND
int signature_index AND
int is_init
1332 AND
const char *name_override AND
int flags
)
1334 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1335 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1336 register const unsigned char *str
= str0
;
1337 const unsigned char *limit
= str
+ length
;
1339 int is_method
= str
[0] == '(';
1340 const unsigned char *next
;
1343 fputs (name_override
, stream
);
1344 else if (name_index
)
1346 /* Declare constructors specially. */
1348 print_base_classname (stream
, jcf
, jcf
->this_class
);
1350 print_name (stream
, jcf
, name_index
);
1355 unsigned char *signature
= JPOOL_UTF_DATA (jcf
, signature_index
);
1356 int sig_len
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1357 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf
, name_index
),
1358 JPOOL_UTF_LENGTH (jcf
, name_index
),
1359 signature
, sig_len
))
1361 /* If this method is overloaded by another native method,
1362 then include the argument information in the mangled
1364 unsigned char *limit
= signature
+ sig_len
;
1365 fputs ("__", stream
);
1366 while (signature
< limit
)
1368 int ch
= UTF8_GET (signature
, limit
);
1369 jni_print_char (stream
, ch
);
1381 /* Have a method or a constructor. Print signature pieces
1383 fputs (" (", stream
);
1387 /* In JNI mode, add extra arguments. */
1390 /* FIXME: it would be nice to know if we are printing a decl
1391 or a definition, and only print `env' for the latter. */
1392 fputs ("JNIEnv *env", stream
);
1394 fputs ((flags
& ACC_STATIC
) ? ", jclass" : ", jobject", stream
);
1397 fputs (", ", stream
);
1400 while (str
< limit
&& *str
!= ')')
1402 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1405 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1410 if (next
< limit
&& *next
!= ')')
1411 fputs (", ", stream
);
1415 fputs (")", stream
);
1419 /* This is a helper for print_stub_or_jni. */
1421 DEFUN (print_name_for_stub_or_jni
, (stream
, jcf
, name_index
, signature_index
,
1422 is_init
, name_override
, flags
),
1423 FILE *stream AND JCF
*jcf
1424 AND
int name_index AND
int signature_index
1425 AND
int is_init AND
const char *name_override AND
int flags
)
1427 const char *const prefix
= flag_jni
? "Java_" : "";
1428 print_cxx_classname (stream
, prefix
, jcf
, jcf
->this_class
);
1429 fputs (flag_jni
? "_" : "::", stream
);
1430 print_full_cxx_name (stream
, jcf
, name_index
,
1431 signature_index
, is_init
, name_override
,
1436 DEFUN(print_stub_or_jni
, (stream
, jcf
, name_index
, signature_index
, is_init
,
1437 name_override
, flags
),
1438 FILE* stream AND JCF
* jcf
1439 AND
int name_index AND
int signature_index
1440 AND
int is_init AND
const char *name_override AND
int flags
)
1442 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
1444 fprintf (stream
, "<not a UTF8 constant>");
1449 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
1450 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
1451 register const unsigned char *str
= str0
;
1452 const unsigned char *limit
= str
+ length
;
1454 int is_method
= str
[0] == '(';
1455 const unsigned char *next
;
1457 /* Don't print fields in the JNI case. */
1458 if (! is_method
&& flag_jni
)
1461 if (flag_jni
&& ! stubs
)
1462 fputs ("extern ", stream
);
1464 /* If printing a method, skip to the return signature and print
1465 that first. However, there is no return value if this is a
1467 if (is_method
&& ! is_init
)
1477 /* If printing a field or an ordinary method, then print the
1478 "return value" now. Note that a constructor can't be native,
1479 so we don't bother checking this in the JNI case. */
1480 if (! is_method
|| ! is_init
)
1482 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
1485 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
1491 /* When printing a JNI header we need to respect the space. In
1492 other cases we're just going to insert a newline anyway. */
1493 fputs (need_space
&& ! stubs
? " " : "\n", stream
);
1495 /* Now print the name of the thing. */
1496 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1497 signature_index
, is_init
, name_override
,
1500 /* Print the body. */
1504 fputs ("\n{\n (*env)->FatalError (\"", stream
);
1506 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream
);
1507 print_name_for_stub_or_jni (stream
, jcf
, name_index
,
1508 signature_index
, is_init
,
1511 fprintf (stream
, " not implemented\")%s;\n}\n\n",
1512 flag_jni
? "" : ")");
1518 DEFUN(print_mangled_classname
, (stream
, jcf
, prefix
, index
),
1519 FILE *stream AND JCF
*jcf AND
const char *prefix AND
int index
)
1521 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1522 fputs (prefix
, stream
);
1523 jcf_print_utf8_replace (out
,
1524 JPOOL_UTF_DATA (jcf
, name_index
),
1525 JPOOL_UTF_LENGTH (jcf
, name_index
),
1529 /* Print PREFIX, then a class name in C++ format. If the name refers
1530 to an array, ignore it and don't print PREFIX. Returns 1 if
1531 something was printed, 0 otherwise. */
1533 print_cxx_classname (stream
, prefix
, jcf
, index
)
1539 int name_index
= JPOOL_USHORT1 (jcf
, index
);
1541 const unsigned char *s
, *p
, *limit
;
1543 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1544 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1547 /* Explicitly omit arrays here. */
1549 c
= UTF8_GET (p
, limit
);
1553 fputs (prefix
, stream
);
1555 /* Print a leading "::" so we look in the right namespace. */
1556 if (! flag_jni
&& ! stubs
)
1557 fputs ("::", stream
);
1561 c
= UTF8_GET (s
, limit
);
1563 fputs (flag_jni
? "_" : "::", stream
);
1565 jni_print_char (stream
, c
);
1571 int written_class_count
= 0;
1573 /* Return name of superclass. If LEN is not NULL, fill it with length
1575 static const unsigned char *
1576 super_class_name (derived_jcf
, len
)
1580 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
1581 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
1582 const unsigned char *supername
=
1583 JPOOL_UTF_DATA (derived_jcf
, supername_index
);
1586 *len
= supername_length
;
1593 /* We keep track of all the `#include's we generate, so we can avoid
1598 struct include
*next
;
1601 /* List of all includes. */
1602 static struct include
*all_includes
= NULL
;
1604 /* Generate a #include. */
1606 print_include (out
, utf8
, len
)
1608 const unsigned char *utf8
;
1611 struct include
*incl
;
1617 len
= strlen (utf8
);
1619 for (incl
= all_includes
; incl
; incl
= incl
->next
)
1621 /* We check the length because we might have a proper prefix. */
1622 if (len
== (int) strlen (incl
->name
)
1623 && ! strncmp (incl
->name
, utf8
, len
))
1627 incl
= (struct include
*) xmalloc (sizeof (struct include
));
1628 incl
->name
= xmalloc (len
+ 1);
1629 strncpy (incl
->name
, utf8
, len
);
1630 incl
->name
[len
] = '\0';
1631 incl
->next
= all_includes
;
1632 all_includes
= incl
;
1634 fputs ("#include <", out
);
1635 jcf_print_utf8_replace (out
, utf8
, len
,
1637 flag_jni
? '_' : '/');
1638 fputs (".h>\n", out
);
1643 /* This is used to represent part of a package or class name. */
1646 /* The text of this part of the name. */
1648 /* True if this represents a class. */
1650 /* Linked list of all classes and packages inside this one. */
1651 struct namelet
*subnamelets
;
1652 /* Pointer to next sibling. */
1653 struct namelet
*next
;
1656 static void add_namelet
PARAMS ((const unsigned char *,
1657 const unsigned char *, struct namelet
*));
1658 static void print_namelet
PARAMS ((FILE *, struct namelet
*, int));
1660 /* The special root namelet. */
1661 static struct namelet root
=
1669 /* This extracts the next name segment from the full UTF-8 encoded
1670 package or class name and links it into the tree. It does this
1673 add_namelet (name
, name_limit
, parent
)
1674 const unsigned char *name
, *name_limit
;
1675 struct namelet
*parent
;
1677 const unsigned char *p
;
1678 struct namelet
*n
= NULL
, *np
;
1680 /* We want to skip the standard namespaces that we assume the
1681 runtime already knows about. We only do this at the top level,
1682 though, hence the check for `root'. */
1683 if (parent
== &root
)
1685 #define JAVALANG "java/lang/"
1686 #define JAVAIO "java/io/"
1687 #define JAVAUTIL "java/util/"
1688 if ((name_limit
- name
>= (int) sizeof (JAVALANG
) - 1
1689 && ! strncmp (name
, JAVALANG
, sizeof (JAVALANG
) - 1))
1690 || (name_limit
- name
>= (int) sizeof (JAVAUTIL
) - 1
1691 && ! strncmp (name
, JAVAUTIL
, sizeof (JAVAUTIL
) - 1))
1692 || (name_limit
- name
>= (int) sizeof (JAVAIO
) - 1
1693 && ! strncmp (name
, JAVAIO
, sizeof (JAVAIO
) - 1)))
1697 for (p
= name
; p
< name_limit
&& *p
!= '/'; ++p
)
1700 /* Search for this name beneath the PARENT node. */
1701 for (np
= parent
->subnamelets
; np
!= NULL
; np
= np
->next
)
1703 /* We check the length because we might have a proper prefix. */
1704 if ((int) strlen (np
->name
) == p
- name
&&
1705 ! strncmp (name
, np
->name
, p
- name
))
1714 n
= (struct namelet
*) xmalloc (sizeof (struct namelet
));
1715 n
->name
= xmalloc (p
- name
+ 1);
1716 strncpy (n
->name
, name
, p
- name
);
1717 n
->name
[p
- name
] = '\0';
1718 n
->is_class
= (p
== name_limit
);
1719 n
->subnamelets
= NULL
;
1720 n
->next
= parent
->subnamelets
;
1721 parent
->subnamelets
= n
;
1724 /* We recurse if there is more text, and if the trailing piece does
1725 not represent an inner class. */
1727 add_namelet (p
+ 1, name_limit
, n
);
1730 /* Print a single namelet. Destroys namelets while printing. */
1732 print_namelet (out
, name
, depth
)
1734 struct namelet
*name
;
1742 for (i
= 0; i
< depth
; ++i
)
1744 fprintf (out
, "%s %s", name
->is_class
? "class" : "namespace",
1746 if (name
->is_class
&& name
->subnamelets
== NULL
)
1752 for (i
= 0; i
< depth
; ++i
)
1758 c
= name
->subnamelets
;
1761 struct namelet
*next
= c
->next
;
1762 print_namelet (out
, c
, depth
+ 2);
1765 name
->subnamelets
= NULL
;
1771 for (i
= 0; i
< depth
; ++i
)
1774 /* Only print a `;' when printing a class. C++ is evil. */
1784 /* This is called to add some classes to the list of classes for which
1785 we need decls. The signature argument can be a function
1788 add_class_decl (out
, jcf
, signature
)
1793 const unsigned char *s
= JPOOL_UTF_DATA (jcf
, signature
);
1794 int len
= JPOOL_UTF_LENGTH (jcf
, signature
);
1797 for (i
= 0; i
< len
; ++i
)
1801 /* If we see an array, then we include the array header. */
1804 print_include (out
, "gcj/array", -1);
1808 /* We're looking for `L<stuff>;' -- everything else is
1813 for (start
= ++i
; i
< len
&& s
[i
] != ';'; ++i
)
1816 add_namelet (&s
[start
], &s
[i
], &root
);
1820 /* Print declarations for all classes required by this class. Any
1821 class or package in the `java' package is assumed to be handled
1822 statically in libjava; we don't generate declarations for these.
1823 This makes the generated headers a bit easier to read. */
1825 print_class_decls (out
, jcf
, self
)
1830 /* Make sure to always add the current class to the list of things
1831 that should be declared. */
1832 int name_index
= JPOOL_USHORT1 (jcf
, self
);
1834 const unsigned char *s
;
1836 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1837 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1838 add_namelet (s
, s
+ len
, &root
);
1840 if (root
.subnamelets
)
1842 fputs ("extern \"Java\"\n{\n", out
);
1843 /* We use an initial offset of 0 because the root namelet
1844 doesn't cause anything to print. */
1845 print_namelet (out
, &root
, 0);
1846 fputs ("};\n\n", out
);
1853 DEFUN(process_file
, (jcf
, out
),
1854 JCF
*jcf AND
FILE *out
)
1857 uint32 field_start
, method_end
, method_start
;
1863 if (jcf_parse_preamble (jcf
) != 0)
1865 fprintf (stderr
, "Not a valid Java .class file.\n");
1870 /* Parse and possibly print constant pool */
1871 code
= jcf_parse_constant_pool (jcf
);
1874 fprintf (stderr
, "error while parsing constant pool\n");
1878 code
= verify_constant_pool (jcf
);
1881 fprintf (stderr
, "error in constant pool entry #%d\n", code
);
1886 jcf_parse_class (jcf
);
1888 if (written_class_count
++ == 0 && out
)
1890 const char *cstart
, *cstart2
, *mode
, *cend
, *what
, *jflag
;
1905 mode
= " -*- c++ -*-";
1911 fprintf (out
, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
1912 cstart
, mode
, cend
);
1915 fprintf (out
, "%s This file was created by `gcjh -stubs%s'.%s\n\
1917 %s This file is intended to give you a head start on implementing native\n\
1918 %s methods using %s.\n\
1919 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
1920 %s overwrite any edits you have made to this file.%s\n\n",
1921 cstart
, jflag
, mode
,
1937 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
1938 fprintf (out
, "__\n");
1940 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
1941 fprintf (out
, "__\n\n");
1945 fprintf (out
, "#include <jni.h>\n\n");
1946 fprintf (out
, "#ifdef __cplusplus\n");
1947 fprintf (out
, "extern \"C\"\n");
1948 fprintf (out
, "{\n");
1949 fprintf (out
, "#endif\n");
1953 /* We do this to ensure that inline methods won't be
1954 `outlined' by g++. This works as long as method and
1955 fields are not added by the user. */
1956 fprintf (out
, "#pragma interface\n");
1958 if (jcf
->super_class
)
1961 const unsigned char *supername
=
1962 super_class_name (jcf
, &super_length
);
1965 print_include (out
, supername
, super_length
);
1971 /* Strip off the ".class" portion of the name when printing
1972 the include file name. */
1974 int i
, len
= strlen (jcf
->classname
);
1975 if (len
> 6 && ! strcmp (&jcf
->classname
[len
- 6], ".class"))
1977 /* Turn the class name into a file name. */
1978 name
= xmalloc (len
+ 1);
1979 for (i
= 0; i
< len
; ++i
)
1980 name
[i
] = jcf
->classname
[i
] == '.' ? '/' : jcf
->classname
[i
];
1982 print_include (out
, name
, len
);
1987 print_include (out
, "gcj/cni", -1);
1988 print_include (out
, "java/lang/UnsupportedOperationException",
1994 /* We want to parse the methods first. But we need to find where
1995 they start. So first we skip the fields, then parse the methods.
1996 Then we parse the fields and skip the methods. This is ugly, but
1997 not too bad since we need two full passes to get class decl
1998 information anyway. */
2000 field_start
= JCF_TELL (jcf
);
2001 jcf_parse_fields (jcf
);
2003 method_start
= JCF_TELL (jcf
);
2005 jcf_parse_methods (jcf
);
2010 if (out
&& ! flag_jni
)
2013 print_class_decls (out
, jcf
, jcf
->this_class
);
2015 for (i
= 0; i
< prepend_count
; ++i
)
2016 fprintf (out
, "%s\n", prepend_specs
[i
]);
2017 if (prepend_count
> 0)
2022 if (! print_cxx_classname (out
, "class ", jcf
, jcf
->this_class
))
2024 fprintf (stderr
, "class is of array type\n");
2028 if (jcf
->super_class
)
2030 if (! print_cxx_classname (out
, " : public ",
2031 jcf
, jcf
->super_class
))
2033 fprintf (stderr
, "base class is of array type\n");
2039 fputs ("\n{\n", out
);
2043 /* Now go back for second pass over methods and fields. */
2044 JCF_SEEK (jcf
, method_start
);
2046 jcf_parse_methods (jcf
);
2047 method_end
= JCF_TELL (jcf
);
2050 JCF_SEEK (jcf
, field_start
);
2051 jcf_parse_fields (jcf
);
2052 JCF_SEEK (jcf
, method_end
);
2054 jcf_parse_final_attributes (jcf
);
2060 fprintf (out
, "\n#ifdef __cplusplus\n");
2061 fprintf (out
, "}\n");
2062 fprintf (out
, "#endif\n");
2066 /* Generate friend decl if we still must. */
2067 for (i
= 0; i
< friend_count
; ++i
)
2068 fprintf (out
, " friend %s\n", friend_specs
[i
]);
2070 /* Generate extra declarations. */
2073 for (i
= 0; i
< add_count
; ++i
)
2074 fprintf (out
, " %s\n", add_specs
[i
]);
2076 /* Generate an entry for the class object. */
2077 generate_access (out
, ACC_PUBLIC
);
2078 fprintf (out
, "\n static ::java::lang::Class class$;\n");
2082 if (jcf
->access_flags
& ACC_INTERFACE
)
2083 fputs (" __attribute__ ((java_interface))", out
);
2087 if (append_count
> 0)
2089 for (i
= 0; i
< append_count
; ++i
)
2090 fprintf (out
, "%s\n", append_specs
[i
]);
2093 print_mangled_classname (out
, jcf
,
2094 "\n#endif /* __", jcf
->this_class
);
2095 fprintf (out
, "__ */\n");
2101 /* This is used to mark options with no short value. */
2102 #define LONG_OPT(Num) ((Num) + 128)
2104 #define OPT_classpath LONG_OPT (0)
2105 #define OPT_CLASSPATH OPT_classpath
2106 #define OPT_bootclasspath LONG_OPT (1)
2107 #define OPT_HELP LONG_OPT (2)
2108 #define OPT_TEMP LONG_OPT (3)
2109 #define OPT_VERSION LONG_OPT (4)
2110 #define OPT_PREPEND LONG_OPT (5)
2111 #define OPT_FRIEND LONG_OPT (6)
2112 #define OPT_ADD LONG_OPT (7)
2113 #define OPT_APPEND LONG_OPT (8)
2114 #define OPT_M LONG_OPT (9)
2115 #define OPT_MM LONG_OPT (10)
2116 #define OPT_MG LONG_OPT (11)
2117 #define OPT_MD LONG_OPT (12)
2118 #define OPT_MMD LONG_OPT (13)
2120 static const struct option options
[] =
2122 { "classpath", required_argument
, NULL
, OPT_classpath
},
2123 { "bootclasspath", required_argument
, NULL
, OPT_bootclasspath
},
2124 { "CLASSPATH", required_argument
, NULL
, OPT_CLASSPATH
},
2125 { "help", no_argument
, NULL
, OPT_HELP
},
2126 { "stubs", no_argument
, &stubs
, 1 },
2127 { "td", required_argument
, NULL
, OPT_TEMP
},
2128 { "verbose", no_argument
, NULL
, 'v' },
2129 { "version", no_argument
, NULL
, OPT_VERSION
},
2130 { "prepend", required_argument
, NULL
, OPT_PREPEND
},
2131 { "friend", required_argument
, NULL
, OPT_FRIEND
},
2132 { "add", required_argument
, NULL
, OPT_ADD
},
2133 { "append", required_argument
, NULL
, OPT_APPEND
},
2134 { "M", no_argument
, NULL
, OPT_M
},
2135 { "MM", no_argument
, NULL
, OPT_MM
},
2136 { "MG", no_argument
, NULL
, OPT_MG
},
2137 { "MD", no_argument
, NULL
, OPT_MD
},
2138 { "MMD", no_argument
, NULL
, OPT_MMD
},
2139 { "jni", no_argument
, &flag_jni
, 1 },
2140 { NULL
, no_argument
, NULL
, 0 }
2146 fprintf (stderr
, "Try `gcjh --help' for more information.\n");
2153 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2154 printf ("Generate C++ header files from .class files\n\n");
2155 printf (" -stubs Generate an implementation stub file\n");
2156 printf (" -jni Generate a JNI header or stub\n");
2158 printf (" -add TEXT Insert TEXT into class body\n");
2159 printf (" -append TEXT Insert TEXT after class declaration\n");
2160 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2161 printf (" -prepend TEXT Insert TEXT before start of class\n");
2163 printf (" --classpath PATH Set path to find .class files\n");
2164 printf (" -IDIR Append directory to class path\n");
2165 printf (" --bootclasspath PATH Override built-in class path\n");
2166 printf (" -d DIRECTORY Set output directory name\n");
2167 printf (" -o FILE Set output file name\n");
2168 printf (" -td DIRECTORY Set temporary directory name\n");
2170 printf (" --help Print this help, then exit\n");
2171 printf (" --version Print version number, then exit\n");
2172 printf (" -v, --verbose Print extra information while running\n");
2174 printf (" -M Print all dependencies to stdout;\n");
2175 printf (" suppress ordinary output\n");
2176 printf (" -MM Print non-system dependencies to stdout;\n");
2177 printf (" suppress ordinary output\n");
2178 printf (" -MD Print all dependencies to stdout\n");
2179 printf (" -MMD Print non-system dependencies to stdout\n");
2180 /* We omit -MG until it is implemented. */
2182 printf ("For bug reporting instructions, please see:\n");
2183 printf ("%s.\n", GCCBUGURL
);
2190 printf ("gcjh (GCC) %s\n\n", version_string
);
2191 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2192 printf ("This is free software; see the source for copying conditions. There is NO\n");
2193 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2198 DEFUN(main
, (argc
, argv
),
2199 int argc AND
char** argv
)
2203 char *output_file
= NULL
;
2204 int emit_dependencies
= 0, suppress_output
= 0;
2209 fprintf (stderr
, "gcjh: no classes specified\n");
2215 /* We use getopt_long_only to allow single `-' long options. For
2216 some of our options this is more natural. */
2217 while ((opt
= getopt_long_only (argc
, argv
, "I:d:o:v", options
, NULL
)) != -1)
2222 /* Already handled. */
2226 output_file
= optarg
;
2230 output_directory
= optarg
;
2234 jcf_path_include_arg (optarg
);
2242 jcf_path_classpath_arg (optarg
);
2245 case OPT_bootclasspath
:
2246 jcf_path_bootclasspath_arg (optarg
);
2254 temp_directory
= optarg
;
2262 if (prepend_count
== 0)
2263 prepend_specs
= (char**) ALLOC (argc
* sizeof (char*));
2264 prepend_specs
[prepend_count
++] = optarg
;
2268 if (friend_count
== 0)
2269 friend_specs
= (char**) ALLOC (argc
* sizeof (char*));
2270 friend_specs
[friend_count
++] = optarg
;
2275 add_specs
= (char**) ALLOC (argc
* sizeof (char*));
2276 add_specs
[add_count
++] = optarg
;
2280 if (append_count
== 0)
2281 append_specs
= (char**) ALLOC (argc
* sizeof (char*));
2282 append_specs
[append_count
++] = optarg
;
2286 emit_dependencies
= 1;
2287 suppress_output
= 1;
2288 jcf_dependency_init (1);
2292 emit_dependencies
= 1;
2293 suppress_output
= 1;
2294 jcf_dependency_init (0);
2298 fprintf (stderr
, "gcjh: `-MG' option is unimplemented\n");
2302 emit_dependencies
= 1;
2303 jcf_dependency_init (1);
2307 emit_dependencies
= 1;
2308 jcf_dependency_init (0);
2319 fprintf (stderr
, "gcjh: no classes specified\n");
2323 jcf_path_seal (verbose
);
2325 if (output_file
&& emit_dependencies
)
2327 fprintf (stderr
, "gcjh: can't specify both -o and -MD\n");
2331 for (argi
= optind
; argi
< argc
; argi
++)
2333 char *classname
= argv
[argi
];
2334 char *current_output_file
;
2335 const char *classfile_name
;
2338 fprintf (stderr
, "Processing %s\n", classname
);
2340 jcf_dependency_reset ();
2341 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 0);
2342 if (classfile_name
== NULL
)
2344 fprintf (stderr
, "%s: no such class\n", classname
);
2348 fprintf (stderr
, "Found in %s\n", classfile_name
);
2351 if (strcmp (output_file
, "-") == 0)
2353 else if (out
== NULL
)
2355 out
= fopen (output_file
, "w");
2359 perror (output_file
);
2362 current_output_file
= output_file
;
2366 int dir_len
= strlen (output_directory
);
2367 int i
, classname_length
= strlen (classname
);
2368 current_output_file
= (char*) ALLOC (dir_len
+ classname_length
+ 5);
2369 strcpy (current_output_file
, output_directory
);
2370 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
2371 current_output_file
[dir_len
++] = '/';
2372 for (i
= 0; classname
[i
] != '\0'; i
++)
2374 char ch
= classname
[i
];
2377 if (flag_jni
&& ch
== '/')
2379 current_output_file
[dir_len
++] = ch
;
2381 if (emit_dependencies
)
2383 if (suppress_output
)
2385 jcf_dependency_set_dep_file ("-");
2390 /* We use `.hd' and not `.d' to avoid clashes with
2391 dependency tracking from straight compilation. */
2392 strcpy (current_output_file
+ dir_len
, ".hd");
2393 jcf_dependency_set_dep_file (current_output_file
);
2396 strcpy (current_output_file
+ dir_len
,
2397 stubs
? (flag_jni
? ".c" : ".cc") : ".h");
2398 jcf_dependency_set_target (current_output_file
);
2399 if (! suppress_output
)
2401 out
= fopen (current_output_file
, "w");
2404 perror (current_output_file
);
2409 process_file (&jcf
, out
);
2411 if (current_output_file
!= output_file
)
2412 free (current_output_file
);
2413 jcf_dependency_write ();
2416 if (out
!= NULL
&& out
!= stdout
)