2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / java / gjavah.c
blobb9a34e3bbdb9179d5807469b2706e1daa91c8c6e
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, 2000, 2001, 2002, 2003
5 Free Software Foundation, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
24 Java and all Java-based marks are trademarks or registered trademarks
25 of Sun Microsystems, Inc. in the United States and other countries.
26 The Free Software Foundation is independent of Sun Microsystems, Inc. */
28 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "tm.h"
34 #include <math.h>
36 #include "jcf.h"
37 #include "tree.h"
38 #include "javaop.h"
39 #include "java-tree.h"
40 #include "java-opcodes.h"
41 #include "ggc.h"
42 #include "hashtab.h"
44 #include <getopt.h>
48 /* The output file. */
49 FILE *out = NULL;
51 /* Nonzero on failure. */
52 static int found_error = 0;
54 /* Nonzero if we're generating JNI output. */
55 int flag_jni = 0;
57 /* When nonzero, warn when source file is newer than matching class
58 file. */
59 int flag_newer = 1;
61 /* Directory to place resulting files in. Set by -d option. */
62 const char *output_directory = "";
64 /* Directory to place temporary file. Set by -td option. Currently unused. */
65 const char *temp_directory = "/tmp";
67 /* Number of friend functions we have to declare. */
68 static int friend_count;
70 /* A class can optionally have a `friend' function declared. If
71 non-NULL, this is that function. */
72 static char **friend_specs = NULL;
74 /* Number of lines we are prepending before the class. */
75 static int prepend_count;
77 /* We can prepend extra lines before the class's start. */
78 static char **prepend_specs = NULL;
80 /* Number of lines we are appending at the end of the class. */
81 static int add_count;
83 /* We can append extra lines just before the class's end. */
84 static char **add_specs = NULL;
86 /* Number of lines we are appending after the class. */
87 static int append_count;
89 /* We can append extra lines after the class's end. */
90 static char **append_specs = NULL;
92 int verbose = 0;
94 int stubs = 0;
96 struct JCF *current_jcf;
98 /* This holds access information for the last field we examined. They
99 let us generate "private:", "public:", and "protected:" properly.
100 If 0 then we haven't previously examined any field. */
101 static JCF_u2 last_access;
103 /* Pass this macro the flags for a class and for a method. It will
104 return true if the method should be considered `final'. */
105 #define METHOD_IS_FINAL(Class, Method) \
106 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
108 /* Pass this macro the flags for a method. It will return true if the
109 method is native. */
110 #define METHOD_IS_NATIVE(Method) \
111 ((Method) & ACC_NATIVE)
113 /* We keep a linked list of all method names we have seen. This lets
114 us determine if a method name and a field name are in conflict. */
115 struct method_name
117 unsigned char *name;
118 int length;
119 unsigned char *signature;
120 int sig_length;
121 struct method_name *next;
124 /* List of method names we've seen. */
125 static struct method_name *method_name_list;
127 static void print_field_info (FILE*, JCF*, int, int, JCF_u2);
128 static void print_mangled_classname (FILE*, JCF*, const char*, int);
129 static int print_cxx_classname (FILE*, const char*, JCF*, int, int);
130 static void print_method_info (FILE*, JCF*, int, int, JCF_u2);
131 static void print_c_decl (FILE*, JCF*, int, int, int, const char *, int);
132 static void print_stub_or_jni (FILE*, JCF*, int, int, int, const char *, int);
133 static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int);
134 static void decompile_method (FILE*, JCF*, int);
135 static void add_class_decl (FILE*, JCF*, JCF_u2);
137 static void print_name (FILE *, JCF *, int);
138 static void print_base_classname (FILE *, JCF *, int);
139 static int utf8_cmp (const unsigned char *, int, const char *);
140 static char *cxx_keyword_subst (const unsigned char *, int);
141 static void generate_access (FILE *, JCF_u2);
142 static int name_is_method_p (const unsigned char *, int);
143 static char *get_field_name (JCF *, int, JCF_u2);
144 static void print_field_name (FILE *, JCF *, int, JCF_u2);
145 static const unsigned char *super_class_name (JCF *, int *);
146 static void print_include (FILE *, const unsigned char *, int);
147 static int gcjh_streq (const void *p1, const void *p2);
148 static int throwable_p (const unsigned char *signature);
149 static const unsigned char *
150 decode_signature_piece (FILE *, const unsigned char *,
151 const unsigned char *, int *);
152 static void print_class_decls (FILE *, JCF *, int);
153 static void usage (void) ATTRIBUTE_NORETURN;
154 static void help (void) ATTRIBUTE_NORETURN;
155 static void version (void) ATTRIBUTE_NORETURN;
156 static int overloaded_jni_method_exists_p (const unsigned char *, int,
157 const char *, int);
158 static void jni_print_char (FILE *, int);
159 static void jni_print_float (FILE *, jfloat);
160 static void jni_print_double (FILE *, jdouble);
161 static void decompile_return_statement (FILE *, JCF *, int, int, int);
163 static void handle_inner_classes (int);
165 JCF_u2 current_field_name;
166 JCF_u2 current_field_value;
167 JCF_u2 current_field_signature;
168 JCF_u2 current_field_flags;
170 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
171 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
172 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
174 /* We pass over fields twice. The first time we just note the types
175 of the fields and then the start of the methods. Then we go back
176 and parse the fields for real. This is ugly. */
177 static int field_pass;
178 /* Likewise we pass over methods twice. The first time we generate
179 class decl information; the second time we generate actual method
180 decls. */
181 static int method_pass;
183 #define HANDLE_END_FIELD() \
184 if (field_pass) \
186 if (out && ! stubs && ! flag_jni) \
187 print_field_info (out, jcf, current_field_name, \
188 current_field_signature, \
189 current_field_flags); \
191 else if (! stubs && ! flag_jni) \
192 add_class_decl (out, jcf, current_field_signature);
194 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
196 static int method_declared = 0;
197 static int method_access = 0;
198 static int method_printed = 0;
199 static int method_synthetic = 0;
200 static int method_signature = 0;
202 /* Set to 1 while the very first data member of a class is being handled. */
203 static int is_first_data_member = 0;
205 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
207 method_synthetic = 0; \
208 method_printed = 0; \
209 decompiled = 0; \
210 method_signature = SIGNATURE; \
211 if (ATTRIBUTE_COUNT) \
212 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
213 (const char *)"Synthetic", 9); \
214 /* If a synthetic methods have been declared, its attribute aren't \
215 worth reading (and triggering side-effects). We skip them an \
216 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
217 jcf_parse_one_method. */ \
218 if (method_synthetic) \
220 skip_attribute (jcf, ATTRIBUTE_COUNT); \
221 ATTRIBUTE_COUNT = 0; \
223 if (method_pass && !method_synthetic) \
225 if (out) \
226 print_method_info (out, jcf, NAME, SIGNATURE, \
227 ACCESS_FLAGS); \
229 else if (!method_synthetic) \
231 print_method_info (NULL, jcf, NAME, SIGNATURE, \
232 ACCESS_FLAGS); \
233 if (! stubs && ! flag_jni) \
234 add_class_decl (out, jcf, SIGNATURE); \
238 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
239 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
241 static int decompiled = 0;
242 #define HANDLE_END_METHOD() \
243 if (out && method_printed && !method_synthetic) \
244 fputs (decompiled || stubs ? "\n" : ";\n", out);
246 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
248 /* We're going to need {peek,skip}_attribute, enable their definition. */
249 #define NEED_PEEK_ATTRIBUTE
250 #define NEED_SKIP_ATTRIBUTE
252 #include "jcf-reader.c"
254 /* Print a single-precision float, suitable for parsing by g++. */
255 static void
256 jni_print_float (FILE *stream, jfloat f)
258 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
259 work in data initializers. FIXME. */
260 if (JFLOAT_FINITE (f))
262 fputs (" = ", stream);
263 if (f.negative)
264 putc ('-', stream);
265 if (f.exponent)
266 fprintf (stream, "0x1.%.6xp%+df",
267 ((unsigned int)f.mantissa) << 1,
268 f.exponent - JFLOAT_EXP_BIAS);
269 else
270 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
271 because the implicit leading 1 bit is no longer present. */
272 fprintf (stream, "0x0.%.6xp%+df",
273 ((unsigned int)f.mantissa) << 1,
274 f.exponent + 1 - JFLOAT_EXP_BIAS);
276 fputs (";\n", stream);
279 /* Print a double-precision float, suitable for parsing by g++. */
280 static void
281 jni_print_double (FILE *stream, jdouble f)
283 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
284 work in data initializers. FIXME. */
285 if (JDOUBLE_FINITE (f))
287 fputs (" = ", stream);
288 if (f.negative)
289 putc ('-', stream);
290 if (f.exponent)
291 fprintf (stream, "0x1.%.5x%.8xp%+d",
292 f.mantissa0, f.mantissa1,
293 f.exponent - JDOUBLE_EXP_BIAS);
294 else
295 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
296 because the implicit leading 1 bit is no longer present. */
297 fprintf (stream, "0x0.%.5x%.8xp%+d",
298 f.mantissa0, f.mantissa1,
299 f.exponent + 1 - JDOUBLE_EXP_BIAS);
301 fputs (";\n", stream);
304 /* Print a character, appropriately mangled for JNI. */
306 static void
307 jni_print_char (FILE *stream, int ch)
309 if (! flag_jni)
310 jcf_print_char (stream, ch);
311 else if (ch == '(' || ch == ')')
313 /* Ignore. */
315 else if (ch == '_')
316 fputs ("_1", stream);
317 else if (ch == ';')
318 fputs ("_2", stream);
319 else if (ch == '[')
320 fputs ("_3", stream);
321 else if (ch == '/')
322 fputs ("_", stream);
323 else if (ISALNUM (ch))
324 fputc (ch, stream);
325 else
327 /* "Unicode" character. */
328 fprintf (stream, "_0%04x", ch);
332 /* Print a name from the class data. If the index does not point to a
333 string, an error results. */
335 static void
336 print_name (FILE* stream, JCF* jcf, int name_index)
338 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
340 fprintf (stream, "<not a UTF8 constant>");
341 found_error = 1;
343 else if (! flag_jni)
344 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
345 JPOOL_UTF_LENGTH (jcf, name_index));
346 else
348 /* For JNI we must correctly quote each character. */
349 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
350 int length = JPOOL_UTF_LENGTH (jcf, name_index);
351 const unsigned char *limit = str + length;
352 while (str < limit)
354 int ch = UTF8_GET (str, limit);
355 if (ch < 0)
357 fprintf (stream, "\\<invalid>");
358 return;
360 jni_print_char (stream, ch);
365 /* Print base name of class. The base name is everything after the
366 final separator. */
368 static void
369 print_base_classname (FILE *stream, JCF *jcf, int index)
371 int name_index = JPOOL_USHORT1 (jcf, index);
372 int len;
373 const unsigned char *s, *p, *limit;
375 s = JPOOL_UTF_DATA (jcf, name_index);
376 len = JPOOL_UTF_LENGTH (jcf, name_index);
377 limit = s + len;
378 p = s;
379 while (s < limit)
381 int c = UTF8_GET (s, limit);
382 if (c == '/')
383 p = s;
386 while (p < limit)
388 int ch = UTF8_GET (p, limit);
389 if (ch == '/')
390 fputs ("::", stream);
391 else
392 jcf_print_char (stream, ch);
396 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
397 and 1 if STR is "greater" than NAME. */
399 static int
400 utf8_cmp (const unsigned char *str, int length, const char *name)
402 const unsigned char *limit = str + length;
403 int i;
405 for (i = 0; name[i]; ++i)
407 int ch = UTF8_GET (str, limit);
408 if (ch != name[i])
409 return ch - name[i];
412 return str == limit ? 0 : 1;
415 /* This is a sorted list of all C++ keywords. */
417 static const char *const cxx_keywords[] =
419 "_Complex",
420 "__alignof",
421 "__alignof__",
422 "__asm",
423 "__asm__",
424 "__attribute",
425 "__attribute__",
426 "__builtin_va_arg",
427 "__complex",
428 "__complex__",
429 "__const",
430 "__const__",
431 "__extension__",
432 "__imag",
433 "__imag__",
434 "__inline",
435 "__inline__",
436 "__label__",
437 "__null",
438 "__real",
439 "__real__",
440 "__restrict",
441 "__restrict__",
442 "__signed",
443 "__signed__",
444 "__typeof",
445 "__typeof__",
446 "__volatile",
447 "__volatile__",
448 "and",
449 "and_eq",
450 "asm",
451 "auto",
452 "bitand",
453 "bitor",
454 "bool",
455 "break",
456 "case",
457 "catch",
458 "char",
459 "class",
460 "compl",
461 "const",
462 "const_cast",
463 "continue",
464 "default",
465 "delete",
466 "do",
467 "double",
468 "dynamic_cast",
469 "else",
470 "enum",
471 "explicit",
472 "export",
473 "extern",
474 "false",
475 "float",
476 "for",
477 "friend",
478 "goto",
479 "if",
480 "inline",
481 "int",
482 "long",
483 "mutable",
484 "namespace",
485 "new",
486 "not",
487 "not_eq",
488 "operator",
489 "or",
490 "or_eq",
491 "private",
492 "protected",
493 "public",
494 "register",
495 "reinterpret_cast",
496 "return",
497 "short",
498 "signed",
499 "sizeof",
500 "static",
501 "static_cast",
502 "struct",
503 "switch",
504 "template",
505 "this",
506 "throw",
507 "true",
508 "try",
509 "typedef",
510 "typeid",
511 "typename",
512 "typeof",
513 "union",
514 "unsigned",
515 "using",
516 "virtual",
517 "void",
518 "volatile",
519 "wchar_t",
520 "while",
521 "xor",
522 "xor_eq"
526 /* If NAME is the name of a C++ keyword, then return an override name.
527 This is a name that can be used in place of the keyword.
528 Otherwise, return NULL. The return value is malloc()d. */
530 static char *
531 cxx_keyword_subst (const unsigned char *str, int length)
533 int last = ARRAY_SIZE (cxx_keywords);
534 int first = 0;
535 int mid = (last + first) / 2;
536 int old = -1;
538 for (mid = (last + first) / 2;
539 mid != old;
540 old = mid, mid = (last + first) / 2)
542 int kwl = strlen (cxx_keywords[mid]);
543 int min_length = kwl > length ? length : kwl;
544 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
546 if (r == 0)
548 int i;
550 /* Skip all trailing `$'. */
551 for (i = min_length; i < length && str[i] == '$'; ++i)
553 /* We've only found a match if all the remaining characters
554 are `$'. */
555 if (i == length)
557 char *dup = xmalloc (2 + length - min_length + kwl);
558 strcpy (dup, cxx_keywords[mid]);
559 for (i = kwl; i < length + 1; ++i)
560 dup[i] = '$';
561 dup[i] = '\0';
562 return dup;
564 r = 1;
567 if (r < 0)
568 last = mid;
569 else
570 first = mid;
572 return NULL;
575 /* Generate an access control keyword based on FLAGS. */
577 static void
578 generate_access (FILE *stream, JCF_u2 flags)
580 if ((flags & ACC_VISIBILITY) == last_access)
581 return;
582 last_access = (flags & ACC_VISIBILITY);
584 switch (last_access)
586 case 0:
587 fputs ("public: // actually package-private\n", stream);
588 break;
589 case ACC_PUBLIC:
590 fputs ("public:\n", stream);
591 break;
592 case ACC_PRIVATE:
593 fputs ("private:\n", stream);
594 break;
595 case ACC_PROTECTED:
596 fputs ("public: // actually protected\n", stream);
597 break;
598 default:
599 found_error = 1;
600 fprintf (stream, "#error unrecognized visibility %d\n",
601 (flags & ACC_VISIBILITY));
602 break;
606 /* See if NAME is already the name of a method. */
607 static int
608 name_is_method_p (const unsigned char *name, int length)
610 struct method_name *p;
612 for (p = method_name_list; p != NULL; p = p->next)
614 if (p->length == length && ! memcmp (p->name, name, length))
615 return 1;
617 return 0;
620 /* If there is already a method named NAME, whose signature is not
621 SIGNATURE, then return true. Otherwise return false. */
622 static int
623 overloaded_jni_method_exists_p (const unsigned char *name, int length,
624 const char *signature, int sig_length)
626 struct method_name *p;
628 for (p = method_name_list; p != NULL; p = p->next)
630 if (p->length == length
631 && ! memcmp (p->name, name, length)
632 && (p->sig_length != sig_length
633 || memcmp (p->signature, signature, sig_length)))
634 return 1;
636 return 0;
639 /* Get name of a field. This handles renamings due to C++ clash. */
640 static char *
641 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
643 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
644 int length = JPOOL_UTF_LENGTH (jcf, name_index);
645 char *override;
647 if (name_is_method_p (name, length))
649 /* This field name matches a method. So override the name with
650 a dummy name. This is yucky, but it isn't clear what else to
651 do. FIXME: if the field is static, then we'll be in real
652 trouble. */
653 if ((flags & ACC_STATIC))
655 fprintf (stderr, "static field has same name as method\n");
656 found_error = 1;
657 return NULL;
660 override = xmalloc (length + 3);
661 memcpy (override, name, length);
662 strcpy (override + length, "__");
664 else
665 override = cxx_keyword_subst (name, length);
667 return override;
670 /* Print a field name. Convenience function for use with
671 get_field_name. */
672 static void
673 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
675 char *override = get_field_name (jcf, name_index, flags);
677 if (override)
679 fputs (override, stream);
680 free (override);
682 else
683 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
684 JPOOL_UTF_LENGTH (jcf, name_index));
687 static void
688 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
689 JCF_u2 flags)
691 char *override = NULL;
693 generate_access (stream, flags);
694 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
696 fprintf (stream, "<not a UTF8 constant>");
697 found_error = 1;
698 return;
701 fputs (" ", out);
702 if ((flags & ACC_STATIC))
703 fputs ("static ", out);
705 if ((flags & ACC_FINAL))
707 if (current_field_value > 0)
709 char buffer[25];
710 int done = 1;
712 switch (JPOOL_TAG (jcf, current_field_value))
714 case CONSTANT_Integer:
716 jint num;
717 int most_negative = 0;
718 fputs ("const jint ", out);
719 print_field_name (out, jcf, name_index, 0);
720 fputs (" = ", out);
721 num = JPOOL_INT (jcf, current_field_value);
722 /* We single out the most negative number to print
723 specially. This avoids later warnings from g++. */
724 if (num == (jint) 0x80000000)
726 most_negative = 1;
727 ++num;
729 format_int (buffer, (jlong) num, 10);
730 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
732 break;
733 case CONSTANT_Long:
735 jlong num;
736 int most_negative = 0;
737 fputs ("const jlong ", out);
738 print_field_name (out, jcf, name_index, 0);
739 fputs (" = ", out);
740 num = JPOOL_LONG (jcf, current_field_value);
741 /* We single out the most negative number to print
742 specially.. This avoids later warnings from g++. */
743 if (num == (jlong) 0x8000000000000000LL)
745 most_negative = 1;
746 ++num;
748 format_int (buffer, num, 10);
749 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
751 break;
752 case CONSTANT_Float:
754 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
755 fputs ("const jfloat ", out);
756 print_field_name (out, jcf, name_index, 0);
757 jni_print_float (out, fnum);
759 break;
760 case CONSTANT_Double:
762 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
763 fputs ("const jdouble ", out);
764 print_field_name (out, jcf, name_index, 0);
765 jni_print_double (out, dnum);
767 break;
768 default:
769 /* We can't print this as a constant, but we can still
770 print something sensible. */
771 done = 0;
772 break;
775 if (done)
776 return;
780 override = get_field_name (jcf, name_index, flags);
781 print_c_decl (out, jcf, name_index, sig_index, 0, override, flags);
782 fputs (";\n", out);
784 if (override)
785 free (override);
789 static void
790 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
791 JCF_u2 flags)
793 const unsigned char *str;
794 int length, is_init = 0;
795 char *override = NULL;
797 method_declared = 0;
798 method_access = flags;
799 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
800 fprintf (stream, "<not a UTF8 constant>");
801 str = JPOOL_UTF_DATA (jcf, name_index);
802 length = JPOOL_UTF_LENGTH (jcf, name_index);
804 if (str[0] == '<')
806 /* Ignore the internally generated method <clinit>. However,
807 treat <init> as a constructor. */
808 if (! utf8_cmp (str, length, "<init>"))
809 is_init = 1;
810 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
811 && ! (flags & ACC_STATIC))
813 /* FIXME: i18n bug here. Order of prints should not be
814 fixed. */
815 fprintf (stderr, "ignored method `");
816 jcf_print_utf8 (stderr, str, length);
817 fprintf (stderr, "' marked virtual\n");
818 found_error = 1;
819 return;
821 else
822 return;
825 /* During the first method pass, build a list of method names. This will
826 be used to determine if field names conflict with method names. */
827 if (! stream)
829 struct method_name *nn;
831 nn = xmalloc (sizeof (struct method_name));
832 nn->name = xmalloc (length);
833 memcpy (nn->name, str, length);
834 nn->length = length;
835 nn->next = method_name_list;
836 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
837 nn->signature = xmalloc (nn->sig_length);
838 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
839 nn->sig_length);
840 method_name_list = nn;
842 /* The rest of this function doesn't matter. */
843 return;
846 /* We don't worry about overrides in JNI mode. */
847 if (! flag_jni)
849 /* We can't generate a method whose name is a C++ reserved word.
850 We can't just ignore the function, because that will cause
851 incorrect code to be generated if the function is virtual
852 (not only for calls to this function for for other functions
853 after it in the vtbl). So we give it a dummy name instead. */
854 override = cxx_keyword_subst (str, length);
857 if (! stubs && ! flag_jni)
859 method_printed = 1;
861 generate_access (stream, flags);
863 fputs (" ", out);
864 if ((flags & ACC_STATIC))
865 fputs ("static ", out);
866 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
868 /* Don't print `virtual' if we have a constructor. */
869 if (! is_init)
870 fputs ("virtual ", out);
872 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
874 if ((flags & ACC_ABSTRACT))
875 fputs (" = 0", out);
876 else
877 method_declared = 1;
879 else
881 if (METHOD_IS_NATIVE (flags))
883 method_printed = 1;
884 print_stub_or_jni (out, jcf, name_index, sig_index,
885 is_init, override, flags);
889 if (override)
890 free (override);
893 /* A helper for the decompiler which prints a `return' statement where
894 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
895 identical, we emit a cast. We do this because the C++ compiler
896 doesn't know that a reference can be cast to the type of an
897 interface it implements. METHODTYPE is the index of the method's
898 signature. NAMEINDEX is the index of the field name; -1 for
899 `this'. OBJECTTYPE is the index of the object's type. */
900 static void
901 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
902 int nameindex, int objecttype)
904 int cast = 0;
905 int obj_name_len, method_name_len;
906 const unsigned char *obj_data, *method_data;
908 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
909 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
911 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
912 method_data = JPOOL_UTF_DATA (jcf, methodtype);
914 /* Skip forward to return type part of method. */
915 while (*method_data != ')')
917 ++method_data;
918 --method_name_len;
920 /* Skip past `)'. */
921 ++method_data;
922 --method_name_len;
924 /* If we see an `L', skip it and the trailing `;'. */
925 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
927 ++method_data;
928 method_name_len -= 2;
930 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
932 ++obj_data;
933 obj_name_len -= 2;
936 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
937 need a cast. Right now there is no way to determine if this is
938 the case. */
939 if (method_name_len != obj_name_len)
940 cast = 1;
941 else
943 int i;
944 for (i = 0; i < method_name_len; ++i)
946 if (method_data[i] != obj_data[i])
948 cast = 1;
949 break;
954 fputs (" { return ", out);
956 if (cast)
958 int array_depth = 0;
959 const unsigned char *limit;
961 fputs ("reinterpret_cast<", out);
963 while (*method_data == '[')
965 ++method_data;
966 ++array_depth;
967 --method_name_len;
968 fputs ("JArray<", out);
971 /* Leading space to avoid C++ digraphs. */
972 fputs (" ::", out);
974 /* If we see an `L', skip it and the trailing `;'. Only do this
975 if we've seen an array specification. If we don't have an
976 array then the `L' was stripped earlier. */
977 if (array_depth && method_data[0] == 'L'
978 && method_data[method_name_len - 1] == ';')
980 ++method_data;
981 method_name_len -= 2;
984 limit = method_data + method_name_len;
985 while (method_data < limit)
987 int ch = UTF8_GET (method_data, limit);
988 if (ch == '/')
989 fputs ("::", out);
990 else
991 jcf_print_char (out, ch);
993 fputs (" *", out);
995 /* Close each array. */
996 while (array_depth > 0)
998 fputs ("> *", out);
999 --array_depth;
1002 /* Close the cast. */
1003 fputs ("> (", out);
1006 if (nameindex == -1)
1007 fputs ("this", out);
1008 else
1009 print_field_name (out, jcf, nameindex, 0);
1011 if (cast)
1012 fputs (")", out);
1014 fputs ("; }", out);
1018 /* Try to decompile a method body. Right now we just try to handle a
1019 simple case that we can do. Expand as desired. */
1020 static void
1021 decompile_method (FILE *out, JCF *jcf, int code_len)
1023 const unsigned char *codes = jcf->read_ptr;
1024 int index;
1025 uint16 name_and_type, name;
1027 /* If the method is synchronized, don't touch it. */
1028 if ((method_access & ACC_SYNCHRONIZED))
1029 return;
1031 if (code_len == 5
1032 && codes[0] == OPCODE_aload_0
1033 && codes[1] == OPCODE_getfield
1034 && (codes[4] == OPCODE_areturn
1035 || codes[4] == OPCODE_dreturn
1036 || codes[4] == OPCODE_freturn
1037 || codes[4] == OPCODE_ireturn
1038 || codes[4] == OPCODE_lreturn))
1040 /* Found code like `return FIELD'. */
1041 index = (codes[2] << 8) | codes[3];
1042 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1043 name_and_type = JPOOL_USHORT2 (jcf, index);
1044 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1045 name = JPOOL_USHORT1 (jcf, name_and_type);
1046 if (codes[4] == OPCODE_areturn)
1047 decompile_return_statement (out, jcf, method_signature,
1048 name, JPOOL_USHORT2 (jcf, name_and_type));
1049 else
1051 fputs (" { return ", out);
1052 /* FIXME: flags. */
1053 print_field_name (out, jcf, name, 0);
1054 fputs ("; }", out);
1056 decompiled = 1;
1058 else if (code_len == 2
1059 && codes[0] == OPCODE_aload_0
1060 && codes[1] == OPCODE_areturn
1061 /* We're going to generate `return this'. This only makes
1062 sense for non-static methods. */
1063 && ! (method_access & ACC_STATIC))
1065 decompile_return_statement (out, jcf, method_signature, -1,
1066 JPOOL_USHORT1 (jcf, jcf->this_class));
1067 decompiled = 1;
1069 else if (code_len == 1 && codes[0] == OPCODE_return)
1071 /* Found plain `return'. */
1072 fputs (" { }", out);
1073 decompiled = 1;
1075 else if (code_len == 2
1076 && codes[0] == OPCODE_aconst_null
1077 && codes[1] == OPCODE_areturn)
1079 /* Found `return null'. We don't want to depend on NULL being
1080 defined. */
1081 fputs (" { return 0; }", out);
1082 decompiled = 1;
1086 /* Like strcmp, but invert the return result for the hash table. This
1087 should probably be in hashtab.c to complement the existing string
1088 hash function. */
1089 static int
1090 gcjh_streq (const void *p1, const void *p2)
1092 return ! strcmp ((char *) p1, (char *) p2);
1095 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1096 or 0 if not. CLNAME may be extracted from a signature, and can be
1097 terminated with either `;' or NULL. */
1098 static int
1099 throwable_p (const unsigned char *clname)
1101 int length;
1102 unsigned char *current;
1103 int i;
1104 int result = 0;
1106 /* We keep two hash tables of class names. In one we list all the
1107 classes which are subclasses of Throwable. In the other we will
1108 all other classes. We keep two tables to make the code a bit
1109 simpler; we don't have to have a structure mapping class name to
1110 a `throwable?' bit. */
1111 static htab_t throw_hash;
1112 static htab_t non_throw_hash;
1113 static int init_done = 0;
1115 if (! init_done)
1117 void **slot;
1118 unsigned char *str;
1120 /* Self-initializing. The cost of this really doesn't matter.
1121 We also don't care about freeing these, either. */
1122 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1123 (htab_del) free);
1124 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1125 (htab_del) free);
1127 /* Make sure the root classes show up in the tables. */
1128 str = xstrdup ("java.lang.Throwable");
1129 slot = htab_find_slot (throw_hash, str, INSERT);
1130 *slot = str;
1132 str = xstrdup ("java.lang.Object");
1133 slot = htab_find_slot (non_throw_hash, str, INSERT);
1134 *slot = str;
1136 init_done = 1;
1139 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1141 current = ALLOC (length + 1);
1142 for (i = 0; i < length; ++i)
1143 current[i] = clname[i] == '/' ? '.' : clname[i];
1144 current[length] = '\0';
1146 /* We don't compute the hash slot here because the table might be
1147 modified by the recursion. In that case the slot could be
1148 invalidated. */
1149 if (htab_find (throw_hash, current))
1150 result = 1;
1151 else if (htab_find (non_throw_hash, current))
1152 result = 0;
1153 else
1155 JCF jcf;
1156 void **slot;
1157 unsigned char *super, *tmp;
1158 int super_length = -1;
1159 const char *classfile_name = find_class (current, strlen (current),
1160 &jcf, 0);
1162 if (! classfile_name)
1164 fprintf (stderr, "couldn't find class %s\n", current);
1165 found_error = 1;
1166 return 0;
1168 if (jcf_parse_preamble (&jcf) != 0
1169 || jcf_parse_constant_pool (&jcf) != 0
1170 || verify_constant_pool (&jcf) > 0)
1172 fprintf (stderr, "parse error while reading %s\n", classfile_name);
1173 found_error = 1;
1174 return 0;
1176 jcf_parse_class (&jcf);
1178 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1179 super = ALLOC (super_length + 1);
1180 memcpy (super, tmp, super_length);
1181 super[super_length] = '\0';
1183 result = throwable_p (super);
1184 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1185 current, INSERT);
1186 *slot = current;
1187 current = NULL;
1189 JCF_FINISH (&jcf);
1192 return result;
1195 /* Print one piece of a signature. Returns pointer to next parseable
1196 character on success, NULL on error. */
1197 static const unsigned char *
1198 decode_signature_piece (FILE *stream, const unsigned char *signature,
1199 const unsigned char *limit, int *need_space)
1201 const char *ctype;
1202 int array_depth = 0;
1204 switch (signature[0])
1206 case '[':
1207 /* More spaghetti. */
1209 array_loop:
1210 for (signature++; (signature < limit
1211 && ISDIGIT (*signature)); signature++)
1213 switch (*signature)
1215 case 'B':
1216 ctype = "jbyteArray";
1217 break;
1218 case 'C':
1219 ctype = "jcharArray";
1220 break;
1221 case 'D':
1222 ctype = "jdoubleArray";
1223 break;
1224 case 'F':
1225 ctype = "jfloatArray";
1226 break;
1227 case 'I':
1228 ctype = "jintArray";
1229 break;
1230 case 'S':
1231 ctype = "jshortArray";
1232 break;
1233 case 'J':
1234 ctype = "jlongArray";
1235 break;
1236 case 'Z':
1237 ctype = "jbooleanArray";
1238 break;
1239 case '[':
1240 /* We have a nested array. */
1241 ++array_depth;
1242 if (! flag_jni)
1243 fputs ("JArray<", stream);
1244 goto array_loop;
1246 case 'L':
1247 /* We have to generate a reference to JArray here, so that
1248 our output matches what the compiler does. */
1249 ++signature;
1250 /* Space between `<' and `:' to avoid C++ digraphs. */
1251 if (! flag_jni)
1252 fputs ("JArray< ::", stream);
1253 while (signature < limit && *signature != ';')
1255 int ch = UTF8_GET (signature, limit);
1256 if (! flag_jni)
1258 if (ch == '/')
1259 fputs ("::", stream);
1260 else
1261 jcf_print_char (stream, ch);
1264 if (! flag_jni)
1265 fputs (" *> *", stream);
1266 *need_space = 0;
1267 ctype = NULL;
1268 break;
1269 default:
1270 /* Unparseable signature. */
1271 return NULL;
1274 /* If the previous iterations left us with something to print,
1275 print it. For JNI, we always print `jobjectArray' in the
1276 nested cases. */
1277 if (flag_jni && (ctype == NULL || array_depth > 0))
1279 ctype = "jobjectArray";
1280 *need_space = 1;
1282 /* The `printit' case will advance SIGNATURE for us. If we
1283 don't go there, we must advance past the `;' ourselves. */
1284 if (ctype != NULL)
1285 goto printit;
1286 ++signature;
1287 break;
1289 case '(':
1290 case ')':
1291 /* This shouldn't happen. */
1292 return NULL;
1294 case 'B': ctype = "jbyte"; goto printit;
1295 case 'C': ctype = "jchar"; goto printit;
1296 case 'D': ctype = "jdouble"; goto printit;
1297 case 'F': ctype = "jfloat"; goto printit;
1298 case 'I': ctype = "jint"; goto printit;
1299 case 'J': ctype = "jlong"; goto printit;
1300 case 'S': ctype = "jshort"; goto printit;
1301 case 'Z': ctype = "jboolean"; goto printit;
1302 case 'V': ctype = "void"; goto printit;
1303 case 'L':
1304 if (flag_jni)
1306 /* We know about certain types and special-case their names. */
1307 if (! strncmp (signature, "Ljava/lang/String;",
1308 sizeof ("Ljava/lang/String;") -1))
1309 ctype = "jstring";
1310 else if (! strncmp (signature, "Ljava/lang/Class;",
1311 sizeof ("Ljava/lang/Class;") - 1))
1312 ctype = "jclass";
1313 /* Skip leading 'L' for throwable_p call. */
1314 else if (throwable_p (signature + 1))
1315 ctype = "jthrowable";
1316 else
1317 ctype = "jobject";
1319 while (*signature && *signature != ';')
1320 ++signature;
1322 goto printit;
1324 /* Print a leading "::" so we look in the right namespace. */
1325 fputs ("::", stream);
1326 ++signature;
1327 while (*signature && *signature != ';')
1329 int ch = UTF8_GET (signature, limit);
1330 if (ch == '/')
1331 fputs ("::", stream);
1332 else
1333 jcf_print_char (stream, ch);
1335 fputs (" *", stream);
1336 if (*signature == ';')
1337 signature++;
1338 *need_space = 0;
1339 break;
1340 default:
1341 *need_space = 1;
1342 jni_print_char (stream, *signature++);
1343 break;
1344 printit:
1345 signature++;
1346 *need_space = 1;
1347 fputs (ctype, stream);
1348 break;
1351 if (! flag_jni)
1353 while (array_depth-- > 0)
1354 fputs ("> *", stream);
1357 return signature;
1360 static void
1361 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1362 int is_init, const char *name_override, int flags)
1364 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1366 fprintf (stream, "<not a UTF8 constant>");
1367 found_error = 1;
1369 else
1371 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1372 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1373 const unsigned char *str = str0;
1374 const unsigned char *limit = str + length;
1375 int need_space = 0;
1376 int is_method = str[0] == '(';
1377 const unsigned char *next;
1379 /* If printing a method, skip to the return signature and print
1380 that first. However, there is no return value if this is a
1381 constructor. */
1382 if (is_method && ! is_init)
1384 while (str < limit)
1386 int ch = *str++;
1387 if (ch == ')')
1388 break;
1392 /* If printing a field or an ordinary method, then print the
1393 "return value" now. */
1394 if (! is_method || ! is_init)
1396 next = decode_signature_piece (stream, str, limit, &need_space);
1397 if (! next)
1399 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1400 found_error = 1;
1401 return;
1405 /* Force the alignment of the first data member. This is
1406 because the "new" C++ ABI changed the alignemnt of non-POD
1407 classes. gcj, however, still uses the "old" alignment. */
1408 if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
1410 is_first_data_member = 0;
1411 print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1412 jcf, jcf->super_class, 1);
1413 fputs (" )))) ", stream);
1416 /* Now print the name of the thing. */
1417 if (need_space)
1418 fputs (" ", stream);
1419 print_full_cxx_name (stream, jcf, name_index,
1420 signature_index, is_init, name_override,
1421 flags);
1425 /* Print the unqualified method name followed by the signature. */
1426 static void
1427 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1428 int signature_index, int is_init,
1429 const char *name_override, int flags)
1431 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1432 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1433 const unsigned char *str = str0;
1434 const unsigned char *limit = str + length;
1435 int need_space = 0;
1436 int is_method = str[0] == '(';
1437 const unsigned char *next;
1439 if (name_override)
1440 fputs (name_override, stream);
1441 else if (name_index)
1443 /* Declare constructors specially. */
1444 if (is_init)
1445 print_base_classname (stream, jcf, jcf->this_class);
1446 else
1447 print_name (stream, jcf, name_index);
1450 if (flag_jni)
1452 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1453 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1454 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1455 JPOOL_UTF_LENGTH (jcf, name_index),
1456 signature, sig_len))
1458 /* If this method is overloaded by another native method,
1459 then include the argument information in the mangled
1460 name. */
1461 unsigned char *limit = signature + sig_len;
1462 fputs ("__", stream);
1463 while (signature < limit)
1465 int ch = UTF8_GET (signature, limit);
1466 jni_print_char (stream, ch);
1467 if (ch == ')')
1469 /* Done. */
1470 break;
1476 if (is_method)
1478 /* Have a method or a constructor. Print signature pieces
1479 until done. */
1480 fputs (" (", stream);
1482 str = str0 + 1;
1484 /* In JNI mode, add extra arguments. */
1485 if (flag_jni)
1487 /* FIXME: it would be nice to know if we are printing a decl
1488 or a definition, and only print `env' for the latter. */
1489 fputs ("JNIEnv *env", stream);
1491 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1493 if (*str != ')')
1494 fputs (", ", stream);
1497 while (str < limit && *str != ')')
1499 next = decode_signature_piece (stream, str, limit, &need_space);
1500 if (! next)
1502 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1503 found_error = 1;
1504 return;
1507 if (next < limit && *next != ')')
1508 fputs (", ", stream);
1509 str = next;
1512 fputs (")", stream);
1516 /* This is a helper for print_stub_or_jni. */
1517 static void
1518 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1519 int signature_index, int is_init,
1520 const char *name_override, int flags)
1522 const char *const prefix = flag_jni ? "Java_" : "";
1523 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1524 fputs (flag_jni ? "_" : "::", stream);
1525 print_full_cxx_name (stream, jcf, name_index,
1526 signature_index, is_init, name_override,
1527 flags);
1530 static void
1531 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1532 int signature_index, int is_init,
1533 const char *name_override, int flags)
1535 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1537 fprintf (stream, "<not a UTF8 constant>");
1538 found_error = 1;
1540 else
1542 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1543 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1544 const unsigned char *str = str0;
1545 const unsigned char *limit = str + length;
1546 int need_space = 0;
1547 int is_method = str[0] == '(';
1548 const unsigned char *next;
1550 /* Don't print fields in the JNI case. */
1551 if (! is_method && flag_jni)
1552 return;
1554 if (flag_jni && ! stubs)
1555 fputs ("extern JNIEXPORT ", stream);
1557 /* If printing a method, skip to the return signature and print
1558 that first. However, there is no return value if this is a
1559 constructor. */
1560 if (is_method && ! is_init)
1562 while (str < limit)
1564 int ch = *str++;
1565 if (ch == ')')
1566 break;
1570 /* If printing a field or an ordinary method, then print the
1571 "return value" now. Note that a constructor can't be native,
1572 so we don't bother checking this in the JNI case. */
1573 if (! is_method || ! is_init)
1575 next = decode_signature_piece (stream, str, limit, &need_space);
1576 if (! next)
1578 fprintf (stderr, "unparseable signature: `%s'\n", str0);
1579 found_error = 1;
1580 return;
1584 /* When printing a JNI header we need to respect the space. In
1585 other cases we're just going to insert a newline anyway. */
1586 fputs (need_space && ! stubs ? " " : "\n", stream);
1588 if (flag_jni && ! stubs)
1589 fputs ("JNICALL ", stream);
1591 /* Now print the name of the thing. */
1592 print_name_for_stub_or_jni (stream, jcf, name_index,
1593 signature_index, is_init, name_override,
1594 flags);
1596 /* Print the body. */
1597 if (stubs)
1599 if (flag_jni)
1600 fputs ("\n{\n (*env)->FatalError (env, \"", stream);
1601 else
1602 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1603 print_name_for_stub_or_jni (stream, jcf, name_index,
1604 signature_index, is_init,
1605 name_override,
1606 flags);
1607 fprintf (stream, " not implemented\")%s;\n}\n\n",
1608 flag_jni ? "" : ")");
1613 static void
1614 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1616 int name_index = JPOOL_USHORT1 (jcf, index);
1617 fputs (prefix, stream);
1618 jcf_print_utf8_replace (out,
1619 JPOOL_UTF_DATA (jcf, name_index),
1620 JPOOL_UTF_LENGTH (jcf, name_index),
1621 '/', '_');
1624 /* Print PREFIX, then a class name in C++ format. If the name refers
1625 to an array, ignore it and don't print PREFIX. Returns 1 if
1626 something was printed, 0 otherwise. */
1627 static int
1628 print_cxx_classname (FILE *stream, const char *prefix,
1629 JCF *jcf, int index, int add_scope)
1631 int name_index = JPOOL_USHORT1 (jcf, index);
1632 int len, c;
1633 const unsigned char *s, *p, *limit;
1635 s = JPOOL_UTF_DATA (jcf, name_index);
1636 len = JPOOL_UTF_LENGTH (jcf, name_index);
1637 limit = s + len;
1639 /* Explicitly omit arrays here. */
1640 p = s;
1641 c = UTF8_GET (p, limit);
1642 if (c == '[')
1643 return 0;
1645 fputs (prefix, stream);
1647 /* Print a leading "::" so we look in the right namespace. */
1648 if (! flag_jni && ! stubs && add_scope)
1649 fputs ("::", stream);
1651 while (s < limit)
1653 c = UTF8_GET (s, limit);
1654 if (c == '/')
1655 fputs (flag_jni ? "_" : "::", stream);
1656 else
1657 jni_print_char (stream, c);
1660 return 1;
1663 int written_class_count = 0;
1665 /* Return name of superclass. If LEN is not NULL, fill it with length
1666 of name. */
1667 static const unsigned char *
1668 super_class_name (JCF *derived_jcf, int *len)
1670 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1671 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1672 const unsigned char *supername =
1673 JPOOL_UTF_DATA (derived_jcf, supername_index);
1675 if (len)
1676 *len = supername_length;
1678 return supername;
1681 static void
1682 handle_inner_classes (int count)
1684 int i;
1686 if (out && ! flag_jni && ! stubs && count > 0)
1687 fprintf (out, "\n");
1689 for (i = 0; i < count; ++i)
1691 JCF_u2 inner_info_index = JCF_readu2 (current_jcf);
1693 /* There are a few more values here, but we don't care about
1694 them. The (void) cast is apparently the only way to avoid a
1695 warning here. */
1696 (void) JCF_readu2 (current_jcf);
1697 (void) JCF_readu2 (current_jcf);
1698 (void) JCF_readu2 (current_jcf);
1700 if (out && ! flag_jni && ! stubs)
1702 print_mangled_classname (out, current_jcf, " friend class ",
1703 inner_info_index);
1704 fprintf (out, ";\n");
1711 /* We keep track of all the `#include's we generate, so we can avoid
1712 duplicates. */
1713 struct include
1715 char *name;
1716 struct include *next;
1719 /* List of all includes. */
1720 static struct include *all_includes = NULL;
1722 /* Generate a #include. */
1723 static void
1724 print_include (FILE *out, const unsigned char *utf8, int len)
1726 struct include *incl;
1728 if (! out)
1729 return;
1731 if (len == -1)
1732 len = strlen (utf8);
1734 for (incl = all_includes; incl; incl = incl->next)
1736 /* We check the length because we might have a proper prefix. */
1737 if (len == (int) strlen (incl->name)
1738 && ! strncmp (incl->name, utf8, len))
1739 return;
1742 incl = xmalloc (sizeof (struct include));
1743 incl->name = xmalloc (len + 1);
1744 strncpy (incl->name, utf8, len);
1745 incl->name[len] = '\0';
1746 incl->next = all_includes;
1747 all_includes = incl;
1749 fputs ("#include <", out);
1750 jcf_print_utf8_replace (out, utf8, len,
1751 '/',
1752 flag_jni ? '_' : '/');
1753 fputs (".h>\n", out);
1758 /* This is used to represent part of a package or class name. */
1759 struct namelet
1761 /* The text of this part of the name. */
1762 char *name;
1763 /* True if this represents a class. */
1764 int is_class;
1765 /* Linked list of all classes and packages inside this one. */
1766 struct namelet *subnamelets;
1767 /* Pointer to next sibling. */
1768 struct namelet *next;
1771 static void add_namelet (const unsigned char *, const unsigned char *,
1772 struct namelet *);
1773 static void print_namelet (FILE *, struct namelet *, int);
1775 /* The special root namelet. */
1776 static struct namelet root =
1778 NULL,
1780 NULL,
1781 NULL
1784 /* This extracts the next name segment from the full UTF-8 encoded
1785 package or class name and links it into the tree. It does this
1786 recursively. */
1787 static void
1788 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1789 struct namelet *parent)
1791 const unsigned char *p;
1792 struct namelet *n = NULL, *np;
1794 /* We want to skip the standard namespaces that we assume the
1795 runtime already knows about. We only do this at the top level,
1796 though, hence the check for `root'. */
1797 if (parent == &root)
1799 #define JAVALANG "java/lang/"
1800 #define JAVAIO "java/io/"
1801 #define JAVAUTIL "java/util/"
1802 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1803 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1804 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1805 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1806 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1807 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1808 return;
1811 for (p = name; p < name_limit && *p != '/'; ++p)
1814 /* Search for this name beneath the PARENT node. */
1815 for (np = parent->subnamelets; np != NULL; np = np->next)
1817 /* We check the length because we might have a proper prefix. */
1818 if ((int) strlen (np->name) == p - name &&
1819 ! strncmp (name, np->name, p - name))
1821 n = np;
1822 break;
1826 if (n == NULL)
1828 n = xmalloc (sizeof (struct namelet));
1829 n->name = xmalloc (p - name + 1);
1830 strncpy (n->name, name, p - name);
1831 n->name[p - name] = '\0';
1832 n->is_class = (p == name_limit);
1833 n->subnamelets = NULL;
1834 n->next = parent->subnamelets;
1835 parent->subnamelets = n;
1838 /* We recurse if there is more text, and if the trailing piece does
1839 not represent an inner class. */
1840 if (p < name_limit)
1841 add_namelet (p + 1, name_limit, n);
1844 /* Print a single namelet. Destroys namelets while printing. */
1845 static void
1846 print_namelet (FILE *out, struct namelet *name, int depth)
1848 int i, term = 0;
1849 struct namelet *c;
1851 if (name->name)
1853 for (i = 0; i < depth; ++i)
1854 fputc (' ', out);
1855 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1856 name->name);
1857 if (name->is_class && name->subnamelets == NULL)
1858 fputs (";\n", out);
1859 else
1861 term = 1;
1862 fputs ("\n", out);
1863 for (i = 0; i < depth; ++i)
1864 fputc (' ', out);
1865 fputs ("{\n", out);
1869 c = name->subnamelets;
1870 while (c != NULL)
1872 struct namelet *next = c->next;
1873 print_namelet (out, c, depth + 2);
1874 c = next;
1876 name->subnamelets = NULL;
1878 if (name->name)
1880 if (term)
1882 for (i = 0; i < depth; ++i)
1883 fputc (' ', out);
1884 fputs ("}\n", out);
1885 /* Only print a `;' when printing a class. C++ is evil. */
1886 if (name->is_class)
1887 fputs (";", out);
1890 free (name->name);
1891 free (name);
1895 /* This is called to add some classes to the list of classes for which
1896 we need decls. The signature argument can be a function
1897 signature. */
1898 static void
1899 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1901 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1902 int len = JPOOL_UTF_LENGTH (jcf, signature);
1903 int i;
1905 for (i = 0; i < len; ++i)
1907 int start;
1909 /* If we see an array, then we include the array header. */
1910 if (s[i] == '[')
1912 print_include (out, "gcj/array", -1);
1913 continue;
1916 /* We're looking for `L<stuff>;' -- everything else is
1917 ignorable. */
1918 if (s[i] != 'L')
1919 continue;
1921 for (start = ++i; i < len && s[i] != ';'; ++i)
1924 add_namelet (&s[start], &s[i], &root);
1928 /* Print declarations for all classes required by this class. Any
1929 class or package in the `java' package is assumed to be handled
1930 statically in libjava; we don't generate declarations for these.
1931 This makes the generated headers a bit easier to read. */
1932 static void
1933 print_class_decls (FILE *out, JCF *jcf, int self)
1935 /* Make sure to always add the current class to the list of things
1936 that should be declared. */
1937 int name_index = JPOOL_USHORT1 (jcf, self);
1938 int len;
1939 const unsigned char *s;
1941 s = JPOOL_UTF_DATA (jcf, name_index);
1942 len = JPOOL_UTF_LENGTH (jcf, name_index);
1943 add_namelet (s, s + len, &root);
1945 if (root.subnamelets)
1947 fputs ("extern \"Java\"\n{\n", out);
1948 /* We use an initial offset of 0 because the root namelet
1949 doesn't cause anything to print. */
1950 print_namelet (out, &root, 0);
1951 fputs ("}\n\n", out);
1957 static void
1958 process_file (JCF *jcf, FILE *out)
1960 int code, i;
1961 uint32 field_start, method_end, method_start;
1963 current_jcf = jcf;
1965 last_access = -1;
1967 if (jcf_parse_preamble (jcf) != 0)
1969 fprintf (stderr, "Not a valid Java .class file.\n");
1970 found_error = 1;
1971 return;
1974 /* Parse and possibly print constant pool */
1975 code = jcf_parse_constant_pool (jcf);
1976 if (code != 0)
1978 fprintf (stderr, "error while parsing constant pool\n");
1979 found_error = 1;
1980 return;
1982 code = verify_constant_pool (jcf);
1983 if (code > 0)
1985 fprintf (stderr, "error in constant pool entry #%d\n", code);
1986 found_error = 1;
1987 return;
1990 jcf_parse_class (jcf);
1992 if (written_class_count++ == 0 && out)
1994 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
1995 if (flag_jni)
1997 cstart = "/*";
1998 cstart2 = " ";
1999 cend = " */";
2000 mode = "";
2001 what = "JNI";
2002 jflag = " -jni";
2004 else
2006 cstart = "//";
2007 cstart2 = "//";
2008 cend = "";
2009 mode = " -*- c++ -*-";
2010 what = "CNI";
2011 jflag = "";
2014 if (! stubs)
2015 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2016 cstart, mode, cend);
2017 else
2019 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2020 %s\n\
2021 %s This file is intended to give you a head start on implementing native\n\
2022 %s methods using %s.\n\
2023 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2024 %s overwrite any edits you have made to this file.%s\n\n",
2025 cstart, jflag, mode,
2026 cstart2,
2027 cstart2,
2028 cstart2,
2029 what,
2030 cstart2,
2031 jflag,
2032 cstart2,
2033 cend);
2037 if (out)
2039 if (! stubs)
2041 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2042 fprintf (out, "__\n");
2044 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2045 fprintf (out, "__\n\n");
2047 if (flag_jni)
2049 fprintf (out, "#include <jni.h>\n\n");
2050 fprintf (out, "#ifdef __cplusplus\n");
2051 fprintf (out, "extern \"C\"\n");
2052 fprintf (out, "{\n");
2053 fprintf (out, "#endif\n");
2055 else
2057 /* We do this to ensure that inline methods won't be
2058 `outlined' by g++. This works as long as method and
2059 fields are not added by the user. */
2060 fprintf (out, "#pragma interface\n");
2062 if (jcf->super_class)
2064 int super_length;
2065 const unsigned char *supername =
2066 super_class_name (jcf, &super_length);
2068 fputs ("\n", out);
2069 print_include (out, supername, super_length);
2073 else
2075 /* Strip off the ".class" portion of the name when printing
2076 the include file name. */
2077 char *name;
2078 int i, len = strlen (jcf->classname);
2079 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2080 len -= 6;
2081 /* Turn the class name into a file name. */
2082 name = xmalloc (len + 1);
2083 for (i = 0; i < len; ++i)
2084 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2085 name[i] = '\0';
2086 print_include (out, name, len);
2087 free (name);
2089 if (! flag_jni)
2091 print_include (out, "gcj/cni", -1);
2092 print_include (out, "java/lang/UnsupportedOperationException",
2093 -1);
2098 /* We want to parse the methods first. But we need to find where
2099 they start. So first we skip the fields, then parse the methods.
2100 Then we parse the fields and skip the methods. This is ugly, but
2101 not too bad since we need two full passes to get class decl
2102 information anyway. */
2103 field_pass = 0;
2104 field_start = JCF_TELL (jcf);
2105 jcf_parse_fields (jcf);
2107 method_start = JCF_TELL (jcf);
2108 method_pass = 0;
2109 jcf_parse_methods (jcf);
2111 if (out)
2112 fputs ("\n", out);
2114 if (out && ! flag_jni)
2116 if (! stubs)
2117 print_class_decls (out, jcf, jcf->this_class);
2119 for (i = 0; i < prepend_count; ++i)
2120 fprintf (out, "%s\n", prepend_specs[i]);
2121 if (prepend_count > 0)
2122 fputc ('\n', out);
2124 if (! stubs)
2126 if (! print_cxx_classname (out, "class ", jcf,
2127 jcf->this_class, 0))
2129 fprintf (stderr, "class is of array type\n");
2130 found_error = 1;
2131 return;
2133 if (jcf->super_class)
2135 if (! print_cxx_classname (out, " : public ",
2136 jcf, jcf->super_class, 1))
2138 fprintf (stderr, "base class is of array type\n");
2139 found_error = 1;
2140 return;
2144 fputs ("\n{\n", out);
2148 /* Now go back for second pass over methods and fields. */
2149 is_first_data_member = 1;
2151 JCF_SEEK (jcf, method_start);
2152 method_pass = 1;
2153 jcf_parse_methods (jcf);
2154 method_end = JCF_TELL (jcf);
2156 field_pass = 1;
2157 JCF_SEEK (jcf, field_start);
2158 jcf_parse_fields (jcf);
2159 JCF_SEEK (jcf, method_end);
2161 jcf_parse_final_attributes (jcf);
2163 if (out && ! stubs)
2165 if (flag_jni)
2167 fprintf (out, "\n#ifdef __cplusplus\n");
2168 fprintf (out, "}\n");
2169 fprintf (out, "#endif\n");
2171 else
2173 /* Generate friend decl if we still must. */
2174 for (i = 0; i < friend_count; ++i)
2175 fprintf (out, " friend %s\n", friend_specs[i]);
2177 /* Generate extra declarations. */
2178 if (add_count > 0)
2179 fputc ('\n', out);
2180 for (i = 0; i < add_count; ++i)
2181 fprintf (out, " %s\n", add_specs[i]);
2183 /* Generate an entry for the class object. */
2184 generate_access (out, ACC_PUBLIC);
2185 fprintf (out, "\n static ::java::lang::Class class$;\n");
2187 fputs ("}", out);
2189 if (jcf->access_flags & ACC_INTERFACE)
2190 fputs (" __attribute__ ((java_interface))", out);
2192 fputs (";\n", out);
2194 if (append_count > 0)
2195 fputc ('\n', out);
2196 for (i = 0; i < append_count; ++i)
2197 fprintf (out, "%s\n", append_specs[i]);
2200 print_mangled_classname (out, jcf,
2201 "\n#endif /* __", jcf->this_class);
2202 fprintf (out, "__ */\n");
2208 /* This is used to mark options with no short value. */
2209 #define LONG_OPT(Num) ((Num) + 128)
2211 #define OPT_classpath LONG_OPT (0)
2212 #define OPT_CLASSPATH OPT_classpath
2213 #define OPT_bootclasspath LONG_OPT (1)
2214 #define OPT_extdirs LONG_OPT (2)
2215 #define OPT_HELP LONG_OPT (3)
2216 #define OPT_TEMP LONG_OPT (4)
2217 #define OPT_VERSION LONG_OPT (5)
2218 #define OPT_PREPEND LONG_OPT (6)
2219 #define OPT_FRIEND LONG_OPT (7)
2220 #define OPT_ADD LONG_OPT (8)
2221 #define OPT_APPEND LONG_OPT (9)
2222 #define OPT_M LONG_OPT (10)
2223 #define OPT_MM LONG_OPT (11)
2224 #define OPT_MG LONG_OPT (12)
2225 #define OPT_MD LONG_OPT (13)
2226 #define OPT_MMD LONG_OPT (14)
2228 static const struct option options[] =
2230 { "classpath", required_argument, NULL, OPT_classpath },
2231 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2232 { "extdirs", required_argument, NULL, OPT_extdirs },
2233 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2234 { "help", no_argument, NULL, OPT_HELP },
2235 { "stubs", no_argument, &stubs, 1 },
2236 { "td", required_argument, NULL, OPT_TEMP },
2237 { "verbose", no_argument, NULL, 'v' },
2238 { "version", no_argument, NULL, OPT_VERSION },
2239 { "prepend", required_argument, NULL, OPT_PREPEND },
2240 { "friend", required_argument, NULL, OPT_FRIEND },
2241 { "add", required_argument, NULL, OPT_ADD },
2242 { "append", required_argument, NULL, OPT_APPEND },
2243 { "M", no_argument, NULL, OPT_M },
2244 { "MM", no_argument, NULL, OPT_MM },
2245 { "MG", no_argument, NULL, OPT_MG },
2246 { "MD", no_argument, NULL, OPT_MD },
2247 { "MMD", no_argument, NULL, OPT_MMD },
2248 { "jni", no_argument, &flag_jni, 1 },
2249 { NULL, no_argument, NULL, 0 }
2252 static void
2253 usage (void)
2255 fprintf (stderr, "Try `gcjh --help' for more information.\n");
2256 exit (1);
2259 static void
2260 help (void)
2262 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
2263 printf ("Generate C++ header files from .class files\n\n");
2264 printf (" -stubs Generate an implementation stub file\n");
2265 printf (" -jni Generate a JNI header or stub\n");
2266 printf ("\n");
2267 printf (" -add TEXT Insert TEXT into class body\n");
2268 printf (" -append TEXT Insert TEXT after class declaration\n");
2269 printf (" -friend TEXT Insert TEXT as `friend' declaration\n");
2270 printf (" -prepend TEXT Insert TEXT before start of class\n");
2271 printf ("\n");
2272 printf (" --classpath PATH Set path to find .class files\n");
2273 printf (" -IDIR Append directory to class path\n");
2274 printf (" --bootclasspath PATH Override built-in class path\n");
2275 printf (" --extdirs PATH Set extensions directory path\n");
2276 printf (" -d DIRECTORY Set output directory name\n");
2277 printf (" -o FILE Set output file name\n");
2278 printf (" -td DIRECTORY Set temporary directory name\n");
2279 printf ("\n");
2280 printf (" --help Print this help, then exit\n");
2281 printf (" --version Print version number, then exit\n");
2282 printf (" -v, --verbose Print extra information while running\n");
2283 printf ("\n");
2284 printf (" -M Print all dependencies to stdout;\n");
2285 printf (" suppress ordinary output\n");
2286 printf (" -MM Print non-system dependencies to stdout;\n");
2287 printf (" suppress ordinary output\n");
2288 printf (" -MD Print all dependencies to stdout\n");
2289 printf (" -MMD Print non-system dependencies to stdout\n");
2290 /* We omit -MG until it is implemented. */
2291 printf ("\n");
2292 printf ("For bug reporting instructions, please see:\n");
2293 printf ("%s.\n", bug_report_url);
2294 exit (0);
2297 static void
2298 version (void)
2300 printf ("gcjh (GCC) %s\n\n", version_string);
2301 printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
2302 printf ("This is free software; see the source for copying conditions. There is NO\n");
2303 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
2304 exit (0);
2308 main (int argc, char** argv)
2310 JCF jcf;
2311 int argi;
2312 char *output_file = NULL;
2313 int emit_dependencies = 0, suppress_output = 0;
2314 int opt;
2316 if (argc <= 1)
2318 fprintf (stderr, "gcjh: no classes specified\n");
2319 usage ();
2322 jcf_path_init ();
2324 /* We use getopt_long_only to allow single `-' long options. For
2325 some of our options this is more natural. */
2326 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2328 switch (opt)
2330 case 0:
2331 /* Already handled. */
2332 break;
2334 case 'o':
2335 output_file = optarg;
2336 break;
2338 case 'd':
2339 output_directory = optarg;
2340 break;
2342 case 'I':
2343 jcf_path_include_arg (optarg);
2344 break;
2346 case 'v':
2347 verbose++;
2348 break;
2350 case OPT_classpath:
2351 jcf_path_classpath_arg (optarg);
2352 break;
2354 case OPT_bootclasspath:
2355 jcf_path_bootclasspath_arg (optarg);
2356 break;
2358 case OPT_extdirs:
2359 jcf_path_extdirs_arg (optarg);
2360 break;
2362 case OPT_HELP:
2363 help ();
2364 break;
2366 case OPT_TEMP:
2367 temp_directory = optarg;
2368 break;
2370 case OPT_VERSION:
2371 version ();
2372 break;
2374 case OPT_PREPEND:
2375 if (prepend_count == 0)
2376 prepend_specs = ALLOC (argc * sizeof (char*));
2377 prepend_specs[prepend_count++] = optarg;
2378 break;
2380 case OPT_FRIEND:
2381 if (friend_count == 0)
2382 friend_specs = ALLOC (argc * sizeof (char*));
2383 friend_specs[friend_count++] = optarg;
2384 break;
2386 case OPT_ADD:
2387 if (add_count == 0)
2388 add_specs = ALLOC (argc * sizeof (char*));
2389 add_specs[add_count++] = optarg;
2390 break;
2392 case OPT_APPEND:
2393 if (append_count == 0)
2394 append_specs = ALLOC (argc * sizeof (char*));
2395 append_specs[append_count++] = optarg;
2396 break;
2398 case OPT_M:
2399 emit_dependencies = 1;
2400 suppress_output = 1;
2401 jcf_dependency_init (1);
2402 break;
2404 case OPT_MM:
2405 emit_dependencies = 1;
2406 suppress_output = 1;
2407 jcf_dependency_init (0);
2408 break;
2410 case OPT_MG:
2411 fprintf (stderr, "gcjh: `-MG' option is unimplemented\n");
2412 exit (1);
2414 case OPT_MD:
2415 emit_dependencies = 1;
2416 jcf_dependency_init (1);
2417 break;
2419 case OPT_MMD:
2420 emit_dependencies = 1;
2421 jcf_dependency_init (0);
2422 break;
2424 default:
2425 usage ();
2426 break;
2430 if (optind == argc)
2432 fprintf (stderr, "gcjh: no classes specified\n");
2433 usage ();
2436 jcf_path_seal (verbose);
2438 if (output_file && emit_dependencies)
2440 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
2441 exit (1);
2444 for (argi = optind; argi < argc; argi++)
2446 char *classname = argv[argi];
2447 char *current_output_file;
2448 const char *classfile_name;
2450 if (verbose)
2451 fprintf (stderr, "Processing %s\n", classname);
2452 if (! output_file)
2453 jcf_dependency_reset ();
2454 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2455 if (classfile_name == NULL)
2457 fprintf (stderr, "%s: no such class\n", classname);
2458 exit (1);
2460 if (verbose)
2461 fprintf (stderr, "Found in %s\n", classfile_name);
2462 if (output_file)
2464 if (strcmp (output_file, "-") == 0)
2465 out = stdout;
2466 else if (out == NULL)
2468 out = fopen (output_file, "w");
2470 if (out == NULL)
2472 perror (output_file);
2473 exit (1);
2475 current_output_file = output_file;
2477 else
2479 int dir_len = strlen (output_directory);
2480 int i, classname_length = strlen (classname);
2481 current_output_file = ALLOC (dir_len + classname_length + 5);
2482 strcpy (current_output_file, output_directory);
2483 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2484 current_output_file[dir_len++] = '/';
2485 for (i = 0; classname[i] != '\0'; i++)
2487 char ch = classname[i];
2488 if (ch == '.')
2489 ch = '/';
2490 if (flag_jni && ch == '/')
2491 ch = '_';
2492 current_output_file[dir_len++] = ch;
2494 if (emit_dependencies)
2496 if (suppress_output)
2498 jcf_dependency_set_dep_file ("-");
2499 out = NULL;
2501 else
2503 /* We use `.hd' and not `.d' to avoid clashes with
2504 dependency tracking from straight compilation. */
2505 strcpy (current_output_file + dir_len, ".hd");
2506 jcf_dependency_set_dep_file (current_output_file);
2509 strcpy (current_output_file + dir_len,
2510 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2511 jcf_dependency_set_target (current_output_file);
2512 if (! suppress_output)
2514 out = fopen (current_output_file, "w");
2515 if (out == NULL)
2517 perror (current_output_file);
2518 exit (1);
2522 process_file (&jcf, out);
2523 JCF_FINISH (&jcf);
2524 if (current_output_file != output_file)
2525 free (current_output_file);
2526 jcf_dependency_write ();
2529 if (out != NULL && out != stdout)
2530 fclose (out);
2532 return found_error;