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));
123 JCF_u2 current_field_name;
124 JCF_u2 current_field_value;
125 JCF_u2 current_field_signature;
126 JCF_u2 current_field_flags;
128 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
129 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
130 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
132 /* We pass over fields twice. The first time we just note the types
133 of the fields and then the start of the methods. Then we go back
134 and parse the fields for real. This is ugly. */
135 static int field_pass;
136 /* Likewise we pass over methods twice. The first time we generate
137 class decl information; the second time we generate actual method
139 static int method_pass;
141 #define HANDLE_END_FIELD() \
144 if (out && ! stubs) \
145 print_field_info (out, jcf, current_field_name, \
146 current_field_signature, \
147 current_field_flags); \
150 if (! stubs) add_class_decl (out, jcf, current_field_signature);
152 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
154 static int method_declared = 0;
155 static int method_access = 0;
156 static int method_printed = 0;
157 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
160 decompiled = 0; method_printed = 0; \
162 print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
165 if (! stubs) add_class_decl (out, jcf, SIGNATURE);
167 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
168 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
170 static int decompiled = 0;
171 #define HANDLE_END_METHOD() \
172 if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out);
174 #include "jcf-reader.c"
176 /* Some useful constants. */
177 #define F_NAN_MASK 0x7f800000
178 #define D_NAN_MASK 0x7ff0000000000000LL
180 /* Return 1 if F is not Inf or NaN. */
182 java_float_finite (f)
191 /* We happen to know that F_NAN_MASK will match all NaN values, and
192 also positive and negative infinity. That's why we only need one
193 test here. See The Java Language Specification, section 20.9. */
194 return (u.i & F_NAN_MASK) != F_NAN_MASK;
197 /* Return 1 if D is not Inf or NaN. */
199 java_double_finite (d)
208 /* Now check for all NaNs. */
209 return (u.i & D_NAN_MASK) != D_NAN_MASK;
213 DEFUN(print_name, (stream, jcf, name_index),
214 FILE* stream AND JCF* jcf AND int name_index)
216 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
217 fprintf (stream, "<not a UTF8 constant>");
219 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
220 JPOOL_UTF_LENGTH (jcf, name_index));
223 /* Print base name of class. The base name is everything after the
227 print_base_classname (stream, jcf, index)
232 int name_index = JPOOL_USHORT1 (jcf, index);
234 unsigned char *s, *p, *limit;
236 s = JPOOL_UTF_DATA (jcf, name_index);
237 len = JPOOL_UTF_LENGTH (jcf, name_index);
242 int c = UTF8_GET (s, limit);
249 int ch = UTF8_GET (p, limit);
251 fputs ("::", stream);
253 jcf_print_char (stream, ch);
257 /* Return 0 if NAME is equal to STR, nonzero otherwise. */
260 utf8_cmp (str, length, name)
265 unsigned char *limit = str + length;
268 for (i = 0; name[i]; ++i)
270 int ch = UTF8_GET (str, limit);
278 /* If NAME is the name of a C++ keyword, then return an override name.
279 This is a name that can be used in place of the keyword.
280 Otherwise, return NULL. FIXME: for now, we only handle those
281 keywords we know to be a problem for libgcj. */
284 cxx_keyword_subst (str, length)
288 if (! utf8_cmp (str, length, "delete"))
289 return "__dummy_delete";
290 else if (! utf8_cmp (str, length, "enum"))
291 return "__dummy_enum";
295 /* Generate an access control keyword based on FLAGS. Returns 0 if
296 FLAGS matches the saved access information, nonzero otherwise. */
299 generate_access (stream, flags)
303 if ((flags & ACC_VISIBILITY) == last_access)
305 last_access = (flags & ACC_VISIBILITY);
310 fputs ("public: // actually package-private\n", stream);
313 fputs ("public:\n", stream);
316 fputs ("private:\n", stream);
319 fputs ("public: // actually protected\n", stream);
323 fprintf (stream, "#error unrecognized visibility %d\n",
324 (flags & ACC_VISIBILITY));
329 /* See if NAME is already the name of a method. */
331 name_is_method_p (name, length)
335 struct method_name *p;
337 for (p = method_name_list; p != NULL; p = p->next)
339 if (p->length == length && ! memcmp (p->name, name, length))
345 /* Get name of a field. This handles renamings due to C++ clash. */
347 get_field_name (jcf, name_index, flags)
352 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
353 int length = JPOOL_UTF_LENGTH (jcf, name_index);
356 if (name_is_method_p (name, length))
358 /* This field name matches a method. So override the name with
359 a dummy name. This is yucky, but it isn't clear what else to
360 do. FIXME: if the field is static, then we'll be in real
362 if ((flags & ACC_STATIC))
364 fprintf (stderr, "static field has same name as method\n");
369 override = (char *) malloc (length + 3);
370 memcpy (override, name, length);
371 strcpy (override + length, "__");
373 else if ((override = cxx_keyword_subst (name, length)) != NULL)
375 /* Must malloc OVERRIDE. */
376 char *o2 = (char *) malloc (strlen (override) + 1);
377 strcpy (o2, override);
384 /* Print a field name. Convenience function for use with
387 print_field_name (stream, jcf, name_index, flags)
393 char *override = get_field_name (jcf, name_index, flags);
397 fputs (override, stream);
401 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
402 JPOOL_UTF_LENGTH (jcf, name_index));
406 DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
407 FILE *stream AND JCF* jcf
408 AND int name_index AND int sig_index AND JCF_u2 flags)
410 char *override = NULL;
412 generate_access (stream, flags);
413 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
415 fprintf (stream, "<not a UTF8 constant>");
420 if (flags & ACC_FINAL)
422 if (current_field_value > 0)
427 switch (JPOOL_TAG (jcf, current_field_value))
429 case CONSTANT_Integer:
432 int most_negative = 0;
433 fputs (" static const jint ", out);
434 print_field_name (out, jcf, name_index);
436 num = JPOOL_INT (jcf, current_field_value);
437 /* We single out the most negative number to print
438 specially. This avoids later warnings from g++. */
439 if (num == (jint) 0x80000000)
444 format_int (buffer, (jlong) num, 10);
445 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
451 int most_negative = 0;
452 fputs (" static const jlong ", out);
453 print_field_name (out, jcf, name_index);
455 num = JPOOL_LONG (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 == (jlong) 0x8000000000000000LL)
463 format_int (buffer, num, 10);
464 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
469 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
470 fputs (" static const jfloat ", out);
471 print_field_name (out, jcf, name_index);
472 if (! java_float_finite (fnum))
475 fprintf (out, " = %.10g;\n", fnum);
478 case CONSTANT_Double:
480 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
481 fputs (" static const jdouble ", out);
482 print_field_name (out, jcf, name_index);
483 if (! java_double_finite (dnum))
486 fprintf (out, " = %.17g;\n", dnum);
490 /* We can't print this as a constant, but we can still
491 print something sensible. */
502 if ((flags & ACC_STATIC))
503 fputs ("static ", out);
505 override = get_field_name (jcf, name_index, flags);
506 print_c_decl (out, jcf, name_index, sig_index, 0, override);
514 DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
515 FILE *stream AND JCF* jcf
516 AND int name_index AND int sig_index AND JCF_u2 flags)
519 int length, is_init = 0;
520 const char *override = NULL;
523 method_access = flags;
524 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
525 fprintf (stream, "<not a UTF8 constant>");
526 str = JPOOL_UTF_DATA (jcf, name_index);
527 length = JPOOL_UTF_LENGTH (jcf, name_index);
528 if (str[0] == '<' || str[0] == '$')
530 /* Ignore internally generated methods like <clinit> and
531 $finit$. However, treat <init> as a constructor. */
532 if (! utf8_cmp (str, length, "<init>"))
534 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
535 && ! (flags & ACC_STATIC))
537 /* FIXME: i18n bug here. Order of prints should not be
539 fprintf (stderr, "ignored method `");
540 jcf_print_utf8 (stderr, str, length);
541 fprintf (stderr, "' marked virtual\n");
550 struct method_name *nn;
552 nn = (struct method_name *) malloc (sizeof (struct method_name));
553 nn->name = (char *) malloc (length);
554 memcpy (nn->name, str, length);
556 nn->next = method_name_list;
557 method_name_list = nn;
560 /* We can't generate a method whose name is a C++ reserved word. We
561 can't just ignore the function, because that will cause incorrect
562 code to be generated if the function is virtual (not only for
563 calls to this function for for other functions after it in the
564 vtbl). So we give it a dummy name instead. */
565 override = cxx_keyword_subst (str, length);
568 /* If the method is static or final, we can safely skip it. If
569 we don't skip it then we'll have problems since the mangling
570 will be wrong. FIXME. */
571 if (METHOD_IS_FINAL (jcf->access_flags, flags)
572 || (flags & ACC_STATIC))
580 generate_access (stream, flags);
583 if ((flags & ACC_STATIC))
584 fputs ("static ", out);
585 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
587 /* Don't print `virtual' if we have a constructor. */
589 fputs ("virtual ", out);
591 print_c_decl (out, jcf, name_index, sig_index, is_init, override);
593 if ((flags & ACC_ABSTRACT))
600 if (METHOD_IS_NATIVE(flags))
603 print_stub (out, jcf, name_index, sig_index, is_init, override);
608 /* Try to decompile a method body. Right now we just try to handle a
609 simple case that we can do. Expand as desired. */
611 decompile_method (out, jcf, code_len)
616 unsigned char *codes = jcf->read_ptr;
618 uint16 name_and_type, name;
620 /* If the method is synchronized, don't touch it. */
621 if ((method_access & ACC_SYNCHRONIZED))
625 && codes[0] == OPCODE_aload_0
626 && codes[1] == OPCODE_getfield
627 && (codes[4] == OPCODE_areturn
628 || codes[4] == OPCODE_dreturn
629 || codes[4] == OPCODE_freturn
630 || codes[4] == OPCODE_ireturn
631 || codes[4] == OPCODE_lreturn))
633 /* Found code like `return FIELD'. */
634 fputs (" { return ", out);
635 index = (codes[2] << 8) | codes[3];
636 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
637 /* FIXME: ensure that the field's class is this class. */
638 name_and_type = JPOOL_USHORT2 (jcf, index);
639 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
640 name = JPOOL_USHORT1 (jcf, name_and_type);
641 print_name (out, jcf, name);
645 else if (code_len == 2
646 && codes[0] == OPCODE_aload_0
647 && codes[1] == OPCODE_areturn)
649 /* Found `return this'. */
650 fputs (" { return this; }", out);
653 else if (code_len == 1 && codes[0] == OPCODE_return)
655 /* Found plain `return'. */
659 else if (code_len == 2
660 && codes[0] == OPCODE_aconst_null
661 && codes[1] == OPCODE_areturn)
663 /* Found `return null'. We don't want to depend on NULL being
665 fputs (" { return 0; }", out);
670 /* Print one piece of a signature. Returns pointer to next parseable
671 character on success, NULL on error. */
672 static unsigned char *
673 decode_signature_piece (stream, signature, limit, need_space)
675 unsigned char *signature, *limit;
680 switch (signature[0])
683 for (signature++; (signature < limit
685 && *signature <= '9'); signature++)
689 case 'B': ctype = "jbyteArray"; goto printit;
690 case 'C': ctype = "jcharArray"; goto printit;
691 case 'D': ctype = "jdoubleArray"; goto printit;
692 case 'F': ctype = "jfloatArray"; goto printit;
693 case 'I': ctype = "jintArray"; goto printit;
694 case 'S': ctype = "jshortArray"; goto printit;
695 case 'J': ctype = "jlongArray"; goto printit;
696 case 'Z': ctype = "jbooleanArray"; goto printit;
697 case '[': ctype = "jobjectArray"; goto printit;
699 /* We have to generate a reference to JArray here,
700 so that our output matches what the compiler
703 fputs ("JArray<", stream);
704 while (signature < limit && *signature != ';')
706 int ch = UTF8_GET (signature, limit);
708 fputs ("::", stream);
710 jcf_print_char (stream, ch);
712 fputs (" *> *", stream);
717 /* Unparseable signature. */
724 /* This shouldn't happen. */
727 case 'B': ctype = "jbyte"; goto printit;
728 case 'C': ctype = "jchar"; goto printit;
729 case 'D': ctype = "jdouble"; goto printit;
730 case 'F': ctype = "jfloat"; goto printit;
731 case 'I': ctype = "jint"; goto printit;
732 case 'J': ctype = "jlong"; goto printit;
733 case 'S': ctype = "jshort"; goto printit;
734 case 'Z': ctype = "jboolean"; goto printit;
735 case 'V': ctype = "void"; goto printit;
738 while (*signature && *signature != ';')
740 int ch = UTF8_GET (signature, limit);
741 /* `$' is the separator for an inner class. */
742 if (ch == '/' || ch == '$')
743 fputs ("::", stream);
745 jcf_print_char (stream, ch);
747 fputs (" *", stream);
748 if (*signature == ';')
754 jcf_print_char (stream, *signature++);
759 fputs (ctype, stream);
767 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
769 FILE* stream AND JCF* jcf
770 AND int name_index AND int signature_index
771 AND int is_init AND const char *name_override)
773 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
775 fprintf (stream, "<not a UTF8 constant>");
780 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
781 unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
782 register unsigned char *str = str0;
783 unsigned char *limit = str + length;
785 int is_method = str[0] == '(';
788 /* If printing a method, skip to the return signature and print
789 that first. However, there is no return value if this is a
791 if (is_method && ! is_init)
801 /* If printing a field or an ordinary method, then print the
802 "return value" now. */
803 if (! is_method || ! is_init)
805 next = decode_signature_piece (stream, str, limit, &need_space);
808 fprintf (stderr, "unparseable signature: `%s'\n", str0);
814 /* Now print the name of the thing. */
817 print_full_cxx_name (stream, jcf, name_index,
818 signature_index, is_init, name_override);
822 // Print the unqualified method name followed by the signature.
824 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, is_init, name_override),
825 FILE* stream AND JCF* jcf
826 AND int name_index AND int signature_index AND int is_init
827 AND const char *name_override)
829 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
830 unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
831 register unsigned char *str = str0;
832 unsigned char *limit = str + length;
834 int is_method = str[0] == '(';
838 fputs (name_override, stream);
841 /* Declare constructors specially. */
843 print_base_classname (stream, jcf, jcf->this_class);
845 print_name (stream, jcf, name_index);
850 /* Have a method or a constructor. Print signature pieces
852 fputs (" (", stream);
854 while (str < limit && *str != ')')
856 next = decode_signature_piece (stream, str, limit, &need_space);
859 fprintf (stderr, "unparseable signature: `%s'\n", str0);
864 if (next < limit && *next != ')')
865 fputs (", ", stream);
874 DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init,
876 FILE* stream AND JCF* jcf
877 AND int name_index AND int signature_index
878 AND int is_init AND const char *name_override)
880 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
882 fprintf (stream, "<not a UTF8 constant>");
887 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
888 unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
889 register unsigned char *str = str0;
890 unsigned char *limit = str + length;
892 int is_method = str[0] == '(';
895 /* If printing a method, skip to the return signature and print
896 that first. However, there is no return value if this is a
898 if (is_method && ! is_init)
908 /* If printing a field or an ordinary method, then print the
909 "return value" now. */
910 if (! is_method || ! is_init)
912 next = decode_signature_piece (stream, str, limit, &need_space);
915 fprintf (stderr, "unparseable signature: `%s'\n", str0);
921 /* Now print the name of the thing. */
922 print_cxx_classname (stream, "\n", jcf, jcf->this_class);
923 fputs ("::", stream);
924 print_full_cxx_name (stream, jcf, name_index,
925 signature_index, is_init, name_override);
926 fputs ("\n{\n JvFail (\"", stream);
927 print_cxx_classname (stream, "", jcf, jcf->this_class);
928 fputs ("::", stream);
929 print_full_cxx_name (stream, jcf, name_index,
930 signature_index, is_init, name_override);
931 fputs (" not implemented\");\n}\n\n", stream);
936 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
937 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
939 int name_index = JPOOL_USHORT1 (jcf, index);
940 fputs (prefix, stream);
941 jcf_print_utf8_replace (out,
942 JPOOL_UTF_DATA (jcf, name_index),
943 JPOOL_UTF_LENGTH (jcf, name_index),
947 /* Print PREFIX, then a class name in C++ format. If the name refers
948 to an array, ignore it and don't print PREFIX. Returns 1 if
949 something was printed, 0 otherwise. */
951 print_cxx_classname (stream, prefix, jcf, index)
957 int name_index = JPOOL_USHORT1 (jcf, index);
959 unsigned char *s, *p, *limit;
961 s = JPOOL_UTF_DATA (jcf, name_index);
962 len = JPOOL_UTF_LENGTH (jcf, name_index);
965 /* Explicitly omit arrays here. */
967 c = UTF8_GET (p, limit);
971 fputs (prefix, stream);
974 c = UTF8_GET (s, limit);
976 fputs ("::", stream);
978 jcf_print_char (stream, c);
984 int written_class_count = 0;
986 /* Return name of superclass. If LEN is not NULL, fill it with length
988 static unsigned char *
989 super_class_name (derived_jcf, len)
993 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
994 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
995 unsigned char *supername = JPOOL_UTF_DATA (derived_jcf, supername_index);
998 *len = supername_length;
1005 /* We keep track of all the `#include's we generate, so we can avoid
1010 struct include *next;
1013 /* List of all includes. */
1014 static struct include *all_includes = NULL;
1016 /* Generate a #include. */
1018 print_include (out, utf8, len)
1020 unsigned char *utf8;
1023 struct include *incl;
1029 len = strlen (utf8);
1031 for (incl = all_includes; incl; incl = incl->next)
1033 /* We check the length because we might have a proper prefix. */
1034 if (len == (int) strlen (incl->name)
1035 && ! strncmp (incl->name, utf8, len))
1039 incl = (struct include *) malloc (sizeof (struct include));
1040 incl->name = malloc (len + 1);
1041 strncpy (incl->name, utf8, len);
1042 incl->name[len] = '\0';
1043 incl->next = all_includes;
1044 all_includes = incl;
1046 fputs ("#include <", out);
1047 jcf_print_utf8 (out, utf8, len);
1048 fputs (".h>\n", out);
1053 /* This is used to represent part of a package or class name. */
1056 /* The text of this part of the name. */
1058 /* True if this represents a class. */
1060 /* Linked list of all classes and packages inside this one. */
1061 struct namelet *subnamelets;
1062 /* Pointer to next sibling. */
1063 struct namelet *next;
1066 /* The special root namelet. */
1067 static struct namelet root =
1075 /* This extracts the next name segment from the full UTF-8 encoded
1076 package or class name and links it into the tree. It does this
1079 add_namelet (name, name_limit, parent)
1080 unsigned char *name, *name_limit;
1081 struct namelet *parent;
1084 struct namelet *n = NULL, *np;
1086 /* We want to skip the standard namespaces that we assume the
1087 runtime already knows about. We only do this at the top level,
1088 though, hence the check for `root'. */
1089 if (parent == &root)
1091 #define JAVALANG "java/lang/"
1092 #define JAVAIO "java/io/"
1093 #define JAVAUTIL "java/util/"
1094 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1095 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1096 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1097 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1098 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1099 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1103 for (p = name; p < name_limit && *p != '/' && *p != '$'; ++p)
1106 /* Search for this name beneath the PARENT node. */
1107 for (np = parent->subnamelets; np != NULL; np = np->next)
1109 /* We check the length because we might have a proper prefix. */
1110 if ((int) strlen (np->name) == p - name &&
1111 ! strncmp (name, np->name, p - name))
1120 n = (struct namelet *) malloc (sizeof (struct namelet));
1121 n->name = malloc (p - name + 1);
1122 strncpy (n->name, name, p - name);
1123 n->name[p - name] = '\0';
1124 n->is_class = (p == name_limit || *p == '$');
1125 n->subnamelets = NULL;
1126 n->next = parent->subnamelets;
1127 parent->subnamelets = n;
1130 /* We recurse if there is more text, and if the trailing piece does
1131 not represent an inner class. */
1132 if (p < name_limit && *p != '$')
1133 add_namelet (p + 1, name_limit, n);
1136 /* Print a single namelet. Destroys namelets while printing. */
1138 print_namelet (out, name, depth)
1140 struct namelet *name;
1148 for (i = 0; i < depth; ++i)
1150 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1152 if (name->is_class && name->subnamelets == NULL)
1158 for (i = 0; i < depth; ++i)
1164 c = name->subnamelets;
1167 struct namelet *next = c->next;
1168 print_namelet (out, c, depth + 2);
1176 for (i = 0; i < depth; ++i)
1178 fputs ("};\n", out);
1186 /* This is called to add some classes to the list of classes for which
1187 we need decls. The signature argument can be a function
1190 add_class_decl (out, jcf, signature)
1195 unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1196 int len = JPOOL_UTF_LENGTH (jcf, signature);
1198 /* Name of class we are processing. */
1199 int name_index = JPOOL_USHORT1 (jcf, jcf->this_class);
1200 int tlen = JPOOL_UTF_LENGTH (jcf, name_index);
1201 char *tname = JPOOL_UTF_DATA (jcf, name_index);
1203 for (i = 0; i < len; ++i)
1205 int start, saw_dollar;
1207 /* If we see an array, then we include the array header. */
1210 print_include (out, "java-array", -1);
1214 /* We're looking for `L<stuff>;' -- everything else is
1220 for (start = ++i; i < len && s[i] != ';'; ++i)
1222 if (! saw_dollar && s[i] == '$' && out)
1225 /* If this class represents an inner class, then
1226 generate a `#include' for the outer class. However,
1227 don't generate the include if the outer class is the
1228 class we are processing. */
1229 if (i - start < tlen || strncmp (&s[start], tname, i - start))
1230 print_include (out, &s[start], i - start);
1235 /* If we saw an inner class, then the generated #include will
1236 declare the class. So in this case we needn't bother. */
1238 add_namelet (&s[start], &s[i], &root);
1242 /* Print declarations for all classes required by this class. Any
1243 class or package in the `java' package is assumed to be handled
1244 statically in libjava; we don't generate declarations for these.
1245 This makes the generated headers a bit easier to read. */
1247 print_class_decls (out, jcf, self)
1252 /* Make sure to always add the current class to the list of things
1253 that should be declared. */
1254 int name_index = JPOOL_USHORT1 (jcf, self);
1258 s = JPOOL_UTF_DATA (jcf, name_index);
1259 len = JPOOL_UTF_LENGTH (jcf, name_index);
1260 add_namelet (s, s + len, &root);
1262 if (root.subnamelets)
1264 fputs ("extern \"Java\"\n{\n", out);
1265 /* We use an initial offset of 0 because the root namelet
1266 doesn't cause anything to print. */
1267 print_namelet (out, &root, 0);
1268 fputs ("};\n\n", out);
1275 DEFUN(process_file, (jcf, out),
1276 JCF *jcf AND FILE *out)
1279 uint32 field_start, method_end, method_start;
1285 if (jcf_parse_preamble (jcf) != 0)
1287 fprintf (stderr, "Not a valid Java .class file.\n");
1292 /* Parse and possibly print constant pool */
1293 code = jcf_parse_constant_pool (jcf);
1296 fprintf (stderr, "error while parsing constant pool\n");
1300 code = verify_constant_pool (jcf);
1303 fprintf (stderr, "error in constant pool entry #%d\n", code);
1308 jcf_parse_class (jcf);
1310 if (written_class_count++ == 0 && out)
1313 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
1317 fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.
1319 // This file is intended to give you a head start on implementing native
1320 // methods using CNI.
1321 // Be aware: running `gcjh -stubs' once more for this class may overwrite any
1322 // edits you have made to this file.\n\n", out);
1330 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1331 fprintf (out, "__\n");
1333 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1334 fprintf (out, "__\n\n");
1336 /* We do this to ensure that inline methods won't be `outlined'
1337 by g++. This works as long as method and fields are not
1338 added by the user. */
1339 fprintf (out, "#pragma interface\n");
1341 if (jcf->super_class)
1344 unsigned char *supername = super_class_name (jcf, &super_length);
1347 print_include (out, supername, super_length);
1352 /* Strip off the ".class" portion of the name when printing
1353 the include file name. */
1354 print_include (out, jcf->classname, strlen (jcf->classname) - 6);
1358 /* We want to parse the methods first. But we need to find where
1359 they start. So first we skip the fields, then parse the methods.
1360 Then we parse the fields and skip the methods. This is ugly, but
1361 not too bad since we need two full passes to get class decl
1362 information anyway. */
1364 field_start = JCF_TELL (jcf);
1365 jcf_parse_fields (jcf);
1367 method_start = JCF_TELL (jcf);
1369 jcf_parse_methods (jcf);
1376 print_class_decls (out, jcf, jcf->this_class);
1378 for (i = 0; i < prepend_count; ++i)
1379 fprintf (out, "%s\n", prepend_specs[i]);
1380 if (prepend_count > 0)
1385 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1387 fprintf (stderr, "class is of array type\n");
1391 if (jcf->super_class)
1393 if (! print_cxx_classname (out, " : public ",
1394 jcf, jcf->super_class))
1396 fprintf (stderr, "base class is of array type\n");
1402 fputs ("\n{\n", out);
1406 /* Now go back for second pass over methods and fields. */
1407 JCF_SEEK (jcf, method_start);
1409 jcf_parse_methods (jcf);
1410 method_end = JCF_TELL (jcf);
1413 JCF_SEEK (jcf, field_start);
1414 jcf_parse_fields (jcf);
1415 JCF_SEEK (jcf, method_end);
1417 jcf_parse_final_attributes (jcf);
1421 /* Generate friend decl if we still must. */
1422 for (i = 0; i < friend_count; ++i)
1423 fprintf (out, " friend %s\n", friend_specs[i]);
1425 /* Generate extra declarations. */
1428 for (i = 0; i < add_count; ++i)
1429 fprintf (out, " %s\n", add_specs[i]);
1432 fputs ("};\n", out);
1434 if (append_count > 0)
1436 for (i = 0; i < append_count; ++i)
1437 fprintf (out, "%s\n", append_specs[i]);
1441 print_mangled_classname (out, jcf,
1442 "\n#endif /* __", jcf->this_class);
1443 fprintf (out, "__ */\n");
1451 fprintf (stderr, "gcjh: no classes specified\n");
1458 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1459 printf ("Generate C++ header files from .class files\n\n");
1460 printf (" --classpath PATH Set path to find .class files\n");
1461 printf (" --CLASSPATH PATH Set path to find .class files\n");
1462 printf (" -IDIR Append directory to class path\n");
1463 printf (" -d DIRECTORY Set output directory name\n");
1464 printf (" --help Print this help, then exit\n");
1465 printf (" -o FILE Set output file name\n");
1466 printf (" -stubs Generate a C++ implementation stub file\n");
1467 printf (" -td DIRECTORY Set temporary directory name\n");
1468 printf (" -v, --verbose Print extra information while running\n");
1469 printf (" --version Print version number, then exit\n");
1470 /* FIXME: print bug-report information. */
1475 java_no_argument (opt)
1478 fprintf (stderr, "gcjh: no argument given for option `%s'\n", opt);
1485 /* FIXME: use version.c? */
1486 printf ("gcjh (%s)\n\n", version_string);
1487 printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1488 printf ("This is free software; see the source for copying conditions. There is NO\n");
1489 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1494 DEFUN(main, (argc, argv),
1495 int argc AND char** argv)
1499 char *output_file = NULL;
1500 int emit_dependencies = 0, suppress_output = 0;
1507 for (argi = 1; argi < argc; argi++)
1509 char *arg = argv[argi];
1511 if (arg[0] != '-' || ! strcmp (arg, "--"))
1514 /* Just let all arguments be given in either "-" or "--" form. */
1518 if (strcmp (arg, "-o") == 0)
1520 if (argi + 1 < argc)
1521 output_file = argv[++argi];
1523 java_no_argument (argv[argi]);
1525 else if (strcmp (arg, "-d") == 0)
1527 if (argi + 1 < argc)
1528 output_directory = argv[++argi];
1530 java_no_argument (argv[argi]);
1532 else if (strcmp (arg, "-td") == 0)
1534 if (argi + 1 < argc)
1535 temp_directory = argv[++argi];
1537 java_no_argument (argv[argi]);
1539 else if (strcmp (arg, "-prepend") == 0)
1541 if (argi + 1 < argc)
1543 if (prepend_count == 0)
1544 prepend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1545 prepend_specs[prepend_count++] = argv[++argi];
1548 java_no_argument (argv[argi]);
1550 else if (strcmp (arg, "-friend") == 0)
1552 if (argi + 1 < argc)
1554 if (friend_count == 0)
1555 friend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1556 friend_specs[friend_count++] = argv[++argi];
1559 java_no_argument (argv[argi]);
1561 else if (strcmp (arg, "-add") == 0)
1563 if (argi + 1 < argc)
1566 add_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1567 add_specs[add_count++] = argv[++argi];
1570 java_no_argument (argv[argi]);
1572 else if (strcmp (arg, "-append") == 0)
1574 if (argi + 1 < argc)
1576 if (append_count == 0)
1577 append_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1578 append_specs[append_count++] = argv[++argi];
1581 java_no_argument (argv[argi]);
1583 else if (strcmp (arg, "-classpath") == 0)
1585 if (argi + 1 < argc)
1586 jcf_path_classpath_arg (argv[++argi]);
1588 java_no_argument (argv[argi]);
1590 else if (strcmp (arg, "-CLASSPATH") == 0)
1592 if (argi + 1 < argc)
1593 jcf_path_CLASSPATH_arg (argv[++argi]);
1595 java_no_argument (argv[argi]);
1597 else if (strncmp (arg, "-I", 2) == 0)
1598 jcf_path_include_arg (arg + 2);
1599 else if (strcmp (arg, "-verbose") == 0 || strcmp (arg, "-v") == 0)
1601 else if (strcmp (arg, "-stubs") == 0)
1603 else if (strcmp (arg, "-help") == 0)
1605 else if (strcmp (arg, "-version") == 0)
1607 else if (strcmp (arg, "-M") == 0)
1609 emit_dependencies = 1;
1610 suppress_output = 1;
1611 jcf_dependency_init (1);
1613 else if (strcmp (arg, "-MM") == 0)
1615 emit_dependencies = 1;
1616 suppress_output = 1;
1617 jcf_dependency_init (0);
1619 else if (strcmp (arg, "-MG") == 0)
1621 fprintf (stderr, "gcjh: `%s' option is unimplemented\n", argv[argi]);
1624 else if (strcmp (arg, "-MD") == 0)
1626 emit_dependencies = 1;
1627 jcf_dependency_init (1);
1629 else if (strcmp (arg, "-MMD") == 0)
1631 emit_dependencies = 1;
1632 jcf_dependency_init (0);
1636 fprintf (stderr, "%s: illegal argument\n", argv[argi]);
1646 if (output_file && emit_dependencies)
1648 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
1652 for (; argi < argc; argi++)
1654 char *classname = argv[argi];
1655 char *current_output_file;
1656 const char *classfile_name;
1659 fprintf (stderr, "Processing %s\n", classname);
1661 jcf_dependency_reset ();
1662 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
1663 if (classfile_name == NULL)
1665 fprintf (stderr, "%s: no such class\n", classname);
1669 fprintf (stderr, "Found in %s\n", classfile_name);
1672 if (strcmp (output_file, "-") == 0)
1674 else if (out == NULL)
1676 out = fopen (output_file, "w");
1680 perror (output_file);
1683 current_output_file = output_file;
1687 int dir_len = strlen (output_directory);
1688 int i, classname_length = strlen (classname);
1689 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
1690 strcpy (current_output_file, output_directory);
1691 if (dir_len > 0 && output_directory[dir_len-1] != '/')
1692 current_output_file[dir_len++] = '/';
1693 for (i = 0; classname[i] != '\0'; i++)
1695 char ch = classname[i];
1698 current_output_file[dir_len++] = ch;
1700 if (emit_dependencies)
1702 if (suppress_output)
1704 jcf_dependency_set_dep_file ("-");
1709 /* We use `.hd' and not `.d' to avoid clashes with
1710 dependency tracking from straight compilation. */
1711 strcpy (current_output_file + dir_len, ".hd");
1712 jcf_dependency_set_dep_file (current_output_file);
1715 strcpy (current_output_file + dir_len,
1716 stubs ? ".cc" : ".h");
1717 jcf_dependency_set_target (current_output_file);
1718 if (! suppress_output)
1720 out = fopen (current_output_file, "w");
1723 perror (current_output_file);
1728 process_file (&jcf, out);
1730 if (current_output_file != output_file)
1731 free (current_output_file);
1732 jcf_dependency_write ();
1735 if (out != NULL && out != stdout)
1743 * Emit "structure forward declarations" when needed.
1745 * Generate C headers, like javah