Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / java / gjavah.c
blobca38b9e92f970b2ac25f113897f8720fd10a7964
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, 2004, 2005
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 "version.h"
39 #include "javaop.h"
40 #include "java-tree.h"
41 #include "java-opcodes.h"
42 #include "ggc.h"
43 #include "hashtab.h"
44 #include "intl.h"
46 #include <getopt.h>
50 /* The output file. */
51 FILE *out = NULL;
53 /* Nonzero on failure. */
54 static int found_error = 0;
56 /* Nonzero if we're generating JNI output. */
57 int flag_jni = 0;
59 /* When nonzero, warn when source file is newer than matching class
60 file. */
61 int flag_newer = 1;
63 /* Directory to place resulting files in. Set by -d option. */
64 static const char *output_directory = "";
66 /* Directory to place temporary file. Set by -td option. Currently unused. */
67 static const char *temp_directory = "/tmp";
69 /* Number of friend functions we have to declare. */
70 static int friend_count;
72 /* A class can optionally have a `friend' function declared. If
73 non-NULL, this is that function. */
74 static char **friend_specs = NULL;
76 /* Number of lines we are prepending before the class. */
77 static int prepend_count;
79 /* We can prepend extra lines before the class's start. */
80 static char **prepend_specs = NULL;
82 /* Number of lines we are appending at the end of the class. */
83 static int add_count;
85 /* We can append extra lines just before the class's end. */
86 static char **add_specs = NULL;
88 /* Number of lines we are appending after the class. */
89 static int append_count;
91 /* We can append extra lines after the class's end. */
92 static char **append_specs = NULL;
94 int verbose = 0;
96 int stubs = 0;
98 struct JCF *current_jcf;
100 /* This holds access information for the last field we examined. They
101 let us generate "private:", "public:", and "protected:" properly.
102 If 0 then we haven't previously examined any field. */
103 static JCF_u2 last_access;
105 /* Pass this macro the flags for a class and for a method. It will
106 return true if the method should be considered `final'. */
107 #define METHOD_IS_FINAL(Class, Method) \
108 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
110 /* Pass this macro the flags for a method. It will return true if the
111 method is native. */
112 #define METHOD_IS_NATIVE(Method) \
113 ((Method) & ACC_NATIVE)
115 #define METHOD_IS_PRIVATE(Class, Method) \
116 (((Method) & ACC_PRIVATE) != 0)
118 /* We keep a linked list of all method names we have seen. This lets
119 us determine if a method name and a field name are in conflict. */
120 struct method_name
122 unsigned char *name;
123 int length;
124 unsigned char *signature;
125 int sig_length;
126 int is_native;
127 struct method_name *next;
130 /* List of method names we've seen. */
131 static struct method_name *method_name_list;
133 static void print_field_info (FILE*, JCF*, int, int, JCF_u2);
134 static void print_mangled_classname (FILE*, JCF*, const char*, int);
135 static int print_cxx_classname (FILE*, const char*, JCF*, int, int);
136 static void print_method_info (FILE*, JCF*, int, int, JCF_u2);
137 static void print_c_decl (FILE*, JCF*, int, int, int, const char *, int);
138 static void print_stub_or_jni (FILE*, JCF*, int, int, int, const char *, int);
139 static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int);
140 static void decompile_method (FILE*, JCF*, int);
141 static void add_class_decl (FILE*, JCF*, JCF_u2);
143 static void print_name (FILE *, JCF *, int);
144 static void print_base_classname (FILE *, JCF *, int);
145 static int utf8_cmp (const unsigned char *, int, const char *);
146 static char *cxx_keyword_subst (const unsigned char *, int);
147 static void generate_access (FILE *, JCF_u2);
148 static int name_is_method_p (const unsigned char *, int);
149 static char *get_field_name (JCF *, int, JCF_u2);
150 static void print_field_name (FILE *, JCF *, int, JCF_u2);
151 static const unsigned char *super_class_name (JCF *, int *);
152 static void print_include (FILE *, const unsigned char *, int);
153 static int gcjh_streq (const void *p1, const void *p2);
154 static int throwable_p (const unsigned char *signature);
155 static const unsigned char *
156 decode_signature_piece (FILE *, const unsigned char *,
157 const unsigned char *, int *);
158 static void print_class_decls (FILE *, JCF *, int);
159 static void error (const char *msgid, ...);
160 static void usage (void) ATTRIBUTE_NORETURN;
161 static void help (void) ATTRIBUTE_NORETURN;
162 static void version (void) ATTRIBUTE_NORETURN;
163 static int overloaded_jni_method_exists_p (const unsigned char *, int,
164 const char *, int);
165 static void jni_print_char (FILE *, int);
166 static void jni_print_float (FILE *, jfloat);
167 static void jni_print_double (FILE *, jdouble);
168 static void decompile_return_statement (FILE *, JCF *, int, int, int);
170 static void handle_inner_classes (int);
172 JCF_u2 current_field_name;
173 JCF_u2 current_field_value;
174 JCF_u2 current_field_signature;
175 JCF_u2 current_field_flags;
177 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
178 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
179 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
181 /* We pass over fields twice. The first time we just note the types
182 of the fields and then the start of the methods. Then we go back
183 and parse the fields for real. This is ugly. */
184 static int field_pass;
185 /* Likewise we pass over methods twice. The first time we generate
186 class decl information; the second time we generate actual method
187 decls. */
188 static int method_pass;
190 #define HANDLE_END_FIELD() \
191 if (field_pass) \
193 if (out && ! stubs) \
194 print_field_info (out, jcf, current_field_name, \
195 current_field_signature, \
196 current_field_flags); \
198 else if (! stubs && ! flag_jni) \
199 add_class_decl (out, jcf, current_field_signature);
201 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
203 static int method_declared = 0;
204 static int method_access = 0;
205 static int method_printed = 0;
206 static int method_synthetic = 0;
207 static int method_signature = 0;
209 /* Set to 1 while the very first data member of a class is being handled. */
210 static int is_first_data_member = 0;
212 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
214 method_synthetic = 0; \
215 method_printed = 0; \
216 decompiled = 0; \
217 method_signature = SIGNATURE; \
218 if (ATTRIBUTE_COUNT) \
219 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
220 (const char *)"Synthetic", 9); \
221 /* If a synthetic methods have been declared, its attribute aren't \
222 worth reading (and triggering side-effects). We skip them an \
223 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
224 jcf_parse_one_method. */ \
225 if (method_synthetic) \
227 skip_attribute (jcf, ATTRIBUTE_COUNT); \
228 ATTRIBUTE_COUNT = 0; \
230 if (method_pass && !method_synthetic) \
232 if (out) \
233 print_method_info (out, jcf, NAME, SIGNATURE, \
234 ACCESS_FLAGS); \
236 else if (!method_synthetic) \
238 print_method_info (NULL, jcf, NAME, SIGNATURE, \
239 ACCESS_FLAGS); \
240 if (! stubs && ! flag_jni) \
241 add_class_decl (out, jcf, SIGNATURE); \
245 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
246 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
248 static int decompiled = 0;
249 #define HANDLE_END_METHOD() \
250 if (out && method_printed && !method_synthetic) \
251 fputs (decompiled || stubs ? "\n" : ";\n", out);
253 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
255 /* We're going to need {peek,skip}_attribute, enable their definition. */
256 #define NEED_PEEK_ATTRIBUTE
257 #define NEED_SKIP_ATTRIBUTE
259 #include "jcf-reader.c"
261 /* Print an error message and set found_error. */
262 static void
263 error (const char *msgid, ...)
265 va_list ap;
267 va_start (ap, msgid);
269 fprintf (stderr, "gcjh: ");
270 vfprintf (stderr, _(msgid), ap);
271 va_end (ap);
272 fprintf (stderr, "\n");
273 found_error = 1;
276 /* Print a single-precision float, suitable for parsing by g++. */
277 static void
278 jni_print_float (FILE *stream, jfloat f)
280 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
281 work in data initializers. FIXME. */
282 if (JFLOAT_FINITE (f))
284 if (flag_jni)
286 fputs (" ", out);
287 if (f.negative)
288 putc ('-', stream);
289 if (f.exponent)
290 fprintf (stream, "0x1.%.6xp%+df",
291 ((unsigned int)f.mantissa) << 1,
292 f.exponent - JFLOAT_EXP_BIAS);
293 else
294 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
295 because the implicit leading 1 bit is no longer present. */
296 fprintf (stream, "0x0.%.6xp%+df",
297 ((unsigned int)f.mantissa) << 1,
298 f.exponent + 1 - JFLOAT_EXP_BIAS);
301 if (! flag_jni)
302 fputs (";\n", stream);
305 /* Print a double-precision float, suitable for parsing by g++. */
306 static void
307 jni_print_double (FILE *stream, jdouble f)
309 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
310 work in data initializers. FIXME. */
311 if (JDOUBLE_FINITE (f))
313 if (flag_jni)
315 fputs (" ", out);
316 if (f.negative)
317 putc ('-', stream);
318 if (f.exponent)
319 fprintf (stream, "0x1.%.5x%.8xp%+d",
320 f.mantissa0, f.mantissa1,
321 f.exponent - JDOUBLE_EXP_BIAS);
322 else
323 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
324 because the implicit leading 1 bit is no longer present. */
325 fprintf (stream, "0x0.%.5x%.8xp%+d",
326 f.mantissa0, f.mantissa1,
327 f.exponent + 1 - JDOUBLE_EXP_BIAS);
330 fputs (flag_jni ? "\n" : ";\n", stream);
333 /* Print a character, appropriately mangled for JNI. */
335 static void
336 jni_print_char (FILE *stream, int ch)
338 if (! flag_jni)
339 jcf_print_char (stream, ch);
340 else if (ch == '(' || ch == ')')
342 /* Ignore. */
344 else if (ch == '_')
345 fputs ("_1", stream);
346 else if (ch == ';')
347 fputs ("_2", stream);
348 else if (ch == '[')
349 fputs ("_3", stream);
350 else if (ch == '/')
351 fputs ("_", stream);
352 else if (ISALNUM (ch))
353 fputc (ch, stream);
354 else
356 /* "Unicode" character. */
357 fprintf (stream, "_0%04x", ch);
361 /* Print a name from the class data. If the index does not point to a
362 string, an error results. */
364 static void
365 print_name (FILE* stream, JCF* jcf, int name_index)
367 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
369 fprintf (stream, "<not a UTF8 constant>");
370 found_error = 1;
372 else if (! flag_jni)
373 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
374 JPOOL_UTF_LENGTH (jcf, name_index));
375 else
377 /* For JNI we must correctly quote each character. */
378 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
379 int length = JPOOL_UTF_LENGTH (jcf, name_index);
380 const unsigned char *limit = str + length;
381 while (str < limit)
383 int ch = UTF8_GET (str, limit);
384 if (ch < 0)
386 fprintf (stream, "\\<invalid>");
387 return;
389 jni_print_char (stream, ch);
394 /* Print base name of class. The base name is everything after the
395 final separator. */
397 static void
398 print_base_classname (FILE *stream, JCF *jcf, int index)
400 int name_index = JPOOL_USHORT1 (jcf, index);
401 int len;
402 const unsigned char *s, *p, *limit;
404 s = JPOOL_UTF_DATA (jcf, name_index);
405 len = JPOOL_UTF_LENGTH (jcf, name_index);
406 limit = s + len;
407 p = s;
408 while (s < limit)
410 int c = UTF8_GET (s, limit);
411 if (c == '/')
412 p = s;
415 while (p < limit)
417 int ch = UTF8_GET (p, limit);
418 if (ch == '/')
419 fputs ("::", stream);
420 else
421 jcf_print_char (stream, ch);
425 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
426 and 1 if STR is "greater" than NAME. */
428 static int
429 utf8_cmp (const unsigned char *str, int length, const char *name)
431 const unsigned char *limit = str + length;
432 int i;
434 for (i = 0; name[i]; ++i)
436 int ch = UTF8_GET (str, limit);
437 if (ch != name[i])
438 return ch - name[i];
441 return str == limit ? 0 : 1;
444 /* This is a sorted list of all C++ keywords. */
446 static const char *const cxx_keywords[] =
448 "_Complex",
449 "__alignof",
450 "__alignof__",
451 "__asm",
452 "__asm__",
453 "__attribute",
454 "__attribute__",
455 "__builtin_va_arg",
456 "__complex",
457 "__complex__",
458 "__const",
459 "__const__",
460 "__extension__",
461 "__imag",
462 "__imag__",
463 "__inline",
464 "__inline__",
465 "__label__",
466 "__null",
467 "__real",
468 "__real__",
469 "__restrict",
470 "__restrict__",
471 "__signed",
472 "__signed__",
473 "__typeof",
474 "__typeof__",
475 "__volatile",
476 "__volatile__",
477 "and",
478 "and_eq",
479 "asm",
480 "auto",
481 "bitand",
482 "bitor",
483 "bool",
484 "break",
485 "case",
486 "catch",
487 "char",
488 "class",
489 "compl",
490 "const",
491 "const_cast",
492 "continue",
493 "default",
494 "delete",
495 "do",
496 "double",
497 "dynamic_cast",
498 "else",
499 "enum",
500 "explicit",
501 "export",
502 "extern",
503 "false",
504 "float",
505 "for",
506 "friend",
507 "goto",
508 "if",
509 "inline",
510 "int",
511 "long",
512 "mutable",
513 "namespace",
514 "new",
515 "not",
516 "not_eq",
517 "operator",
518 "or",
519 "or_eq",
520 "private",
521 "protected",
522 "public",
523 "register",
524 "reinterpret_cast",
525 "return",
526 "short",
527 "signed",
528 "sizeof",
529 "static",
530 "static_cast",
531 "struct",
532 "switch",
533 "template",
534 "this",
535 "throw",
536 "true",
537 "try",
538 "typedef",
539 "typeid",
540 "typename",
541 "typeof",
542 "union",
543 "unsigned",
544 "using",
545 "virtual",
546 "void",
547 "volatile",
548 "wchar_t",
549 "while",
550 "xor",
551 "xor_eq"
555 /* If NAME is the name of a C++ keyword, then return an override name.
556 This is a name that can be used in place of the keyword.
557 Otherwise, return NULL. The return value is malloc()d. */
559 static char *
560 cxx_keyword_subst (const unsigned char *str, int length)
562 int last = ARRAY_SIZE (cxx_keywords);
563 int first = 0;
564 int mid = (last + first) / 2;
565 int old = -1;
567 for (mid = (last + first) / 2;
568 mid != old;
569 old = mid, mid = (last + first) / 2)
571 int kwl = strlen (cxx_keywords[mid]);
572 int min_length = kwl > length ? length : kwl;
573 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
575 if (r == 0)
577 int i;
579 /* Skip all trailing `$'. */
580 for (i = min_length; i < length && str[i] == '$'; ++i)
582 /* We've only found a match if all the remaining characters
583 are `$'. */
584 if (i == length)
586 char *dup = xmalloc (2 + length - min_length + kwl);
587 strcpy (dup, cxx_keywords[mid]);
588 for (i = kwl; i < length + 1; ++i)
589 dup[i] = '$';
590 dup[i] = '\0';
591 return dup;
593 r = 1;
596 if (r < 0)
597 last = mid;
598 else
599 first = mid;
601 return NULL;
604 /* Generate an access control keyword based on FLAGS. */
606 static void
607 generate_access (FILE *stream, JCF_u2 flags)
609 if ((flags & ACC_VISIBILITY) == last_access)
610 return;
611 last_access = (flags & ACC_VISIBILITY);
613 switch (last_access)
615 case 0:
616 fputs ("public: // actually package-private\n", stream);
617 break;
618 case ACC_PUBLIC:
619 fputs ("public:\n", stream);
620 break;
621 case ACC_PRIVATE:
622 fputs ("private:\n", stream);
623 break;
624 case ACC_PROTECTED:
625 fputs ("public: // actually protected\n", stream);
626 break;
627 default:
628 found_error = 1;
629 fprintf (stream, "#error unrecognized visibility %d\n",
630 (flags & ACC_VISIBILITY));
631 break;
635 /* See if NAME is already the name of a method. */
636 static int
637 name_is_method_p (const unsigned char *name, int length)
639 struct method_name *p;
641 for (p = method_name_list; p != NULL; p = p->next)
643 if (p->length == length && ! memcmp (p->name, name, length))
644 return 1;
646 return 0;
649 /* Free the method name list. */
650 static void
651 free_method_name_list (void)
653 struct method_name *p = method_name_list;
654 while (p != NULL)
656 struct method_name *next = p->next;
657 free (p->name);
658 free (p->signature);
659 free (p);
660 p = next;
662 method_name_list = NULL;
665 /* If there is already a native method named NAME, whose signature is not
666 SIGNATURE, then return true. Otherwise return false. */
667 static int
668 overloaded_jni_method_exists_p (const unsigned char *name, int length,
669 const char *signature, int sig_length)
671 struct method_name *p;
673 for (p = method_name_list; p != NULL; p = p->next)
675 if (p->is_native
676 && p->length == length
677 && ! memcmp (p->name, name, length)
678 && (p->sig_length != sig_length
679 || memcmp (p->signature, signature, sig_length)))
680 return 1;
682 return 0;
685 /* Get name of a field. This handles renamings due to C++ clash. */
686 static char *
687 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
689 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
690 int length = JPOOL_UTF_LENGTH (jcf, name_index);
691 char *override;
693 if (name_is_method_p (name, length))
695 /* This field name matches a method. So override the name with
696 a dummy name. This is yucky, but it isn't clear what else to
697 do. FIXME: if the field is static, then we'll be in real
698 trouble. */
699 if ((flags & ACC_STATIC))
701 error ("static field has same name as method");
702 return NULL;
705 override = xmalloc (length + 3);
706 memcpy (override, name, length);
707 strcpy (override + length, "__");
709 else if (flag_jni)
710 override = NULL;
711 else
712 override = cxx_keyword_subst (name, length);
714 return override;
717 /* Print a field name. Convenience function for use with
718 get_field_name. */
719 static void
720 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
722 char *override = get_field_name (jcf, name_index, flags);
724 if (override)
726 fputs (override, stream);
727 free (override);
729 else
730 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
731 JPOOL_UTF_LENGTH (jcf, name_index));
734 static void
735 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
736 JCF_u2 flags)
738 char *override = NULL;
740 if (! flag_jni)
741 generate_access (stream, flags);
742 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
744 fprintf (stream, "<not a UTF8 constant>");
745 found_error = 1;
746 return;
749 if (flag_jni)
751 /* For JNI we only want to print real constants. */
752 int val;
753 if (! (flags & ACC_STATIC)
754 || ! (flags & ACC_FINAL)
755 || current_field_value <= 0)
756 return;
757 val = JPOOL_TAG (jcf, current_field_value);
758 if (val != CONSTANT_Integer && val != CONSTANT_Long
759 && val != CONSTANT_Float && val != CONSTANT_Double)
760 return;
762 else
764 /* Initial indentation. */
765 fputs (" ", stream);
768 if ((flags & ACC_STATIC))
770 if (flag_jni)
772 print_cxx_classname (stream, "#undef ", jcf, jcf->this_class, 1);
773 fputs ("_", stream);
774 print_field_name (stream, jcf, name_index, 0);
775 fputs ("\n", stream);
776 print_cxx_classname (stream, "#define ", jcf, jcf->this_class, 1);
777 fputs ("_", stream);
779 else
780 fputs ("static ", stream);
782 if ((flags & ACC_FINAL) && current_field_value > 0)
784 char buffer[25];
785 int done = 1;
787 switch (JPOOL_TAG (jcf, current_field_value))
789 case CONSTANT_Integer:
791 jint num;
792 int most_negative = 0;
793 if (! flag_jni)
794 fputs ("const jint ", stream);
795 print_field_name (stream, jcf, name_index, 0);
796 fputs (flag_jni ? " " : " = ", stream);
797 num = JPOOL_INT (jcf, current_field_value);
798 /* We single out the most negative number to print
799 specially. This avoids later warnings from g++. */
800 if (num == (jint) 0x80000000)
802 most_negative = 1;
803 ++num;
805 format_int (buffer, (jlong) num, 10);
806 fprintf (stream, "%sL%s%s\n", buffer,
807 most_negative ? " - 1" : "",
808 flag_jni ? "" : ";");
810 break;
811 case CONSTANT_Long:
813 jlong num;
814 int most_negative = 0;
815 if (! flag_jni)
816 fputs ("const jlong ", stream);
817 print_field_name (stream, jcf, name_index, 0);
818 fputs (flag_jni ? " " : " = ", stream);
819 num = JPOOL_LONG (jcf, current_field_value);
820 /* We single out the most negative number to print
821 specially.. This avoids later warnings from g++. */
822 if (num == (jlong) 0x8000000000000000LL)
824 most_negative = 1;
825 ++num;
827 format_int (buffer, num, 10);
828 fprintf (stream, "%sLL%s%s\n", buffer,
829 most_negative ? " - 1" :"",
830 flag_jni ? "" : ";");
832 break;
833 case CONSTANT_Float:
835 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
836 if (! flag_jni)
837 fputs ("const jfloat ", stream);
838 print_field_name (stream, jcf, name_index, 0);
839 jni_print_float (stream, fnum);
841 break;
842 case CONSTANT_Double:
844 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
845 if (! flag_jni)
846 fputs ("const jdouble ", stream);
847 print_field_name (stream, jcf, name_index, 0);
848 jni_print_double (stream, dnum);
850 break;
851 default:
852 /* We can't print this as a constant, but we can still
853 print something sensible. */
854 done = 0;
855 break;
858 if (done)
859 return;
863 /* assert (! flag_jni); */
864 override = get_field_name (jcf, name_index, flags);
865 print_c_decl (stream, jcf, name_index, sig_index, 0, override, flags);
866 fputs (";\n", stream);
868 if (override)
869 free (override);
873 static void
874 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
875 JCF_u2 flags)
877 const unsigned char *str;
878 int length, is_init = 0;
879 char *override = NULL;
881 method_declared = 0;
882 method_access = flags;
883 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
884 fprintf (stream, "<not a UTF8 constant>");
885 str = JPOOL_UTF_DATA (jcf, name_index);
886 length = JPOOL_UTF_LENGTH (jcf, name_index);
888 if (str[0] == '<')
890 /* Ignore the internally generated method <clinit>. However,
891 treat <init> as a constructor. */
892 if (! utf8_cmp (str, length, "<init>"))
893 is_init = 1;
894 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
895 && ! (flags & ACC_STATIC))
897 /* FIXME: i18n bug here. Order of prints should not be
898 fixed. */
899 fprintf (stderr, _("ignored method '"));
900 jcf_print_utf8 (stderr, str, length);
901 fprintf (stderr, _("' marked virtual\n"));
902 found_error = 1;
903 return;
905 else
906 return;
909 /* During the first method pass, build a list of method names. This will
910 be used to determine if field names conflict with method names. */
911 if (! stream)
913 struct method_name *nn;
915 nn = xmalloc (sizeof (struct method_name));
916 nn->name = xmalloc (length);
917 memcpy (nn->name, str, length);
918 nn->length = length;
919 nn->next = method_name_list;
920 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
921 nn->signature = xmalloc (nn->sig_length);
922 nn->is_native = METHOD_IS_NATIVE (flags);
923 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
924 nn->sig_length);
925 method_name_list = nn;
927 /* The rest of this function doesn't matter. */
928 return;
931 /* We don't worry about overrides in JNI mode. */
932 if (! flag_jni)
934 /* We can't generate a method whose name is a C++ reserved word.
935 We can't just ignore the function, because that will cause
936 incorrect code to be generated if the function is virtual
937 (not only for calls to this function for for other functions
938 after it in the vtbl). So we give it a dummy name instead. */
939 override = cxx_keyword_subst (str, length);
942 if (! stubs && ! flag_jni)
944 method_printed = 1;
946 generate_access (stream, flags);
948 fputs (" ", out);
949 if ((flags & ACC_STATIC))
950 fputs ("static ", out);
951 else if (! METHOD_IS_PRIVATE (jcf->access_flags, flags))
953 /* Don't print `virtual' if we have a constructor. */
954 if (! is_init)
955 fputs ("virtual ", out);
957 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
959 if ((flags & ACC_ABSTRACT))
960 fputs (" = 0", out);
961 else
962 method_declared = 1;
964 else
966 if (METHOD_IS_NATIVE (flags))
968 method_printed = 1;
969 print_stub_or_jni (out, jcf, name_index, sig_index,
970 is_init, override, flags);
974 if (override)
975 free (override);
978 /* A helper for the decompiler which prints a `return' statement where
979 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
980 identical, we emit a cast. We do this because the C++ compiler
981 doesn't know that a reference can be cast to the type of an
982 interface it implements. METHODTYPE is the index of the method's
983 signature. NAMEINDEX is the index of the field name; -1 for
984 `this'. OBJECTTYPE is the index of the object's type. */
985 static void
986 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
987 int nameindex, int objecttype)
989 int cast = 0;
990 int obj_name_len, method_name_len;
991 const unsigned char *obj_data, *method_data;
993 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
994 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
996 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
997 method_data = JPOOL_UTF_DATA (jcf, methodtype);
999 /* Skip forward to return type part of method. */
1000 while (*method_data != ')')
1002 ++method_data;
1003 --method_name_len;
1005 /* Skip past `)'. */
1006 ++method_data;
1007 --method_name_len;
1009 /* If we see an `L', skip it and the trailing `;'. */
1010 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
1012 ++method_data;
1013 method_name_len -= 2;
1015 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
1017 ++obj_data;
1018 obj_name_len -= 2;
1021 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
1022 need a cast. Right now there is no way to determine if this is
1023 the case. */
1024 if (method_name_len != obj_name_len)
1025 cast = 1;
1026 else
1028 int i;
1029 for (i = 0; i < method_name_len; ++i)
1031 if (method_data[i] != obj_data[i])
1033 cast = 1;
1034 break;
1039 fputs (" { return ", out);
1041 if (cast)
1043 int array_depth = 0;
1044 const unsigned char *limit;
1046 fputs ("reinterpret_cast<", out);
1048 while (*method_data == '[')
1050 ++method_data;
1051 ++array_depth;
1052 --method_name_len;
1053 fputs ("JArray<", out);
1056 /* Leading space to avoid C++ digraphs. */
1057 fputs (" ::", out);
1059 /* If we see an `L', skip it and the trailing `;'. Only do this
1060 if we've seen an array specification. If we don't have an
1061 array then the `L' was stripped earlier. */
1062 if (array_depth && method_data[0] == 'L'
1063 && method_data[method_name_len - 1] == ';')
1065 ++method_data;
1066 method_name_len -= 2;
1069 limit = method_data + method_name_len;
1070 while (method_data < limit)
1072 int ch = UTF8_GET (method_data, limit);
1073 if (ch == '/')
1074 fputs ("::", out);
1075 else
1076 jcf_print_char (out, ch);
1078 fputs (" *", out);
1080 /* Close each array. */
1081 while (array_depth > 0)
1083 fputs ("> *", out);
1084 --array_depth;
1087 /* Close the cast. */
1088 fputs ("> (", out);
1091 if (nameindex == -1)
1092 fputs ("this", out);
1093 else
1094 print_field_name (out, jcf, nameindex, 0);
1096 if (cast)
1097 fputs (")", out);
1099 fputs ("; }", out);
1103 /* Try to decompile a method body. Right now we just try to handle a
1104 simple case that we can do. Expand as desired. */
1105 static void
1106 decompile_method (FILE *out, JCF *jcf, int code_len)
1108 const unsigned char *codes = jcf->read_ptr;
1109 int index;
1110 uint16 name_and_type, name;
1112 /* If the method is synchronized, don't touch it. */
1113 if ((method_access & ACC_SYNCHRONIZED))
1114 return;
1116 if (code_len == 5
1117 && codes[0] == OPCODE_aload_0
1118 && codes[1] == OPCODE_getfield
1119 && (codes[4] == OPCODE_areturn
1120 || codes[4] == OPCODE_dreturn
1121 || codes[4] == OPCODE_freturn
1122 || codes[4] == OPCODE_ireturn
1123 || codes[4] == OPCODE_lreturn))
1125 /* Found code like `return FIELD'. */
1126 index = (codes[2] << 8) | codes[3];
1127 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1128 name_and_type = JPOOL_USHORT2 (jcf, index);
1129 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1130 name = JPOOL_USHORT1 (jcf, name_and_type);
1131 if (codes[4] == OPCODE_areturn)
1132 decompile_return_statement (out, jcf, method_signature,
1133 name, JPOOL_USHORT2 (jcf, name_and_type));
1134 else
1136 fputs (" { return ", out);
1137 /* FIXME: flags. */
1138 print_field_name (out, jcf, name, 0);
1139 fputs ("; }", out);
1141 decompiled = 1;
1143 else if (code_len == 2
1144 && codes[0] == OPCODE_aload_0
1145 && codes[1] == OPCODE_areturn
1146 /* We're going to generate `return this'. This only makes
1147 sense for non-static methods. */
1148 && ! (method_access & ACC_STATIC))
1150 decompile_return_statement (out, jcf, method_signature, -1,
1151 JPOOL_USHORT1 (jcf, jcf->this_class));
1152 decompiled = 1;
1154 else if (code_len == 1 && codes[0] == OPCODE_return)
1156 /* Found plain `return'. */
1157 fputs (" { }", out);
1158 decompiled = 1;
1160 else if (code_len == 2
1161 && codes[0] == OPCODE_aconst_null
1162 && codes[1] == OPCODE_areturn)
1164 /* Found `return null'. We don't want to depend on NULL being
1165 defined. */
1166 fputs (" { return 0; }", out);
1167 decompiled = 1;
1171 /* Like strcmp, but invert the return result for the hash table. This
1172 should probably be in hashtab.c to complement the existing string
1173 hash function. */
1174 static int
1175 gcjh_streq (const void *p1, const void *p2)
1177 return ! strcmp ((char *) p1, (char *) p2);
1180 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1181 or 0 if not. CLNAME may be extracted from a signature, and can be
1182 terminated with either `;' or NULL. */
1183 static int
1184 throwable_p (const unsigned char *clname)
1186 int length;
1187 unsigned char *current;
1188 int i;
1189 int result = 0;
1191 /* We keep two hash tables of class names. In one we list all the
1192 classes which are subclasses of Throwable. In the other we will
1193 all other classes. We keep two tables to make the code a bit
1194 simpler; we don't have to have a structure mapping class name to
1195 a `throwable?' bit. */
1196 static htab_t throw_hash;
1197 static htab_t non_throw_hash;
1198 static int init_done = 0;
1200 if (! init_done)
1202 void **slot;
1203 unsigned char *str;
1205 /* Self-initializing. The cost of this really doesn't matter.
1206 We also don't care about freeing these, either. */
1207 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1208 (htab_del) free);
1209 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1210 (htab_del) free);
1212 /* Make sure the root classes show up in the tables. */
1213 str = (unsigned char *) xstrdup ("java.lang.Throwable");
1214 slot = htab_find_slot (throw_hash, str, INSERT);
1215 *slot = str;
1217 str = (unsigned char *) xstrdup ("java.lang.Object");
1218 slot = htab_find_slot (non_throw_hash, str, INSERT);
1219 *slot = str;
1221 init_done = 1;
1224 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1226 current = ALLOC (length + 1);
1227 for (i = 0; i < length; ++i)
1228 current[i] = clname[i] == '/' ? '.' : clname[i];
1229 current[length] = '\0';
1231 /* We don't compute the hash slot here because the table might be
1232 modified by the recursion. In that case the slot could be
1233 invalidated. */
1234 if (htab_find (throw_hash, current))
1235 result = 1;
1236 else if (htab_find (non_throw_hash, current))
1237 result = 0;
1238 else
1240 JCF jcf;
1241 void **slot;
1242 unsigned char *super, *tmp;
1243 int super_length = -1;
1244 const char *classfile_name = find_class ((char *) current, strlen ((const char *) current),
1245 &jcf, 0);
1247 if (! classfile_name)
1249 error ("couldn't find class %s", current);
1250 return 0;
1252 if (jcf_parse_preamble (&jcf) != 0
1253 || jcf_parse_constant_pool (&jcf) != 0
1254 || verify_constant_pool (&jcf) > 0)
1256 error ("parse error while reading %s", classfile_name);
1257 return 0;
1259 jcf_parse_class (&jcf);
1261 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1262 super = ALLOC (super_length + 1);
1263 memcpy (super, tmp, super_length);
1264 super[super_length] = '\0';
1266 result = throwable_p (super);
1267 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1268 current, INSERT);
1269 *slot = current;
1270 current = NULL;
1272 JCF_FINISH (&jcf);
1275 return result;
1278 /* Print one piece of a signature. Returns pointer to next parseable
1279 character on success, NULL on error. */
1280 static const unsigned char *
1281 decode_signature_piece (FILE *stream, const unsigned char *signature,
1282 const unsigned char *limit, int *need_space)
1284 const char *ctype;
1285 int array_depth = 0;
1287 switch (signature[0])
1289 case '[':
1290 /* More spaghetti. */
1292 array_loop:
1293 for (signature++; (signature < limit
1294 && ISDIGIT (*signature)); signature++)
1296 switch (*signature)
1298 case 'B':
1299 ctype = "jbyteArray";
1300 break;
1301 case 'C':
1302 ctype = "jcharArray";
1303 break;
1304 case 'D':
1305 ctype = "jdoubleArray";
1306 break;
1307 case 'F':
1308 ctype = "jfloatArray";
1309 break;
1310 case 'I':
1311 ctype = "jintArray";
1312 break;
1313 case 'S':
1314 ctype = "jshortArray";
1315 break;
1316 case 'J':
1317 ctype = "jlongArray";
1318 break;
1319 case 'Z':
1320 ctype = "jbooleanArray";
1321 break;
1322 case '[':
1323 /* We have a nested array. */
1324 ++array_depth;
1325 if (! flag_jni)
1326 fputs ("JArray<", stream);
1327 goto array_loop;
1329 case 'L':
1330 /* We have to generate a reference to JArray here, so that
1331 our output matches what the compiler does. */
1332 ++signature;
1333 /* Space between `<' and `:' to avoid C++ digraphs. */
1334 if (! flag_jni)
1335 fputs ("JArray< ::", stream);
1336 while (signature < limit && *signature != ';')
1338 int ch = UTF8_GET (signature, limit);
1339 if (! flag_jni)
1341 if (ch == '/')
1342 fputs ("::", stream);
1343 else
1344 jcf_print_char (stream, ch);
1347 if (! flag_jni)
1348 fputs (" *> *", stream);
1349 *need_space = 0;
1350 ctype = NULL;
1351 break;
1352 default:
1353 /* Unparseable signature. */
1354 return NULL;
1357 /* If the previous iterations left us with something to print,
1358 print it. For JNI, we always print `jobjectArray' in the
1359 nested cases. */
1360 if (flag_jni && (ctype == NULL || array_depth > 0))
1362 ctype = "jobjectArray";
1363 *need_space = 1;
1365 /* The `printit' case will advance SIGNATURE for us. If we
1366 don't go there, we must advance past the `;' ourselves. */
1367 if (ctype != NULL)
1368 goto printit;
1369 ++signature;
1370 break;
1372 case '(':
1373 case ')':
1374 /* This shouldn't happen. */
1375 return NULL;
1377 case 'B': ctype = "jbyte"; goto printit;
1378 case 'C': ctype = "jchar"; goto printit;
1379 case 'D': ctype = "jdouble"; goto printit;
1380 case 'F': ctype = "jfloat"; goto printit;
1381 case 'I': ctype = "jint"; goto printit;
1382 case 'J': ctype = "jlong"; goto printit;
1383 case 'S': ctype = "jshort"; goto printit;
1384 case 'Z': ctype = "jboolean"; goto printit;
1385 case 'V': ctype = "void"; goto printit;
1386 case 'L':
1387 if (flag_jni)
1389 /* We know about certain types and special-case their names. */
1390 if (! strncmp ((const char *) signature, "Ljava/lang/String;",
1391 sizeof ("Ljava/lang/String;") -1))
1392 ctype = "jstring";
1393 else if (! strncmp ((const char *) signature, "Ljava/lang/Class;",
1394 sizeof ("Ljava/lang/Class;") - 1))
1395 ctype = "jclass";
1396 /* Skip leading 'L' for throwable_p call. */
1397 else if (throwable_p (signature + 1))
1398 ctype = "jthrowable";
1399 else
1400 ctype = "jobject";
1402 while (*signature && *signature != ';')
1403 ++signature;
1405 goto printit;
1407 /* Print a leading "::" so we look in the right namespace. */
1408 fputs ("::", stream);
1409 ++signature;
1410 while (*signature && *signature != ';')
1412 int ch = UTF8_GET (signature, limit);
1413 if (ch == '/')
1414 fputs ("::", stream);
1415 else
1416 jcf_print_char (stream, ch);
1418 fputs (" *", stream);
1419 if (*signature == ';')
1420 signature++;
1421 *need_space = 0;
1422 break;
1423 default:
1424 *need_space = 1;
1425 jni_print_char (stream, *signature++);
1426 break;
1427 printit:
1428 signature++;
1429 *need_space = 1;
1430 fputs (ctype, stream);
1431 break;
1434 if (! flag_jni)
1436 while (array_depth-- > 0)
1437 fputs ("> *", stream);
1440 return signature;
1443 static void
1444 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1445 int is_init, const char *name_override, int flags)
1447 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1449 fprintf (stream, "<not a UTF8 constant>");
1450 found_error = 1;
1452 else
1454 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1455 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1456 const unsigned char *str = str0;
1457 const unsigned char *limit = str + length;
1458 int need_space = 0;
1459 int is_method = str[0] == '(';
1460 const unsigned char *next;
1462 /* If printing a method, skip to the return signature and print
1463 that first. However, there is no return value if this is a
1464 constructor. */
1465 if (is_method && ! is_init)
1467 while (str < limit)
1469 int ch = *str++;
1470 if (ch == ')')
1471 break;
1475 /* If printing a field or an ordinary method, then print the
1476 "return value" now. */
1477 if (! is_method || ! is_init)
1479 next = decode_signature_piece (stream, str, limit, &need_space);
1480 if (! next)
1482 error ("unparseable signature: '%s'", str0);
1483 return;
1487 /* Force the alignment of the first data member. This is
1488 because the "new" C++ ABI changed the alignment of non-POD
1489 classes. gcj, however, still uses the "old" alignment. */
1490 if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
1492 is_first_data_member = 0;
1493 print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1494 jcf, jcf->super_class, 1);
1495 fputs (" )))) ", stream);
1498 /* Now print the name of the thing. */
1499 if (need_space)
1500 fputs (" ", stream);
1501 print_full_cxx_name (stream, jcf, name_index,
1502 signature_index, is_init, name_override,
1503 flags);
1507 /* Print the unqualified method name followed by the signature. */
1508 static void
1509 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1510 int signature_index, int is_init,
1511 const char *name_override, int flags)
1513 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1514 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1515 const unsigned char *str = str0;
1516 const unsigned char *limit = str + length;
1517 int need_space = 0;
1518 int is_method = str[0] == '(';
1519 const unsigned char *next;
1521 if (name_override)
1522 fputs (name_override, stream);
1523 else if (name_index)
1525 /* Declare constructors specially. */
1526 if (is_init)
1527 print_base_classname (stream, jcf, jcf->this_class);
1528 else
1529 print_name (stream, jcf, name_index);
1532 if (flag_jni)
1534 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1535 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1536 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1537 JPOOL_UTF_LENGTH (jcf, name_index),
1538 (const char *) signature, sig_len))
1540 /* If this method is overloaded by another native method,
1541 then include the argument information in the mangled
1542 name. */
1543 unsigned char *limit = signature + sig_len;
1544 fputs ("__", stream);
1545 while (signature < limit)
1547 int ch = UTF8_GET (signature, limit);
1548 jni_print_char (stream, ch);
1549 if (ch == ')')
1551 /* Done. */
1552 break;
1558 if (is_method)
1560 /* Have a method or a constructor. Print signature pieces
1561 until done. */
1562 fputs (" (", stream);
1564 str = str0 + 1;
1566 /* In JNI mode, add extra arguments. */
1567 if (flag_jni)
1569 /* FIXME: it would be nice to know if we are printing a decl
1570 or a definition, and only print `env' for the latter. */
1571 fputs ("JNIEnv *env", stream);
1573 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1575 if (*str != ')')
1576 fputs (", ", stream);
1579 while (str < limit && *str != ')')
1581 next = decode_signature_piece (stream, str, limit, &need_space);
1582 if (! next)
1584 error ("unparseable signature: '%s'", str0);
1585 return;
1588 if (next < limit && *next != ')')
1589 fputs (", ", stream);
1590 str = next;
1593 fputs (")", stream);
1597 /* This is a helper for print_stub_or_jni. */
1598 static void
1599 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1600 int signature_index, int is_init,
1601 const char *name_override, int flags)
1603 const char *const prefix = flag_jni ? "Java_" : "";
1604 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1605 fputs (flag_jni ? "_" : "::", stream);
1606 print_full_cxx_name (stream, jcf, name_index,
1607 signature_index, is_init, name_override,
1608 flags);
1611 static void
1612 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1613 int signature_index, int is_init,
1614 const char *name_override, int flags)
1616 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1618 fprintf (stream, "<not a UTF8 constant>");
1619 found_error = 1;
1621 else
1623 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1624 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1625 const unsigned char *str = str0;
1626 const unsigned char *limit = str + length;
1627 int need_space = 0;
1628 int is_method = str[0] == '(';
1629 const unsigned char *next;
1631 /* Don't print fields in the JNI case. */
1632 if (! is_method && flag_jni)
1633 return;
1635 if (flag_jni && ! stubs)
1636 fputs ("JNIEXPORT ", stream);
1638 /* If printing a method, skip to the return signature and print
1639 that first. However, there is no return value if this is a
1640 constructor. */
1641 if (is_method && ! is_init)
1643 while (str < limit)
1645 int ch = *str++;
1646 if (ch == ')')
1647 break;
1651 /* If printing a field or an ordinary method, then print the
1652 "return value" now. Note that a constructor can't be native,
1653 so we don't bother checking this in the JNI case. */
1654 if (! is_method || ! is_init)
1656 next = decode_signature_piece (stream, str, limit, &need_space);
1657 if (! next)
1659 error ("unparseable signature: '%s'", str0);
1660 return;
1664 /* When printing a JNI header we need to respect the space. In
1665 other cases we're just going to insert a newline anyway. */
1666 fputs (need_space && ! stubs ? " " : "\n", stream);
1668 if (flag_jni && ! stubs)
1669 fputs ("JNICALL ", stream);
1671 /* Now print the name of the thing. */
1672 print_name_for_stub_or_jni (stream, jcf, name_index,
1673 signature_index, is_init, name_override,
1674 flags);
1676 /* Print the body. */
1677 if (stubs)
1679 if (flag_jni)
1680 fputs ("\n{\n (*env)->FatalError (env, \"", stream);
1681 else
1682 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1683 print_name_for_stub_or_jni (stream, jcf, name_index,
1684 signature_index, is_init,
1685 name_override,
1686 flags);
1687 fprintf (stream, " not implemented\")%s;\n}\n\n",
1688 flag_jni ? "" : ")");
1693 static void
1694 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1696 int name_index = JPOOL_USHORT1 (jcf, index);
1697 fputs (prefix, stream);
1698 jcf_print_utf8_replace (out,
1699 JPOOL_UTF_DATA (jcf, name_index),
1700 JPOOL_UTF_LENGTH (jcf, name_index),
1701 '/', '_');
1704 /* Print PREFIX, then a class name in C++ format. If the name refers
1705 to an array, ignore it and don't print PREFIX. Returns 1 if
1706 something was printed, 0 otherwise. */
1707 static int
1708 print_cxx_classname (FILE *stream, const char *prefix,
1709 JCF *jcf, int index, int add_scope)
1711 int name_index = JPOOL_USHORT1 (jcf, index);
1712 int len, c;
1713 const unsigned char *s, *p, *limit;
1715 s = JPOOL_UTF_DATA (jcf, name_index);
1716 len = JPOOL_UTF_LENGTH (jcf, name_index);
1717 limit = s + len;
1719 /* Explicitly omit arrays here. */
1720 p = s;
1721 c = UTF8_GET (p, limit);
1722 if (c == '[')
1723 return 0;
1725 fputs (prefix, stream);
1727 /* Print a leading "::" so we look in the right namespace. */
1728 if (! flag_jni && ! stubs && add_scope)
1729 fputs ("::", stream);
1731 while (s < limit)
1733 c = UTF8_GET (s, limit);
1734 if (c == '/')
1735 fputs (flag_jni ? "_" : "::", stream);
1736 else
1737 jni_print_char (stream, c);
1740 return 1;
1743 int written_class_count = 0;
1745 /* Return name of superclass. If LEN is not NULL, fill it with length
1746 of name. */
1747 static const unsigned char *
1748 super_class_name (JCF *derived_jcf, int *len)
1750 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1751 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1752 const unsigned char *supername =
1753 JPOOL_UTF_DATA (derived_jcf, supername_index);
1755 if (len)
1756 *len = supername_length;
1758 return supername;
1761 static void
1762 handle_inner_classes (int count)
1764 int i;
1766 if (out && ! flag_jni && ! stubs && count > 0)
1767 fprintf (out, "\n");
1769 for (i = 0; i < count; ++i)
1771 JCF_u2 inner_info_index = JCF_readu2 (current_jcf);
1773 /* There are a few more values here, but we don't care about
1774 them. The (void) cast is apparently the only way to avoid a
1775 warning here. */
1776 (void) JCF_readu2 (current_jcf);
1777 (void) JCF_readu2 (current_jcf);
1778 (void) JCF_readu2 (current_jcf);
1780 if (out && ! flag_jni && ! stubs)
1782 print_mangled_classname (out, current_jcf, " friend class ",
1783 inner_info_index);
1784 fprintf (out, ";\n");
1791 /* We keep track of all the `#include's we generate, so we can avoid
1792 duplicates. */
1793 struct include
1795 char *name;
1796 struct include *next;
1799 /* List of all includes. */
1800 static struct include *all_includes = NULL;
1802 /* Generate a #include. */
1803 static void
1804 print_include (FILE *out, const unsigned char *utf8, int len)
1806 struct include *incl;
1808 if (! out)
1809 return;
1811 if (len == -1)
1812 len = strlen ((const char *) utf8);
1814 for (incl = all_includes; incl; incl = incl->next)
1816 /* We check the length because we might have a proper prefix. */
1817 if (len == (int) strlen (incl->name)
1818 && ! strncmp (incl->name, (const char *) utf8, len))
1819 return;
1822 incl = xmalloc (sizeof (struct include));
1823 incl->name = xmalloc (len + 1);
1824 strncpy (incl->name, (const char *) utf8, len);
1825 incl->name[len] = '\0';
1826 incl->next = all_includes;
1827 all_includes = incl;
1829 fputs ("#include <", out);
1830 jcf_print_utf8_replace (out, utf8, len,
1831 '/',
1832 flag_jni ? '_' : '/');
1833 fputs (".h>\n", out);
1838 /* This is used to represent part of a package or class name. */
1839 struct namelet
1841 /* The text of this part of the name. */
1842 char *name;
1843 /* True if this represents a class. */
1844 int is_class;
1845 /* Linked list of all classes and packages inside this one. */
1846 struct namelet *subnamelets;
1847 /* Pointer to next sibling. */
1848 struct namelet *next;
1851 static void add_namelet (const unsigned char *, const unsigned char *,
1852 struct namelet *);
1853 static void print_namelet (FILE *, struct namelet *, int);
1855 /* The special root namelet. */
1856 static struct namelet root =
1858 NULL,
1860 NULL,
1861 NULL
1864 /* This extracts the next name segment from the full UTF-8 encoded
1865 package or class name and links it into the tree. It does this
1866 recursively. */
1867 static void
1868 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1869 struct namelet *parent)
1871 const unsigned char *p;
1872 struct namelet *n = NULL, *np;
1874 /* We want to skip the standard namespaces that we assume the
1875 runtime already knows about. We only do this at the top level,
1876 though, hence the check for `root'. */
1877 if (parent == &root)
1879 #define JAVALANG "java/lang/"
1880 #define JAVAIO "java/io/"
1881 #define JAVAUTIL "java/util/"
1882 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1883 && ! strncmp ((const char *) name, JAVALANG, sizeof (JAVALANG) - 1))
1884 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1885 && ! strncmp ((const char *) name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1886 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1887 && ! strncmp ((const char *) name, JAVAIO, sizeof (JAVAIO) - 1)))
1888 return;
1891 for (p = name; p < name_limit && *p != '/'; ++p)
1894 /* Search for this name beneath the PARENT node. */
1895 for (np = parent->subnamelets; np != NULL; np = np->next)
1897 /* We check the length because we might have a proper prefix. */
1898 if ((int) strlen (np->name) == p - name &&
1899 ! strncmp ((const char *) name, np->name, p - name))
1901 n = np;
1902 break;
1906 if (n == NULL)
1908 n = xmalloc (sizeof (struct namelet));
1909 n->name = xmalloc (p - name + 1);
1910 strncpy (n->name, (const char *) name, p - name);
1911 n->name[p - name] = '\0';
1912 n->is_class = (p == name_limit);
1913 n->subnamelets = NULL;
1914 n->next = parent->subnamelets;
1915 parent->subnamelets = n;
1918 /* We recurse if there is more text, and if the trailing piece does
1919 not represent an inner class. */
1920 if (p < name_limit)
1921 add_namelet (p + 1, name_limit, n);
1924 /* Print a single namelet. Destroys namelets while printing. */
1925 static void
1926 print_namelet (FILE *out, struct namelet *name, int depth)
1928 int i, term = 0;
1929 struct namelet *c;
1931 if (name->name)
1933 for (i = 0; i < depth; ++i)
1934 fputc (' ', out);
1935 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1936 name->name);
1937 if (name->is_class && name->subnamelets == NULL)
1938 fputs (";\n", out);
1939 else
1941 term = 1;
1942 fputs ("\n", out);
1943 for (i = 0; i < depth; ++i)
1944 fputc (' ', out);
1945 fputs ("{\n", out);
1949 c = name->subnamelets;
1950 while (c != NULL)
1952 struct namelet *next = c->next;
1953 print_namelet (out, c, depth + 2);
1954 c = next;
1956 name->subnamelets = NULL;
1958 if (name->name)
1960 if (term)
1962 for (i = 0; i < depth; ++i)
1963 fputc (' ', out);
1964 fputs ("}\n", out);
1965 /* Only print a `;' when printing a class. C++ is evil. */
1966 if (name->is_class)
1967 fputs (";", out);
1970 free (name->name);
1971 free (name);
1975 /* This is called to add some classes to the list of classes for which
1976 we need decls. The signature argument can be a function
1977 signature. */
1978 static void
1979 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1981 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1982 int len = JPOOL_UTF_LENGTH (jcf, signature);
1983 int i;
1985 for (i = 0; i < len; ++i)
1987 int start;
1989 /* If we see an array, then we include the array header. */
1990 if (s[i] == '[')
1992 print_include (out, (const unsigned char *) "gcj/array", -1);
1993 continue;
1996 /* We're looking for `L<stuff>;' -- everything else is
1997 ignorable. */
1998 if (s[i] != 'L')
1999 continue;
2001 for (start = ++i; i < len && s[i] != ';'; ++i)
2004 add_namelet (&s[start], &s[i], &root);
2008 /* Print declarations for all classes required by this class. Any
2009 class or package in the `java' package is assumed to be handled
2010 statically in libjava; we don't generate declarations for these.
2011 This makes the generated headers a bit easier to read. */
2012 static void
2013 print_class_decls (FILE *out, JCF *jcf, int self)
2015 /* Make sure to always add the current class to the list of things
2016 that should be declared. */
2017 int name_index = JPOOL_USHORT1 (jcf, self);
2018 int len;
2019 const unsigned char *s;
2021 s = JPOOL_UTF_DATA (jcf, name_index);
2022 len = JPOOL_UTF_LENGTH (jcf, name_index);
2023 add_namelet (s, s + len, &root);
2025 if (root.subnamelets)
2027 fputs ("extern \"Java\"\n{\n", out);
2028 /* We use an initial offset of 0 because the root namelet
2029 doesn't cause anything to print. */
2030 print_namelet (out, &root, 0);
2031 fputs ("}\n\n", out);
2037 static void
2038 process_file (JCF *jcf, FILE *out)
2040 int code, i;
2041 uint32 field_start, method_end, method_start;
2043 current_jcf = jcf;
2045 last_access = -1;
2047 if (jcf_parse_preamble (jcf) != 0)
2049 error ("Not a valid Java .class file.");
2050 return;
2053 /* Parse and possibly print constant pool */
2054 code = jcf_parse_constant_pool (jcf);
2055 if (code != 0)
2057 error ("error while parsing constant pool");
2058 return;
2060 code = verify_constant_pool (jcf);
2061 if (code > 0)
2063 error ("error in constant pool entry #%d", code);
2064 return;
2067 jcf_parse_class (jcf);
2069 if (written_class_count++ == 0 && out)
2071 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
2072 if (flag_jni)
2074 cstart = "/*";
2075 cstart2 = " ";
2076 cend = " */";
2077 mode = "";
2078 what = "JNI";
2079 jflag = " -jni";
2081 else
2083 cstart = "//";
2084 cstart2 = "//";
2085 cend = "";
2086 mode = " -*- c++ -*-";
2087 what = "CNI";
2088 jflag = "";
2091 if (! stubs)
2092 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2093 cstart, mode, cend);
2094 else
2096 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2097 %s\n\
2098 %s This file is intended to give you a head start on implementing native\n\
2099 %s methods using %s.\n\
2100 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2101 %s overwrite any edits you have made to this file.%s\n\n",
2102 cstart, jflag, mode,
2103 cstart2,
2104 cstart2,
2105 cstart2,
2106 what,
2107 cstart2,
2108 jflag,
2109 cstart2,
2110 cend);
2114 if (out)
2116 if (! stubs)
2118 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2119 fprintf (out, "__\n");
2121 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2122 fprintf (out, "__\n\n");
2124 if (flag_jni)
2126 fprintf (out, "#include <jni.h>\n\n");
2127 fprintf (out, "#ifdef __cplusplus\n");
2128 fprintf (out, "extern \"C\"\n");
2129 fprintf (out, "{\n");
2130 fprintf (out, "#endif\n");
2132 else
2134 /* We do this to ensure that inline methods won't be
2135 `outlined' by g++. This works as long as method and
2136 fields are not added by the user. */
2137 fprintf (out, "#pragma interface\n");
2139 if (jcf->super_class)
2141 int super_length;
2142 const unsigned char *supername =
2143 super_class_name (jcf, &super_length);
2145 fputs ("\n", out);
2146 print_include (out, supername, super_length);
2150 else
2152 /* Strip off the ".class" portion of the name when printing
2153 the include file name. */
2154 char *name;
2155 int i, len = strlen (jcf->classname);
2156 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2157 len -= 6;
2158 /* Turn the class name into a file name. */
2159 name = xmalloc (len + 1);
2160 for (i = 0; i < len; ++i)
2161 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2162 name[i] = '\0';
2163 print_include (out, (const unsigned char *) name, len);
2164 free (name);
2166 if (! flag_jni)
2168 print_include (out, (const unsigned char *) "gcj/cni", -1);
2169 print_include (out, (const unsigned char *) "java/lang/UnsupportedOperationException",
2170 -1);
2175 /* We want to parse the methods first. But we need to find where
2176 they start. So first we skip the fields, then parse the methods.
2177 Then we parse the fields and skip the methods. This is ugly, but
2178 not too bad since we need two full passes to get class decl
2179 information anyway. */
2180 field_pass = 0;
2181 field_start = JCF_TELL (jcf);
2182 jcf_parse_fields (jcf);
2184 method_start = JCF_TELL (jcf);
2185 method_pass = 0;
2186 jcf_parse_methods (jcf);
2188 if (out)
2189 fputs ("\n", out);
2191 if (out && ! flag_jni)
2193 if (! stubs)
2194 print_class_decls (out, jcf, jcf->this_class);
2196 for (i = 0; i < prepend_count; ++i)
2197 fprintf (out, "%s\n", prepend_specs[i]);
2198 if (prepend_count > 0)
2199 fputc ('\n', out);
2201 if (! stubs)
2203 if (! print_cxx_classname (out, "class ", jcf,
2204 jcf->this_class, 0))
2206 error ("class is of array type\n");
2207 return;
2209 if (jcf->super_class)
2211 if (! print_cxx_classname (out, " : public ",
2212 jcf, jcf->super_class, 1))
2214 error ("base class is of array type");
2215 return;
2219 fputs ("\n{\n", out);
2223 /* Now go back for second pass over methods and fields. */
2224 is_first_data_member = 1;
2226 JCF_SEEK (jcf, method_start);
2227 method_pass = 1;
2228 jcf_parse_methods (jcf);
2229 method_end = JCF_TELL (jcf);
2231 field_pass = 1;
2232 JCF_SEEK (jcf, field_start);
2233 jcf_parse_fields (jcf);
2234 JCF_SEEK (jcf, method_end);
2236 jcf_parse_final_attributes (jcf);
2238 if (out && ! stubs)
2240 if (flag_jni)
2242 fprintf (out, "\n#ifdef __cplusplus\n");
2243 fprintf (out, "}\n");
2244 fprintf (out, "#endif\n");
2246 else
2248 /* Generate friend decl if we still must. */
2249 for (i = 0; i < friend_count; ++i)
2250 fprintf (out, " friend %s\n", friend_specs[i]);
2252 /* Generate extra declarations. */
2253 if (add_count > 0)
2254 fputc ('\n', out);
2255 for (i = 0; i < add_count; ++i)
2256 fprintf (out, " %s\n", add_specs[i]);
2258 /* Generate an entry for the class object. */
2259 generate_access (out, ACC_PUBLIC);
2260 fprintf (out, "\n static ::java::lang::Class class$;\n");
2262 fputs ("}", out);
2264 if (jcf->access_flags & ACC_INTERFACE)
2265 fputs (" __attribute__ ((java_interface))", out);
2267 fputs (";\n", out);
2269 if (append_count > 0)
2270 fputc ('\n', out);
2271 for (i = 0; i < append_count; ++i)
2272 fprintf (out, "%s\n", append_specs[i]);
2275 print_mangled_classname (out, jcf,
2276 "\n#endif /* __", jcf->this_class);
2277 fprintf (out, "__ */\n");
2283 /* This is used to mark options with no short value. */
2284 #define LONG_OPT(Num) ((Num) + 128)
2286 #define OPT_classpath LONG_OPT (0)
2287 #define OPT_CLASSPATH OPT_classpath
2288 #define OPT_bootclasspath LONG_OPT (1)
2289 #define OPT_extdirs LONG_OPT (2)
2290 #define OPT_HELP LONG_OPT (3)
2291 #define OPT_TEMP LONG_OPT (4)
2292 #define OPT_VERSION LONG_OPT (5)
2293 #define OPT_PREPEND LONG_OPT (6)
2294 #define OPT_FRIEND LONG_OPT (7)
2295 #define OPT_ADD LONG_OPT (8)
2296 #define OPT_APPEND LONG_OPT (9)
2297 #define OPT_M LONG_OPT (10)
2298 #define OPT_MM LONG_OPT (11)
2299 #define OPT_MG LONG_OPT (12)
2300 #define OPT_MD LONG_OPT (13)
2301 #define OPT_MMD LONG_OPT (14)
2303 static const struct option options[] =
2305 { "classpath", required_argument, NULL, OPT_classpath },
2306 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2307 { "extdirs", required_argument, NULL, OPT_extdirs },
2308 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2309 { "help", no_argument, NULL, OPT_HELP },
2310 { "stubs", no_argument, &stubs, 1 },
2311 { "td", required_argument, NULL, OPT_TEMP },
2312 { "verbose", no_argument, NULL, 'v' },
2313 { "version", no_argument, NULL, OPT_VERSION },
2314 { "prepend", required_argument, NULL, OPT_PREPEND },
2315 { "friend", required_argument, NULL, OPT_FRIEND },
2316 { "add", required_argument, NULL, OPT_ADD },
2317 { "append", required_argument, NULL, OPT_APPEND },
2318 { "M", no_argument, NULL, OPT_M },
2319 { "MM", no_argument, NULL, OPT_MM },
2320 { "MG", no_argument, NULL, OPT_MG },
2321 { "MD", no_argument, NULL, OPT_MD },
2322 { "MMD", no_argument, NULL, OPT_MMD },
2323 { "jni", no_argument, &flag_jni, 1 },
2324 { NULL, no_argument, NULL, 0 }
2327 static void
2328 usage (void)
2330 fprintf (stderr, _("Try 'gcjh --help' for more information.\n"));
2331 exit (1);
2334 static void
2335 help (void)
2337 printf (_("Usage: gcjh [OPTION]... CLASS...\n\n"));
2338 printf (_("Generate C++ header files from .class files\n\n"));
2339 printf (_(" -stubs Generate an implementation stub file\n"));
2340 printf (_(" -jni Generate a JNI header or stub\n"));
2341 printf ("\n");
2342 printf (_(" -add TEXT Insert TEXT into class body\n"));
2343 printf (_(" -append TEXT Insert TEXT after class declaration\n"));
2344 printf (_(" -friend TEXT Insert TEXT as 'friend' declaration\n"));
2345 printf (_(" -prepend TEXT Insert TEXT before start of class\n"));
2346 printf ("\n");
2347 printf (_(" --classpath PATH Set path to find .class files\n"));
2348 printf (_(" -IDIR Append directory to class path\n"));
2349 printf (_(" --bootclasspath PATH Override built-in class path\n"));
2350 printf (_(" --extdirs PATH Set extensions directory path\n"));
2351 printf (_(" -d DIRECTORY Set output directory name\n"));
2352 printf (_(" -o FILE Set output file name\n"));
2353 printf (_(" -td DIRECTORY Set temporary directory name\n"));
2354 printf ("\n");
2355 printf (_(" --help Print this help, then exit\n"));
2356 printf (_(" --version Print version number, then exit\n"));
2357 printf (_(" -v, --verbose Print extra information while running\n"));
2358 printf ("\n");
2359 printf (_(" -M Print all dependencies to stdout;\n"
2360 " suppress ordinary output\n"));
2361 printf (_(" -MM Print non-system dependencies to stdout;\n"
2362 " suppress ordinary output\n"));
2363 printf (_(" -MD Print all dependencies to stdout\n"));
2364 printf (_(" -MMD Print non-system dependencies to stdout\n"));
2365 /* We omit -MG until it is implemented. */
2366 printf ("\n");
2367 printf (_("For bug reporting instructions, please see:\n"
2368 "%s.\n"), bug_report_url);
2369 exit (0);
2372 static void
2373 version (void)
2375 printf ("gcjh (GCC) %s\n\n", version_string);
2376 printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
2377 printf (_("This is free software; see the source for copying conditions. There is NO\n"
2378 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
2379 exit (0);
2383 main (int argc, char** argv)
2385 JCF jcf;
2386 int argi;
2387 char *output_file = NULL;
2388 int emit_dependencies = 0, suppress_output = 0;
2389 int opt;
2391 gcc_init_libintl ();
2393 if (argc <= 1)
2395 error ("no classes specified");
2396 usage ();
2399 jcf_path_init ();
2401 /* We use getopt_long_only to allow single `-' long options. For
2402 some of our options this is more natural. */
2403 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2405 switch (opt)
2407 case 0:
2408 /* Already handled. */
2409 break;
2411 case 'o':
2412 output_file = optarg;
2413 break;
2415 case 'd':
2416 output_directory = optarg;
2417 break;
2419 case 'I':
2420 jcf_path_include_arg (optarg);
2421 break;
2423 case 'v':
2424 verbose++;
2425 break;
2427 case OPT_classpath:
2428 jcf_path_classpath_arg (optarg);
2429 break;
2431 case OPT_bootclasspath:
2432 jcf_path_bootclasspath_arg (optarg);
2433 break;
2435 case OPT_extdirs:
2436 jcf_path_extdirs_arg (optarg);
2437 break;
2439 case OPT_HELP:
2440 help ();
2441 break;
2443 case OPT_TEMP:
2444 temp_directory = optarg;
2445 break;
2447 case OPT_VERSION:
2448 version ();
2449 break;
2451 case OPT_PREPEND:
2452 if (prepend_count == 0)
2453 prepend_specs = ALLOC (argc * sizeof (char*));
2454 prepend_specs[prepend_count++] = optarg;
2455 break;
2457 case OPT_FRIEND:
2458 if (friend_count == 0)
2459 friend_specs = ALLOC (argc * sizeof (char*));
2460 friend_specs[friend_count++] = optarg;
2461 break;
2463 case OPT_ADD:
2464 if (add_count == 0)
2465 add_specs = ALLOC (argc * sizeof (char*));
2466 add_specs[add_count++] = optarg;
2467 break;
2469 case OPT_APPEND:
2470 if (append_count == 0)
2471 append_specs = ALLOC (argc * sizeof (char*));
2472 append_specs[append_count++] = optarg;
2473 break;
2475 case OPT_M:
2476 emit_dependencies = 1;
2477 suppress_output = 1;
2478 jcf_dependency_init (1);
2479 break;
2481 case OPT_MM:
2482 emit_dependencies = 1;
2483 suppress_output = 1;
2484 jcf_dependency_init (0);
2485 break;
2487 case OPT_MG:
2488 error ("'-MG' option is unimplemented");
2489 exit (1);
2491 case OPT_MD:
2492 emit_dependencies = 1;
2493 jcf_dependency_init (1);
2494 break;
2496 case OPT_MMD:
2497 emit_dependencies = 1;
2498 jcf_dependency_init (0);
2499 break;
2501 default:
2502 usage ();
2503 break;
2507 if (optind == argc)
2509 error ("no classes specified");
2510 usage ();
2513 jcf_path_seal (verbose);
2515 if (output_file && emit_dependencies)
2517 error ("can't specify both -o and -MD");
2518 exit (1);
2521 for (argi = optind; argi < argc; argi++)
2523 char *classname = argv[argi];
2524 char *current_output_file;
2525 const char *classfile_name;
2527 if (verbose)
2528 printf (_("Processing %s\n"), classname);
2529 if (! output_file)
2530 jcf_dependency_reset ();
2531 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2532 if (classfile_name == NULL)
2534 error ("%s: no such class", classname);
2535 exit (1);
2537 if (verbose)
2538 printf (_("Found in %s\n"), classfile_name);
2539 if (output_file)
2541 if (strcmp (output_file, "-") == 0)
2542 out = stdout;
2543 else if (out == NULL)
2545 out = fopen (output_file, "w");
2547 if (out == NULL)
2549 perror (output_file);
2550 exit (1);
2552 current_output_file = output_file;
2554 else
2556 int dir_len = strlen (output_directory);
2557 int i, classname_length = strlen (classname);
2558 current_output_file = ALLOC (dir_len + classname_length + 5);
2559 strcpy (current_output_file, output_directory);
2560 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2561 current_output_file[dir_len++] = '/';
2562 for (i = 0; classname[i] != '\0'; i++)
2564 char ch = classname[i];
2565 if (ch == '.')
2566 ch = '/';
2567 if (flag_jni && ch == '/')
2568 ch = '_';
2569 current_output_file[dir_len++] = ch;
2571 if (emit_dependencies)
2573 if (suppress_output)
2575 jcf_dependency_set_dep_file ("-");
2576 out = NULL;
2578 else
2580 /* We use `.hd' and not `.d' to avoid clashes with
2581 dependency tracking from straight compilation. */
2582 strcpy (current_output_file + dir_len, ".hd");
2583 jcf_dependency_set_dep_file (current_output_file);
2586 strcpy (current_output_file + dir_len,
2587 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2588 jcf_dependency_set_target (current_output_file);
2589 if (! suppress_output)
2591 out = fopen (current_output_file, "w");
2592 if (out == NULL)
2594 perror (current_output_file);
2595 exit (1);
2599 free_method_name_list ();
2600 process_file (&jcf, out);
2601 JCF_FINISH (&jcf);
2602 if (current_output_file != output_file)
2603 free (current_output_file);
2604 jcf_dependency_write ();
2607 if (out != NULL && out != stdout)
2608 fclose (out);
2610 return found_error;