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 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. */
33 #include "java-tree.h"
34 #include "java-opcodes.h"
38 /* The output file. */
41 /* Nonzero on failure. */
42 static int found_error
= 0;
44 /* Directory to place resulting files in. Set by -d option. */
45 const char *output_directory
= "";
47 /* Directory to place temporary file. Set by -td option. Currently unused. */
48 const char *temp_directory
= "/tmp";
50 /* Number of friend functions we have to declare. */
51 static int friend_count
;
53 /* A class can optionally have a `friend' function declared. If
54 non-NULL, this is that function. */
55 static char **friend_specs
= NULL
;
57 /* Number of lines we are prepending before the class. */
58 static int prepend_count
;
60 /* We can prepend extra lines before the class's start. */
61 static char **prepend_specs
= NULL
;
63 /* Number of lines we are appending at the end of the class. */
66 /* We can append extra lines just before the class's end. */
67 static char **add_specs
= NULL
;
69 /* Number of lines we are appending after the class. */
70 static int append_count
;
72 /* We can append extra lines after the class's end. */
73 static char **append_specs
= NULL
;
79 struct JCF
*current_jcf
;
81 /* This holds access information for the last field we examined. They
82 let us generate "private:", "public:", and "protected:" properly.
83 If 0 then we haven't previously examined any field. */
84 static JCF_u2 last_access
;
86 #define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
88 /* Pass this macro the flags for a class and for a method. It will
89 return true if the method should be considered `final'. */
90 #define METHOD_IS_FINAL(Class, Method) \
91 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
93 /* Pass this macro the flags for a method. It will return true if the
95 #define METHOD_IS_NATIVE(Method) \
96 ((Method) & ACC_NATIVE)
98 /* We keep a linked list of all method names we have seen. This lets
99 us determine if a method name and a field name are in conflict. */
104 struct method_name
*next
;
107 /* List of method names we've seen. */
108 static struct method_name
*method_name_list
;
110 static void print_field_info
PROTO ((FILE*, JCF
*, int, int, JCF_u2
));
111 static void print_mangled_classname
PROTO ((FILE*, JCF
*, const char*, int));
112 static int print_cxx_classname
PROTO ((FILE*, const char*, JCF
*, int));
113 static void print_method_info
PROTO ((FILE*, JCF
*, int, int, JCF_u2
));
114 static void print_c_decl
PROTO ((FILE*, JCF
*, int, int, int, const char *));
115 static void print_stub
PROTO ((FILE*, JCF
*, int, int, int, const char *));
116 static void print_full_cxx_name
PROTO ((FILE*, JCF
*, int, int, int, const char *));
117 static void decompile_method
PROTO ((FILE*, JCF
*, int));
118 static void add_class_decl
PROTO ((FILE*, JCF
*, JCF_u2
));
120 static int java_float_finite
PROTO ((jfloat
));
121 static int java_double_finite
PROTO ((jdouble
));
122 static void print_name
PROTO ((FILE *, JCF
*, int));
123 static void print_base_classname
PROTO ((FILE *, JCF
*, int));
124 static int utf8_cmp
PROTO ((const unsigned char *, int, const char *));
125 static const char *cxx_keyword_subst
PROTO ((const unsigned char *, int));
126 static void generate_access
PROTO ((FILE *, JCF_u2
));
127 static int name_is_method_p
PROTO ((const unsigned char *, int));
128 static char *get_field_name
PROTO ((JCF
*, int, JCF_u2
));
129 static void print_field_name
PROTO ((FILE *, JCF
*, int, JCF_u2
));
130 static const unsigned char *super_class_name
PROTO ((JCF
*, int *));
131 static void print_include
PROTO ((FILE *, const unsigned char *, int));
132 static const unsigned char *decode_signature_piece
133 PROTO ((FILE *, const unsigned char *, const unsigned char *, int *));
134 static void print_class_decls
PROTO ((FILE *, JCF
*, int));
135 static void usage
PROTO ((void)) ATTRIBUTE_NORETURN
;
136 static void help
PROTO ((void)) ATTRIBUTE_NORETURN
;
137 static void java_no_argument
PROTO ((const char *)) ATTRIBUTE_NORETURN
;
138 static void version
PROTO ((void)) ATTRIBUTE_NORETURN
;
140 JCF_u2 current_field_name
;
141 JCF_u2 current_field_value
;
142 JCF_u2 current_field_signature
;
143 JCF_u2 current_field_flags
;
145 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
146 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
147 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
149 /* We pass over fields twice. The first time we just note the types
150 of the fields and then the start of the methods. Then we go back
151 and parse the fields for real. This is ugly. */
152 static int field_pass
;
153 /* Likewise we pass over methods twice. The first time we generate
154 class decl information; the second time we generate actual method
156 static int method_pass
;
158 #define HANDLE_END_FIELD() \
161 if (out && ! stubs) \
162 print_field_info (out, jcf, current_field_name, \
163 current_field_signature, \
164 current_field_flags); \
167 if (! stubs) add_class_decl (out, jcf, current_field_signature);
169 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
171 static int method_declared
= 0;
172 static int method_access
= 0;
173 static int method_printed
= 0;
174 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
177 decompiled = 0; method_printed = 0; \
179 print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
182 if (! stubs) add_class_decl (out, jcf, SIGNATURE);
184 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
185 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
187 static int decompiled
= 0;
188 #define HANDLE_END_METHOD() \
189 if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out);
191 #include "jcf-reader.c"
193 /* Some useful constants. */
194 #define F_NAN_MASK 0x7f800000
195 #define D_NAN_MASK 0x7ff0000000000000LL
197 /* Return 1 if F is not Inf or NaN. */
199 java_float_finite (f
)
208 /* We happen to know that F_NAN_MASK will match all NaN values, and
209 also positive and negative infinity. That's why we only need one
210 test here. See The Java Language Specification, section 20.9. */
211 return (u
.i
& F_NAN_MASK
) != F_NAN_MASK
;
214 /* Return 1 if D is not Inf or NaN. */
216 java_double_finite (d
)
225 /* Now check for all NaNs. */
226 return (u
.i
& D_NAN_MASK
) != D_NAN_MASK
;
230 DEFUN(print_name
, (stream
, jcf
, name_index
),
231 FILE* stream AND JCF
* jcf AND
int name_index
)
233 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
234 fprintf (stream
, "<not a UTF8 constant>");
236 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
237 JPOOL_UTF_LENGTH (jcf
, name_index
));
240 /* Print base name of class. The base name is everything after the
244 print_base_classname (stream
, jcf
, index
)
249 int name_index
= JPOOL_USHORT1 (jcf
, index
);
251 const unsigned char *s
, *p
, *limit
;
253 s
= JPOOL_UTF_DATA (jcf
, name_index
);
254 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
259 int c
= UTF8_GET (s
, limit
);
266 int ch
= UTF8_GET (p
, limit
);
268 fputs ("::", stream
);
270 jcf_print_char (stream
, ch
);
274 /* Return 0 if NAME is equal to STR, nonzero otherwise. */
277 utf8_cmp (str
, length
, name
)
278 const unsigned char *str
;
282 const unsigned char *limit
= str
+ length
;
285 for (i
= 0; name
[i
]; ++i
)
287 int ch
= UTF8_GET (str
, limit
);
295 /* If NAME is the name of a C++ keyword, then return an override name.
296 This is a name that can be used in place of the keyword.
297 Otherwise, return NULL. FIXME: for now, we only handle those
298 keywords we know to be a problem for libgcj. */
301 cxx_keyword_subst (str
, length
)
302 const unsigned char *str
;
305 if (! utf8_cmp (str
, length
, "delete"))
306 return "__dummy_delete";
307 else if (! utf8_cmp (str
, length
, "enum"))
308 return "__dummy_enum";
312 /* Generate an access control keyword based on FLAGS. Returns 0 if
313 FLAGS matches the saved access information, nonzero otherwise. */
316 generate_access (stream
, flags
)
320 if ((flags
& ACC_VISIBILITY
) == last_access
)
322 last_access
= (flags
& ACC_VISIBILITY
);
327 fputs ("public: // actually package-private\n", stream
);
330 fputs ("public:\n", stream
);
333 fputs ("private:\n", stream
);
336 fputs ("public: // actually protected\n", stream
);
340 fprintf (stream
, "#error unrecognized visibility %d\n",
341 (flags
& ACC_VISIBILITY
));
346 /* See if NAME is already the name of a method. */
348 name_is_method_p (name
, length
)
349 const unsigned char *name
;
352 struct method_name
*p
;
354 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
356 if (p
->length
== length
&& ! memcmp (p
->name
, name
, length
))
362 /* Get name of a field. This handles renamings due to C++ clash. */
364 get_field_name (jcf
, name_index
, flags
)
369 unsigned char *name
= JPOOL_UTF_DATA (jcf
, name_index
);
370 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
372 const char *tmpconstptr
;
375 if (name_is_method_p (name
, length
))
377 /* This field name matches a method. So override the name with
378 a dummy name. This is yucky, but it isn't clear what else to
379 do. FIXME: if the field is static, then we'll be in real
381 if ((flags
& ACC_STATIC
))
383 fprintf (stderr
, "static field has same name as method\n");
388 override
= xmalloc (length
+ 3);
389 memcpy (override
, name
, length
);
390 strcpy (override
+ length
, "__");
392 else if ((tmpconstptr
= cxx_keyword_subst (name
, length
)) != NULL
)
394 /* Must malloc OVERRIDE. */
395 override
= xstrdup (tmpconstptr
);
403 /* Print a field name. Convenience function for use with
406 print_field_name (stream
, jcf
, name_index
, flags
)
412 char *override
= get_field_name (jcf
, name_index
, flags
);
416 fputs (override
, stream
);
420 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
421 JPOOL_UTF_LENGTH (jcf
, name_index
));
425 DEFUN(print_field_info
, (stream
, jcf
, name_index
, sig_index
, flags
),
426 FILE *stream AND JCF
* jcf
427 AND
int name_index AND
int sig_index AND JCF_u2 flags
)
429 char *override
= NULL
;
431 generate_access (stream
, flags
);
432 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
434 fprintf (stream
, "<not a UTF8 constant>");
439 if (flags
& ACC_FINAL
)
441 if (current_field_value
> 0)
446 switch (JPOOL_TAG (jcf
, current_field_value
))
448 case CONSTANT_Integer
:
451 int most_negative
= 0;
452 fputs (" static const jint ", out
);
453 print_field_name (out
, jcf
, name_index
, 0);
455 num
= JPOOL_INT (jcf
, current_field_value
);
456 /* We single out the most negative number to print
457 specially. This avoids later warnings from g++. */
458 if (num
== (jint
) 0x80000000)
463 format_int (buffer
, (jlong
) num
, 10);
464 fprintf (out
, "%sL%s;\n", buffer
, most_negative
? " - 1" : "");
470 int most_negative
= 0;
471 fputs (" static const jlong ", out
);
472 print_field_name (out
, jcf
, name_index
, 0);
474 num
= JPOOL_LONG (jcf
, current_field_value
);
475 /* We single out the most negative number to print
476 specially.. This avoids later warnings from g++. */
477 if (num
== (jlong
) 0x8000000000000000LL
)
482 format_int (buffer
, num
, 10);
483 fprintf (out
, "%sLL%s;\n", buffer
, most_negative
? " - 1" :"");
488 jfloat fnum
= JPOOL_FLOAT (jcf
, current_field_value
);
489 fputs (" static const jfloat ", out
);
490 print_field_name (out
, jcf
, name_index
, 0);
491 if (! java_float_finite (fnum
))
494 fprintf (out
, " = %.10g;\n", fnum
);
497 case CONSTANT_Double
:
499 jdouble dnum
= JPOOL_DOUBLE (jcf
, current_field_value
);
500 fputs (" static const jdouble ", out
);
501 print_field_name (out
, jcf
, name_index
, 0);
502 if (! java_double_finite (dnum
))
505 fprintf (out
, " = %.17g;\n", dnum
);
509 /* We can't print this as a constant, but we can still
510 print something sensible. */
521 if ((flags
& ACC_STATIC
))
522 fputs ("static ", out
);
524 override
= get_field_name (jcf
, name_index
, flags
);
525 print_c_decl (out
, jcf
, name_index
, sig_index
, 0, override
);
533 DEFUN(print_method_info
, (stream
, jcf
, name_index
, sig_index
, flags
),
534 FILE *stream AND JCF
* jcf
535 AND
int name_index AND
int sig_index AND JCF_u2 flags
)
537 const unsigned char *str
;
538 int length
, is_init
= 0;
539 const char *override
= NULL
;
542 method_access
= flags
;
543 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
544 fprintf (stream
, "<not a UTF8 constant>");
545 str
= JPOOL_UTF_DATA (jcf
, name_index
);
546 length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
547 if (str
[0] == '<' || str
[0] == '$')
549 /* Ignore internally generated methods like <clinit> and
550 $finit$. However, treat <init> as a constructor. */
551 if (! utf8_cmp (str
, length
, "<init>"))
553 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
)
554 && ! (flags
& ACC_STATIC
))
556 /* FIXME: i18n bug here. Order of prints should not be
558 fprintf (stderr
, "ignored method `");
559 jcf_print_utf8 (stderr
, str
, length
);
560 fprintf (stderr
, "' marked virtual\n");
569 struct method_name
*nn
;
571 nn
= (struct method_name
*) xmalloc (sizeof (struct method_name
));
572 nn
->name
= (char *) xmalloc (length
);
573 memcpy (nn
->name
, str
, length
);
575 nn
->next
= method_name_list
;
576 method_name_list
= nn
;
579 /* We can't generate a method whose name is a C++ reserved word. We
580 can't just ignore the function, because that will cause incorrect
581 code to be generated if the function is virtual (not only for
582 calls to this function for for other functions after it in the
583 vtbl). So we give it a dummy name instead. */
584 override
= cxx_keyword_subst (str
, length
);
587 /* If the method is static or final, we can safely skip it. If
588 we don't skip it then we'll have problems since the mangling
589 will be wrong. FIXME. */
590 if (METHOD_IS_FINAL (jcf
->access_flags
, flags
)
591 || (flags
& ACC_STATIC
))
599 generate_access (stream
, flags
);
602 if ((flags
& ACC_STATIC
))
603 fputs ("static ", out
);
604 else if (! METHOD_IS_FINAL (jcf
->access_flags
, flags
))
606 /* Don't print `virtual' if we have a constructor. */
608 fputs ("virtual ", out
);
610 print_c_decl (out
, jcf
, name_index
, sig_index
, is_init
, override
);
612 if ((flags
& ACC_ABSTRACT
))
619 if (METHOD_IS_NATIVE(flags
))
622 print_stub (out
, jcf
, name_index
, sig_index
, is_init
, override
);
627 /* Try to decompile a method body. Right now we just try to handle a
628 simple case that we can do. Expand as desired. */
630 decompile_method (out
, jcf
, code_len
)
635 const unsigned char *codes
= jcf
->read_ptr
;
637 uint16 name_and_type
, name
;
639 /* If the method is synchronized, don't touch it. */
640 if ((method_access
& ACC_SYNCHRONIZED
))
644 && codes
[0] == OPCODE_aload_0
645 && codes
[1] == OPCODE_getfield
646 && (codes
[4] == OPCODE_areturn
647 || codes
[4] == OPCODE_dreturn
648 || codes
[4] == OPCODE_freturn
649 || codes
[4] == OPCODE_ireturn
650 || codes
[4] == OPCODE_lreturn
))
652 /* Found code like `return FIELD'. */
653 fputs (" { return ", out
);
654 index
= (codes
[2] << 8) | codes
[3];
655 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
656 /* FIXME: ensure that the field's class is this class. */
657 name_and_type
= JPOOL_USHORT2 (jcf
, index
);
658 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
659 name
= JPOOL_USHORT1 (jcf
, name_and_type
);
660 print_name (out
, jcf
, name
);
664 else if (code_len
== 2
665 && codes
[0] == OPCODE_aload_0
666 && codes
[1] == OPCODE_areturn
)
668 /* Found `return this'. */
669 fputs (" { return this; }", out
);
672 else if (code_len
== 1 && codes
[0] == OPCODE_return
)
674 /* Found plain `return'. */
678 else if (code_len
== 2
679 && codes
[0] == OPCODE_aconst_null
680 && codes
[1] == OPCODE_areturn
)
682 /* Found `return null'. We don't want to depend on NULL being
684 fputs (" { return 0; }", out
);
689 /* Print one piece of a signature. Returns pointer to next parseable
690 character on success, NULL on error. */
691 static const unsigned char *
692 decode_signature_piece (stream
, signature
, limit
, need_space
)
694 const unsigned char *signature
, *limit
;
700 switch (signature
[0])
703 /* More spaghetti. */
705 for (signature
++; (signature
< limit
707 && *signature
<= '9'); signature
++)
711 case 'B': ctype
= "jbyteArray"; goto printit
;
712 case 'C': ctype
= "jcharArray"; goto printit
;
713 case 'D': ctype
= "jdoubleArray"; goto printit
;
714 case 'F': ctype
= "jfloatArray"; goto printit
;
715 case 'I': ctype
= "jintArray"; goto printit
;
716 case 'S': ctype
= "jshortArray"; goto printit
;
717 case 'J': ctype
= "jlongArray"; goto printit
;
718 case 'Z': ctype
= "jbooleanArray"; goto printit
;
720 /* We have a nested array. */
722 fputs ("JArray<", stream
);
726 /* We have to generate a reference to JArray here, so that
727 our output matches what the compiler does. */
729 fputs ("JArray<", stream
);
730 while (signature
< limit
&& *signature
!= ';')
732 int ch
= UTF8_GET (signature
, limit
);
734 fputs ("::", stream
);
736 jcf_print_char (stream
, ch
);
738 fputs (" *> *", stream
);
743 /* Unparseable signature. */
750 /* This shouldn't happen. */
753 case 'B': ctype
= "jbyte"; goto printit
;
754 case 'C': ctype
= "jchar"; goto printit
;
755 case 'D': ctype
= "jdouble"; goto printit
;
756 case 'F': ctype
= "jfloat"; goto printit
;
757 case 'I': ctype
= "jint"; goto printit
;
758 case 'J': ctype
= "jlong"; goto printit
;
759 case 'S': ctype
= "jshort"; goto printit
;
760 case 'Z': ctype
= "jboolean"; goto printit
;
761 case 'V': ctype
= "void"; goto printit
;
763 /* Print a leading "::" so we look in the right namespace. */
764 fputs ("::", stream
);
766 while (*signature
&& *signature
!= ';')
768 int ch
= UTF8_GET (signature
, limit
);
769 /* `$' is the separator for an inner class. */
770 if (ch
== '/' || ch
== '$')
771 fputs ("::", stream
);
773 jcf_print_char (stream
, ch
);
775 fputs (" *", stream
);
776 if (*signature
== ';')
782 jcf_print_char (stream
, *signature
++);
787 fputs (ctype
, stream
);
791 while (array_depth
-- > 0)
792 fputs ("> *", stream
);
798 DEFUN(print_c_decl
, (stream
, jcf
, name_index
, signature_index
, is_init
,
800 FILE* stream AND JCF
* jcf
801 AND
int name_index AND
int signature_index
802 AND
int is_init AND
const char *name_override
)
804 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
806 fprintf (stream
, "<not a UTF8 constant>");
811 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
812 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
813 register const unsigned char *str
= str0
;
814 const unsigned char *limit
= str
+ length
;
816 int is_method
= str
[0] == '(';
817 const unsigned char *next
;
819 /* If printing a method, skip to the return signature and print
820 that first. However, there is no return value if this is a
822 if (is_method
&& ! is_init
)
832 /* If printing a field or an ordinary method, then print the
833 "return value" now. */
834 if (! is_method
|| ! is_init
)
836 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
839 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
845 /* Now print the name of the thing. */
848 print_full_cxx_name (stream
, jcf
, name_index
,
849 signature_index
, is_init
, name_override
);
853 /* Print the unqualified method name followed by the signature. */
855 DEFUN(print_full_cxx_name
, (stream
, jcf
, name_index
, signature_index
, is_init
, name_override
),
856 FILE* stream AND JCF
* jcf
857 AND
int name_index AND
int signature_index AND
int is_init
858 AND
const char *name_override
)
860 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
861 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
862 register const unsigned char *str
= str0
;
863 const unsigned char *limit
= str
+ length
;
865 int is_method
= str
[0] == '(';
866 const unsigned char *next
;
869 fputs (name_override
, stream
);
872 /* Declare constructors specially. */
874 print_base_classname (stream
, jcf
, jcf
->this_class
);
876 print_name (stream
, jcf
, name_index
);
881 /* Have a method or a constructor. Print signature pieces
883 fputs (" (", stream
);
885 while (str
< limit
&& *str
!= ')')
887 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
890 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
895 if (next
< limit
&& *next
!= ')')
896 fputs (", ", stream
);
905 DEFUN(print_stub
, (stream
, jcf
, name_index
, signature_index
, is_init
,
907 FILE* stream AND JCF
* jcf
908 AND
int name_index AND
int signature_index
909 AND
int is_init AND
const char *name_override
)
911 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
913 fprintf (stream
, "<not a UTF8 constant>");
918 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
919 const unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
920 register const unsigned char *str
= str0
;
921 const unsigned char *limit
= str
+ length
;
923 int is_method
= str
[0] == '(';
924 const unsigned char *next
;
926 /* If printing a method, skip to the return signature and print
927 that first. However, there is no return value if this is a
929 if (is_method
&& ! is_init
)
939 /* If printing a field or an ordinary method, then print the
940 "return value" now. */
941 if (! is_method
|| ! is_init
)
943 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
946 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
952 /* Now print the name of the thing. */
953 print_cxx_classname (stream
, "\n", jcf
, jcf
->this_class
);
954 fputs ("::", stream
);
955 print_full_cxx_name (stream
, jcf
, name_index
,
956 signature_index
, is_init
, name_override
);
957 fputs ("\n{\n JvFail (\"", stream
);
958 print_cxx_classname (stream
, "", jcf
, jcf
->this_class
);
959 fputs ("::", stream
);
960 print_full_cxx_name (stream
, jcf
, name_index
,
961 signature_index
, is_init
, name_override
);
962 fputs (" not implemented\");\n}\n\n", stream
);
967 DEFUN(print_mangled_classname
, (stream
, jcf
, prefix
, index
),
968 FILE *stream AND JCF
*jcf AND
const char *prefix AND
int index
)
970 int name_index
= JPOOL_USHORT1 (jcf
, index
);
971 fputs (prefix
, stream
);
972 jcf_print_utf8_replace (out
,
973 JPOOL_UTF_DATA (jcf
, name_index
),
974 JPOOL_UTF_LENGTH (jcf
, name_index
),
978 /* Print PREFIX, then a class name in C++ format. If the name refers
979 to an array, ignore it and don't print PREFIX. Returns 1 if
980 something was printed, 0 otherwise. */
982 print_cxx_classname (stream
, prefix
, jcf
, index
)
988 int name_index
= JPOOL_USHORT1 (jcf
, index
);
990 const unsigned char *s
, *p
, *limit
;
992 s
= JPOOL_UTF_DATA (jcf
, name_index
);
993 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
996 /* Explicitly omit arrays here. */
998 c
= UTF8_GET (p
, limit
);
1002 fputs (prefix
, stream
);
1004 /* Print a leading "::" so we look in the right namespace. */
1005 fputs ("::", stream
);
1009 c
= UTF8_GET (s
, limit
);
1011 fputs ("::", stream
);
1013 jcf_print_char (stream
, c
);
1019 int written_class_count
= 0;
1021 /* Return name of superclass. If LEN is not NULL, fill it with length
1023 static const unsigned char *
1024 super_class_name (derived_jcf
, len
)
1028 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
1029 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
1030 const unsigned char *supername
=
1031 JPOOL_UTF_DATA (derived_jcf
, supername_index
);
1034 *len
= supername_length
;
1041 /* We keep track of all the `#include's we generate, so we can avoid
1046 struct include
*next
;
1049 /* List of all includes. */
1050 static struct include
*all_includes
= NULL
;
1052 /* Generate a #include. */
1054 print_include (out
, utf8
, len
)
1056 const unsigned char *utf8
;
1059 struct include
*incl
;
1065 len
= strlen (utf8
);
1067 for (incl
= all_includes
; incl
; incl
= incl
->next
)
1069 /* We check the length because we might have a proper prefix. */
1070 if (len
== (int) strlen (incl
->name
)
1071 && ! strncmp (incl
->name
, utf8
, len
))
1075 incl
= (struct include
*) xmalloc (sizeof (struct include
));
1076 incl
->name
= xmalloc (len
+ 1);
1077 strncpy (incl
->name
, utf8
, len
);
1078 incl
->name
[len
] = '\0';
1079 incl
->next
= all_includes
;
1080 all_includes
= incl
;
1082 fputs ("#include <", out
);
1083 jcf_print_utf8 (out
, utf8
, len
);
1084 fputs (".h>\n", out
);
1089 /* This is used to represent part of a package or class name. */
1092 /* The text of this part of the name. */
1094 /* True if this represents a class. */
1096 /* Linked list of all classes and packages inside this one. */
1097 struct namelet
*subnamelets
;
1098 /* Pointer to next sibling. */
1099 struct namelet
*next
;
1102 static void add_namelet
PROTO ((const unsigned char *,
1103 const unsigned char *, struct namelet
*));
1104 static void print_namelet
PROTO ((FILE *, struct namelet
*, int));
1106 /* The special root namelet. */
1107 static struct namelet root
=
1115 /* This extracts the next name segment from the full UTF-8 encoded
1116 package or class name and links it into the tree. It does this
1119 add_namelet (name
, name_limit
, parent
)
1120 const unsigned char *name
, *name_limit
;
1121 struct namelet
*parent
;
1123 const unsigned char *p
;
1124 struct namelet
*n
= NULL
, *np
;
1126 /* We want to skip the standard namespaces that we assume the
1127 runtime already knows about. We only do this at the top level,
1128 though, hence the check for `root'. */
1129 if (parent
== &root
)
1131 #define JAVALANG "java/lang/"
1132 #define JAVAIO "java/io/"
1133 #define JAVAUTIL "java/util/"
1134 if ((name_limit
- name
>= (int) sizeof (JAVALANG
) - 1
1135 && ! strncmp (name
, JAVALANG
, sizeof (JAVALANG
) - 1))
1136 || (name_limit
- name
>= (int) sizeof (JAVAUTIL
) - 1
1137 && ! strncmp (name
, JAVAUTIL
, sizeof (JAVAUTIL
) - 1))
1138 || (name_limit
- name
>= (int) sizeof (JAVAIO
) - 1
1139 && ! strncmp (name
, JAVAIO
, sizeof (JAVAIO
) - 1)))
1143 for (p
= name
; p
< name_limit
&& *p
!= '/' && *p
!= '$'; ++p
)
1146 /* Search for this name beneath the PARENT node. */
1147 for (np
= parent
->subnamelets
; np
!= NULL
; np
= np
->next
)
1149 /* We check the length because we might have a proper prefix. */
1150 if ((int) strlen (np
->name
) == p
- name
&&
1151 ! strncmp (name
, np
->name
, p
- name
))
1160 n
= (struct namelet
*) xmalloc (sizeof (struct namelet
));
1161 n
->name
= xmalloc (p
- name
+ 1);
1162 strncpy (n
->name
, name
, p
- name
);
1163 n
->name
[p
- name
] = '\0';
1164 n
->is_class
= (p
== name_limit
|| *p
== '$');
1165 n
->subnamelets
= NULL
;
1166 n
->next
= parent
->subnamelets
;
1167 parent
->subnamelets
= n
;
1170 /* We recurse if there is more text, and if the trailing piece does
1171 not represent an inner class. */
1172 if (p
< name_limit
&& *p
!= '$')
1173 add_namelet (p
+ 1, name_limit
, n
);
1176 /* Print a single namelet. Destroys namelets while printing. */
1178 print_namelet (out
, name
, depth
)
1180 struct namelet
*name
;
1188 for (i
= 0; i
< depth
; ++i
)
1190 fprintf (out
, "%s %s", name
->is_class
? "class" : "namespace",
1192 if (name
->is_class
&& name
->subnamelets
== NULL
)
1198 for (i
= 0; i
< depth
; ++i
)
1204 c
= name
->subnamelets
;
1207 struct namelet
*next
= c
->next
;
1208 print_namelet (out
, c
, depth
+ 2);
1216 for (i
= 0; i
< depth
; ++i
)
1219 /* Only print a `;' when printing a class. C++ is evil. */
1229 /* This is called to add some classes to the list of classes for which
1230 we need decls. The signature argument can be a function
1233 add_class_decl (out
, jcf
, signature
)
1238 const unsigned char *s
= JPOOL_UTF_DATA (jcf
, signature
);
1239 int len
= JPOOL_UTF_LENGTH (jcf
, signature
);
1241 /* Name of class we are processing. */
1242 int name_index
= JPOOL_USHORT1 (jcf
, jcf
->this_class
);
1243 int tlen
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1244 const char *tname
= JPOOL_UTF_DATA (jcf
, name_index
);
1246 for (i
= 0; i
< len
; ++i
)
1248 int start
, saw_dollar
;
1250 /* If we see an array, then we include the array header. */
1253 print_include (out
, "gcj/array", -1);
1257 /* We're looking for `L<stuff>;' -- everything else is
1263 for (start
= ++i
; i
< len
&& s
[i
] != ';'; ++i
)
1265 if (! saw_dollar
&& s
[i
] == '$' && out
)
1268 /* If this class represents an inner class, then
1269 generate a `#include' for the outer class. However,
1270 don't generate the include if the outer class is the
1271 class we are processing. */
1272 if (i
- start
< tlen
|| strncmp (&s
[start
], tname
, i
- start
))
1273 print_include (out
, &s
[start
], i
- start
);
1278 /* If we saw an inner class, then the generated #include will
1279 declare the class. So in this case we needn't bother. */
1281 add_namelet (&s
[start
], &s
[i
], &root
);
1285 /* Print declarations for all classes required by this class. Any
1286 class or package in the `java' package is assumed to be handled
1287 statically in libjava; we don't generate declarations for these.
1288 This makes the generated headers a bit easier to read. */
1290 print_class_decls (out
, jcf
, self
)
1295 /* Make sure to always add the current class to the list of things
1296 that should be declared. */
1297 int name_index
= JPOOL_USHORT1 (jcf
, self
);
1299 const unsigned char *s
;
1301 s
= JPOOL_UTF_DATA (jcf
, name_index
);
1302 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
1303 add_namelet (s
, s
+ len
, &root
);
1305 if (root
.subnamelets
)
1307 fputs ("extern \"Java\"\n{\n", out
);
1308 /* We use an initial offset of 0 because the root namelet
1309 doesn't cause anything to print. */
1310 print_namelet (out
, &root
, 0);
1311 fputs ("};\n\n", out
);
1318 DEFUN(process_file
, (jcf
, out
),
1319 JCF
*jcf AND
FILE *out
)
1322 uint32 field_start
, method_end
, method_start
;
1328 if (jcf_parse_preamble (jcf
) != 0)
1330 fprintf (stderr
, "Not a valid Java .class file.\n");
1335 /* Parse and possibly print constant pool */
1336 code
= jcf_parse_constant_pool (jcf
);
1339 fprintf (stderr
, "error while parsing constant pool\n");
1343 code
= verify_constant_pool (jcf
);
1346 fprintf (stderr
, "error in constant pool entry #%d\n", code
);
1351 jcf_parse_class (jcf
);
1353 if (written_class_count
++ == 0 && out
)
1356 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
1360 fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.
1362 // This file is intended to give you a head start on implementing native
1363 // methods using CNI.
1364 // Be aware: running `gcjh -stubs' once more for this class may overwrite any
1365 // edits you have made to this file.\n\n", out
);
1373 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
1374 fprintf (out
, "__\n");
1376 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
1377 fprintf (out
, "__\n\n");
1379 /* We do this to ensure that inline methods won't be `outlined'
1380 by g++. This works as long as method and fields are not
1381 added by the user. */
1382 fprintf (out
, "#pragma interface\n");
1384 if (jcf
->super_class
)
1387 const unsigned char *supername
=
1388 super_class_name (jcf
, &super_length
);
1391 print_include (out
, supername
, super_length
);
1396 /* Strip off the ".class" portion of the name when printing
1397 the include file name. */
1398 print_include (out
, jcf
->classname
, strlen (jcf
->classname
) - 6);
1402 /* We want to parse the methods first. But we need to find where
1403 they start. So first we skip the fields, then parse the methods.
1404 Then we parse the fields and skip the methods. This is ugly, but
1405 not too bad since we need two full passes to get class decl
1406 information anyway. */
1408 field_start
= JCF_TELL (jcf
);
1409 jcf_parse_fields (jcf
);
1411 method_start
= JCF_TELL (jcf
);
1413 jcf_parse_methods (jcf
);
1420 print_class_decls (out
, jcf
, jcf
->this_class
);
1422 for (i
= 0; i
< prepend_count
; ++i
)
1423 fprintf (out
, "%s\n", prepend_specs
[i
]);
1424 if (prepend_count
> 0)
1429 if (! print_cxx_classname (out
, "class ", jcf
, jcf
->this_class
))
1431 fprintf (stderr
, "class is of array type\n");
1435 if (jcf
->super_class
)
1437 if (! print_cxx_classname (out
, " : public ",
1438 jcf
, jcf
->super_class
))
1440 fprintf (stderr
, "base class is of array type\n");
1446 fputs ("\n{\n", out
);
1450 /* Now go back for second pass over methods and fields. */
1451 JCF_SEEK (jcf
, method_start
);
1453 jcf_parse_methods (jcf
);
1454 method_end
= JCF_TELL (jcf
);
1457 JCF_SEEK (jcf
, field_start
);
1458 jcf_parse_fields (jcf
);
1459 JCF_SEEK (jcf
, method_end
);
1461 jcf_parse_final_attributes (jcf
);
1465 /* Generate friend decl if we still must. */
1466 for (i
= 0; i
< friend_count
; ++i
)
1467 fprintf (out
, " friend %s\n", friend_specs
[i
]);
1469 /* Generate extra declarations. */
1472 for (i
= 0; i
< add_count
; ++i
)
1473 fprintf (out
, " %s\n", add_specs
[i
]);
1476 fputs ("};\n", out
);
1478 if (append_count
> 0)
1480 for (i
= 0; i
< append_count
; ++i
)
1481 fprintf (out
, "%s\n", append_specs
[i
]);
1485 print_mangled_classname (out
, jcf
,
1486 "\n#endif /* __", jcf
->this_class
);
1487 fprintf (out
, "__ */\n");
1495 fprintf (stderr
, "gcjh: no classes specified\n");
1502 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1503 printf ("Generate C++ header files from .class files\n\n");
1504 printf (" --classpath PATH Set path to find .class files\n");
1505 printf (" --CLASSPATH PATH Set path to find .class files\n");
1506 printf (" -IDIR Append directory to class path\n");
1507 printf (" -d DIRECTORY Set output directory name\n");
1508 printf (" --help Print this help, then exit\n");
1509 printf (" -o FILE Set output file name\n");
1510 printf (" -stubs Generate a C++ implementation stub file\n");
1511 printf (" -td DIRECTORY Set temporary directory name\n");
1512 printf (" -v, --verbose Print extra information while running\n");
1513 printf (" --version Print version number, then exit\n");
1514 /* FIXME: print bug-report information. */
1519 java_no_argument (opt
)
1522 fprintf (stderr
, "gcjh: no argument given for option `%s'\n", opt
);
1529 /* FIXME: use version.c? */
1530 printf ("gcjh (%s)\n\n", version_string
);
1531 printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1532 printf ("This is free software; see the source for copying conditions. There is NO\n");
1533 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1538 DEFUN(main
, (argc
, argv
),
1539 int argc AND
char** argv
)
1543 char *output_file
= NULL
;
1544 int emit_dependencies
= 0, suppress_output
= 0;
1551 for (argi
= 1; argi
< argc
; argi
++)
1553 char *arg
= argv
[argi
];
1555 if (arg
[0] != '-' || ! strcmp (arg
, "--"))
1558 /* Just let all arguments be given in either "-" or "--" form. */
1562 if (strcmp (arg
, "-o") == 0)
1564 if (argi
+ 1 < argc
)
1565 output_file
= argv
[++argi
];
1567 java_no_argument (argv
[argi
]);
1569 else if (strcmp (arg
, "-d") == 0)
1571 if (argi
+ 1 < argc
)
1572 output_directory
= argv
[++argi
];
1574 java_no_argument (argv
[argi
]);
1576 else if (strcmp (arg
, "-td") == 0)
1578 if (argi
+ 1 < argc
)
1579 temp_directory
= argv
[++argi
];
1581 java_no_argument (argv
[argi
]);
1583 else if (strcmp (arg
, "-prepend") == 0)
1585 if (argi
+ 1 < argc
)
1587 if (prepend_count
== 0)
1588 prepend_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
1589 prepend_specs
[prepend_count
++] = argv
[++argi
];
1592 java_no_argument (argv
[argi
]);
1594 else if (strcmp (arg
, "-friend") == 0)
1596 if (argi
+ 1 < argc
)
1598 if (friend_count
== 0)
1599 friend_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
1600 friend_specs
[friend_count
++] = argv
[++argi
];
1603 java_no_argument (argv
[argi
]);
1605 else if (strcmp (arg
, "-add") == 0)
1607 if (argi
+ 1 < argc
)
1610 add_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
1611 add_specs
[add_count
++] = argv
[++argi
];
1614 java_no_argument (argv
[argi
]);
1616 else if (strcmp (arg
, "-append") == 0)
1618 if (argi
+ 1 < argc
)
1620 if (append_count
== 0)
1621 append_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
1622 append_specs
[append_count
++] = argv
[++argi
];
1625 java_no_argument (argv
[argi
]);
1627 else if (strcmp (arg
, "-classpath") == 0)
1629 if (argi
+ 1 < argc
)
1630 jcf_path_classpath_arg (argv
[++argi
]);
1632 java_no_argument (argv
[argi
]);
1634 else if (strcmp (arg
, "-CLASSPATH") == 0)
1636 if (argi
+ 1 < argc
)
1637 jcf_path_CLASSPATH_arg (argv
[++argi
]);
1639 java_no_argument (argv
[argi
]);
1641 else if (strncmp (arg
, "-I", 2) == 0)
1642 jcf_path_include_arg (arg
+ 2);
1643 else if (strcmp (arg
, "-verbose") == 0 || strcmp (arg
, "-v") == 0)
1645 else if (strcmp (arg
, "-stubs") == 0)
1647 else if (strcmp (arg
, "-help") == 0)
1649 else if (strcmp (arg
, "-version") == 0)
1651 else if (strcmp (arg
, "-M") == 0)
1653 emit_dependencies
= 1;
1654 suppress_output
= 1;
1655 jcf_dependency_init (1);
1657 else if (strcmp (arg
, "-MM") == 0)
1659 emit_dependencies
= 1;
1660 suppress_output
= 1;
1661 jcf_dependency_init (0);
1663 else if (strcmp (arg
, "-MG") == 0)
1665 fprintf (stderr
, "gcjh: `%s' option is unimplemented\n", argv
[argi
]);
1668 else if (strcmp (arg
, "-MD") == 0)
1670 emit_dependencies
= 1;
1671 jcf_dependency_init (1);
1673 else if (strcmp (arg
, "-MMD") == 0)
1675 emit_dependencies
= 1;
1676 jcf_dependency_init (0);
1680 fprintf (stderr
, "%s: illegal argument\n", argv
[argi
]);
1690 if (output_file
&& emit_dependencies
)
1692 fprintf (stderr
, "gcjh: can't specify both -o and -MD\n");
1696 for (; argi
< argc
; argi
++)
1698 char *classname
= argv
[argi
];
1699 char *current_output_file
;
1700 const char *classfile_name
;
1703 fprintf (stderr
, "Processing %s\n", classname
);
1705 jcf_dependency_reset ();
1706 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 0);
1707 if (classfile_name
== NULL
)
1709 fprintf (stderr
, "%s: no such class\n", classname
);
1713 fprintf (stderr
, "Found in %s\n", classfile_name
);
1716 if (strcmp (output_file
, "-") == 0)
1718 else if (out
== NULL
)
1720 out
= fopen (output_file
, "w");
1724 perror (output_file
);
1727 current_output_file
= output_file
;
1731 int dir_len
= strlen (output_directory
);
1732 int i
, classname_length
= strlen (classname
);
1733 current_output_file
= (char*) ALLOC (dir_len
+ classname_length
+ 5);
1734 strcpy (current_output_file
, output_directory
);
1735 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
1736 current_output_file
[dir_len
++] = '/';
1737 for (i
= 0; classname
[i
] != '\0'; i
++)
1739 char ch
= classname
[i
];
1742 current_output_file
[dir_len
++] = ch
;
1744 if (emit_dependencies
)
1746 if (suppress_output
)
1748 jcf_dependency_set_dep_file ("-");
1753 /* We use `.hd' and not `.d' to avoid clashes with
1754 dependency tracking from straight compilation. */
1755 strcpy (current_output_file
+ dir_len
, ".hd");
1756 jcf_dependency_set_dep_file (current_output_file
);
1759 strcpy (current_output_file
+ dir_len
,
1760 stubs
? ".cc" : ".h");
1761 jcf_dependency_set_target (current_output_file
);
1762 if (! suppress_output
)
1764 out
= fopen (current_output_file
, "w");
1767 perror (current_output_file
);
1772 process_file (&jcf
, out
);
1774 if (current_output_file
!= output_file
)
1775 free (current_output_file
);
1776 jcf_dependency_write ();
1779 if (out
!= NULL
&& out
!= stdout
)
1787 * Emit "structure forward declarations" when needed.
1789 * Generate C headers, like javah