* ggc-common.c (ggc_print_statistics): Make arguments to fprintf
[official-gcc.git] / gcc / java / gjavah.c
bloba29cb62b87a5ebe6bb9c5762d41c073eba9ea3db
1 /* Program to write C++-suitable header files from a Java(TM) .class
2 file. This is similar to SUN's javah.
4 Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
27 #include "config.h"
28 #include "system.h"
29 #include <math.h>
31 #include "jcf.h"
32 #include "tree.h"
33 #include "java-tree.h"
34 #include "java-opcodes.h"
36 #include "version.c"
38 /* The output file. */
39 FILE *out = NULL;
41 /* Nonzero on failure. */
42 static int found_error = 0;
44 /* Directory to place resulting files in. Set by -d option. */
45 const char *output_directory = "";
47 /* Directory to place temporary file. Set by -td option. Currently unused. */
48 const char *temp_directory = "/tmp";
50 /* Number of friend functions we have to declare. */
51 static int friend_count;
53 /* A class can optionally have a `friend' function declared. If
54 non-NULL, this is that function. */
55 static char **friend_specs = NULL;
57 /* Number of lines we are prepending before the class. */
58 static int prepend_count;
60 /* We can prepend extra lines before the class's start. */
61 static char **prepend_specs = NULL;
63 /* Number of lines we are appending at the end of the class. */
64 static int add_count;
66 /* We can append extra lines just before the class's end. */
67 static char **add_specs = NULL;
69 /* Number of lines we are appending after the class. */
70 static int append_count;
72 /* We can append extra lines after the class's end. */
73 static char **append_specs = NULL;
75 int verbose = 0;
77 int stubs = 0;
79 struct JCF *current_jcf;
81 /* This holds access information for the last field we examined. They
82 let us generate "private:", "public:", and "protected:" properly.
83 If 0 then we haven't previously examined any field. */
84 static JCF_u2 last_access;
86 #define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
88 /* Pass this macro the flags for a class and for a method. It will
89 return true if the method should be considered `final'. */
90 #define METHOD_IS_FINAL(Class, Method) \
91 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
93 /* Pass this macro the flags for a method. It will return true if the
94 method is native. */
95 #define METHOD_IS_NATIVE(Method) \
96 ((Method) & ACC_NATIVE)
98 /* We keep a linked list of all method names we have seen. This lets
99 us determine if a method name and a field name are in conflict. */
100 struct method_name
102 unsigned char *name;
103 int length;
104 struct method_name *next;
107 /* List of method names we've seen. */
108 static struct method_name *method_name_list;
110 static void print_field_info PROTO ((FILE*, JCF*, int, int, JCF_u2));
111 static void print_mangled_classname PROTO ((FILE*, JCF*, const char*, int));
112 static int print_cxx_classname PROTO ((FILE*, const char*, JCF*, int));
113 static void print_method_info PROTO ((FILE*, JCF*, int, int, JCF_u2));
114 static void print_c_decl PROTO ((FILE*, JCF*, int, int, int, const char *));
115 static void print_stub PROTO ((FILE*, JCF*, int, int, int, const char *));
116 static void print_full_cxx_name PROTO ((FILE*, JCF*, int, int, int, const char *));
117 static void decompile_method PROTO ((FILE*, JCF*, int));
118 static void add_class_decl PROTO ((FILE*, JCF*, JCF_u2));
120 static int java_float_finite PROTO ((jfloat));
121 static int java_double_finite PROTO ((jdouble));
122 static void print_name PROTO ((FILE *, JCF *, int));
123 static void print_base_classname PROTO ((FILE *, JCF *, int));
124 static int utf8_cmp PROTO ((const unsigned char *, int, const char *));
125 static const char *cxx_keyword_subst PROTO ((const unsigned char *, int));
126 static void generate_access PROTO ((FILE *, JCF_u2));
127 static int name_is_method_p PROTO ((const unsigned char *, int));
128 static char *get_field_name PROTO ((JCF *, int, JCF_u2));
129 static void print_field_name PROTO ((FILE *, JCF *, int, JCF_u2));
130 static const unsigned char *super_class_name PROTO ((JCF *, int *));
131 static void print_include PROTO ((FILE *, const unsigned char *, int));
132 static const unsigned char *decode_signature_piece
133 PROTO ((FILE *, const unsigned char *, const unsigned char *, int *));
134 static void print_class_decls PROTO ((FILE *, JCF *, int));
135 static void usage PROTO ((void)) ATTRIBUTE_NORETURN;
136 static void help PROTO ((void)) ATTRIBUTE_NORETURN;
137 static void java_no_argument PROTO ((const char *)) ATTRIBUTE_NORETURN;
138 static void version PROTO ((void)) ATTRIBUTE_NORETURN;
140 JCF_u2 current_field_name;
141 JCF_u2 current_field_value;
142 JCF_u2 current_field_signature;
143 JCF_u2 current_field_flags;
145 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
146 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
147 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
149 /* We pass over fields twice. The first time we just note the types
150 of the fields and then the start of the methods. Then we go back
151 and parse the fields for real. This is ugly. */
152 static int field_pass;
153 /* Likewise we pass over methods twice. The first time we generate
154 class decl information; the second time we generate actual method
155 decls. */
156 static int method_pass;
158 #define HANDLE_END_FIELD() \
159 if (field_pass) \
161 if (out && ! stubs) \
162 print_field_info (out, jcf, current_field_name, \
163 current_field_signature, \
164 current_field_flags); \
166 else \
167 if (! stubs) add_class_decl (out, jcf, current_field_signature);
169 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
171 static int method_declared = 0;
172 static int method_access = 0;
173 static int method_printed = 0;
174 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
175 if (method_pass) \
177 decompiled = 0; method_printed = 0; \
178 if (out) \
179 print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
181 else \
182 if (! stubs) add_class_decl (out, jcf, SIGNATURE);
184 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
185 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
187 static int decompiled = 0;
188 #define HANDLE_END_METHOD() \
189 if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out);
191 #include "jcf-reader.c"
193 /* Some useful constants. */
194 #define F_NAN_MASK 0x7f800000
195 #define D_NAN_MASK 0x7ff0000000000000LL
197 /* Return 1 if F is not Inf or NaN. */
198 static int
199 java_float_finite (f)
200 jfloat f;
202 union {
203 jfloat f;
204 int32 i;
205 } u;
206 u.f = f;
208 /* We happen to know that F_NAN_MASK will match all NaN values, and
209 also positive and negative infinity. That's why we only need one
210 test here. See The Java Language Specification, section 20.9. */
211 return (u.i & F_NAN_MASK) != F_NAN_MASK;
214 /* Return 1 if D is not Inf or NaN. */
215 static int
216 java_double_finite (d)
217 jdouble d;
219 union {
220 jdouble d;
221 int64 i;
222 } u;
223 u.d = d;
225 /* Now check for all NaNs. */
226 return (u.i & D_NAN_MASK) != D_NAN_MASK;
229 static void
230 DEFUN(print_name, (stream, jcf, name_index),
231 FILE* stream AND JCF* jcf AND int name_index)
233 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
234 fprintf (stream, "<not a UTF8 constant>");
235 else
236 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
237 JPOOL_UTF_LENGTH (jcf, name_index));
240 /* Print base name of class. The base name is everything after the
241 final separator. */
243 static void
244 print_base_classname (stream, jcf, index)
245 FILE *stream;
246 JCF *jcf;
247 int index;
249 int name_index = JPOOL_USHORT1 (jcf, index);
250 int len;
251 const unsigned char *s, *p, *limit;
253 s = JPOOL_UTF_DATA (jcf, name_index);
254 len = JPOOL_UTF_LENGTH (jcf, name_index);
255 limit = s + len;
256 p = s;
257 while (s < limit)
259 int c = UTF8_GET (s, limit);
260 if (c == '/')
261 p = s;
264 while (p < limit)
266 int ch = UTF8_GET (p, limit);
267 if (ch == '/')
268 fputs ("::", stream);
269 else
270 jcf_print_char (stream, ch);
274 /* Return 0 if NAME is equal to STR, nonzero otherwise. */
276 static int
277 utf8_cmp (str, length, name)
278 const unsigned char *str;
279 int length;
280 const char *name;
282 const unsigned char *limit = str + length;
283 int i;
285 for (i = 0; name[i]; ++i)
287 int ch = UTF8_GET (str, limit);
288 if (ch != name[i])
289 return 1;
292 return str != limit;
295 /* If NAME is the name of a C++ keyword, then return an override name.
296 This is a name that can be used in place of the keyword.
297 Otherwise, return NULL. FIXME: for now, we only handle those
298 keywords we know to be a problem for libgcj. */
300 static const char *
301 cxx_keyword_subst (str, length)
302 const unsigned char *str;
303 int length;
305 if (! utf8_cmp (str, length, "delete"))
306 return "__dummy_delete";
307 else if (! utf8_cmp (str, length, "enum"))
308 return "__dummy_enum";
309 return NULL;
312 /* Generate an access control keyword based on FLAGS. Returns 0 if
313 FLAGS matches the saved access information, nonzero otherwise. */
315 static void
316 generate_access (stream, flags)
317 FILE *stream;
318 JCF_u2 flags;
320 if ((flags & ACC_VISIBILITY) == last_access)
321 return;
322 last_access = (flags & ACC_VISIBILITY);
324 switch (last_access)
326 case 0:
327 fputs ("public: // actually package-private\n", stream);
328 break;
329 case ACC_PUBLIC:
330 fputs ("public:\n", stream);
331 break;
332 case ACC_PRIVATE:
333 fputs ("private:\n", stream);
334 break;
335 case ACC_PROTECTED:
336 fputs ("public: // actually protected\n", stream);
337 break;
338 default:
339 found_error = 1;
340 fprintf (stream, "#error unrecognized visibility %d\n",
341 (flags & ACC_VISIBILITY));
342 break;
346 /* See if NAME is already the name of a method. */
347 static int
348 name_is_method_p (name, length)
349 const unsigned char *name;
350 int length;
352 struct method_name *p;
354 for (p = method_name_list; p != NULL; p = p->next)
356 if (p->length == length && ! memcmp (p->name, name, length))
357 return 1;
359 return 0;
362 /* Get name of a field. This handles renamings due to C++ clash. */
363 static char *
364 get_field_name (jcf, name_index, flags)
365 JCF *jcf;
366 int name_index;
367 JCF_u2 flags;
369 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
370 int length = JPOOL_UTF_LENGTH (jcf, name_index);
371 char *override;
372 const char *tmpconstptr;
375 if (name_is_method_p (name, length))
377 /* This field name matches a method. So override the name with
378 a dummy name. This is yucky, but it isn't clear what else to
379 do. FIXME: if the field is static, then we'll be in real
380 trouble. */
381 if ((flags & ACC_STATIC))
383 fprintf (stderr, "static field has same name as method\n");
384 found_error = 1;
385 return NULL;
388 override = xmalloc (length + 3);
389 memcpy (override, name, length);
390 strcpy (override + length, "__");
392 else if ((tmpconstptr = cxx_keyword_subst (name, length)) != NULL)
394 /* Must malloc OVERRIDE. */
395 override = xstrdup (tmpconstptr);
397 else
398 override = NULL;
400 return override;
403 /* Print a field name. Convenience function for use with
404 get_field_name. */
405 static void
406 print_field_name (stream, jcf, name_index, flags)
407 FILE *stream;
408 JCF *jcf;
409 int name_index;
410 JCF_u2 flags;
412 char *override = get_field_name (jcf, name_index, flags);
414 if (override)
416 fputs (override, stream);
417 free (override);
419 else
420 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
421 JPOOL_UTF_LENGTH (jcf, name_index));
424 static void
425 DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
426 FILE *stream AND JCF* jcf
427 AND int name_index AND int sig_index AND JCF_u2 flags)
429 char *override = NULL;
431 generate_access (stream, flags);
432 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
434 fprintf (stream, "<not a UTF8 constant>");
435 found_error = 1;
436 return;
439 if (flags & ACC_FINAL)
441 if (current_field_value > 0)
443 char buffer[25];
444 int done = 1;
446 switch (JPOOL_TAG (jcf, current_field_value))
448 case CONSTANT_Integer:
450 jint num;
451 int most_negative = 0;
452 fputs (" static const jint ", out);
453 print_field_name (out, jcf, name_index, 0);
454 fputs (" = ", out);
455 num = JPOOL_INT (jcf, current_field_value);
456 /* We single out the most negative number to print
457 specially. This avoids later warnings from g++. */
458 if (num == (jint) 0x80000000)
460 most_negative = 1;
461 ++num;
463 format_int (buffer, (jlong) num, 10);
464 fprintf (out, "%sL%s;\n", buffer, most_negative ? " - 1" : "");
466 break;
467 case CONSTANT_Long:
469 jlong num;
470 int most_negative = 0;
471 fputs (" static const jlong ", out);
472 print_field_name (out, jcf, name_index, 0);
473 fputs (" = ", out);
474 num = JPOOL_LONG (jcf, current_field_value);
475 /* We single out the most negative number to print
476 specially.. This avoids later warnings from g++. */
477 if (num == (jlong) 0x8000000000000000LL)
479 most_negative = 1;
480 ++num;
482 format_int (buffer, num, 10);
483 fprintf (out, "%sLL%s;\n", buffer, most_negative ? " - 1" :"");
485 break;
486 case CONSTANT_Float:
488 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
489 fputs (" static const jfloat ", out);
490 print_field_name (out, jcf, name_index, 0);
491 if (! java_float_finite (fnum))
492 fputs (";\n", out);
493 else
494 fprintf (out, " = %.10g;\n", fnum);
496 break;
497 case CONSTANT_Double:
499 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
500 fputs (" static const jdouble ", out);
501 print_field_name (out, jcf, name_index, 0);
502 if (! java_double_finite (dnum))
503 fputs (";\n", out);
504 else
505 fprintf (out, " = %.17g;\n", dnum);
507 break;
508 default:
509 /* We can't print this as a constant, but we can still
510 print something sensible. */
511 done = 0;
512 break;
515 if (done)
516 return;
520 fputs (" ", out);
521 if ((flags & ACC_STATIC))
522 fputs ("static ", out);
524 override = get_field_name (jcf, name_index, flags);
525 print_c_decl (out, jcf, name_index, sig_index, 0, override);
526 fputs (";\n", out);
528 if (override)
529 free (override);
532 static void
533 DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
534 FILE *stream AND JCF* jcf
535 AND int name_index AND int sig_index AND JCF_u2 flags)
537 const unsigned char *str;
538 int length, is_init = 0;
539 const char *override = NULL;
541 method_declared = 0;
542 method_access = flags;
543 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
544 fprintf (stream, "<not a UTF8 constant>");
545 str = JPOOL_UTF_DATA (jcf, name_index);
546 length = JPOOL_UTF_LENGTH (jcf, name_index);
547 if (str[0] == '<' || str[0] == '$')
549 /* Ignore internally generated methods like <clinit> and
550 $finit$. However, treat <init> as a constructor. */
551 if (! utf8_cmp (str, length, "<init>"))
552 is_init = 1;
553 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
554 && ! (flags & ACC_STATIC))
556 /* FIXME: i18n bug here. Order of prints should not be
557 fixed. */
558 fprintf (stderr, "ignored method `");
559 jcf_print_utf8 (stderr, str, length);
560 fprintf (stderr, "' marked virtual\n");
561 found_error = 1;
562 return;
564 else
565 return;
567 else
569 struct method_name *nn;
571 nn = (struct method_name *) xmalloc (sizeof (struct method_name));
572 nn->name = (char *) xmalloc (length);
573 memcpy (nn->name, str, length);
574 nn->length = length;
575 nn->next = method_name_list;
576 method_name_list = nn;
579 /* We can't generate a method whose name is a C++ reserved word. We
580 can't just ignore the function, because that will cause incorrect
581 code to be generated if the function is virtual (not only for
582 calls to this function for for other functions after it in the
583 vtbl). So we give it a dummy name instead. */
584 override = cxx_keyword_subst (str, length);
585 if (override)
587 /* If the method is static or final, we can safely skip it. If
588 we don't skip it then we'll have problems since the mangling
589 will be wrong. FIXME. */
590 if (METHOD_IS_FINAL (jcf->access_flags, flags)
591 || (flags & ACC_STATIC))
592 return;
595 if (! stubs)
597 method_printed = 1;
599 generate_access (stream, flags);
601 fputs (" ", out);
602 if ((flags & ACC_STATIC))
603 fputs ("static ", out);
604 else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
606 /* Don't print `virtual' if we have a constructor. */
607 if (! is_init)
608 fputs ("virtual ", out);
610 print_c_decl (out, jcf, name_index, sig_index, is_init, override);
612 if ((flags & ACC_ABSTRACT))
613 fputs (" = 0", out);
614 else
615 method_declared = 1;
617 else
619 if (METHOD_IS_NATIVE(flags))
621 method_printed = 1;
622 print_stub (out, jcf, name_index, sig_index, is_init, override);
627 /* Try to decompile a method body. Right now we just try to handle a
628 simple case that we can do. Expand as desired. */
629 static void
630 decompile_method (out, jcf, code_len)
631 FILE *out;
632 JCF *jcf;
633 int code_len;
635 const unsigned char *codes = jcf->read_ptr;
636 int index;
637 uint16 name_and_type, name;
639 /* If the method is synchronized, don't touch it. */
640 if ((method_access & ACC_SYNCHRONIZED))
641 return;
643 if (code_len == 5
644 && codes[0] == OPCODE_aload_0
645 && codes[1] == OPCODE_getfield
646 && (codes[4] == OPCODE_areturn
647 || codes[4] == OPCODE_dreturn
648 || codes[4] == OPCODE_freturn
649 || codes[4] == OPCODE_ireturn
650 || codes[4] == OPCODE_lreturn))
652 /* Found code like `return FIELD'. */
653 fputs (" { return ", out);
654 index = (codes[2] << 8) | codes[3];
655 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
656 /* FIXME: ensure that the field's class is this class. */
657 name_and_type = JPOOL_USHORT2 (jcf, index);
658 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
659 name = JPOOL_USHORT1 (jcf, name_and_type);
660 print_name (out, jcf, name);
661 fputs ("; }", out);
662 decompiled = 1;
664 else if (code_len == 2
665 && codes[0] == OPCODE_aload_0
666 && codes[1] == OPCODE_areturn)
668 /* Found `return this'. */
669 fputs (" { return this; }", out);
670 decompiled = 1;
672 else if (code_len == 1 && codes[0] == OPCODE_return)
674 /* Found plain `return'. */
675 fputs (" { }", out);
676 decompiled = 1;
678 else if (code_len == 2
679 && codes[0] == OPCODE_aconst_null
680 && codes[1] == OPCODE_areturn)
682 /* Found `return null'. We don't want to depend on NULL being
683 defined. */
684 fputs (" { return 0; }", out);
685 decompiled = 1;
689 /* Print one piece of a signature. Returns pointer to next parseable
690 character on success, NULL on error. */
691 static const unsigned char *
692 decode_signature_piece (stream, signature, limit, need_space)
693 FILE *stream;
694 const unsigned char *signature, *limit;
695 int *need_space;
697 const char *ctype;
698 int array_depth = 0;
700 switch (signature[0])
702 case '[':
703 /* More spaghetti. */
704 array_loop:
705 for (signature++; (signature < limit
706 && *signature >= '0'
707 && *signature <= '9'); signature++)
709 switch (*signature)
711 case 'B': ctype = "jbyteArray"; goto printit;
712 case 'C': ctype = "jcharArray"; goto printit;
713 case 'D': ctype = "jdoubleArray"; goto printit;
714 case 'F': ctype = "jfloatArray"; goto printit;
715 case 'I': ctype = "jintArray"; goto printit;
716 case 'S': ctype = "jshortArray"; goto printit;
717 case 'J': ctype = "jlongArray"; goto printit;
718 case 'Z': ctype = "jbooleanArray"; goto printit;
719 case '[':
720 /* We have a nested array. */
721 ++array_depth;
722 fputs ("JArray<", stream);
723 goto array_loop;
725 case 'L':
726 /* We have to generate a reference to JArray here, so that
727 our output matches what the compiler does. */
728 ++signature;
729 fputs ("JArray<", stream);
730 while (signature < limit && *signature != ';')
732 int ch = UTF8_GET (signature, limit);
733 if (ch == '/')
734 fputs ("::", stream);
735 else
736 jcf_print_char (stream, ch);
738 fputs (" *> *", stream);
739 *need_space = 0;
740 ++signature;
741 break;
742 default:
743 /* Unparseable signature. */
744 return NULL;
746 break;
748 case '(':
749 case ')':
750 /* This shouldn't happen. */
751 return NULL;
753 case 'B': ctype = "jbyte"; goto printit;
754 case 'C': ctype = "jchar"; goto printit;
755 case 'D': ctype = "jdouble"; goto printit;
756 case 'F': ctype = "jfloat"; goto printit;
757 case 'I': ctype = "jint"; goto printit;
758 case 'J': ctype = "jlong"; goto printit;
759 case 'S': ctype = "jshort"; goto printit;
760 case 'Z': ctype = "jboolean"; goto printit;
761 case 'V': ctype = "void"; goto printit;
762 case 'L':
763 /* Print a leading "::" so we look in the right namespace. */
764 fputs ("::", stream);
765 ++signature;
766 while (*signature && *signature != ';')
768 int ch = UTF8_GET (signature, limit);
769 /* `$' is the separator for an inner class. */
770 if (ch == '/' || ch == '$')
771 fputs ("::", stream);
772 else
773 jcf_print_char (stream, ch);
775 fputs (" *", stream);
776 if (*signature == ';')
777 signature++;
778 *need_space = 0;
779 break;
780 default:
781 *need_space = 1;
782 jcf_print_char (stream, *signature++);
783 break;
784 printit:
785 signature++;
786 *need_space = 1;
787 fputs (ctype, stream);
788 break;
791 while (array_depth-- > 0)
792 fputs ("> *", stream);
794 return signature;
797 static void
798 DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
799 name_override),
800 FILE* stream AND JCF* jcf
801 AND int name_index AND int signature_index
802 AND int is_init AND const char *name_override)
804 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
806 fprintf (stream, "<not a UTF8 constant>");
807 found_error = 1;
809 else
811 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
812 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
813 register const unsigned char *str = str0;
814 const unsigned char *limit = str + length;
815 int need_space = 0;
816 int is_method = str[0] == '(';
817 const unsigned char *next;
819 /* If printing a method, skip to the return signature and print
820 that first. However, there is no return value if this is a
821 constructor. */
822 if (is_method && ! is_init)
824 while (str < limit)
826 int ch = *str++;
827 if (ch == ')')
828 break;
832 /* If printing a field or an ordinary method, then print the
833 "return value" now. */
834 if (! is_method || ! is_init)
836 next = decode_signature_piece (stream, str, limit, &need_space);
837 if (! next)
839 fprintf (stderr, "unparseable signature: `%s'\n", str0);
840 found_error = 1;
841 return;
845 /* Now print the name of the thing. */
846 if (need_space)
847 fputs (" ", stream);
848 print_full_cxx_name (stream, jcf, name_index,
849 signature_index, is_init, name_override);
853 /* Print the unqualified method name followed by the signature. */
854 static void
855 DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, is_init, name_override),
856 FILE* stream AND JCF* jcf
857 AND int name_index AND int signature_index AND int is_init
858 AND const char *name_override)
860 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
861 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
862 register const unsigned char *str = str0;
863 const unsigned char *limit = str + length;
864 int need_space = 0;
865 int is_method = str[0] == '(';
866 const unsigned char *next;
868 if (name_override)
869 fputs (name_override, stream);
870 else if (name_index)
872 /* Declare constructors specially. */
873 if (is_init)
874 print_base_classname (stream, jcf, jcf->this_class);
875 else
876 print_name (stream, jcf, name_index);
879 if (is_method)
881 /* Have a method or a constructor. Print signature pieces
882 until done. */
883 fputs (" (", stream);
884 str = str0 + 1;
885 while (str < limit && *str != ')')
887 next = decode_signature_piece (stream, str, limit, &need_space);
888 if (! next)
890 fprintf (stderr, "unparseable signature: `%s'\n", str0);
891 found_error = 1;
892 return;
895 if (next < limit && *next != ')')
896 fputs (", ", stream);
897 str = next;
900 fputs (")", stream);
904 static void
905 DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init,
906 name_override),
907 FILE* stream AND JCF* jcf
908 AND int name_index AND int signature_index
909 AND int is_init AND const char *name_override)
911 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
913 fprintf (stream, "<not a UTF8 constant>");
914 found_error = 1;
916 else
918 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
919 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
920 register const unsigned char *str = str0;
921 const unsigned char *limit = str + length;
922 int need_space = 0;
923 int is_method = str[0] == '(';
924 const unsigned char *next;
926 /* If printing a method, skip to the return signature and print
927 that first. However, there is no return value if this is a
928 constructor. */
929 if (is_method && ! is_init)
931 while (str < limit)
933 int ch = *str++;
934 if (ch == ')')
935 break;
939 /* If printing a field or an ordinary method, then print the
940 "return value" now. */
941 if (! is_method || ! is_init)
943 next = decode_signature_piece (stream, str, limit, &need_space);
944 if (! next)
946 fprintf (stderr, "unparseable signature: `%s'\n", str0);
947 found_error = 1;
948 return;
952 /* Now print the name of the thing. */
953 print_cxx_classname (stream, "\n", jcf, jcf->this_class);
954 fputs ("::", stream);
955 print_full_cxx_name (stream, jcf, name_index,
956 signature_index, is_init, name_override);
957 fputs ("\n{\n JvFail (\"", stream);
958 print_cxx_classname (stream, "", jcf, jcf->this_class);
959 fputs ("::", stream);
960 print_full_cxx_name (stream, jcf, name_index,
961 signature_index, is_init, name_override);
962 fputs (" not implemented\");\n}\n\n", stream);
966 static void
967 DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
968 FILE *stream AND JCF *jcf AND const char *prefix AND int index)
970 int name_index = JPOOL_USHORT1 (jcf, index);
971 fputs (prefix, stream);
972 jcf_print_utf8_replace (out,
973 JPOOL_UTF_DATA (jcf, name_index),
974 JPOOL_UTF_LENGTH (jcf, name_index),
975 '/', '_');
978 /* Print PREFIX, then a class name in C++ format. If the name refers
979 to an array, ignore it and don't print PREFIX. Returns 1 if
980 something was printed, 0 otherwise. */
981 static int
982 print_cxx_classname (stream, prefix, jcf, index)
983 FILE *stream;
984 const char *prefix;
985 JCF *jcf;
986 int index;
988 int name_index = JPOOL_USHORT1 (jcf, index);
989 int len, c;
990 const unsigned char *s, *p, *limit;
992 s = JPOOL_UTF_DATA (jcf, name_index);
993 len = JPOOL_UTF_LENGTH (jcf, name_index);
994 limit = s + len;
996 /* Explicitly omit arrays here. */
997 p = s;
998 c = UTF8_GET (p, limit);
999 if (c == '[')
1000 return 0;
1002 fputs (prefix, stream);
1004 /* Print a leading "::" so we look in the right namespace. */
1005 fputs ("::", stream);
1007 while (s < limit)
1009 c = UTF8_GET (s, limit);
1010 if (c == '/')
1011 fputs ("::", stream);
1012 else
1013 jcf_print_char (stream, c);
1016 return 1;
1019 int written_class_count = 0;
1021 /* Return name of superclass. If LEN is not NULL, fill it with length
1022 of name. */
1023 static const unsigned char *
1024 super_class_name (derived_jcf, len)
1025 JCF *derived_jcf;
1026 int *len;
1028 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1029 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
1030 const unsigned char *supername =
1031 JPOOL_UTF_DATA (derived_jcf, supername_index);
1033 if (len)
1034 *len = supername_length;
1036 return supername;
1041 /* We keep track of all the `#include's we generate, so we can avoid
1042 duplicates. */
1043 struct include
1045 char *name;
1046 struct include *next;
1049 /* List of all includes. */
1050 static struct include *all_includes = NULL;
1052 /* Generate a #include. */
1053 static void
1054 print_include (out, utf8, len)
1055 FILE *out;
1056 const unsigned char *utf8;
1057 int len;
1059 struct include *incl;
1061 if (! out)
1062 return;
1064 if (len == -1)
1065 len = strlen (utf8);
1067 for (incl = all_includes; incl; incl = incl->next)
1069 /* We check the length because we might have a proper prefix. */
1070 if (len == (int) strlen (incl->name)
1071 && ! strncmp (incl->name, utf8, len))
1072 return;
1075 incl = (struct include *) xmalloc (sizeof (struct include));
1076 incl->name = xmalloc (len + 1);
1077 strncpy (incl->name, utf8, len);
1078 incl->name[len] = '\0';
1079 incl->next = all_includes;
1080 all_includes = incl;
1082 fputs ("#include <", out);
1083 jcf_print_utf8 (out, utf8, len);
1084 fputs (".h>\n", out);
1089 /* This is used to represent part of a package or class name. */
1090 struct namelet
1092 /* The text of this part of the name. */
1093 char *name;
1094 /* True if this represents a class. */
1095 int is_class;
1096 /* Linked list of all classes and packages inside this one. */
1097 struct namelet *subnamelets;
1098 /* Pointer to next sibling. */
1099 struct namelet *next;
1102 static void add_namelet PROTO ((const unsigned char *,
1103 const unsigned char *, struct namelet *));
1104 static void print_namelet PROTO ((FILE *, struct namelet *, int));
1106 /* The special root namelet. */
1107 static struct namelet root =
1109 NULL,
1111 NULL,
1112 NULL
1115 /* This extracts the next name segment from the full UTF-8 encoded
1116 package or class name and links it into the tree. It does this
1117 recursively. */
1118 static void
1119 add_namelet (name, name_limit, parent)
1120 const unsigned char *name, *name_limit;
1121 struct namelet *parent;
1123 const unsigned char *p;
1124 struct namelet *n = NULL, *np;
1126 /* We want to skip the standard namespaces that we assume the
1127 runtime already knows about. We only do this at the top level,
1128 though, hence the check for `root'. */
1129 if (parent == &root)
1131 #define JAVALANG "java/lang/"
1132 #define JAVAIO "java/io/"
1133 #define JAVAUTIL "java/util/"
1134 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
1135 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1))
1136 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
1137 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
1138 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
1139 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1)))
1140 return;
1143 for (p = name; p < name_limit && *p != '/' && *p != '$'; ++p)
1146 /* Search for this name beneath the PARENT node. */
1147 for (np = parent->subnamelets; np != NULL; np = np->next)
1149 /* We check the length because we might have a proper prefix. */
1150 if ((int) strlen (np->name) == p - name &&
1151 ! strncmp (name, np->name, p - name))
1153 n = np;
1154 break;
1158 if (n == NULL)
1160 n = (struct namelet *) xmalloc (sizeof (struct namelet));
1161 n->name = xmalloc (p - name + 1);
1162 strncpy (n->name, name, p - name);
1163 n->name[p - name] = '\0';
1164 n->is_class = (p == name_limit || *p == '$');
1165 n->subnamelets = NULL;
1166 n->next = parent->subnamelets;
1167 parent->subnamelets = n;
1170 /* We recurse if there is more text, and if the trailing piece does
1171 not represent an inner class. */
1172 if (p < name_limit && *p != '$')
1173 add_namelet (p + 1, name_limit, n);
1176 /* Print a single namelet. Destroys namelets while printing. */
1177 static void
1178 print_namelet (out, name, depth)
1179 FILE *out;
1180 struct namelet *name;
1181 int depth;
1183 int i, term = 0;
1184 struct namelet *c;
1186 if (name->name)
1188 for (i = 0; i < depth; ++i)
1189 fputc (' ', out);
1190 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1191 name->name);
1192 if (name->is_class && name->subnamelets == NULL)
1193 fputs (";\n", out);
1194 else
1196 term = 1;
1197 fputs ("\n", out);
1198 for (i = 0; i < depth; ++i)
1199 fputc (' ', out);
1200 fputs ("{\n", out);
1204 c = name->subnamelets;
1205 while (c != NULL)
1207 struct namelet *next = c->next;
1208 print_namelet (out, c, depth + 2);
1209 c = next;
1212 if (name->name)
1214 if (term)
1216 for (i = 0; i < depth; ++i)
1217 fputc (' ', out);
1218 fputs ("}\n", out);
1219 /* Only print a `;' when printing a class. C++ is evil. */
1220 if (name->is_class)
1221 fputs (";", out);
1224 free (name->name);
1225 free (name);
1229 /* This is called to add some classes to the list of classes for which
1230 we need decls. The signature argument can be a function
1231 signature. */
1232 static void
1233 add_class_decl (out, jcf, signature)
1234 FILE *out;
1235 JCF *jcf;
1236 JCF_u2 signature;
1238 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
1239 int len = JPOOL_UTF_LENGTH (jcf, signature);
1240 int i;
1241 /* Name of class we are processing. */
1242 int name_index = JPOOL_USHORT1 (jcf, jcf->this_class);
1243 int tlen = JPOOL_UTF_LENGTH (jcf, name_index);
1244 const char *tname = JPOOL_UTF_DATA (jcf, name_index);
1246 for (i = 0; i < len; ++i)
1248 int start, saw_dollar;
1250 /* If we see an array, then we include the array header. */
1251 if (s[i] == '[')
1253 print_include (out, "gcj/array", -1);
1254 continue;
1257 /* We're looking for `L<stuff>;' -- everything else is
1258 ignorable. */
1259 if (s[i] != 'L')
1260 continue;
1262 saw_dollar = 0;
1263 for (start = ++i; i < len && s[i] != ';'; ++i)
1265 if (! saw_dollar && s[i] == '$' && out)
1267 saw_dollar = 1;
1268 /* If this class represents an inner class, then
1269 generate a `#include' for the outer class. However,
1270 don't generate the include if the outer class is the
1271 class we are processing. */
1272 if (i - start < tlen || strncmp (&s[start], tname, i - start))
1273 print_include (out, &s[start], i - start);
1274 break;
1278 /* If we saw an inner class, then the generated #include will
1279 declare the class. So in this case we needn't bother. */
1280 if (! saw_dollar)
1281 add_namelet (&s[start], &s[i], &root);
1285 /* Print declarations for all classes required by this class. Any
1286 class or package in the `java' package is assumed to be handled
1287 statically in libjava; we don't generate declarations for these.
1288 This makes the generated headers a bit easier to read. */
1289 static void
1290 print_class_decls (out, jcf, self)
1291 FILE *out;
1292 JCF *jcf;
1293 int self;
1295 /* Make sure to always add the current class to the list of things
1296 that should be declared. */
1297 int name_index = JPOOL_USHORT1 (jcf, self);
1298 int len;
1299 const unsigned char *s;
1301 s = JPOOL_UTF_DATA (jcf, name_index);
1302 len = JPOOL_UTF_LENGTH (jcf, name_index);
1303 add_namelet (s, s + len, &root);
1305 if (root.subnamelets)
1307 fputs ("extern \"Java\"\n{\n", out);
1308 /* We use an initial offset of 0 because the root namelet
1309 doesn't cause anything to print. */
1310 print_namelet (out, &root, 0);
1311 fputs ("};\n\n", out);
1317 static void
1318 DEFUN(process_file, (jcf, out),
1319 JCF *jcf AND FILE *out)
1321 int code, i;
1322 uint32 field_start, method_end, method_start;
1324 current_jcf = jcf;
1326 last_access = -1;
1328 if (jcf_parse_preamble (jcf) != 0)
1330 fprintf (stderr, "Not a valid Java .class file.\n");
1331 found_error = 1;
1332 return;
1335 /* Parse and possibly print constant pool */
1336 code = jcf_parse_constant_pool (jcf);
1337 if (code != 0)
1339 fprintf (stderr, "error while parsing constant pool\n");
1340 found_error = 1;
1341 return;
1343 code = verify_constant_pool (jcf);
1344 if (code > 0)
1346 fprintf (stderr, "error in constant pool entry #%d\n", code);
1347 found_error = 1;
1348 return;
1351 jcf_parse_class (jcf);
1353 if (written_class_count++ == 0 && out)
1355 if (! stubs)
1356 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
1357 out);
1358 else
1360 fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.
1362 // This file is intended to give you a head start on implementing native
1363 // methods using CNI.
1364 // Be aware: running `gcjh -stubs' once more for this class may overwrite any
1365 // edits you have made to this file.\n\n", out);
1369 if (out)
1371 if (! stubs)
1373 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
1374 fprintf (out, "__\n");
1376 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
1377 fprintf (out, "__\n\n");
1379 /* We do this to ensure that inline methods won't be `outlined'
1380 by g++. This works as long as method and fields are not
1381 added by the user. */
1382 fprintf (out, "#pragma interface\n");
1384 if (jcf->super_class)
1386 int super_length;
1387 const unsigned char *supername =
1388 super_class_name (jcf, &super_length);
1390 fputs ("\n", out);
1391 print_include (out, supername, super_length);
1394 else
1396 /* Strip off the ".class" portion of the name when printing
1397 the include file name. */
1398 print_include (out, jcf->classname, strlen (jcf->classname) - 6);
1402 /* We want to parse the methods first. But we need to find where
1403 they start. So first we skip the fields, then parse the methods.
1404 Then we parse the fields and skip the methods. This is ugly, but
1405 not too bad since we need two full passes to get class decl
1406 information anyway. */
1407 field_pass = 0;
1408 field_start = JCF_TELL (jcf);
1409 jcf_parse_fields (jcf);
1411 method_start = JCF_TELL (jcf);
1412 method_pass = 0;
1413 jcf_parse_methods (jcf);
1415 if (out)
1417 fputs ("\n", out);
1419 if (! stubs)
1420 print_class_decls (out, jcf, jcf->this_class);
1422 for (i = 0; i < prepend_count; ++i)
1423 fprintf (out, "%s\n", prepend_specs[i]);
1424 if (prepend_count > 0)
1425 fputc ('\n', out);
1427 if (! stubs)
1429 if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
1431 fprintf (stderr, "class is of array type\n");
1432 found_error = 1;
1433 return;
1435 if (jcf->super_class)
1437 if (! print_cxx_classname (out, " : public ",
1438 jcf, jcf->super_class))
1440 fprintf (stderr, "base class is of array type\n");
1441 found_error = 1;
1442 return;
1446 fputs ("\n{\n", out);
1450 /* Now go back for second pass over methods and fields. */
1451 JCF_SEEK (jcf, method_start);
1452 method_pass = 1;
1453 jcf_parse_methods (jcf);
1454 method_end = JCF_TELL (jcf);
1456 field_pass = 1;
1457 JCF_SEEK (jcf, field_start);
1458 jcf_parse_fields (jcf);
1459 JCF_SEEK (jcf, method_end);
1461 jcf_parse_final_attributes (jcf);
1463 if (out)
1465 /* Generate friend decl if we still must. */
1466 for (i = 0; i < friend_count; ++i)
1467 fprintf (out, " friend %s\n", friend_specs[i]);
1469 /* Generate extra declarations. */
1470 if (add_count > 0)
1471 fputc ('\n', out);
1472 for (i = 0; i < add_count; ++i)
1473 fprintf (out, " %s\n", add_specs[i]);
1475 if (! stubs)
1476 fputs ("};\n", out);
1478 if (append_count > 0)
1479 fputc ('\n', out);
1480 for (i = 0; i < append_count; ++i)
1481 fprintf (out, "%s\n", append_specs[i]);
1483 if (!stubs)
1485 print_mangled_classname (out, jcf,
1486 "\n#endif /* __", jcf->this_class);
1487 fprintf (out, "__ */\n");
1492 static void
1493 usage ()
1495 fprintf (stderr, "gcjh: no classes specified\n");
1496 exit (1);
1499 static void
1500 help ()
1502 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
1503 printf ("Generate C++ header files from .class files\n\n");
1504 printf (" --classpath PATH Set path to find .class files\n");
1505 printf (" --CLASSPATH PATH Set path to find .class files\n");
1506 printf (" -IDIR Append directory to class path\n");
1507 printf (" -d DIRECTORY Set output directory name\n");
1508 printf (" --help Print this help, then exit\n");
1509 printf (" -o FILE Set output file name\n");
1510 printf (" -stubs Generate a C++ implementation stub file\n");
1511 printf (" -td DIRECTORY Set temporary directory name\n");
1512 printf (" -v, --verbose Print extra information while running\n");
1513 printf (" --version Print version number, then exit\n");
1514 /* FIXME: print bug-report information. */
1515 exit (0);
1518 static void
1519 java_no_argument (opt)
1520 const char *opt;
1522 fprintf (stderr, "gcjh: no argument given for option `%s'\n", opt);
1523 exit (1);
1526 static void
1527 version ()
1529 /* FIXME: use version.c? */
1530 printf ("gcjh (%s)\n\n", version_string);
1531 printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
1532 printf ("This is free software; see the source for copying conditions. There is NO\n");
1533 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
1534 exit (0);
1538 DEFUN(main, (argc, argv),
1539 int argc AND char** argv)
1541 JCF jcf;
1542 int argi;
1543 char *output_file = NULL;
1544 int emit_dependencies = 0, suppress_output = 0;
1546 if (argc <= 1)
1547 usage ();
1549 jcf_path_init ();
1551 for (argi = 1; argi < argc; argi++)
1553 char *arg = argv[argi];
1555 if (arg[0] != '-' || ! strcmp (arg, "--"))
1556 break;
1558 /* Just let all arguments be given in either "-" or "--" form. */
1559 if (arg[1] == '-')
1560 ++arg;
1562 if (strcmp (arg, "-o") == 0)
1564 if (argi + 1 < argc)
1565 output_file = argv[++argi];
1566 else
1567 java_no_argument (argv[argi]);
1569 else if (strcmp (arg, "-d") == 0)
1571 if (argi + 1 < argc)
1572 output_directory = argv[++argi];
1573 else
1574 java_no_argument (argv[argi]);
1576 else if (strcmp (arg, "-td") == 0)
1578 if (argi + 1 < argc)
1579 temp_directory = argv[++argi];
1580 else
1581 java_no_argument (argv[argi]);
1583 else if (strcmp (arg, "-prepend") == 0)
1585 if (argi + 1 < argc)
1587 if (prepend_count == 0)
1588 prepend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1589 prepend_specs[prepend_count++] = argv[++argi];
1591 else
1592 java_no_argument (argv[argi]);
1594 else if (strcmp (arg, "-friend") == 0)
1596 if (argi + 1 < argc)
1598 if (friend_count == 0)
1599 friend_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1600 friend_specs[friend_count++] = argv[++argi];
1602 else
1603 java_no_argument (argv[argi]);
1605 else if (strcmp (arg, "-add") == 0)
1607 if (argi + 1 < argc)
1609 if (add_count == 0)
1610 add_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1611 add_specs[add_count++] = argv[++argi];
1613 else
1614 java_no_argument (argv[argi]);
1616 else if (strcmp (arg, "-append") == 0)
1618 if (argi + 1 < argc)
1620 if (append_count == 0)
1621 append_specs = (char**) ALLOC ((argc-argi) * sizeof (char*));
1622 append_specs[append_count++] = argv[++argi];
1624 else
1625 java_no_argument (argv[argi]);
1627 else if (strcmp (arg, "-classpath") == 0)
1629 if (argi + 1 < argc)
1630 jcf_path_classpath_arg (argv[++argi]);
1631 else
1632 java_no_argument (argv[argi]);
1634 else if (strcmp (arg, "-CLASSPATH") == 0)
1636 if (argi + 1 < argc)
1637 jcf_path_CLASSPATH_arg (argv[++argi]);
1638 else
1639 java_no_argument (argv[argi]);
1641 else if (strncmp (arg, "-I", 2) == 0)
1642 jcf_path_include_arg (arg + 2);
1643 else if (strcmp (arg, "-verbose") == 0 || strcmp (arg, "-v") == 0)
1644 verbose++;
1645 else if (strcmp (arg, "-stubs") == 0)
1646 stubs++;
1647 else if (strcmp (arg, "-help") == 0)
1648 help ();
1649 else if (strcmp (arg, "-version") == 0)
1650 version ();
1651 else if (strcmp (arg, "-M") == 0)
1653 emit_dependencies = 1;
1654 suppress_output = 1;
1655 jcf_dependency_init (1);
1657 else if (strcmp (arg, "-MM") == 0)
1659 emit_dependencies = 1;
1660 suppress_output = 1;
1661 jcf_dependency_init (0);
1663 else if (strcmp (arg, "-MG") == 0)
1665 fprintf (stderr, "gcjh: `%s' option is unimplemented\n", argv[argi]);
1666 exit (1);
1668 else if (strcmp (arg, "-MD") == 0)
1670 emit_dependencies = 1;
1671 jcf_dependency_init (1);
1673 else if (strcmp (arg, "-MMD") == 0)
1675 emit_dependencies = 1;
1676 jcf_dependency_init (0);
1678 else
1680 fprintf (stderr, "%s: illegal argument\n", argv[argi]);
1681 exit (1);
1685 if (argi == argc)
1686 usage ();
1688 jcf_path_seal ();
1690 if (output_file && emit_dependencies)
1692 fprintf (stderr, "gcjh: can't specify both -o and -MD\n");
1693 exit (1);
1696 for (; argi < argc; argi++)
1698 char *classname = argv[argi];
1699 char *current_output_file;
1700 const char *classfile_name;
1702 if (verbose)
1703 fprintf (stderr, "Processing %s\n", classname);
1704 if (! output_file)
1705 jcf_dependency_reset ();
1706 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
1707 if (classfile_name == NULL)
1709 fprintf (stderr, "%s: no such class\n", classname);
1710 exit (1);
1712 if (verbose)
1713 fprintf (stderr, "Found in %s\n", classfile_name);
1714 if (output_file)
1716 if (strcmp (output_file, "-") == 0)
1717 out = stdout;
1718 else if (out == NULL)
1720 out = fopen (output_file, "w");
1722 if (out == NULL)
1724 perror (output_file);
1725 exit (1);
1727 current_output_file = output_file;
1729 else
1731 int dir_len = strlen (output_directory);
1732 int i, classname_length = strlen (classname);
1733 current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
1734 strcpy (current_output_file, output_directory);
1735 if (dir_len > 0 && output_directory[dir_len-1] != '/')
1736 current_output_file[dir_len++] = '/';
1737 for (i = 0; classname[i] != '\0'; i++)
1739 char ch = classname[i];
1740 if (ch == '.')
1741 ch = '/';
1742 current_output_file[dir_len++] = ch;
1744 if (emit_dependencies)
1746 if (suppress_output)
1748 jcf_dependency_set_dep_file ("-");
1749 out = NULL;
1751 else
1753 /* We use `.hd' and not `.d' to avoid clashes with
1754 dependency tracking from straight compilation. */
1755 strcpy (current_output_file + dir_len, ".hd");
1756 jcf_dependency_set_dep_file (current_output_file);
1759 strcpy (current_output_file + dir_len,
1760 stubs ? ".cc" : ".h");
1761 jcf_dependency_set_target (current_output_file);
1762 if (! suppress_output)
1764 out = fopen (current_output_file, "w");
1765 if (out == NULL)
1767 perror (current_output_file);
1768 exit (1);
1772 process_file (&jcf, out);
1773 JCF_FINISH (&jcf);
1774 if (current_output_file != output_file)
1775 free (current_output_file);
1776 jcf_dependency_write ();
1779 if (out != NULL && out != stdout)
1780 fclose (out);
1782 return found_error;
1785 /* TODO:
1787 * Emit "structure forward declarations" when needed.
1789 * Generate C headers, like javah