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. */
30 #include "java-opcodes.h"
33 /* The output file. */
36 /* Nonzero on failure. */
37 static int found_error = 0;
39 /* Directory to place resulting files in. Set by -d option. */
40 const char *output_directory = "";
42 /* Directory to place temporary file. Set by -td option. Currently unused. */
43 const char *temp_directory = "/tmp";
45 /* Number of friend functions we have to declare. */
46 static int friend_count;
48 /* A class can optionally have a `friend' function declared. If
49 non-NULL, this is that function. */
50 static char **friend_specs = NULL;
52 /* Number of lines we are prepending before the class. */
53 static int prepend_count;
55 /* We can prepend extra lines before the class's start. */
56 static char **prepend_specs = NULL;
58 /* Number of lines we are appending at the end of the class. */
61 /* We can append extra lines just before the class's end. */
62 static char **add_specs = NULL;
64 /* Number of lines we are appending after the class. */
65 static int append_count;
67 /* We can append extra lines after the class's end. */
68 static char **append_specs = NULL;
74 struct JCF *current_jcf;
77 /* This holds access information for the last field we examined. They
78 let us generate "private:", "public:", and "protected:" properly.
79 If 0 then we haven't previously examined any field. */
80 static JCF_u2 last_access;
82 #define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
84 /* Pass this macro the flags for a class and for a method. It will
85 return true if the method should be considered `final'. */
86 #define METHOD_IS_FINAL(Class, Method) \
87 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
89 /* We keep a linked list of all method names we have seen. This lets
90 us determine if a method name and a field name are in conflict. */
95 struct method_name *next;
98 /* List of method names we've seen. */
99 static struct method_name *method_name_list;
101 static void print_field_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
102 static void print_method_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
103 static void print_c_decl PROTO ((FILE*, JCF*, int, int, JCF_u2, int, const char *));
104 static void decompile_method PROTO ((FILE *, JCF *, int));
105 static void add_class_decl PROTO ((FILE *, JCF *, JCF_u2));
107 JCF_u2 current_field_name;
108 JCF_u2 current_field_value;
109 JCF_u2 current_field_signature;
110 JCF_u2 current_field_flags;
112 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
113 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
114 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
116 /* We pass over fields twice. The first time we just note the types
117 of the fields and then the start of the methods. Then we go back
118 and parse the fields for real. This is ugly. */
119 static int field_pass;
120 /* Likewise we pass over methods twice. The first time we generate
121 class decl information; the second time we generate actual method
123 static int method_pass;
125 #define HANDLE_END_FIELD() \
129 print_field_info (out, jcf, current_field_name, \
130 current_field_signature, \
131 current_field_flags); \
134 add_class_decl (out, jcf, current_field_signature);
136 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
138 static int method_declared = 0;
139 static int method_access = 0;
140 static int method_printed = 0;
141 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
144 decompiled = 0; method_printed = 0; \
146 print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
149 add_class_decl (out, jcf, SIGNATURE);
151 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
152 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
154 static int decompiled = 0;
155 #define HANDLE_END_METHOD() \
156 if (out && method_printed) fputs (decompiled ? "\n" : ";\n", out);
158 #include "jcf-reader.c"
160 /* Some useful constants. */
161 #define F_NAN_MASK 0x7f800000
162 #define D_NAN_MASK 0x7ff0000000000000LL
164 /* Return 1 if F is not Inf or NaN. */
166 java_float_finite (f)
175 /* We happen to know that F_NAN_MASK will match all NaN values, and
176 also positive and negative infinity. That's why we only need one
177 test here. See The Java Language Specification, section 20.9. */
178 return (u.i & F_NAN_MASK) != F_NAN_MASK;
181 /* Return 1 if D is not Inf or NaN. */
183 java_double_finite (d)
192 /* Now check for all NaNs. */
193 return (u.i & D_NAN_MASK) != D_NAN_MASK;
197 DEFUN(print_name, (stream, jcf, name_index),
198 FILE* stream AND JCF* jcf AND int name_index)
200 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
201 fprintf (stream, "<not a UTF8 constant>");
203 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
204 JPOOL_UTF_LENGTH (jcf, name_index));
207 /* Print base name of class. The base name is everything after the
211 print_base_classname (stream, jcf, index)
216 int name_index = JPOOL_USHORT1 (jcf, index);
218 unsigned char *s, *p, *limit;
220 s = JPOOL_UTF_DATA (jcf, name_index);
221 len = JPOOL_UTF_LENGTH (jcf, name_index);
226 int c = UTF8_GET (s, limit);
233 int ch = UTF8_GET (p, limit);
235 fputs ("::", stream);
237 jcf_print_char (stream, ch);
241 /* Return 0 if NAME is equal to STR, nonzero otherwise. */
244 utf8_cmp (str, length, name)
249 unsigned char *limit = str + length;
252 for (i = 0; name[i]; ++i)
254 int ch = UTF8_GET (str, limit);
262 /* Generate an access control keyword based on FLAGS. Returns 0 if
263 FLAGS matches the saved access information, nonzero otherwise. */
266 generate_access (stream, flags)
270 if ((flags & ACC_VISIBILITY) == last_access)
272 last_access = (flags & ACC_VISIBILITY);
277 fputs ("public: // actually package-private\n", stream);
280 fputs ("public:\n", stream);
283 fputs ("private:\n", stream);
286 fputs ("public: // actually protected\n", stream);
290 fprintf (stream, "#error unrecognized visibility %d\n",
291 (flags & ACC_VISIBILITY));
296 /* See if NAME is already the name of a method. */
298 name_is_method_p (name, length)
302 struct method_name *p;
304 for (p = method_name_list; p != NULL; p = p->next)
306 if (p->length == length && ! memcmp (p->name, name, length))
313 DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
314 FILE *stream AND JCF* jcf
315 AND int name_index AND int sig_index AND JCF_u2 flags)
317 char *override = NULL;
319 if (flags & ACC_FINAL)
321 if (current_field_value > 0)
325 generate_access (stream, flags);
326 switch (JPOOL_TAG (jcf, current_field_value))
328 case CONSTANT_Integer:
331 int most_negative = 0;
332 fputs (" static const jint ", out);
333 print_name (out, jcf, name_index);
335 num = JPOOL_INT (jcf, current_field_value);
336 /* We single out the most negative number to print
337 specially. This avoids later warnings from g++. */
338 if (num == 0x80000000)
343 format_int (buffer, (jlong) num, 10);
344 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
350 int most_negative = 0;
351 fputs (" static const jlong ", out);
352 print_name (out, jcf, name_index);
354 num = JPOOL_LONG (jcf, current_field_value);
355 /* We single out the most negative number to print
356 specially.. This avoids later warnings from g++. */
357 if (num == 0x8000000000000000LL)
362 format_int (buffer, num, 10);
363 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
368 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
369 fputs (" static const jfloat ", out);
370 print_name (out, jcf, name_index);
371 if (! java_float_finite (fnum))
374 fprintf (out, " = %.10g;\n", fnum);
377 case CONSTANT_Double:
379 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
380 fputs (" static const jdouble ", out);
381 print_name (out, jcf, name_index);
382 if (! java_double_finite (dnum))
385 fprintf (out, " = %.17g;\n", dnum);
389 fprintf(out, " <<inappropriate constant type>>\n");
396 generate_access (stream, flags);
398 if ((flags & ACC_STATIC))
399 fputs ("static ", out);
401 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
403 fprintf (stream, "<not a UTF8 constant>");
408 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
409 int length = JPOOL_UTF_LENGTH (jcf, name_index);
411 if (name_is_method_p (name, length))
413 /* This field name matches a method. So override the name
414 with a dummy name. This is yucky, but it isn't clear
415 what else to do. FIXME: if the field is static, then
416 we'll be in real trouble. */
417 if ((flags & ACC_STATIC))
419 fprintf (stderr, "static field has same name as method\n");
423 override = (char *) malloc (length + 3);
424 memcpy (override, name, length);
425 strcpy (override + length, "__");
429 print_c_decl (out, jcf, name_index, sig_index, flags, 0, override);
437 DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
438 FILE *stream AND JCF* jcf
439 AND int name_index AND int sig_index AND JCF_u2 flags)
442 int length, is_init = 0;
443 const char *override = NULL;
446 method_access = flags;
447 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
448 fprintf (stream, "<not a UTF8 constant>");
449 str = JPOOL_UTF_DATA (jcf, name_index);
450 length = JPOOL_UTF_LENGTH (jcf, name_index);
451 if (str[0] == '<' || str[0] == '$')
453 /* Ignore internally generated methods like <clinit> and
454 $finit$. However, treat <init> as a constructor. */
455 if (! utf8_cmp (str, length, "<init>"))
457 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
458 && ! (flags & ACC_STATIC))
460 /* FIXME: i18n bug here. Order of prints should not be
462 fprintf (stderr, "ignored method `");
463 jcf_print_utf8 (stderr, str, length);
464 fprintf (stderr, "' marked virtual\n");
473 struct method_name *nn;
475 nn = (struct method_name *) malloc (sizeof (struct method_name));
476 nn->name = (char *) malloc (length);
477 memcpy (nn->name, str, length);
479 nn->next = method_name_list;
480 method_name_list = nn;
483 /* We can't generate a method whose name is a C++ reserved word.
484 For now the only problem has been `delete'; add more here as
485 required. We can't just ignore the function, because that will
486 cause incorrect code to be generated if the function is virtual
487 (not only for calls to this function for for other functions
488 after it in the vtbl). So we give it a dummy name instead. */
489 if (! utf8_cmp (str, length, "delete"))
491 /* If the method is static or final, we can safely skip it. If
492 we don't skip it then we'll have problems since the mangling
493 will be wrong. FIXME. */
494 if (METHOD_IS_FINAL (jcf->access_flags, flags)
495 || (flags & ACC_STATIC))
497 override = "__dummy_delete";
501 generate_access (stream, flags);
504 if ((flags & ACC_STATIC))
505 fputs ("static ", out);
506 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
508 /* Don't print `virtual' if we have a constructor. */
510 fputs ("virtual ", out);
512 print_c_decl (out, jcf, name_index, sig_index, flags, is_init, override);
514 if ((flags & ACC_ABSTRACT))
520 /* Try to decompile a method body. Right now we just try to handle a
521 simple case that we can do. Expand as desired. */
523 decompile_method (out, jcf, code_len)
528 unsigned char *codes = jcf->read_ptr;
530 uint16 name_and_type, name;
532 /* If the method is synchronized, don't touch it. */
533 if ((method_access & ACC_SYNCHRONIZED))
537 && codes[0] == OPCODE_aload_0
538 && codes[1] == OPCODE_getfield
539 && (codes[4] == OPCODE_areturn
540 || codes[4] == OPCODE_dreturn
541 || codes[4] == OPCODE_freturn
542 || codes[4] == OPCODE_ireturn
543 || codes[4] == OPCODE_lreturn))
545 /* Found code like `return FIELD'. */
546 fputs (" { return ", out);
547 index = (codes[2] << 8) | codes[3];
548 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
549 /* FIXME: ensure that the field's class is this class. */
550 name_and_type = JPOOL_USHORT2 (jcf, index);
551 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
552 name = JPOOL_USHORT1 (jcf, name_and_type);
553 print_name (out, jcf, name);
557 else if (code_len == 2
558 && codes[0] == OPCODE_aload_0
559 && codes[1] == OPCODE_areturn)
561 /* Found `return this'. */
562 fputs (" { return this; }", out);
565 else if (code_len == 1 && codes[0] == OPCODE_return)
567 /* Found plain `return'. */
571 else if (code_len == 2
572 && codes[0] == OPCODE_aconst_null
573 && codes[1] == OPCODE_areturn)
575 /* Found `return null'. We don't want to depend on NULL being
577 fputs (" { return 0; }", out);
582 /* Print one piece of a signature. Returns pointer to next parseable
583 character on success, NULL on error. */
584 static unsigned char *
585 decode_signature_piece (stream, signature, limit, need_space)
587 unsigned char *signature, *limit;
592 switch (signature[0])
595 for (signature++; (signature < limit
597 && *signature <= '9'); signature++)
601 case 'B': ctype = "jbyteArray"; goto printit;
602 case 'C': ctype = "jcharArray"; goto printit;
603 case 'D': ctype = "jdoubleArray"; goto printit;
604 case 'F': ctype = "jfloatArray"; goto printit;
605 case 'I': ctype = "jintArray"; goto printit;
606 case 'S': ctype = "jshortArray"; goto printit;
607 case 'J': ctype = "jlongArray"; goto printit;
608 case 'Z': ctype = "jbooleanArray"; goto printit;
609 case '[': ctype = "jobjectArray"; goto printit;
611 /* We have to generate a reference to JArray here,
612 so that our output matches what the compiler
615 fputs ("JArray<", stream);
616 while (signature < limit && *signature != ';')
618 int ch = UTF8_GET (signature, limit);
620 fputs ("::", stream);
622 jcf_print_char (stream, ch);
624 fputs (" *> *", stream);
629 /* Unparseable signature. */
636 /* This shouldn't happen. */
639 case 'B': ctype = "jbyte"; goto printit;
640 case 'C': ctype = "jchar"; goto printit;
641 case 'D': ctype = "jdouble"; goto printit;
642 case 'F': ctype = "jfloat"; goto printit;
643 case 'I': ctype = "jint"; goto printit;
644 case 'J': ctype = "jlong"; goto printit;
645 case 'S': ctype = "jshort"; goto printit;
646 case 'Z': ctype = "jboolean"; goto printit;
647 case 'V': ctype = "void"; goto printit;
650 while (*signature && *signature != ';')
652 int ch = UTF8_GET (signature, limit);
654 fputs ("::", stream);
656 jcf_print_char (stream, ch);
658 fputs (" *", stream);
659 if (*signature == ';')
665 jcf_print_char (stream, *signature++);
670 fputs (ctype, stream);
678 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, flags, is_init,
680 FILE* stream AND JCF* jcf
681 AND int name_index AND int signature_index AND JCF_u2 flags
682 AND int is_init AND const char *name_override)
684 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
686 fprintf (stream, "<not a UTF8 constant>");
691 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
692 unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
693 register unsigned char *str = str0;
694 unsigned char *limit = str + length;
696 int is_method = str[0] == '(';
699 /* If printing a method, skip to the return signature and print
700 that first. However, there is no return value if this is a
702 if (is_method && ! is_init)
712 /* If printing a field or an ordinary method, then print the
713 "return value" now. */
714 if (! is_method || ! is_init)
716 next = decode_signature_piece (stream, str, limit, &need_space);
719 fprintf (stderr, "unparseable signature: `%s'\n", str0);
725 /* Now print the name of the thing. */
729 fputs (name_override, stream);
732 /* Declare constructors specially. */
734 print_base_classname (stream, jcf, jcf->this_class);
736 print_name (stream, jcf, name_index);
741 /* Have a method or a constructor. Print signature pieces
743 fputs (" (", stream);
745 while (str < limit && *str != ')')
747 next = decode_signature_piece (stream, str, limit, &need_space);
750 fprintf (stderr, "unparseable signature: `%s'\n", str0);
755 if (next < limit && *next != ')')
756 fputs (", ", stream);
766 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
767 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
769 int name_index = JPOOL_USHORT1 (jcf, index);
770 fputs (prefix, stream);
771 jcf_print_utf8_replace (out,
772 JPOOL_UTF_DATA (jcf, name_index),
773 JPOOL_UTF_LENGTH (jcf, name_index),
777 /* Print PREFIX, then a class name in C++ format. If the name refers
778 to an array, ignore it and don't print PREFIX. Returns 1 if
779 something was printed, 0 otherwise. */
781 print_cxx_classname (stream, prefix, jcf, index)
787 int name_index = JPOOL_USHORT1 (jcf, index);
789 unsigned char *s, *p, *limit;
791 s = JPOOL_UTF_DATA (jcf, name_index);
792 len = JPOOL_UTF_LENGTH (jcf, name_index);
795 /* Explicitly omit arrays here. */
797 c = UTF8_GET (p, limit);
801 fputs (prefix, stream);
804 c = UTF8_GET (s, limit);
806 fputs ("::", stream);
808 jcf_print_char (stream, c);
814 int written_class_count = 0;
816 /* Return name of superclass. If LEN is not NULL, fill it with length
818 static unsigned char *
819 super_class_name (derived_jcf, len)
823 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
824 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
825 unsigned char *supername = JPOOL_UTF_DATA (derived_jcf, supername_index);
828 *len = supername_length;
835 /* This is used to represent part of a package or class name. */
838 /* The text of this part of the name. */
840 /* True if this represents a class. */
842 /* Linked list of all classes and packages inside this one. */
843 struct namelet *subnamelets;
844 /* Pointer to next sibling. */
845 struct namelet *next;
848 /* The special root namelet. */
849 static struct namelet root =
857 /* This extracts the next name segment from the full UTF-8 encoded
858 package or class name and links it into the tree. It does this
861 add_namelet (name, name_limit, parent)
862 unsigned char *name, *name_limit;
863 struct namelet *parent;
866 struct namelet *n = NULL, *np;
868 /* We want to skip the standard namespaces that we assume the
869 runtime already knows about. We only do this at the top level,
870 though, hence the check for `root'. */
873 #define JAVALANG "java/lang/"
874 #define JAVAIO "java/io/"
875 #define JAVAUTIL "java/util/"
876 if ((name_limit - name >= sizeof (JAVALANG) - 1
877 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
878 || (name_limit - name >= sizeof (JAVAUTIL) - 1
879 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
880 || (name_limit - name >= sizeof (JAVAIO) - 1
881 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
885 for (p = name; p < name_limit && *p != '/' && *p != '$'; ++p)
888 /* Search for this name beneath the PARENT node. */
889 for (np = parent->subnamelets; np != NULL; np = np->next)
891 if (! strncmp (name, np->name, p - name))
900 n = (struct namelet *) malloc (sizeof (struct namelet));
901 n->name = malloc (p - name + 1);
902 strncpy (n->name, name, p - name);
903 n->name[p - name] = '\0';
904 n->is_class = (p == name_limit || *p == '$');
905 n->subnamelets = NULL;
906 n->next = parent->subnamelets;
907 parent->subnamelets = n;
910 /* We recurse if there is more text, and if the trailing piece does
911 not represent an inner class. */
912 if (p < name_limit && *p != '$')
913 add_namelet (p + 1, name_limit, n);
916 /* Print a single namelet. Destroys namelets while printing. */
918 print_namelet (out, name, depth)
920 struct namelet *name;
928 for (i = 0; i < depth; ++i)
930 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
932 if (name->is_class && name->subnamelets == NULL)
938 for (i = 0; i < depth; ++i)
944 c = name->subnamelets;
947 struct namelet *next = c->next;
948 print_namelet (out, c, depth + 2);
956 for (i = 0; i < depth; ++i)
966 /* This is called to add some classes to the list of classes for which
967 we need decls. The signature argument can be a function
970 add_class_decl (out, jcf, signature)
975 unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
976 int len = JPOOL_UTF_LENGTH (jcf, signature);
979 for (i = 0; i < len; ++i)
982 /* We're looking for `L<stuff>;' -- everything else is
986 for (start = ++i; i < len && s[i] != ';'; ++i)
988 if (s[i] == '$' && out)
990 /* If this class represents an inner class, then
991 generate a `#include' for the outer class. */
992 fputs ("#include <", out);
993 jcf_print_utf8 (out, &s[start], i - start);
998 add_namelet (&s[start], &s[i], &root);
1002 /* Print declarations for all classes required by this class. Any
1003 class or package in the `java' package is assumed to be handled
1004 statically in libjava; we don't generate declarations for these.
1005 This makes the generated headers a bit easier to read. */
1007 print_class_decls (out, jcf, self)
1012 /* Make sure to always add the current class to the list of things
1013 that should be declared. */
1014 int name_index = JPOOL_USHORT1 (jcf, self);
1018 s = JPOOL_UTF_DATA (jcf, name_index);
1019 len = JPOOL_UTF_LENGTH (jcf, name_index);
1020 add_namelet (s, s + len, &root);
1022 if (root.subnamelets)
1024 fputs ("extern \"Java\"\n{\n", out);
1025 /* We use an initial offset of 0 because the root namelet
1026 doesn't cause anything to print. */
1027 print_namelet (out, &root, 0);
1028 fputs ("};\n\n", out);
1035 DEFUN(process_file, (jcf, out),
1036 JCF *jcf AND FILE *out)
1039 uint32 field_start, method_end, method_start;
1041 current_jcf = main_jcf = jcf;
1045 if (jcf_parse_preamble (jcf) != 0)
1047 fprintf (stderr, "Not a valid Java .class file.\n");
1052 /* Parse and possibly print constant pool */
1053 code = jcf_parse_constant_pool (jcf);
1056 fprintf (stderr, "error while parsing constant pool\n");
1060 code = verify_constant_pool (jcf);
1063 fprintf (stderr, "error in constant pool entry #%d\n", code);
1068 jcf_parse_class (jcf);
1070 if (written_class_count++ == 0 && out)
1071 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
1076 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1077 fprintf (out, "__\n");
1079 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1080 fprintf (out, "__\n\n");
1082 /* We do this to ensure that inline methods won't be `outlined'
1083 by g++. This works as long as method and fields are not
1084 added by the user. */
1085 fprintf (out, "#pragma interface\n\n");
1088 if (jcf->super_class && out)
1091 unsigned char *supername = super_class_name (jcf, &super_length);
1093 fputs ("#include <", out);
1094 jcf_print_utf8 (out, supername, super_length);
1095 fputs (".h>\n", out);
1097 /* FIXME: If our superclass is Object, then we include
1098 java-array.h. The right thing to do here is look at all the
1099 methods and fields and see if an array is in use. Only then
1100 would we need to include java-array.h. */
1101 if (! utf8_cmp (supername, super_length, "java/lang/Object"))
1102 fputs ("#include <java-array.h>\n", out);
1107 /* We want to parse the methods first. But we need to find where
1108 they start. So first we skip the fields, then parse the methods.
1109 Then we parse the fields and skip the methods. This is ugly, but
1110 not too bad since we need two full passes to get class decl
1111 information anyway. */
1113 field_start = JCF_TELL (jcf);
1114 jcf_parse_fields (jcf);
1116 method_start = JCF_TELL (jcf);
1118 jcf_parse_methods (jcf);
1122 print_class_decls (out, jcf, jcf->this_class);
1124 for (i = 0; i < prepend_count; ++i)
1125 fprintf (out, "%s\n", prepend_specs[i]);
1126 if (prepend_count > 0)
1130 if (out && ! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1132 fprintf (stderr, "class is of array type\n");
1136 if (out && jcf->super_class)
1138 if (! print_cxx_classname (out, " : public ", jcf, jcf->super_class))
1140 fprintf (stderr, "base class is of array type\n");
1146 fputs ("\n{\n", out);
1148 /* Now go back for second pass over methods and fields. */
1149 JCF_SEEK (jcf, method_start);
1151 jcf_parse_methods (jcf);
1152 method_end = JCF_TELL (jcf);
1155 JCF_SEEK (jcf, field_start);
1156 jcf_parse_fields (jcf);
1157 JCF_SEEK (jcf, method_end);
1159 jcf_parse_final_attributes (jcf);
1163 /* Generate friend decl if we still must. */
1164 for (i = 0; i < friend_count; ++i)
1165 fprintf (out, " friend %s\n", friend_specs[i]);
1167 /* Generate extra declarations. */
1170 for (i = 0; i < add_count; ++i)
1171 fprintf (out, " %s\n", add_specs[i]);
1173 fputs ("};\n", out);
1175 if (append_count > 0)
1177 for (i = 0; i < append_count; ++i)
1178 fprintf (out, "%s\n", append_specs[i]);
1180 print_mangled_classname (out, jcf, "\n#endif /* __", jcf->this_class);
1181 fprintf (out, "__ */\n");
1188 fprintf (stderr, "gcjh: no classes specified\n");
1195 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1196 printf ("Generate C++ header files from .class files\n\n");
1197 printf (" --classpath PATH Set path to find .class files\n");
1198 printf (" --CLASSPATH PATH Set path to find .class files\n");
1199 printf (" -IDIR Append directory to class path\n");
1200 printf (" -d DIRECTORY Set output directory name\n");
1201 printf (" --help Print this help, then exit\n");
1202 printf (" -o FILE Set output file name\n");
1203 printf (" -td DIRECTORY Set temporary directory name\n");
1204 printf (" -v, --verbose Print extra information while running\n");
1205 printf (" --version Print version number, then exit\n");
1206 /* FIXME: print bug-report information. */
1211 java_no_argument (opt)
1214 fprintf (stderr, "gcjh: no argument given for option `%s'\n", opt);
1221 /* FIXME: use version.c? */
1222 printf ("gcjh (GNU gcc) 0.0\n\n");
1223 printf ("Copyright (C) 1998 Free Software Foundation, Inc.\n");
1224 printf ("This is free software; see the source for copying conditions. There is NO\n");
1225 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1230 DEFUN(main, (argc, argv),
1231 int argc AND char** argv)
1235 char *output_file = NULL;
1236 int emit_dependencies = 0, suppress_output = 0;
1243 for (argi = 1; argi < argc; argi++)
1245 char *arg = argv[argi];
1247 if (arg[0] != '-' || ! strcmp (arg, "--"))
1250 /* Just let all arguments be given in either "-" or "--" form. */
1254 if (strcmp (arg, "-o") == 0)
1256 if (argi + 1 < argc)
1257 output_file = argv[++argi];
1259 java_no_argument (argv[argi]);
1261 else if (strcmp (arg, "-d") == 0)
1263 if (argi + 1 < argc)
1264 output_directory = argv[++argi];
1266 java_no_argument (argv[argi]);
1268 else if (strcmp (arg, "-td") == 0)
1270 if (argi + 1 < argc)
1271 temp_directory = argv[++argi];
1273 java_no_argument (argv[argi]);
1275 else if (strcmp (arg, "-prepend") == 0)
1277 if (argi + 1 < argc)
1279 if (prepend_count == 0)
1280 prepend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1281 prepend_specs[prepend_count++] = argv[++argi];
1284 java_no_argument (argv[argi]);
1286 else if (strcmp (arg, "-friend") == 0)
1288 if (argi + 1 < argc)
1290 if (friend_count == 0)
1291 friend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1292 friend_specs[friend_count++] = argv[++argi];
1295 java_no_argument (argv[argi]);
1297 else if (strcmp (arg, "-add") == 0)
1299 if (argi + 1 < argc)
1302 add_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1303 add_specs[add_count++] = argv[++argi];
1306 java_no_argument (argv[argi]);
1308 else if (strcmp (arg, "-append") == 0)
1310 if (argi + 1 < argc)
1312 if (append_count == 0)
1313 append_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1314 append_specs[append_count++] = argv[++argi];
1317 java_no_argument (argv[argi]);
1319 else if (strcmp (arg, "-classpath") == 0)
1321 if (argi + 1 < argc)
1322 jcf_path_classpath_arg (argv[++argi]);
1324 java_no_argument (argv[argi]);
1326 else if (strcmp (arg, "-CLASSPATH") == 0)
1328 if (argi + 1 < argc)
1329 jcf_path_CLASSPATH_arg (argv[++argi]);
1331 java_no_argument (argv[argi]);
1333 else if (strncmp (arg, "-I", 2) == 0)
1334 jcf_path_include_arg (arg + 2);
1335 else if (strcmp (arg, "-verbose") == 0 || strcmp (arg, "-v") == 0)
1337 else if (strcmp (arg, "-stubs") == 0)
1339 else if (strcmp (arg, "-help") == 0)
1341 else if (strcmp (arg, "-version") == 0)
1343 else if (strcmp (arg, "-M") == 0)
1345 emit_dependencies = 1;
1346 suppress_output = 1;
1347 jcf_dependency_init (1);
1349 else if (strcmp (arg, "-MM") == 0)
1351 emit_dependencies = 1;
1352 suppress_output = 1;
1353 jcf_dependency_init (0);
1355 else if (strcmp (arg, "-MG") == 0)
1357 fprintf (stderr, "gcjh: `%s' option is unimplemented\n", argv[argi]);
1360 else if (strcmp (arg, "-MD") == 0)
1362 emit_dependencies = 1;
1363 jcf_dependency_init (1);
1365 else if (strcmp (arg, "-MMD") == 0)
1367 emit_dependencies = 1;
1368 jcf_dependency_init (0);
1372 fprintf (stderr, "%s: illegal argument\n", argv[argi]);
1382 if (output_file && emit_dependencies)
1384 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
1388 for (; argi < argc; argi++)
1390 char *classname = argv[argi];
1391 char *classfile_name, *current_output_file;
1394 fprintf (stderr, "Processing %s\n", classname);
1396 jcf_dependency_reset ();
1397 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
1398 if (classfile_name == NULL)
1400 fprintf (stderr, "%s: no such class\n", classname);
1404 fprintf (stderr, "Found in %s\n", classfile_name);
1407 if (strcmp (output_file, "-") == 0)
1409 else if (out == NULL)
1411 out = fopen (output_file, "w");
1415 perror (output_file);
1418 current_output_file = output_file;
1422 int dir_len = strlen (output_directory);
1423 int i, classname_length = strlen (classname);
1424 current_output_file = (char*) ALLOC (dir_len + classname_length + 4);
1425 strcpy (current_output_file, output_directory);
1426 if (dir_len > 0 && output_directory[dir_len-1] != '/')
1427 current_output_file[dir_len++] = '/';
1428 for (i = 0; classname[i] != '\0'; i++)
1430 char ch = classname[i];
1433 current_output_file[dir_len++] = ch;
1435 if (emit_dependencies)
1437 if (suppress_output)
1439 jcf_dependency_set_dep_file ("-");
1444 /* We use `.hd' and not `.d' to avoid clashes with
1445 dependency tracking from straight compilation. */
1446 strcpy (current_output_file + dir_len, ".hd");
1447 jcf_dependency_set_dep_file (current_output_file);
1450 strcpy (current_output_file + dir_len, ".h");
1451 jcf_dependency_set_target (current_output_file);
1452 if (! suppress_output)
1454 out = fopen (current_output_file, "w");
1457 perror (current_output_file);
1462 process_file (&jcf, out);
1464 if (current_output_file != output_file)
1465 free (current_output_file);
1466 jcf_dependency_write ();
1469 if (out != NULL && out != stdout)
1477 * Do whatever the javah -stubs flag does.
1479 * Emit "structure forward declarations" when needed.
1481 * Generate C headers, like javah