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)
1312 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
1316 fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.
1318 // This file is intended to give you a head start on implementing native
1319 // methods using CNI.
1320 // Be aware: running `gcjh -stubs' once more for this class may overwrite any
1321 // edits you have made to this file.\n\n", out);
1328 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1329 fprintf (out, "__\n");
1331 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1332 fprintf (out, "__\n\n");
1334 /* We do this to ensure that inline methods won't be `outlined'
1335 by g++. This works as long as method and fields are not
1336 added by the user. */
1337 fprintf (out, "#pragma interface\n");
1339 if (jcf->super_class)
1342 unsigned char *supername = super_class_name (jcf, &super_length);
1345 print_include (out, supername, super_length);
1350 /* Strip off the ".class" portion of the name when printing
1351 the include file name. */
1352 print_include (out, jcf->classname, strlen (jcf->classname) - 6);
1356 /* We want to parse the methods first. But we need to find where
1357 they start. So first we skip the fields, then parse the methods.
1358 Then we parse the fields and skip the methods. This is ugly, but
1359 not too bad since we need two full passes to get class decl
1360 information anyway. */
1362 field_start = JCF_TELL (jcf);
1363 jcf_parse_fields (jcf);
1365 method_start = JCF_TELL (jcf);
1367 jcf_parse_methods (jcf);
1374 print_class_decls (out, jcf, jcf->this_class);
1376 for (i = 0; i < prepend_count; ++i)
1377 fprintf (out, "%s\n", prepend_specs[i]);
1378 if (prepend_count > 0)
1383 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1385 fprintf (stderr, "class is of array type\n");
1389 if (jcf->super_class)
1391 if (! print_cxx_classname (out, " : public ",
1392 jcf, jcf->super_class))
1394 fprintf (stderr, "base class is of array type\n");
1400 fputs ("\n{\n", out);
1404 /* Now go back for second pass over methods and fields. */
1405 JCF_SEEK (jcf, method_start);
1407 jcf_parse_methods (jcf);
1408 method_end = JCF_TELL (jcf);
1411 JCF_SEEK (jcf, field_start);
1412 jcf_parse_fields (jcf);
1413 JCF_SEEK (jcf, method_end);
1415 jcf_parse_final_attributes (jcf);
1419 /* Generate friend decl if we still must. */
1420 for (i = 0; i < friend_count; ++i)
1421 fprintf (out, " friend %s\n", friend_specs[i]);
1423 /* Generate extra declarations. */
1426 for (i = 0; i < add_count; ++i)
1427 fprintf (out, " %s\n", add_specs[i]);
1430 fputs ("};\n", out);
1432 if (append_count > 0)
1434 for (i = 0; i < append_count; ++i)
1435 fprintf (out, "%s\n", append_specs[i]);
1439 print_mangled_classname (out, jcf,
1440 "\n#endif /* __", jcf->this_class);
1441 fprintf (out, "__ */\n");
1449 fprintf (stderr, "gcjh: no classes specified\n");
1456 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1457 printf ("Generate C++ header files from .class files\n\n");
1458 printf (" --classpath PATH Set path to find .class files\n");
1459 printf (" --CLASSPATH PATH Set path to find .class files\n");
1460 printf (" -IDIR Append directory to class path\n");
1461 printf (" -d DIRECTORY Set output directory name\n");
1462 printf (" --help Print this help, then exit\n");
1463 printf (" -o FILE Set output file name\n");
1464 printf (" -stubs Generate a C++ implementation stub file\n");
1465 printf (" -td DIRECTORY Set temporary directory name\n");
1466 printf (" -v, --verbose Print extra information while running\n");
1467 printf (" --version Print version number, then exit\n");
1468 /* FIXME: print bug-report information. */
1473 java_no_argument (opt)
1476 fprintf (stderr, "gcjh: no argument given for option `%s'\n", opt);
1483 /* FIXME: use version.c? */
1484 printf ("gcjh (%s)\n\n", version_string);
1485 printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1486 printf ("This is free software; see the source for copying conditions. There is NO\n");
1487 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1492 DEFUN(main, (argc, argv),
1493 int argc AND char** argv)
1497 char *output_file = NULL;
1498 int emit_dependencies = 0, suppress_output = 0;
1505 for (argi = 1; argi < argc; argi++)
1507 char *arg = argv[argi];
1509 if (arg[0] != '-' || ! strcmp (arg, "--"))
1512 /* Just let all arguments be given in either "-" or "--" form. */
1516 if (strcmp (arg, "-o") == 0)
1518 if (argi + 1 < argc)
1519 output_file = argv[++argi];
1521 java_no_argument (argv[argi]);
1523 else if (strcmp (arg, "-d") == 0)
1525 if (argi + 1 < argc)
1526 output_directory = argv[++argi];
1528 java_no_argument (argv[argi]);
1530 else if (strcmp (arg, "-td") == 0)
1532 if (argi + 1 < argc)
1533 temp_directory = argv[++argi];
1535 java_no_argument (argv[argi]);
1537 else if (strcmp (arg, "-prepend") == 0)
1539 if (argi + 1 < argc)
1541 if (prepend_count == 0)
1542 prepend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1543 prepend_specs[prepend_count++] = argv[++argi];
1546 java_no_argument (argv[argi]);
1548 else if (strcmp (arg, "-friend") == 0)
1550 if (argi + 1 < argc)
1552 if (friend_count == 0)
1553 friend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1554 friend_specs[friend_count++] = argv[++argi];
1557 java_no_argument (argv[argi]);
1559 else if (strcmp (arg, "-add") == 0)
1561 if (argi + 1 < argc)
1564 add_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1565 add_specs[add_count++] = argv[++argi];
1568 java_no_argument (argv[argi]);
1570 else if (strcmp (arg, "-append") == 0)
1572 if (argi + 1 < argc)
1574 if (append_count == 0)
1575 append_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1576 append_specs[append_count++] = argv[++argi];
1579 java_no_argument (argv[argi]);
1581 else if (strcmp (arg, "-classpath") == 0)
1583 if (argi + 1 < argc)
1584 jcf_path_classpath_arg (argv[++argi]);
1586 java_no_argument (argv[argi]);
1588 else if (strcmp (arg, "-CLASSPATH") == 0)
1590 if (argi + 1 < argc)
1591 jcf_path_CLASSPATH_arg (argv[++argi]);
1593 java_no_argument (argv[argi]);
1595 else if (strncmp (arg, "-I", 2) == 0)
1596 jcf_path_include_arg (arg + 2);
1597 else if (strcmp (arg, "-verbose") == 0 || strcmp (arg, "-v") == 0)
1599 else if (strcmp (arg, "-stubs") == 0)
1601 else if (strcmp (arg, "-help") == 0)
1603 else if (strcmp (arg, "-version") == 0)
1605 else if (strcmp (arg, "-M") == 0)
1607 emit_dependencies = 1;
1608 suppress_output = 1;
1609 jcf_dependency_init (1);
1611 else if (strcmp (arg, "-MM") == 0)
1613 emit_dependencies = 1;
1614 suppress_output = 1;
1615 jcf_dependency_init (0);
1617 else if (strcmp (arg, "-MG") == 0)
1619 fprintf (stderr, "gcjh: `%s' option is unimplemented\n", argv[argi]);
1622 else if (strcmp (arg, "-MD") == 0)
1624 emit_dependencies = 1;
1625 jcf_dependency_init (1);
1627 else if (strcmp (arg, "-MMD") == 0)
1629 emit_dependencies = 1;
1630 jcf_dependency_init (0);
1634 fprintf (stderr, "%s: illegal argument\n", argv[argi]);
1644 if (output_file && emit_dependencies)
1646 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
1650 for (; argi < argc; argi++)
1652 char *classname = argv[argi];
1653 char *classfile_name, *current_output_file;
1656 fprintf (stderr, "Processing %s\n", classname);
1658 jcf_dependency_reset ();
1659 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
1660 if (classfile_name == NULL)
1662 fprintf (stderr, "%s: no such class\n", classname);
1666 fprintf (stderr, "Found in %s\n", classfile_name);
1669 if (strcmp (output_file, "-") == 0)
1671 else if (out == NULL)
1673 out = fopen (output_file, "w");
1677 perror (output_file);
1680 current_output_file = output_file;
1684 int dir_len = strlen (output_directory);
1685 int i, classname_length = strlen (classname);
1686 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
1687 strcpy (current_output_file, output_directory);
1688 if (dir_len > 0 && output_directory[dir_len-1] != '/')
1689 current_output_file[dir_len++] = '/';
1690 for (i = 0; classname[i] != '\0'; i++)
1692 char ch = classname[i];
1695 current_output_file[dir_len++] = ch;
1697 if (emit_dependencies)
1699 if (suppress_output)
1701 jcf_dependency_set_dep_file ("-");
1706 /* We use `.hd' and not `.d' to avoid clashes with
1707 dependency tracking from straight compilation. */
1708 strcpy (current_output_file + dir_len, ".hd");
1709 jcf_dependency_set_dep_file (current_output_file);
1712 strcpy (current_output_file + dir_len,
1713 stubs ? ".cc" : ".h");
1714 jcf_dependency_set_target (current_output_file);
1715 if (! suppress_output)
1717 out = fopen (current_output_file, "w");
1720 perror (current_output_file);
1725 process_file (&jcf, out);
1727 if (current_output_file != output_file)
1728 free (current_output_file);
1729 jcf_dependency_write ();
1732 if (out != NULL && out != stdout)
1740 * Emit "structure forward declarations" when needed.
1742 * Generate C headers, like javah