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 = (char *) malloc (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 *) malloc (sizeof (struct method_name));
572 nn->name = (char *) malloc (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;
699 switch (signature[0])
702 for (signature++; (signature < limit
704 && *signature <= '9'); signature++)
708 case 'B': ctype = "jbyteArray"; goto printit;
709 case 'C': ctype = "jcharArray"; goto printit;
710 case 'D': ctype = "jdoubleArray"; goto printit;
711 case 'F': ctype = "jfloatArray"; goto printit;
712 case 'I': ctype = "jintArray"; goto printit;
713 case 'S': ctype = "jshortArray"; goto printit;
714 case 'J': ctype = "jlongArray"; goto printit;
715 case 'Z': ctype = "jbooleanArray"; goto printit;
716 case '[': ctype = "jobjectArray"; goto printit;
718 /* We have to generate a reference to JArray here,
719 so that our output matches what the compiler
722 fputs ("JArray<", stream);
723 while (signature < limit && *signature != ';')
725 int ch = UTF8_GET (signature, limit);
727 fputs ("::", stream);
729 jcf_print_char (stream, ch);
731 fputs (" *> *", stream);
736 /* Unparseable signature. */
743 /* This shouldn't happen. */
746 case 'B': ctype = "jbyte"; goto printit;
747 case 'C': ctype = "jchar"; goto printit;
748 case 'D': ctype = "jdouble"; goto printit;
749 case 'F': ctype = "jfloat"; goto printit;
750 case 'I': ctype = "jint"; goto printit;
751 case 'J': ctype = "jlong"; goto printit;
752 case 'S': ctype = "jshort"; goto printit;
753 case 'Z': ctype = "jboolean"; goto printit;
754 case 'V': ctype = "void"; goto printit;
756 /* Print a leading "::" so we look in the right namespace. */
757 fputs ("::", stream);
759 while (*signature && *signature != ';')
761 int ch = UTF8_GET (signature, limit);
762 /* `$' is the separator for an inner class. */
763 if (ch == '/' || ch == '$')
764 fputs ("::", stream);
766 jcf_print_char (stream, ch);
768 fputs (" *", stream);
769 if (*signature == ';')
775 jcf_print_char (stream, *signature++);
780 fputs (ctype, stream);
788 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
790 FILE* stream AND JCF* jcf
791 AND int name_index AND int signature_index
792 AND int is_init AND const char *name_override)
794 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
796 fprintf (stream, "<not a UTF8 constant>");
801 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
802 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
803 register const unsigned char *str = str0;
804 const unsigned char *limit = str + length;
806 int is_method = str[0] == '(';
807 const unsigned char *next;
809 /* If printing a method, skip to the return signature and print
810 that first. However, there is no return value if this is a
812 if (is_method && ! is_init)
822 /* If printing a field or an ordinary method, then print the
823 "return value" now. */
824 if (! is_method || ! is_init)
826 next = decode_signature_piece (stream, str, limit, &need_space);
829 fprintf (stderr, "unparseable signature: `%s'\n", str0);
835 /* Now print the name of the thing. */
838 print_full_cxx_name (stream, jcf, name_index,
839 signature_index, is_init, name_override);
843 /* Print the unqualified method name followed by the signature. */
845 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, is_init, name_override),
846 FILE* stream AND JCF* jcf
847 AND int name_index AND int signature_index AND int is_init
848 AND const char *name_override)
850 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
851 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
852 register const unsigned char *str = str0;
853 const unsigned char *limit = str + length;
855 int is_method = str[0] == '(';
856 const unsigned char *next;
859 fputs (name_override, stream);
862 /* Declare constructors specially. */
864 print_base_classname (stream, jcf, jcf->this_class);
866 print_name (stream, jcf, name_index);
871 /* Have a method or a constructor. Print signature pieces
873 fputs (" (", stream);
875 while (str < limit && *str != ')')
877 next = decode_signature_piece (stream, str, limit, &need_space);
880 fprintf (stderr, "unparseable signature: `%s'\n", str0);
885 if (next < limit && *next != ')')
886 fputs (", ", stream);
895 DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init,
897 FILE* stream AND JCF* jcf
898 AND int name_index AND int signature_index
899 AND int is_init AND const char *name_override)
901 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
903 fprintf (stream, "<not a UTF8 constant>");
908 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
909 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
910 register const unsigned char *str = str0;
911 const unsigned char *limit = str + length;
913 int is_method = str[0] == '(';
914 const unsigned char *next;
916 /* If printing a method, skip to the return signature and print
917 that first. However, there is no return value if this is a
919 if (is_method && ! is_init)
929 /* If printing a field or an ordinary method, then print the
930 "return value" now. */
931 if (! is_method || ! is_init)
933 next = decode_signature_piece (stream, str, limit, &need_space);
936 fprintf (stderr, "unparseable signature: `%s'\n", str0);
942 /* Now print the name of the thing. */
943 print_cxx_classname (stream, "\n", jcf, jcf->this_class);
944 fputs ("::", stream);
945 print_full_cxx_name (stream, jcf, name_index,
946 signature_index, is_init, name_override);
947 fputs ("\n{\n JvFail (\"", stream);
948 print_cxx_classname (stream, "", jcf, jcf->this_class);
949 fputs ("::", stream);
950 print_full_cxx_name (stream, jcf, name_index,
951 signature_index, is_init, name_override);
952 fputs (" not implemented\");\n}\n\n", stream);
957 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
958 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
960 int name_index = JPOOL_USHORT1 (jcf, index);
961 fputs (prefix, stream);
962 jcf_print_utf8_replace (out,
963 JPOOL_UTF_DATA (jcf, name_index),
964 JPOOL_UTF_LENGTH (jcf, name_index),
968 /* Print PREFIX, then a class name in C++ format. If the name refers
969 to an array, ignore it and don't print PREFIX. Returns 1 if
970 something was printed, 0 otherwise. */
972 print_cxx_classname (stream, prefix, jcf, index)
978 int name_index = JPOOL_USHORT1 (jcf, index);
980 const unsigned char *s, *p, *limit;
982 s = JPOOL_UTF_DATA (jcf, name_index);
983 len = JPOOL_UTF_LENGTH (jcf, name_index);
986 /* Explicitly omit arrays here. */
988 c = UTF8_GET (p, limit);
992 fputs (prefix, stream);
994 /* Print a leading "::" so we look in the right namespace. */
995 fputs ("::", stream);
999 c = UTF8_GET (s, limit);
1001 fputs ("::", stream);
1003 jcf_print_char (stream, c);
1009 int written_class_count = 0;
1011 /* Return name of superclass. If LEN is not NULL, fill it with length
1013 static const unsigned char *
1014 super_class_name (derived_jcf, len)
1018 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1019 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1020 const unsigned char *supername =
1021 JPOOL_UTF_DATA (derived_jcf, supername_index);
1024 *len = supername_length;
1031 /* We keep track of all the `#include's we generate, so we can avoid
1036 struct include *next;
1039 /* List of all includes. */
1040 static struct include *all_includes = NULL;
1042 /* Generate a #include. */
1044 print_include (out, utf8, len)
1046 const unsigned char *utf8;
1049 struct include *incl;
1055 len = strlen (utf8);
1057 for (incl = all_includes; incl; incl = incl->next)
1059 /* We check the length because we might have a proper prefix. */
1060 if (len == (int) strlen (incl->name)
1061 && ! strncmp (incl->name, utf8, len))
1065 incl = (struct include *) malloc (sizeof (struct include));
1066 incl->name = malloc (len + 1);
1067 strncpy (incl->name, utf8, len);
1068 incl->name[len] = '\0';
1069 incl->next = all_includes;
1070 all_includes = incl;
1072 fputs ("#include <", out);
1073 jcf_print_utf8 (out, utf8, len);
1074 fputs (".h>\n", out);
1079 /* This is used to represent part of a package or class name. */
1082 /* The text of this part of the name. */
1084 /* True if this represents a class. */
1086 /* Linked list of all classes and packages inside this one. */
1087 struct namelet *subnamelets;
1088 /* Pointer to next sibling. */
1089 struct namelet *next;
1092 static void add_namelet PROTO ((const unsigned char *,
1093 const unsigned char *, struct namelet *));
1094 static void print_namelet PROTO ((FILE *, struct namelet *, int));
1096 /* The special root namelet. */
1097 static struct namelet root =
1105 /* This extracts the next name segment from the full UTF-8 encoded
1106 package or class name and links it into the tree. It does this
1109 add_namelet (name, name_limit, parent)
1110 const unsigned char *name, *name_limit;
1111 struct namelet *parent;
1113 const unsigned char *p;
1114 struct namelet *n = NULL, *np;
1116 /* We want to skip the standard namespaces that we assume the
1117 runtime already knows about. We only do this at the top level,
1118 though, hence the check for `root'. */
1119 if (parent == &root)
1121 #define JAVALANG "java/lang/"
1122 #define JAVAIO "java/io/"
1123 #define JAVAUTIL "java/util/"
1124 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1125 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1126 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1127 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1128 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1129 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1133 for (p = name; p < name_limit && *p != '/' && *p != '$'; ++p)
1136 /* Search for this name beneath the PARENT node. */
1137 for (np = parent->subnamelets; np != NULL; np = np->next)
1139 /* We check the length because we might have a proper prefix. */
1140 if ((int) strlen (np->name) == p - name &&
1141 ! strncmp (name, np->name, p - name))
1150 n = (struct namelet *) malloc (sizeof (struct namelet));
1151 n->name = malloc (p - name + 1);
1152 strncpy (n->name, name, p - name);
1153 n->name[p - name] = '\0';
1154 n->is_class = (p == name_limit || *p == '$');
1155 n->subnamelets = NULL;
1156 n->next = parent->subnamelets;
1157 parent->subnamelets = n;
1160 /* We recurse if there is more text, and if the trailing piece does
1161 not represent an inner class. */
1162 if (p < name_limit && *p != '$')
1163 add_namelet (p + 1, name_limit, n);
1166 /* Print a single namelet. Destroys namelets while printing. */
1168 print_namelet (out, name, depth)
1170 struct namelet *name;
1178 for (i = 0; i < depth; ++i)
1180 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1182 if (name->is_class && name->subnamelets == NULL)
1188 for (i = 0; i < depth; ++i)
1194 c = name->subnamelets;
1197 struct namelet *next = c->next;
1198 print_namelet (out, c, depth + 2);
1206 for (i = 0; i < depth; ++i)
1208 fputs ("};\n", out);
1216 /* This is called to add some classes to the list of classes for which
1217 we need decls. The signature argument can be a function
1220 add_class_decl (out, jcf, signature)
1225 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1226 int len = JPOOL_UTF_LENGTH (jcf, signature);
1228 /* Name of class we are processing. */
1229 int name_index = JPOOL_USHORT1 (jcf, jcf->this_class);
1230 int tlen = JPOOL_UTF_LENGTH (jcf, name_index);
1231 const char *tname = JPOOL_UTF_DATA (jcf, name_index);
1233 for (i = 0; i < len; ++i)
1235 int start, saw_dollar;
1237 /* If we see an array, then we include the array header. */
1240 print_include (out, "java-array", -1);
1244 /* We're looking for `L<stuff>;' -- everything else is
1250 for (start = ++i; i < len && s[i] != ';'; ++i)
1252 if (! saw_dollar && s[i] == '$' && out)
1255 /* If this class represents an inner class, then
1256 generate a `#include' for the outer class. However,
1257 don't generate the include if the outer class is the
1258 class we are processing. */
1259 if (i - start < tlen || strncmp (&s[start], tname, i - start))
1260 print_include (out, &s[start], i - start);
1265 /* If we saw an inner class, then the generated #include will
1266 declare the class. So in this case we needn't bother. */
1268 add_namelet (&s[start], &s[i], &root);
1272 /* Print declarations for all classes required by this class. Any
1273 class or package in the `java' package is assumed to be handled
1274 statically in libjava; we don't generate declarations for these.
1275 This makes the generated headers a bit easier to read. */
1277 print_class_decls (out, jcf, self)
1282 /* Make sure to always add the current class to the list of things
1283 that should be declared. */
1284 int name_index = JPOOL_USHORT1 (jcf, self);
1286 const unsigned char *s;
1288 s = JPOOL_UTF_DATA (jcf, name_index);
1289 len = JPOOL_UTF_LENGTH (jcf, name_index);
1290 add_namelet (s, s + len, &root);
1292 if (root.subnamelets)
1294 fputs ("extern \"Java\"\n{\n", out);
1295 /* We use an initial offset of 0 because the root namelet
1296 doesn't cause anything to print. */
1297 print_namelet (out, &root, 0);
1298 fputs ("};\n\n", out);
1305 DEFUN(process_file, (jcf, out),
1306 JCF *jcf AND FILE *out)
1309 uint32 field_start, method_end, method_start;
1315 if (jcf_parse_preamble (jcf) != 0)
1317 fprintf (stderr, "Not a valid Java .class file.\n");
1322 /* Parse and possibly print constant pool */
1323 code = jcf_parse_constant_pool (jcf);
1326 fprintf (stderr, "error while parsing constant pool\n");
1330 code = verify_constant_pool (jcf);
1333 fprintf (stderr, "error in constant pool entry #%d\n", code);
1338 jcf_parse_class (jcf);
1340 if (written_class_count++ == 0 && out)
1343 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
1347 fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.
1349 // This file is intended to give you a head start on implementing native
1350 // methods using CNI.
1351 // Be aware: running `gcjh -stubs' once more for this class may overwrite any
1352 // edits you have made to this file.\n\n", out);
1360 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1361 fprintf (out, "__\n");
1363 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1364 fprintf (out, "__\n\n");
1366 /* We do this to ensure that inline methods won't be `outlined'
1367 by g++. This works as long as method and fields are not
1368 added by the user. */
1369 fprintf (out, "#pragma interface\n");
1371 if (jcf->super_class)
1374 const unsigned char *supername =
1375 super_class_name (jcf, &super_length);
1378 print_include (out, supername, super_length);
1383 /* Strip off the ".class" portion of the name when printing
1384 the include file name. */
1385 print_include (out, jcf->classname, strlen (jcf->classname) - 6);
1389 /* We want to parse the methods first. But we need to find where
1390 they start. So first we skip the fields, then parse the methods.
1391 Then we parse the fields and skip the methods. This is ugly, but
1392 not too bad since we need two full passes to get class decl
1393 information anyway. */
1395 field_start = JCF_TELL (jcf);
1396 jcf_parse_fields (jcf);
1398 method_start = JCF_TELL (jcf);
1400 jcf_parse_methods (jcf);
1407 print_class_decls (out, jcf, jcf->this_class);
1409 for (i = 0; i < prepend_count; ++i)
1410 fprintf (out, "%s\n", prepend_specs[i]);
1411 if (prepend_count > 0)
1416 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1418 fprintf (stderr, "class is of array type\n");
1422 if (jcf->super_class)
1424 if (! print_cxx_classname (out, " : public ",
1425 jcf, jcf->super_class))
1427 fprintf (stderr, "base class is of array type\n");
1433 fputs ("\n{\n", out);
1437 /* Now go back for second pass over methods and fields. */
1438 JCF_SEEK (jcf, method_start);
1440 jcf_parse_methods (jcf);
1441 method_end = JCF_TELL (jcf);
1444 JCF_SEEK (jcf, field_start);
1445 jcf_parse_fields (jcf);
1446 JCF_SEEK (jcf, method_end);
1448 jcf_parse_final_attributes (jcf);
1452 /* Generate friend decl if we still must. */
1453 for (i = 0; i < friend_count; ++i)
1454 fprintf (out, " friend %s\n", friend_specs[i]);
1456 /* Generate extra declarations. */
1459 for (i = 0; i < add_count; ++i)
1460 fprintf (out, " %s\n", add_specs[i]);
1463 fputs ("};\n", out);
1465 if (append_count > 0)
1467 for (i = 0; i < append_count; ++i)
1468 fprintf (out, "%s\n", append_specs[i]);
1472 print_mangled_classname (out, jcf,
1473 "\n#endif /* __", jcf->this_class);
1474 fprintf (out, "__ */\n");
1482 fprintf (stderr, "gcjh: no classes specified\n");
1489 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1490 printf ("Generate C++ header files from .class files\n\n");
1491 printf (" --classpath PATH Set path to find .class files\n");
1492 printf (" --CLASSPATH PATH Set path to find .class files\n");
1493 printf (" -IDIR Append directory to class path\n");
1494 printf (" -d DIRECTORY Set output directory name\n");
1495 printf (" --help Print this help, then exit\n");
1496 printf (" -o FILE Set output file name\n");
1497 printf (" -stubs Generate a C++ implementation stub file\n");
1498 printf (" -td DIRECTORY Set temporary directory name\n");
1499 printf (" -v, --verbose Print extra information while running\n");
1500 printf (" --version Print version number, then exit\n");
1501 /* FIXME: print bug-report information. */
1506 java_no_argument (opt)
1509 fprintf (stderr, "gcjh: no argument given for option `%s'\n", opt);
1516 /* FIXME: use version.c? */
1517 printf ("gcjh (%s)\n\n", version_string);
1518 printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1519 printf ("This is free software; see the source for copying conditions. There is NO\n");
1520 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1525 DEFUN(main, (argc, argv),
1526 int argc AND char** argv)
1530 char *output_file = NULL;
1531 int emit_dependencies = 0, suppress_output = 0;
1538 for (argi = 1; argi < argc; argi++)
1540 char *arg = argv[argi];
1542 if (arg[0] != '-' || ! strcmp (arg, "--"))
1545 /* Just let all arguments be given in either "-" or "--" form. */
1549 if (strcmp (arg, "-o") == 0)
1551 if (argi + 1 < argc)
1552 output_file = argv[++argi];
1554 java_no_argument (argv[argi]);
1556 else if (strcmp (arg, "-d") == 0)
1558 if (argi + 1 < argc)
1559 output_directory = argv[++argi];
1561 java_no_argument (argv[argi]);
1563 else if (strcmp (arg, "-td") == 0)
1565 if (argi + 1 < argc)
1566 temp_directory = argv[++argi];
1568 java_no_argument (argv[argi]);
1570 else if (strcmp (arg, "-prepend") == 0)
1572 if (argi + 1 < argc)
1574 if (prepend_count == 0)
1575 prepend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1576 prepend_specs[prepend_count++] = argv[++argi];
1579 java_no_argument (argv[argi]);
1581 else if (strcmp (arg, "-friend") == 0)
1583 if (argi + 1 < argc)
1585 if (friend_count == 0)
1586 friend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1587 friend_specs[friend_count++] = argv[++argi];
1590 java_no_argument (argv[argi]);
1592 else if (strcmp (arg, "-add") == 0)
1594 if (argi + 1 < argc)
1597 add_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1598 add_specs[add_count++] = argv[++argi];
1601 java_no_argument (argv[argi]);
1603 else if (strcmp (arg, "-append") == 0)
1605 if (argi + 1 < argc)
1607 if (append_count == 0)
1608 append_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1609 append_specs[append_count++] = argv[++argi];
1612 java_no_argument (argv[argi]);
1614 else if (strcmp (arg, "-classpath") == 0)
1616 if (argi + 1 < argc)
1617 jcf_path_classpath_arg (argv[++argi]);
1619 java_no_argument (argv[argi]);
1621 else if (strcmp (arg, "-CLASSPATH") == 0)
1623 if (argi + 1 < argc)
1624 jcf_path_CLASSPATH_arg (argv[++argi]);
1626 java_no_argument (argv[argi]);
1628 else if (strncmp (arg, "-I", 2) == 0)
1629 jcf_path_include_arg (arg + 2);
1630 else if (strcmp (arg, "-verbose") == 0 || strcmp (arg, "-v") == 0)
1632 else if (strcmp (arg, "-stubs") == 0)
1634 else if (strcmp (arg, "-help") == 0)
1636 else if (strcmp (arg, "-version") == 0)
1638 else if (strcmp (arg, "-M") == 0)
1640 emit_dependencies = 1;
1641 suppress_output = 1;
1642 jcf_dependency_init (1);
1644 else if (strcmp (arg, "-MM") == 0)
1646 emit_dependencies = 1;
1647 suppress_output = 1;
1648 jcf_dependency_init (0);
1650 else if (strcmp (arg, "-MG") == 0)
1652 fprintf (stderr, "gcjh: `%s' option is unimplemented\n", argv[argi]);
1655 else if (strcmp (arg, "-MD") == 0)
1657 emit_dependencies = 1;
1658 jcf_dependency_init (1);
1660 else if (strcmp (arg, "-MMD") == 0)
1662 emit_dependencies = 1;
1663 jcf_dependency_init (0);
1667 fprintf (stderr, "%s: illegal argument\n", argv[argi]);
1677 if (output_file && emit_dependencies)
1679 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
1683 for (; argi < argc; argi++)
1685 char *classname = argv[argi];
1686 char *current_output_file;
1687 const char *classfile_name;
1690 fprintf (stderr, "Processing %s\n", classname);
1692 jcf_dependency_reset ();
1693 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
1694 if (classfile_name == NULL)
1696 fprintf (stderr, "%s: no such class\n", classname);
1700 fprintf (stderr, "Found in %s\n", classfile_name);
1703 if (strcmp (output_file, "-") == 0)
1705 else if (out == NULL)
1707 out = fopen (output_file, "w");
1711 perror (output_file);
1714 current_output_file = output_file;
1718 int dir_len = strlen (output_directory);
1719 int i, classname_length = strlen (classname);
1720 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
1721 strcpy (current_output_file, output_directory);
1722 if (dir_len > 0 && output_directory[dir_len-1] != '/')
1723 current_output_file[dir_len++] = '/';
1724 for (i = 0; classname[i] != '\0'; i++)
1726 char ch = classname[i];
1729 current_output_file[dir_len++] = ch;
1731 if (emit_dependencies)
1733 if (suppress_output)
1735 jcf_dependency_set_dep_file ("-");
1740 /* We use `.hd' and not `.d' to avoid clashes with
1741 dependency tracking from straight compilation. */
1742 strcpy (current_output_file + dir_len, ".hd");
1743 jcf_dependency_set_dep_file (current_output_file);
1746 strcpy (current_output_file + dir_len,
1747 stubs ? ".cc" : ".h");
1748 jcf_dependency_set_target (current_output_file);
1749 if (! suppress_output)
1751 out = fopen (current_output_file, "w");
1754 perror (current_output_file);
1759 process_file (&jcf, out);
1761 if (current_output_file != output_file)
1762 free (current_output_file);
1763 jcf_dependency_write ();
1766 if (out != NULL && out != stdout)
1774 * Emit "structure forward declarations" when needed.
1776 * Generate C headers, like javah