2005-01-22 Thomas Koenig <Thomas.Koenig@online.de>
[official-gcc.git] / gcc / java / gjavah.c
blob1f25ce62610c19251670ec08fee492a27f705d9b
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
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 fputs (flag_jni ? " " : " = ", out);
285 if (f.negative)
286 putc ('-', stream);
287 if (f.exponent)
288 fprintf (stream, "0x1.%.6xp%+df",
289 ((unsigned int)f.mantissa) << 1,
290 f.exponent - JFLOAT_EXP_BIAS);
291 else
292 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
293 because the implicit leading 1 bit is no longer present. */
294 fprintf (stream, "0x0.%.6xp%+df",
295 ((unsigned int)f.mantissa) << 1,
296 f.exponent + 1 - JFLOAT_EXP_BIAS);
298 if (! flag_jni)
299 fputs (";\n", stream);
302 /* Print a double-precision float, suitable for parsing by g++. */
303 static void
304 jni_print_double (FILE *stream, jdouble f)
306 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
307 work in data initializers. FIXME. */
308 if (JDOUBLE_FINITE (f))
310 fputs (flag_jni ? " " : " = ", out);
311 if (f.negative)
312 putc ('-', stream);
313 if (f.exponent)
314 fprintf (stream, "0x1.%.5x%.8xp%+d",
315 f.mantissa0, f.mantissa1,
316 f.exponent - JDOUBLE_EXP_BIAS);
317 else
318 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
319 because the implicit leading 1 bit is no longer present. */
320 fprintf (stream, "0x0.%.5x%.8xp%+d",
321 f.mantissa0, f.mantissa1,
322 f.exponent + 1 - JDOUBLE_EXP_BIAS);
324 fputs (flag_jni ? "\n" : ";\n", stream);
327 /* Print a character, appropriately mangled for JNI. */
329 static void
330 jni_print_char (FILE *stream, int ch)
332 if (! flag_jni)
333 jcf_print_char (stream, ch);
334 else if (ch == '(' || ch == ')')
336 /* Ignore. */
338 else if (ch == '_')
339 fputs ("_1", stream);
340 else if (ch == ';')
341 fputs ("_2", stream);
342 else if (ch == '[')
343 fputs ("_3", stream);
344 else if (ch == '/')
345 fputs ("_", stream);
346 else if (ISALNUM (ch))
347 fputc (ch, stream);
348 else
350 /* "Unicode" character. */
351 fprintf (stream, "_0%04x", ch);
355 /* Print a name from the class data. If the index does not point to a
356 string, an error results. */
358 static void
359 print_name (FILE* stream, JCF* jcf, int name_index)
361 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
363 fprintf (stream, "<not a UTF8 constant>");
364 found_error = 1;
366 else if (! flag_jni)
367 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
368 JPOOL_UTF_LENGTH (jcf, name_index));
369 else
371 /* For JNI we must correctly quote each character. */
372 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
373 int length = JPOOL_UTF_LENGTH (jcf, name_index);
374 const unsigned char *limit = str + length;
375 while (str < limit)
377 int ch = UTF8_GET (str, limit);
378 if (ch < 0)
380 fprintf (stream, "\\<invalid>");
381 return;
383 jni_print_char (stream, ch);
388 /* Print base name of class. The base name is everything after the
389 final separator. */
391 static void
392 print_base_classname (FILE *stream, JCF *jcf, int index)
394 int name_index = JPOOL_USHORT1 (jcf, index);
395 int len;
396 const unsigned char *s, *p, *limit;
398 s = JPOOL_UTF_DATA (jcf, name_index);
399 len = JPOOL_UTF_LENGTH (jcf, name_index);
400 limit = s + len;
401 p = s;
402 while (s < limit)
404 int c = UTF8_GET (s, limit);
405 if (c == '/')
406 p = s;
409 while (p < limit)
411 int ch = UTF8_GET (p, limit);
412 if (ch == '/')
413 fputs ("::", stream);
414 else
415 jcf_print_char (stream, ch);
419 /* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
420 and 1 if STR is "greater" than NAME. */
422 static int
423 utf8_cmp (const unsigned char *str, int length, const char *name)
425 const unsigned char *limit = str + length;
426 int i;
428 for (i = 0; name[i]; ++i)
430 int ch = UTF8_GET (str, limit);
431 if (ch != name[i])
432 return ch - name[i];
435 return str == limit ? 0 : 1;
438 /* This is a sorted list of all C++ keywords. */
440 static const char *const cxx_keywords[] =
442 "_Complex",
443 "__alignof",
444 "__alignof__",
445 "__asm",
446 "__asm__",
447 "__attribute",
448 "__attribute__",
449 "__builtin_va_arg",
450 "__complex",
451 "__complex__",
452 "__const",
453 "__const__",
454 "__extension__",
455 "__imag",
456 "__imag__",
457 "__inline",
458 "__inline__",
459 "__label__",
460 "__null",
461 "__real",
462 "__real__",
463 "__restrict",
464 "__restrict__",
465 "__signed",
466 "__signed__",
467 "__typeof",
468 "__typeof__",
469 "__volatile",
470 "__volatile__",
471 "and",
472 "and_eq",
473 "asm",
474 "auto",
475 "bitand",
476 "bitor",
477 "bool",
478 "break",
479 "case",
480 "catch",
481 "char",
482 "class",
483 "compl",
484 "const",
485 "const_cast",
486 "continue",
487 "default",
488 "delete",
489 "do",
490 "double",
491 "dynamic_cast",
492 "else",
493 "enum",
494 "explicit",
495 "export",
496 "extern",
497 "false",
498 "float",
499 "for",
500 "friend",
501 "goto",
502 "if",
503 "inline",
504 "int",
505 "long",
506 "mutable",
507 "namespace",
508 "new",
509 "not",
510 "not_eq",
511 "operator",
512 "or",
513 "or_eq",
514 "private",
515 "protected",
516 "public",
517 "register",
518 "reinterpret_cast",
519 "return",
520 "short",
521 "signed",
522 "sizeof",
523 "static",
524 "static_cast",
525 "struct",
526 "switch",
527 "template",
528 "this",
529 "throw",
530 "true",
531 "try",
532 "typedef",
533 "typeid",
534 "typename",
535 "typeof",
536 "union",
537 "unsigned",
538 "using",
539 "virtual",
540 "void",
541 "volatile",
542 "wchar_t",
543 "while",
544 "xor",
545 "xor_eq"
549 /* If NAME is the name of a C++ keyword, then return an override name.
550 This is a name that can be used in place of the keyword.
551 Otherwise, return NULL. The return value is malloc()d. */
553 static char *
554 cxx_keyword_subst (const unsigned char *str, int length)
556 int last = ARRAY_SIZE (cxx_keywords);
557 int first = 0;
558 int mid = (last + first) / 2;
559 int old = -1;
561 for (mid = (last + first) / 2;
562 mid != old;
563 old = mid, mid = (last + first) / 2)
565 int kwl = strlen (cxx_keywords[mid]);
566 int min_length = kwl > length ? length : kwl;
567 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
569 if (r == 0)
571 int i;
573 /* Skip all trailing `$'. */
574 for (i = min_length; i < length && str[i] == '$'; ++i)
576 /* We've only found a match if all the remaining characters
577 are `$'. */
578 if (i == length)
580 char *dup = xmalloc (2 + length - min_length + kwl);
581 strcpy (dup, cxx_keywords[mid]);
582 for (i = kwl; i < length + 1; ++i)
583 dup[i] = '$';
584 dup[i] = '\0';
585 return dup;
587 r = 1;
590 if (r < 0)
591 last = mid;
592 else
593 first = mid;
595 return NULL;
598 /* Generate an access control keyword based on FLAGS. */
600 static void
601 generate_access (FILE *stream, JCF_u2 flags)
603 if ((flags & ACC_VISIBILITY) == last_access)
604 return;
605 last_access = (flags & ACC_VISIBILITY);
607 switch (last_access)
609 case 0:
610 fputs ("public: // actually package-private\n", stream);
611 break;
612 case ACC_PUBLIC:
613 fputs ("public:\n", stream);
614 break;
615 case ACC_PRIVATE:
616 fputs ("private:\n", stream);
617 break;
618 case ACC_PROTECTED:
619 fputs ("public: // actually protected\n", stream);
620 break;
621 default:
622 found_error = 1;
623 fprintf (stream, "#error unrecognized visibility %d\n",
624 (flags & ACC_VISIBILITY));
625 break;
629 /* See if NAME is already the name of a method. */
630 static int
631 name_is_method_p (const unsigned char *name, int length)
633 struct method_name *p;
635 for (p = method_name_list; p != NULL; p = p->next)
637 if (p->length == length && ! memcmp (p->name, name, length))
638 return 1;
640 return 0;
643 /* Free the method name list. */
644 static void
645 free_method_name_list (void)
647 struct method_name *p = method_name_list;
648 while (p != NULL)
650 struct method_name *next = p->next;
651 free (p->name);
652 free (p->signature);
653 free (p);
654 p = next;
656 method_name_list = NULL;
659 /* If there is already a native method named NAME, whose signature is not
660 SIGNATURE, then return true. Otherwise return false. */
661 static int
662 overloaded_jni_method_exists_p (const unsigned char *name, int length,
663 const char *signature, int sig_length)
665 struct method_name *p;
667 for (p = method_name_list; p != NULL; p = p->next)
669 if (p->is_native
670 && p->length == length
671 && ! memcmp (p->name, name, length)
672 && (p->sig_length != sig_length
673 || memcmp (p->signature, signature, sig_length)))
674 return 1;
676 return 0;
679 /* Get name of a field. This handles renamings due to C++ clash. */
680 static char *
681 get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
683 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
684 int length = JPOOL_UTF_LENGTH (jcf, name_index);
685 char *override;
687 if (name_is_method_p (name, length))
689 /* This field name matches a method. So override the name with
690 a dummy name. This is yucky, but it isn't clear what else to
691 do. FIXME: if the field is static, then we'll be in real
692 trouble. */
693 if ((flags & ACC_STATIC))
695 error ("static field has same name as method");
696 return NULL;
699 override = xmalloc (length + 3);
700 memcpy (override, name, length);
701 strcpy (override + length, "__");
703 else
704 override = cxx_keyword_subst (name, length);
706 return override;
709 /* Print a field name. Convenience function for use with
710 get_field_name. */
711 static void
712 print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
714 char *override = get_field_name (jcf, name_index, flags);
716 if (override)
718 fputs (override, stream);
719 free (override);
721 else
722 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
723 JPOOL_UTF_LENGTH (jcf, name_index));
726 static void
727 print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
728 JCF_u2 flags)
730 char *override = NULL;
732 if (! flag_jni)
733 generate_access (stream, flags);
734 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
736 fprintf (stream, "<not a UTF8 constant>");
737 found_error = 1;
738 return;
741 if (flag_jni)
743 /* For JNI we only want to print real constants. */
744 int val;
745 if (! (flags & ACC_STATIC)
746 || ! (flags & ACC_FINAL)
747 || current_field_value <= 0)
748 return;
749 val = JPOOL_TAG (jcf, current_field_value);
750 if (val != CONSTANT_Integer && val != CONSTANT_Long
751 && val != CONSTANT_Float && val != CONSTANT_Double)
752 return;
754 else
756 /* Initial indentation. */
757 fputs (" ", stream);
760 if ((flags & ACC_STATIC))
762 if (flag_jni)
764 print_cxx_classname (stream, "#undef ", jcf, jcf->this_class, 1);
765 fputs ("_", stream);
766 print_field_name (stream, jcf, name_index, 0);
767 fputs ("\n", stream);
768 print_cxx_classname (stream, "#define ", jcf, jcf->this_class, 1);
769 fputs ("_", stream);
771 else
772 fputs ("static ", stream);
774 if ((flags & ACC_FINAL) && current_field_value > 0)
776 char buffer[25];
777 int done = 1;
779 switch (JPOOL_TAG (jcf, current_field_value))
781 case CONSTANT_Integer:
783 jint num;
784 int most_negative = 0;
785 if (! flag_jni)
786 fputs ("const jint ", stream);
787 print_field_name (stream, jcf, name_index, 0);
788 fputs (flag_jni ? " " : " = ", stream);
789 num = JPOOL_INT (jcf, current_field_value);
790 /* We single out the most negative number to print
791 specially. This avoids later warnings from g++. */
792 if (num == (jint) 0x80000000)
794 most_negative = 1;
795 ++num;
797 format_int (buffer, (jlong) num, 10);
798 fprintf (stream, "%sL%s%s\n", buffer,
799 most_negative ? " - 1" : "",
800 flag_jni ? "" : ";");
802 break;
803 case CONSTANT_Long:
805 jlong num;
806 int most_negative = 0;
807 if (! flag_jni)
808 fputs ("const jlong ", stream);
809 print_field_name (stream, jcf, name_index, 0);
810 fputs (flag_jni ? " " : " = ", stream);
811 num = JPOOL_LONG (jcf, current_field_value);
812 /* We single out the most negative number to print
813 specially.. This avoids later warnings from g++. */
814 if (num == (jlong) 0x8000000000000000LL)
816 most_negative = 1;
817 ++num;
819 format_int (buffer, num, 10);
820 fprintf (stream, "%sLL%s%s\n", buffer,
821 most_negative ? " - 1" :"",
822 flag_jni ? "" : ";");
824 break;
825 case CONSTANT_Float:
827 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
828 if (! flag_jni)
829 fputs ("const jfloat ", stream);
830 print_field_name (stream, jcf, name_index, 0);
831 jni_print_float (stream, fnum);
833 break;
834 case CONSTANT_Double:
836 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
837 if (! flag_jni)
838 fputs ("const jdouble ", stream);
839 print_field_name (stream, jcf, name_index, 0);
840 jni_print_double (stream, dnum);
842 break;
843 default:
844 /* We can't print this as a constant, but we can still
845 print something sensible. */
846 done = 0;
847 break;
850 if (done)
851 return;
855 /* assert (! flag_jni); */
856 override = get_field_name (jcf, name_index, flags);
857 print_c_decl (stream, jcf, name_index, sig_index, 0, override, flags);
858 fputs (";\n", stream);
860 if (override)
861 free (override);
865 static void
866 print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
867 JCF_u2 flags)
869 const unsigned char *str;
870 int length, is_init = 0;
871 char *override = NULL;
873 method_declared = 0;
874 method_access = flags;
875 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
876 fprintf (stream, "<not a UTF8 constant>");
877 str = JPOOL_UTF_DATA (jcf, name_index);
878 length = JPOOL_UTF_LENGTH (jcf, name_index);
880 if (str[0] == '<')
882 /* Ignore the internally generated method <clinit>. However,
883 treat <init> as a constructor. */
884 if (! utf8_cmp (str, length, "<init>"))
885 is_init = 1;
886 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
887 && ! (flags & ACC_STATIC))
889 /* FIXME: i18n bug here. Order of prints should not be
890 fixed. */
891 fprintf (stderr, _("ignored method '"));
892 jcf_print_utf8 (stderr, str, length);
893 fprintf (stderr, _("' marked virtual\n"));
894 found_error = 1;
895 return;
897 else
898 return;
901 /* During the first method pass, build a list of method names. This will
902 be used to determine if field names conflict with method names. */
903 if (! stream)
905 struct method_name *nn;
907 nn = xmalloc (sizeof (struct method_name));
908 nn->name = xmalloc (length);
909 memcpy (nn->name, str, length);
910 nn->length = length;
911 nn->next = method_name_list;
912 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
913 nn->signature = xmalloc (nn->sig_length);
914 nn->is_native = METHOD_IS_NATIVE (flags);
915 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
916 nn->sig_length);
917 method_name_list = nn;
919 /* The rest of this function doesn't matter. */
920 return;
923 /* We don't worry about overrides in JNI mode. */
924 if (! flag_jni)
926 /* We can't generate a method whose name is a C++ reserved word.
927 We can't just ignore the function, because that will cause
928 incorrect code to be generated if the function is virtual
929 (not only for calls to this function for for other functions
930 after it in the vtbl). So we give it a dummy name instead. */
931 override = cxx_keyword_subst (str, length);
934 if (! stubs && ! flag_jni)
936 method_printed = 1;
938 generate_access (stream, flags);
940 fputs (" ", out);
941 if ((flags & ACC_STATIC))
942 fputs ("static ", out);
943 else if (! METHOD_IS_PRIVATE (jcf->access_flags, flags))
945 /* Don't print `virtual' if we have a constructor. */
946 if (! is_init)
947 fputs ("virtual ", out);
949 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
951 if ((flags & ACC_ABSTRACT))
952 fputs (" = 0", out);
953 else
954 method_declared = 1;
956 else
958 if (METHOD_IS_NATIVE (flags))
960 method_printed = 1;
961 print_stub_or_jni (out, jcf, name_index, sig_index,
962 is_init, override, flags);
966 if (override)
967 free (override);
970 /* A helper for the decompiler which prints a `return' statement where
971 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
972 identical, we emit a cast. We do this because the C++ compiler
973 doesn't know that a reference can be cast to the type of an
974 interface it implements. METHODTYPE is the index of the method's
975 signature. NAMEINDEX is the index of the field name; -1 for
976 `this'. OBJECTTYPE is the index of the object's type. */
977 static void
978 decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
979 int nameindex, int objecttype)
981 int cast = 0;
982 int obj_name_len, method_name_len;
983 const unsigned char *obj_data, *method_data;
985 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
986 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
988 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
989 method_data = JPOOL_UTF_DATA (jcf, methodtype);
991 /* Skip forward to return type part of method. */
992 while (*method_data != ')')
994 ++method_data;
995 --method_name_len;
997 /* Skip past `)'. */
998 ++method_data;
999 --method_name_len;
1001 /* If we see an `L', skip it and the trailing `;'. */
1002 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
1004 ++method_data;
1005 method_name_len -= 2;
1007 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
1009 ++obj_data;
1010 obj_name_len -= 2;
1013 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
1014 need a cast. Right now there is no way to determine if this is
1015 the case. */
1016 if (method_name_len != obj_name_len)
1017 cast = 1;
1018 else
1020 int i;
1021 for (i = 0; i < method_name_len; ++i)
1023 if (method_data[i] != obj_data[i])
1025 cast = 1;
1026 break;
1031 fputs (" { return ", out);
1033 if (cast)
1035 int array_depth = 0;
1036 const unsigned char *limit;
1038 fputs ("reinterpret_cast<", out);
1040 while (*method_data == '[')
1042 ++method_data;
1043 ++array_depth;
1044 --method_name_len;
1045 fputs ("JArray<", out);
1048 /* Leading space to avoid C++ digraphs. */
1049 fputs (" ::", out);
1051 /* If we see an `L', skip it and the trailing `;'. Only do this
1052 if we've seen an array specification. If we don't have an
1053 array then the `L' was stripped earlier. */
1054 if (array_depth && method_data[0] == 'L'
1055 && method_data[method_name_len - 1] == ';')
1057 ++method_data;
1058 method_name_len -= 2;
1061 limit = method_data + method_name_len;
1062 while (method_data < limit)
1064 int ch = UTF8_GET (method_data, limit);
1065 if (ch == '/')
1066 fputs ("::", out);
1067 else
1068 jcf_print_char (out, ch);
1070 fputs (" *", out);
1072 /* Close each array. */
1073 while (array_depth > 0)
1075 fputs ("> *", out);
1076 --array_depth;
1079 /* Close the cast. */
1080 fputs ("> (", out);
1083 if (nameindex == -1)
1084 fputs ("this", out);
1085 else
1086 print_field_name (out, jcf, nameindex, 0);
1088 if (cast)
1089 fputs (")", out);
1091 fputs ("; }", out);
1095 /* Try to decompile a method body. Right now we just try to handle a
1096 simple case that we can do. Expand as desired. */
1097 static void
1098 decompile_method (FILE *out, JCF *jcf, int code_len)
1100 const unsigned char *codes = jcf->read_ptr;
1101 int index;
1102 uint16 name_and_type, name;
1104 /* If the method is synchronized, don't touch it. */
1105 if ((method_access & ACC_SYNCHRONIZED))
1106 return;
1108 if (code_len == 5
1109 && codes[0] == OPCODE_aload_0
1110 && codes[1] == OPCODE_getfield
1111 && (codes[4] == OPCODE_areturn
1112 || codes[4] == OPCODE_dreturn
1113 || codes[4] == OPCODE_freturn
1114 || codes[4] == OPCODE_ireturn
1115 || codes[4] == OPCODE_lreturn))
1117 /* Found code like `return FIELD'. */
1118 index = (codes[2] << 8) | codes[3];
1119 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
1120 name_and_type = JPOOL_USHORT2 (jcf, index);
1121 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1122 name = JPOOL_USHORT1 (jcf, name_and_type);
1123 if (codes[4] == OPCODE_areturn)
1124 decompile_return_statement (out, jcf, method_signature,
1125 name, JPOOL_USHORT2 (jcf, name_and_type));
1126 else
1128 fputs (" { return ", out);
1129 /* FIXME: flags. */
1130 print_field_name (out, jcf, name, 0);
1131 fputs ("; }", out);
1133 decompiled = 1;
1135 else if (code_len == 2
1136 && codes[0] == OPCODE_aload_0
1137 && codes[1] == OPCODE_areturn
1138 /* We're going to generate `return this'. This only makes
1139 sense for non-static methods. */
1140 && ! (method_access & ACC_STATIC))
1142 decompile_return_statement (out, jcf, method_signature, -1,
1143 JPOOL_USHORT1 (jcf, jcf->this_class));
1144 decompiled = 1;
1146 else if (code_len == 1 && codes[0] == OPCODE_return)
1148 /* Found plain `return'. */
1149 fputs (" { }", out);
1150 decompiled = 1;
1152 else if (code_len == 2
1153 && codes[0] == OPCODE_aconst_null
1154 && codes[1] == OPCODE_areturn)
1156 /* Found `return null'. We don't want to depend on NULL being
1157 defined. */
1158 fputs (" { return 0; }", out);
1159 decompiled = 1;
1163 /* Like strcmp, but invert the return result for the hash table. This
1164 should probably be in hashtab.c to complement the existing string
1165 hash function. */
1166 static int
1167 gcjh_streq (const void *p1, const void *p2)
1169 return ! strcmp ((char *) p1, (char *) p2);
1172 /* Return 1 if the initial part of CLNAME names a subclass of throwable,
1173 or 0 if not. CLNAME may be extracted from a signature, and can be
1174 terminated with either `;' or NULL. */
1175 static int
1176 throwable_p (const unsigned char *clname)
1178 int length;
1179 unsigned char *current;
1180 int i;
1181 int result = 0;
1183 /* We keep two hash tables of class names. In one we list all the
1184 classes which are subclasses of Throwable. In the other we will
1185 all other classes. We keep two tables to make the code a bit
1186 simpler; we don't have to have a structure mapping class name to
1187 a `throwable?' bit. */
1188 static htab_t throw_hash;
1189 static htab_t non_throw_hash;
1190 static int init_done = 0;
1192 if (! init_done)
1194 void **slot;
1195 unsigned char *str;
1197 /* Self-initializing. The cost of this really doesn't matter.
1198 We also don't care about freeing these, either. */
1199 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1200 (htab_del) free);
1201 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1202 (htab_del) free);
1204 /* Make sure the root classes show up in the tables. */
1205 str = (unsigned char *) xstrdup ("java.lang.Throwable");
1206 slot = htab_find_slot (throw_hash, str, INSERT);
1207 *slot = str;
1209 str = (unsigned char *) xstrdup ("java.lang.Object");
1210 slot = htab_find_slot (non_throw_hash, str, INSERT);
1211 *slot = str;
1213 init_done = 1;
1216 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
1218 current = ALLOC (length + 1);
1219 for (i = 0; i < length; ++i)
1220 current[i] = clname[i] == '/' ? '.' : clname[i];
1221 current[length] = '\0';
1223 /* We don't compute the hash slot here because the table might be
1224 modified by the recursion. In that case the slot could be
1225 invalidated. */
1226 if (htab_find (throw_hash, current))
1227 result = 1;
1228 else if (htab_find (non_throw_hash, current))
1229 result = 0;
1230 else
1232 JCF jcf;
1233 void **slot;
1234 unsigned char *super, *tmp;
1235 int super_length = -1;
1236 const char *classfile_name = find_class ((char *) current, strlen ((const char *) current),
1237 &jcf, 0);
1239 if (! classfile_name)
1241 error ("couldn't find class %s", current);
1242 return 0;
1244 if (jcf_parse_preamble (&jcf) != 0
1245 || jcf_parse_constant_pool (&jcf) != 0
1246 || verify_constant_pool (&jcf) > 0)
1248 error ("parse error while reading %s", classfile_name);
1249 return 0;
1251 jcf_parse_class (&jcf);
1253 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
1254 super = ALLOC (super_length + 1);
1255 memcpy (super, tmp, super_length);
1256 super[super_length] = '\0';
1258 result = throwable_p (super);
1259 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1260 current, INSERT);
1261 *slot = current;
1262 current = NULL;
1264 JCF_FINISH (&jcf);
1267 return result;
1270 /* Print one piece of a signature. Returns pointer to next parseable
1271 character on success, NULL on error. */
1272 static const unsigned char *
1273 decode_signature_piece (FILE *stream, const unsigned char *signature,
1274 const unsigned char *limit, int *need_space)
1276 const char *ctype;
1277 int array_depth = 0;
1279 switch (signature[0])
1281 case '[':
1282 /* More spaghetti. */
1284 array_loop:
1285 for (signature++; (signature < limit
1286 && ISDIGIT (*signature)); signature++)
1288 switch (*signature)
1290 case 'B':
1291 ctype = "jbyteArray";
1292 break;
1293 case 'C':
1294 ctype = "jcharArray";
1295 break;
1296 case 'D':
1297 ctype = "jdoubleArray";
1298 break;
1299 case 'F':
1300 ctype = "jfloatArray";
1301 break;
1302 case 'I':
1303 ctype = "jintArray";
1304 break;
1305 case 'S':
1306 ctype = "jshortArray";
1307 break;
1308 case 'J':
1309 ctype = "jlongArray";
1310 break;
1311 case 'Z':
1312 ctype = "jbooleanArray";
1313 break;
1314 case '[':
1315 /* We have a nested array. */
1316 ++array_depth;
1317 if (! flag_jni)
1318 fputs ("JArray<", stream);
1319 goto array_loop;
1321 case 'L':
1322 /* We have to generate a reference to JArray here, so that
1323 our output matches what the compiler does. */
1324 ++signature;
1325 /* Space between `<' and `:' to avoid C++ digraphs. */
1326 if (! flag_jni)
1327 fputs ("JArray< ::", stream);
1328 while (signature < limit && *signature != ';')
1330 int ch = UTF8_GET (signature, limit);
1331 if (! flag_jni)
1333 if (ch == '/')
1334 fputs ("::", stream);
1335 else
1336 jcf_print_char (stream, ch);
1339 if (! flag_jni)
1340 fputs (" *> *", stream);
1341 *need_space = 0;
1342 ctype = NULL;
1343 break;
1344 default:
1345 /* Unparseable signature. */
1346 return NULL;
1349 /* If the previous iterations left us with something to print,
1350 print it. For JNI, we always print `jobjectArray' in the
1351 nested cases. */
1352 if (flag_jni && (ctype == NULL || array_depth > 0))
1354 ctype = "jobjectArray";
1355 *need_space = 1;
1357 /* The `printit' case will advance SIGNATURE for us. If we
1358 don't go there, we must advance past the `;' ourselves. */
1359 if (ctype != NULL)
1360 goto printit;
1361 ++signature;
1362 break;
1364 case '(':
1365 case ')':
1366 /* This shouldn't happen. */
1367 return NULL;
1369 case 'B': ctype = "jbyte"; goto printit;
1370 case 'C': ctype = "jchar"; goto printit;
1371 case 'D': ctype = "jdouble"; goto printit;
1372 case 'F': ctype = "jfloat"; goto printit;
1373 case 'I': ctype = "jint"; goto printit;
1374 case 'J': ctype = "jlong"; goto printit;
1375 case 'S': ctype = "jshort"; goto printit;
1376 case 'Z': ctype = "jboolean"; goto printit;
1377 case 'V': ctype = "void"; goto printit;
1378 case 'L':
1379 if (flag_jni)
1381 /* We know about certain types and special-case their names. */
1382 if (! strncmp ((const char *) signature, "Ljava/lang/String;",
1383 sizeof ("Ljava/lang/String;") -1))
1384 ctype = "jstring";
1385 else if (! strncmp ((const char *) signature, "Ljava/lang/Class;",
1386 sizeof ("Ljava/lang/Class;") - 1))
1387 ctype = "jclass";
1388 /* Skip leading 'L' for throwable_p call. */
1389 else if (throwable_p (signature + 1))
1390 ctype = "jthrowable";
1391 else
1392 ctype = "jobject";
1394 while (*signature && *signature != ';')
1395 ++signature;
1397 goto printit;
1399 /* Print a leading "::" so we look in the right namespace. */
1400 fputs ("::", stream);
1401 ++signature;
1402 while (*signature && *signature != ';')
1404 int ch = UTF8_GET (signature, limit);
1405 if (ch == '/')
1406 fputs ("::", stream);
1407 else
1408 jcf_print_char (stream, ch);
1410 fputs (" *", stream);
1411 if (*signature == ';')
1412 signature++;
1413 *need_space = 0;
1414 break;
1415 default:
1416 *need_space = 1;
1417 jni_print_char (stream, *signature++);
1418 break;
1419 printit:
1420 signature++;
1421 *need_space = 1;
1422 fputs (ctype, stream);
1423 break;
1426 if (! flag_jni)
1428 while (array_depth-- > 0)
1429 fputs ("> *", stream);
1432 return signature;
1435 static void
1436 print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1437 int is_init, const char *name_override, int flags)
1439 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1441 fprintf (stream, "<not a UTF8 constant>");
1442 found_error = 1;
1444 else
1446 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1447 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1448 const unsigned char *str = str0;
1449 const unsigned char *limit = str + length;
1450 int need_space = 0;
1451 int is_method = str[0] == '(';
1452 const unsigned char *next;
1454 /* If printing a method, skip to the return signature and print
1455 that first. However, there is no return value if this is a
1456 constructor. */
1457 if (is_method && ! is_init)
1459 while (str < limit)
1461 int ch = *str++;
1462 if (ch == ')')
1463 break;
1467 /* If printing a field or an ordinary method, then print the
1468 "return value" now. */
1469 if (! is_method || ! is_init)
1471 next = decode_signature_piece (stream, str, limit, &need_space);
1472 if (! next)
1474 error ("unparseable signature: '%s'", str0);
1475 return;
1479 /* Force the alignment of the first data member. This is
1480 because the "new" C++ ABI changed the alignment of non-POD
1481 classes. gcj, however, still uses the "old" alignment. */
1482 if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
1484 is_first_data_member = 0;
1485 print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1486 jcf, jcf->super_class, 1);
1487 fputs (" )))) ", stream);
1490 /* Now print the name of the thing. */
1491 if (need_space)
1492 fputs (" ", stream);
1493 print_full_cxx_name (stream, jcf, name_index,
1494 signature_index, is_init, name_override,
1495 flags);
1499 /* Print the unqualified method name followed by the signature. */
1500 static void
1501 print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1502 int signature_index, int is_init,
1503 const char *name_override, int flags)
1505 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1506 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1507 const unsigned char *str = str0;
1508 const unsigned char *limit = str + length;
1509 int need_space = 0;
1510 int is_method = str[0] == '(';
1511 const unsigned char *next;
1513 if (name_override)
1514 fputs (name_override, stream);
1515 else if (name_index)
1517 /* Declare constructors specially. */
1518 if (is_init)
1519 print_base_classname (stream, jcf, jcf->this_class);
1520 else
1521 print_name (stream, jcf, name_index);
1524 if (flag_jni)
1526 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1527 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1528 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1529 JPOOL_UTF_LENGTH (jcf, name_index),
1530 (const char *) signature, sig_len))
1532 /* If this method is overloaded by another native method,
1533 then include the argument information in the mangled
1534 name. */
1535 unsigned char *limit = signature + sig_len;
1536 fputs ("__", stream);
1537 while (signature < limit)
1539 int ch = UTF8_GET (signature, limit);
1540 jni_print_char (stream, ch);
1541 if (ch == ')')
1543 /* Done. */
1544 break;
1550 if (is_method)
1552 /* Have a method or a constructor. Print signature pieces
1553 until done. */
1554 fputs (" (", stream);
1556 str = str0 + 1;
1558 /* In JNI mode, add extra arguments. */
1559 if (flag_jni)
1561 /* FIXME: it would be nice to know if we are printing a decl
1562 or a definition, and only print `env' for the latter. */
1563 fputs ("JNIEnv *env", stream);
1565 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1567 if (*str != ')')
1568 fputs (", ", stream);
1571 while (str < limit && *str != ')')
1573 next = decode_signature_piece (stream, str, limit, &need_space);
1574 if (! next)
1576 error ("unparseable signature: '%s'", str0);
1577 return;
1580 if (next < limit && *next != ')')
1581 fputs (", ", stream);
1582 str = next;
1585 fputs (")", stream);
1589 /* This is a helper for print_stub_or_jni. */
1590 static void
1591 print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1592 int signature_index, int is_init,
1593 const char *name_override, int flags)
1595 const char *const prefix = flag_jni ? "Java_" : "";
1596 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
1597 fputs (flag_jni ? "_" : "::", stream);
1598 print_full_cxx_name (stream, jcf, name_index,
1599 signature_index, is_init, name_override,
1600 flags);
1603 static void
1604 print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1605 int signature_index, int is_init,
1606 const char *name_override, int flags)
1608 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1610 fprintf (stream, "<not a UTF8 constant>");
1611 found_error = 1;
1613 else
1615 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
1616 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
1617 const unsigned char *str = str0;
1618 const unsigned char *limit = str + length;
1619 int need_space = 0;
1620 int is_method = str[0] == '(';
1621 const unsigned char *next;
1623 /* Don't print fields in the JNI case. */
1624 if (! is_method && flag_jni)
1625 return;
1627 if (flag_jni && ! stubs)
1628 fputs ("JNIEXPORT ", stream);
1630 /* If printing a method, skip to the return signature and print
1631 that first. However, there is no return value if this is a
1632 constructor. */
1633 if (is_method && ! is_init)
1635 while (str < limit)
1637 int ch = *str++;
1638 if (ch == ')')
1639 break;
1643 /* If printing a field or an ordinary method, then print the
1644 "return value" now. Note that a constructor can't be native,
1645 so we don't bother checking this in the JNI case. */
1646 if (! is_method || ! is_init)
1648 next = decode_signature_piece (stream, str, limit, &need_space);
1649 if (! next)
1651 error ("unparseable signature: '%s'", str0);
1652 return;
1656 /* When printing a JNI header we need to respect the space. In
1657 other cases we're just going to insert a newline anyway. */
1658 fputs (need_space && ! stubs ? " " : "\n", stream);
1660 if (flag_jni && ! stubs)
1661 fputs ("JNICALL ", stream);
1663 /* Now print the name of the thing. */
1664 print_name_for_stub_or_jni (stream, jcf, name_index,
1665 signature_index, is_init, name_override,
1666 flags);
1668 /* Print the body. */
1669 if (stubs)
1671 if (flag_jni)
1672 fputs ("\n{\n (*env)->FatalError (env, \"", stream);
1673 else
1674 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
1675 print_name_for_stub_or_jni (stream, jcf, name_index,
1676 signature_index, is_init,
1677 name_override,
1678 flags);
1679 fprintf (stream, " not implemented\")%s;\n}\n\n",
1680 flag_jni ? "" : ")");
1685 static void
1686 print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
1688 int name_index = JPOOL_USHORT1 (jcf, index);
1689 fputs (prefix, stream);
1690 jcf_print_utf8_replace (out,
1691 JPOOL_UTF_DATA (jcf, name_index),
1692 JPOOL_UTF_LENGTH (jcf, name_index),
1693 '/', '_');
1696 /* Print PREFIX, then a class name in C++ format. If the name refers
1697 to an array, ignore it and don't print PREFIX. Returns 1 if
1698 something was printed, 0 otherwise. */
1699 static int
1700 print_cxx_classname (FILE *stream, const char *prefix,
1701 JCF *jcf, int index, int add_scope)
1703 int name_index = JPOOL_USHORT1 (jcf, index);
1704 int len, c;
1705 const unsigned char *s, *p, *limit;
1707 s = JPOOL_UTF_DATA (jcf, name_index);
1708 len = JPOOL_UTF_LENGTH (jcf, name_index);
1709 limit = s + len;
1711 /* Explicitly omit arrays here. */
1712 p = s;
1713 c = UTF8_GET (p, limit);
1714 if (c == '[')
1715 return 0;
1717 fputs (prefix, stream);
1719 /* Print a leading "::" so we look in the right namespace. */
1720 if (! flag_jni && ! stubs && add_scope)
1721 fputs ("::", stream);
1723 while (s < limit)
1725 c = UTF8_GET (s, limit);
1726 if (c == '/')
1727 fputs (flag_jni ? "_" : "::", stream);
1728 else
1729 jni_print_char (stream, c);
1732 return 1;
1735 int written_class_count = 0;
1737 /* Return name of superclass. If LEN is not NULL, fill it with length
1738 of name. */
1739 static const unsigned char *
1740 super_class_name (JCF *derived_jcf, int *len)
1742 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1743 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1744 const unsigned char *supername =
1745 JPOOL_UTF_DATA (derived_jcf, supername_index);
1747 if (len)
1748 *len = supername_length;
1750 return supername;
1753 static void
1754 handle_inner_classes (int count)
1756 int i;
1758 if (out && ! flag_jni && ! stubs && count > 0)
1759 fprintf (out, "\n");
1761 for (i = 0; i < count; ++i)
1763 JCF_u2 inner_info_index = JCF_readu2 (current_jcf);
1765 /* There are a few more values here, but we don't care about
1766 them. The (void) cast is apparently the only way to avoid a
1767 warning here. */
1768 (void) JCF_readu2 (current_jcf);
1769 (void) JCF_readu2 (current_jcf);
1770 (void) JCF_readu2 (current_jcf);
1772 if (out && ! flag_jni && ! stubs)
1774 print_mangled_classname (out, current_jcf, " friend class ",
1775 inner_info_index);
1776 fprintf (out, ";\n");
1783 /* We keep track of all the `#include's we generate, so we can avoid
1784 duplicates. */
1785 struct include
1787 char *name;
1788 struct include *next;
1791 /* List of all includes. */
1792 static struct include *all_includes = NULL;
1794 /* Generate a #include. */
1795 static void
1796 print_include (FILE *out, const unsigned char *utf8, int len)
1798 struct include *incl;
1800 if (! out)
1801 return;
1803 if (len == -1)
1804 len = strlen ((const char *) utf8);
1806 for (incl = all_includes; incl; incl = incl->next)
1808 /* We check the length because we might have a proper prefix. */
1809 if (len == (int) strlen (incl->name)
1810 && ! strncmp (incl->name, (const char *) utf8, len))
1811 return;
1814 incl = xmalloc (sizeof (struct include));
1815 incl->name = xmalloc (len + 1);
1816 strncpy (incl->name, (const char *) utf8, len);
1817 incl->name[len] = '\0';
1818 incl->next = all_includes;
1819 all_includes = incl;
1821 fputs ("#include <", out);
1822 jcf_print_utf8_replace (out, utf8, len,
1823 '/',
1824 flag_jni ? '_' : '/');
1825 fputs (".h>\n", out);
1830 /* This is used to represent part of a package or class name. */
1831 struct namelet
1833 /* The text of this part of the name. */
1834 char *name;
1835 /* True if this represents a class. */
1836 int is_class;
1837 /* Linked list of all classes and packages inside this one. */
1838 struct namelet *subnamelets;
1839 /* Pointer to next sibling. */
1840 struct namelet *next;
1843 static void add_namelet (const unsigned char *, const unsigned char *,
1844 struct namelet *);
1845 static void print_namelet (FILE *, struct namelet *, int);
1847 /* The special root namelet. */
1848 static struct namelet root =
1850 NULL,
1852 NULL,
1853 NULL
1856 /* This extracts the next name segment from the full UTF-8 encoded
1857 package or class name and links it into the tree. It does this
1858 recursively. */
1859 static void
1860 add_namelet (const unsigned char *name, const unsigned char *name_limit,
1861 struct namelet *parent)
1863 const unsigned char *p;
1864 struct namelet *n = NULL, *np;
1866 /* We want to skip the standard namespaces that we assume the
1867 runtime already knows about. We only do this at the top level,
1868 though, hence the check for `root'. */
1869 if (parent == &root)
1871 #define JAVALANG "java/lang/"
1872 #define JAVAIO "java/io/"
1873 #define JAVAUTIL "java/util/"
1874 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1875 && ! strncmp ((const char *) name, JAVALANG, sizeof (JAVALANG) - 1))
1876 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1877 && ! strncmp ((const char *) name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1878 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1879 && ! strncmp ((const char *) name, JAVAIO, sizeof (JAVAIO) - 1)))
1880 return;
1883 for (p = name; p < name_limit && *p != '/'; ++p)
1886 /* Search for this name beneath the PARENT node. */
1887 for (np = parent->subnamelets; np != NULL; np = np->next)
1889 /* We check the length because we might have a proper prefix. */
1890 if ((int) strlen (np->name) == p - name &&
1891 ! strncmp ((const char *) name, np->name, p - name))
1893 n = np;
1894 break;
1898 if (n == NULL)
1900 n = xmalloc (sizeof (struct namelet));
1901 n->name = xmalloc (p - name + 1);
1902 strncpy (n->name, (const char *) name, p - name);
1903 n->name[p - name] = '\0';
1904 n->is_class = (p == name_limit);
1905 n->subnamelets = NULL;
1906 n->next = parent->subnamelets;
1907 parent->subnamelets = n;
1910 /* We recurse if there is more text, and if the trailing piece does
1911 not represent an inner class. */
1912 if (p < name_limit)
1913 add_namelet (p + 1, name_limit, n);
1916 /* Print a single namelet. Destroys namelets while printing. */
1917 static void
1918 print_namelet (FILE *out, struct namelet *name, int depth)
1920 int i, term = 0;
1921 struct namelet *c;
1923 if (name->name)
1925 for (i = 0; i < depth; ++i)
1926 fputc (' ', out);
1927 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1928 name->name);
1929 if (name->is_class && name->subnamelets == NULL)
1930 fputs (";\n", out);
1931 else
1933 term = 1;
1934 fputs ("\n", out);
1935 for (i = 0; i < depth; ++i)
1936 fputc (' ', out);
1937 fputs ("{\n", out);
1941 c = name->subnamelets;
1942 while (c != NULL)
1944 struct namelet *next = c->next;
1945 print_namelet (out, c, depth + 2);
1946 c = next;
1948 name->subnamelets = NULL;
1950 if (name->name)
1952 if (term)
1954 for (i = 0; i < depth; ++i)
1955 fputc (' ', out);
1956 fputs ("}\n", out);
1957 /* Only print a `;' when printing a class. C++ is evil. */
1958 if (name->is_class)
1959 fputs (";", out);
1962 free (name->name);
1963 free (name);
1967 /* This is called to add some classes to the list of classes for which
1968 we need decls. The signature argument can be a function
1969 signature. */
1970 static void
1971 add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
1973 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1974 int len = JPOOL_UTF_LENGTH (jcf, signature);
1975 int i;
1977 for (i = 0; i < len; ++i)
1979 int start;
1981 /* If we see an array, then we include the array header. */
1982 if (s[i] == '[')
1984 print_include (out, (const unsigned char *) "gcj/array", -1);
1985 continue;
1988 /* We're looking for `L<stuff>;' -- everything else is
1989 ignorable. */
1990 if (s[i] != 'L')
1991 continue;
1993 for (start = ++i; i < len && s[i] != ';'; ++i)
1996 add_namelet (&s[start], &s[i], &root);
2000 /* Print declarations for all classes required by this class. Any
2001 class or package in the `java' package is assumed to be handled
2002 statically in libjava; we don't generate declarations for these.
2003 This makes the generated headers a bit easier to read. */
2004 static void
2005 print_class_decls (FILE *out, JCF *jcf, int self)
2007 /* Make sure to always add the current class to the list of things
2008 that should be declared. */
2009 int name_index = JPOOL_USHORT1 (jcf, self);
2010 int len;
2011 const unsigned char *s;
2013 s = JPOOL_UTF_DATA (jcf, name_index);
2014 len = JPOOL_UTF_LENGTH (jcf, name_index);
2015 add_namelet (s, s + len, &root);
2017 if (root.subnamelets)
2019 fputs ("extern \"Java\"\n{\n", out);
2020 /* We use an initial offset of 0 because the root namelet
2021 doesn't cause anything to print. */
2022 print_namelet (out, &root, 0);
2023 fputs ("}\n\n", out);
2029 static void
2030 process_file (JCF *jcf, FILE *out)
2032 int code, i;
2033 uint32 field_start, method_end, method_start;
2035 current_jcf = jcf;
2037 last_access = -1;
2039 if (jcf_parse_preamble (jcf) != 0)
2041 error ("Not a valid Java .class file.");
2042 return;
2045 /* Parse and possibly print constant pool */
2046 code = jcf_parse_constant_pool (jcf);
2047 if (code != 0)
2049 error ("error while parsing constant pool");
2050 return;
2052 code = verify_constant_pool (jcf);
2053 if (code > 0)
2055 error ("error in constant pool entry #%d", code);
2056 return;
2059 jcf_parse_class (jcf);
2061 if (written_class_count++ == 0 && out)
2063 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
2064 if (flag_jni)
2066 cstart = "/*";
2067 cstart2 = " ";
2068 cend = " */";
2069 mode = "";
2070 what = "JNI";
2071 jflag = " -jni";
2073 else
2075 cstart = "//";
2076 cstart2 = "//";
2077 cend = "";
2078 mode = " -*- c++ -*-";
2079 what = "CNI";
2080 jflag = "";
2083 if (! stubs)
2084 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2085 cstart, mode, cend);
2086 else
2088 fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\
2089 %s\n\
2090 %s This file is intended to give you a head start on implementing native\n\
2091 %s methods using %s.\n\
2092 %s Be aware: running `gcjh -stubs %s' once more for this class may\n\
2093 %s overwrite any edits you have made to this file.%s\n\n",
2094 cstart, jflag, mode,
2095 cstart2,
2096 cstart2,
2097 cstart2,
2098 what,
2099 cstart2,
2100 jflag,
2101 cstart2,
2102 cend);
2106 if (out)
2108 if (! stubs)
2110 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2111 fprintf (out, "__\n");
2113 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2114 fprintf (out, "__\n\n");
2116 if (flag_jni)
2118 fprintf (out, "#include <jni.h>\n\n");
2119 fprintf (out, "#ifdef __cplusplus\n");
2120 fprintf (out, "extern \"C\"\n");
2121 fprintf (out, "{\n");
2122 fprintf (out, "#endif\n");
2124 else
2126 /* We do this to ensure that inline methods won't be
2127 `outlined' by g++. This works as long as method and
2128 fields are not added by the user. */
2129 fprintf (out, "#pragma interface\n");
2131 if (jcf->super_class)
2133 int super_length;
2134 const unsigned char *supername =
2135 super_class_name (jcf, &super_length);
2137 fputs ("\n", out);
2138 print_include (out, supername, super_length);
2142 else
2144 /* Strip off the ".class" portion of the name when printing
2145 the include file name. */
2146 char *name;
2147 int i, len = strlen (jcf->classname);
2148 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2149 len -= 6;
2150 /* Turn the class name into a file name. */
2151 name = xmalloc (len + 1);
2152 for (i = 0; i < len; ++i)
2153 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2154 name[i] = '\0';
2155 print_include (out, (const unsigned char *) name, len);
2156 free (name);
2158 if (! flag_jni)
2160 print_include (out, (const unsigned char *) "gcj/cni", -1);
2161 print_include (out, (const unsigned char *) "java/lang/UnsupportedOperationException",
2162 -1);
2167 /* We want to parse the methods first. But we need to find where
2168 they start. So first we skip the fields, then parse the methods.
2169 Then we parse the fields and skip the methods. This is ugly, but
2170 not too bad since we need two full passes to get class decl
2171 information anyway. */
2172 field_pass = 0;
2173 field_start = JCF_TELL (jcf);
2174 jcf_parse_fields (jcf);
2176 method_start = JCF_TELL (jcf);
2177 method_pass = 0;
2178 jcf_parse_methods (jcf);
2180 if (out)
2181 fputs ("\n", out);
2183 if (out && ! flag_jni)
2185 if (! stubs)
2186 print_class_decls (out, jcf, jcf->this_class);
2188 for (i = 0; i < prepend_count; ++i)
2189 fprintf (out, "%s\n", prepend_specs[i]);
2190 if (prepend_count > 0)
2191 fputc ('\n', out);
2193 if (! stubs)
2195 if (! print_cxx_classname (out, "class ", jcf,
2196 jcf->this_class, 0))
2198 error ("class is of array type\n");
2199 return;
2201 if (jcf->super_class)
2203 if (! print_cxx_classname (out, " : public ",
2204 jcf, jcf->super_class, 1))
2206 error ("base class is of array type");
2207 return;
2211 fputs ("\n{\n", out);
2215 /* Now go back for second pass over methods and fields. */
2216 is_first_data_member = 1;
2218 JCF_SEEK (jcf, method_start);
2219 method_pass = 1;
2220 jcf_parse_methods (jcf);
2221 method_end = JCF_TELL (jcf);
2223 field_pass = 1;
2224 JCF_SEEK (jcf, field_start);
2225 jcf_parse_fields (jcf);
2226 JCF_SEEK (jcf, method_end);
2228 jcf_parse_final_attributes (jcf);
2230 if (out && ! stubs)
2232 if (flag_jni)
2234 fprintf (out, "\n#ifdef __cplusplus\n");
2235 fprintf (out, "}\n");
2236 fprintf (out, "#endif\n");
2238 else
2240 /* Generate friend decl if we still must. */
2241 for (i = 0; i < friend_count; ++i)
2242 fprintf (out, " friend %s\n", friend_specs[i]);
2244 /* Generate extra declarations. */
2245 if (add_count > 0)
2246 fputc ('\n', out);
2247 for (i = 0; i < add_count; ++i)
2248 fprintf (out, " %s\n", add_specs[i]);
2250 /* Generate an entry for the class object. */
2251 generate_access (out, ACC_PUBLIC);
2252 fprintf (out, "\n static ::java::lang::Class class$;\n");
2254 fputs ("}", out);
2256 if (jcf->access_flags & ACC_INTERFACE)
2257 fputs (" __attribute__ ((java_interface))", out);
2259 fputs (";\n", out);
2261 if (append_count > 0)
2262 fputc ('\n', out);
2263 for (i = 0; i < append_count; ++i)
2264 fprintf (out, "%s\n", append_specs[i]);
2267 print_mangled_classname (out, jcf,
2268 "\n#endif /* __", jcf->this_class);
2269 fprintf (out, "__ */\n");
2275 /* This is used to mark options with no short value. */
2276 #define LONG_OPT(Num) ((Num) + 128)
2278 #define OPT_classpath LONG_OPT (0)
2279 #define OPT_CLASSPATH OPT_classpath
2280 #define OPT_bootclasspath LONG_OPT (1)
2281 #define OPT_extdirs LONG_OPT (2)
2282 #define OPT_HELP LONG_OPT (3)
2283 #define OPT_TEMP LONG_OPT (4)
2284 #define OPT_VERSION LONG_OPT (5)
2285 #define OPT_PREPEND LONG_OPT (6)
2286 #define OPT_FRIEND LONG_OPT (7)
2287 #define OPT_ADD LONG_OPT (8)
2288 #define OPT_APPEND LONG_OPT (9)
2289 #define OPT_M LONG_OPT (10)
2290 #define OPT_MM LONG_OPT (11)
2291 #define OPT_MG LONG_OPT (12)
2292 #define OPT_MD LONG_OPT (13)
2293 #define OPT_MMD LONG_OPT (14)
2295 static const struct option options[] =
2297 { "classpath", required_argument, NULL, OPT_classpath },
2298 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
2299 { "extdirs", required_argument, NULL, OPT_extdirs },
2300 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2301 { "help", no_argument, NULL, OPT_HELP },
2302 { "stubs", no_argument, &stubs, 1 },
2303 { "td", required_argument, NULL, OPT_TEMP },
2304 { "verbose", no_argument, NULL, 'v' },
2305 { "version", no_argument, NULL, OPT_VERSION },
2306 { "prepend", required_argument, NULL, OPT_PREPEND },
2307 { "friend", required_argument, NULL, OPT_FRIEND },
2308 { "add", required_argument, NULL, OPT_ADD },
2309 { "append", required_argument, NULL, OPT_APPEND },
2310 { "M", no_argument, NULL, OPT_M },
2311 { "MM", no_argument, NULL, OPT_MM },
2312 { "MG", no_argument, NULL, OPT_MG },
2313 { "MD", no_argument, NULL, OPT_MD },
2314 { "MMD", no_argument, NULL, OPT_MMD },
2315 { "jni", no_argument, &flag_jni, 1 },
2316 { NULL, no_argument, NULL, 0 }
2319 static void
2320 usage (void)
2322 fprintf (stderr, _("Try 'gcjh --help' for more information.\n"));
2323 exit (1);
2326 static void
2327 help (void)
2329 printf (_("Usage: gcjh [OPTION]... CLASS...\n\n"));
2330 printf (_("Generate C++ header files from .class files\n\n"));
2331 printf (_(" -stubs Generate an implementation stub file\n"));
2332 printf (_(" -jni Generate a JNI header or stub\n"));
2333 printf ("\n");
2334 printf (_(" -add TEXT Insert TEXT into class body\n"));
2335 printf (_(" -append TEXT Insert TEXT after class declaration\n"));
2336 printf (_(" -friend TEXT Insert TEXT as 'friend' declaration\n"));
2337 printf (_(" -prepend TEXT Insert TEXT before start of class\n"));
2338 printf ("\n");
2339 printf (_(" --classpath PATH Set path to find .class files\n"));
2340 printf (_(" -IDIR Append directory to class path\n"));
2341 printf (_(" --bootclasspath PATH Override built-in class path\n"));
2342 printf (_(" --extdirs PATH Set extensions directory path\n"));
2343 printf (_(" -d DIRECTORY Set output directory name\n"));
2344 printf (_(" -o FILE Set output file name\n"));
2345 printf (_(" -td DIRECTORY Set temporary directory name\n"));
2346 printf ("\n");
2347 printf (_(" --help Print this help, then exit\n"));
2348 printf (_(" --version Print version number, then exit\n"));
2349 printf (_(" -v, --verbose Print extra information while running\n"));
2350 printf ("\n");
2351 printf (_(" -M Print all dependencies to stdout;\n"
2352 " suppress ordinary output\n"));
2353 printf (_(" -MM Print non-system dependencies to stdout;\n"
2354 " suppress ordinary output\n"));
2355 printf (_(" -MD Print all dependencies to stdout\n"));
2356 printf (_(" -MMD Print non-system dependencies to stdout\n"));
2357 /* We omit -MG until it is implemented. */
2358 printf ("\n");
2359 printf (_("For bug reporting instructions, please see:\n"
2360 "%s.\n"), bug_report_url);
2361 exit (0);
2364 static void
2365 version (void)
2367 printf ("gcjh (GCC) %s\n\n", version_string);
2368 printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", _("(C)"));
2369 printf (_("This is free software; see the source for copying conditions. There is NO\n"
2370 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
2371 exit (0);
2375 main (int argc, char** argv)
2377 JCF jcf;
2378 int argi;
2379 char *output_file = NULL;
2380 int emit_dependencies = 0, suppress_output = 0;
2381 int opt;
2383 gcc_init_libintl ();
2385 if (argc <= 1)
2387 error ("no classes specified");
2388 usage ();
2391 jcf_path_init ();
2393 /* We use getopt_long_only to allow single `-' long options. For
2394 some of our options this is more natural. */
2395 while ((opt = getopt_long_only (argc, argv, "I:d:o:v", options, NULL)) != -1)
2397 switch (opt)
2399 case 0:
2400 /* Already handled. */
2401 break;
2403 case 'o':
2404 output_file = optarg;
2405 break;
2407 case 'd':
2408 output_directory = optarg;
2409 break;
2411 case 'I':
2412 jcf_path_include_arg (optarg);
2413 break;
2415 case 'v':
2416 verbose++;
2417 break;
2419 case OPT_classpath:
2420 jcf_path_classpath_arg (optarg);
2421 break;
2423 case OPT_bootclasspath:
2424 jcf_path_bootclasspath_arg (optarg);
2425 break;
2427 case OPT_extdirs:
2428 jcf_path_extdirs_arg (optarg);
2429 break;
2431 case OPT_HELP:
2432 help ();
2433 break;
2435 case OPT_TEMP:
2436 temp_directory = optarg;
2437 break;
2439 case OPT_VERSION:
2440 version ();
2441 break;
2443 case OPT_PREPEND:
2444 if (prepend_count == 0)
2445 prepend_specs = ALLOC (argc * sizeof (char*));
2446 prepend_specs[prepend_count++] = optarg;
2447 break;
2449 case OPT_FRIEND:
2450 if (friend_count == 0)
2451 friend_specs = ALLOC (argc * sizeof (char*));
2452 friend_specs[friend_count++] = optarg;
2453 break;
2455 case OPT_ADD:
2456 if (add_count == 0)
2457 add_specs = ALLOC (argc * sizeof (char*));
2458 add_specs[add_count++] = optarg;
2459 break;
2461 case OPT_APPEND:
2462 if (append_count == 0)
2463 append_specs = ALLOC (argc * sizeof (char*));
2464 append_specs[append_count++] = optarg;
2465 break;
2467 case OPT_M:
2468 emit_dependencies = 1;
2469 suppress_output = 1;
2470 jcf_dependency_init (1);
2471 break;
2473 case OPT_MM:
2474 emit_dependencies = 1;
2475 suppress_output = 1;
2476 jcf_dependency_init (0);
2477 break;
2479 case OPT_MG:
2480 error ("'-MG' option is unimplemented");
2481 exit (1);
2483 case OPT_MD:
2484 emit_dependencies = 1;
2485 jcf_dependency_init (1);
2486 break;
2488 case OPT_MMD:
2489 emit_dependencies = 1;
2490 jcf_dependency_init (0);
2491 break;
2493 default:
2494 usage ();
2495 break;
2499 if (optind == argc)
2501 error ("no classes specified");
2502 usage ();
2505 jcf_path_seal (verbose);
2507 if (output_file && emit_dependencies)
2509 error ("can't specify both -o and -MD");
2510 exit (1);
2513 for (argi = optind; argi < argc; argi++)
2515 char *classname = argv[argi];
2516 char *current_output_file;
2517 const char *classfile_name;
2519 if (verbose)
2520 printf (_("Processing %s\n"), classname);
2521 if (! output_file)
2522 jcf_dependency_reset ();
2523 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
2524 if (classfile_name == NULL)
2526 error ("%s: no such class", classname);
2527 exit (1);
2529 if (verbose)
2530 printf (_("Found in %s\n"), classfile_name);
2531 if (output_file)
2533 if (strcmp (output_file, "-") == 0)
2534 out = stdout;
2535 else if (out == NULL)
2537 out = fopen (output_file, "w");
2539 if (out == NULL)
2541 perror (output_file);
2542 exit (1);
2544 current_output_file = output_file;
2546 else
2548 int dir_len = strlen (output_directory);
2549 int i, classname_length = strlen (classname);
2550 current_output_file = ALLOC (dir_len + classname_length + 5);
2551 strcpy (current_output_file, output_directory);
2552 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2553 current_output_file[dir_len++] = '/';
2554 for (i = 0; classname[i] != '\0'; i++)
2556 char ch = classname[i];
2557 if (ch == '.')
2558 ch = '/';
2559 if (flag_jni && ch == '/')
2560 ch = '_';
2561 current_output_file[dir_len++] = ch;
2563 if (emit_dependencies)
2565 if (suppress_output)
2567 jcf_dependency_set_dep_file ("-");
2568 out = NULL;
2570 else
2572 /* We use `.hd' and not `.d' to avoid clashes with
2573 dependency tracking from straight compilation. */
2574 strcpy (current_output_file + dir_len, ".hd");
2575 jcf_dependency_set_dep_file (current_output_file);
2578 strcpy (current_output_file + dir_len,
2579 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
2580 jcf_dependency_set_target (current_output_file);
2581 if (! suppress_output)
2583 out = fopen (current_output_file, "w");
2584 if (out == NULL)
2586 perror (current_output_file);
2587 exit (1);
2591 free_method_name_list ();
2592 process_file (&jcf, out);
2593 JCF_FINISH (&jcf);
2594 if (current_output_file != output_file)
2595 free (current_output_file);
2596 jcf_dependency_write ();
2599 if (out != NULL && out != stdout)
2600 fclose (out);
2602 return found_error;