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 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
36 /* The output file. */
39 /* Nonzero on failure. */
40 static int found_error
= 0;
42 /* Directory to place resulting files in. Set by -d option. */
43 char *output_directory
= "";
45 /* Directory to place temporary file. Set by -td option. Currently unused. */
46 char *temp_directory
= "/tmp";
48 /* Number of friend functions we have to declare. */
49 static int friend_count
;
51 /* A class can optionally have a `friend' function declared. If
52 non-NULL, this is that function. */
53 static char **friend_specs
= NULL
;
55 /* Number of lines we are prepending before the class. */
56 static int prepend_count
;
58 /* We can prepend extra lines before the class's start. */
59 static char **prepend_specs
= NULL
;
61 /* Number of lines we are appending at the end of the class. */
64 /* We can append extra lines just before the class's end. */
65 static char **add_specs
= NULL
;
67 /* Number of lines we are appending after the class. */
68 static int append_count
;
70 /* We can append extra lines after the class's end. */
71 static char **append_specs
= NULL
;
77 struct JCF
*current_jcf
;
80 /* This holds access information for the last field we examined. They
81 let us generate "private:", "public:", and "protected:" properly.
82 If 0 then we haven't previously examined any field. */
83 static JCF_u2 last_access
;
85 #define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
87 /* We keep a linked list of all method names we have seen. This lets
88 us determine if a method name and a field name are in conflict. */
93 struct method_name
*next
;
96 /* List of method names we've seen. */
97 static struct method_name
*method_name_list
;
99 static void print_field_info
PROTO ((FILE *, JCF
*, int, int, JCF_u2
));
100 static void print_method_info
PROTO ((FILE *, JCF
*, int, int, JCF_u2
));
101 static void print_c_decl
PROTO ((FILE*, JCF
*, int, int, JCF_u2
, int, char *));
103 JCF_u2 current_field_name
;
104 JCF_u2 current_field_value
;
105 JCF_u2 current_field_signature
;
106 JCF_u2 current_field_flags
;
108 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
109 ( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
110 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
112 /* We pass over fields twice. The first time we just note the start
113 of the methods. Then we go back and parse the fields for real.
115 static int field_pass
;
117 #define HANDLE_END_FIELD() \
118 if (out && field_pass) print_field_info (out, jcf, current_field_name, \
119 current_field_signature, \
120 current_field_flags);
122 #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
124 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
125 if (out) print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS)
127 #include "jcf-reader.c"
129 /* Some useful constants. */
130 #define F_NAN_MASK 0x7f800000
131 #define D_NAN_MASK 0x7ff0000000000000LL
133 /* Return 1 if F is not Inf or NaN. */
135 java_float_finite (f
)
138 int32
*ip
= (int32
*) &f
;
140 /* We happen to know that F_NAN_MASK will match all NaN values, and
141 also positive and negative infinity. That's why we only need one
142 test here. See The Java Language Specification, section 20.9. */
143 return (*ip
& F_NAN_MASK
) != F_NAN_MASK
;
146 /* Return 1 if D is not Inf or NaN. */
148 java_double_finite (d
)
151 int64
*ip
= (int64
*) &d
;
153 /* Now check for all NaNs. */
154 return (*ip
& D_NAN_MASK
) != D_NAN_MASK
;
158 DEFUN(print_name
, (stream
, jcf
, name_index
),
159 FILE* stream AND JCF
* jcf AND
int name_index
)
161 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
162 fprintf (stream
, "<not a UTF8 constant>");
164 jcf_print_utf8 (stream
, JPOOL_UTF_DATA (jcf
, name_index
),
165 JPOOL_UTF_LENGTH (jcf
, name_index
));
168 /* Print base name of class. The base name is everything after the
172 print_base_classname (stream
, jcf
, index
)
177 int name_index
= JPOOL_USHORT1 (jcf
, index
);
179 unsigned char *s
, *p
, *limit
;
181 s
= JPOOL_UTF_DATA (jcf
, name_index
);
182 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
187 int c
= UTF8_GET (s
, limit
);
194 int ch
= UTF8_GET (p
, limit
);
196 fputs ("::", stream
);
198 jcf_print_char (stream
, ch
);
202 /* Return 0 if NAME is equal to STR, nonzero otherwise. */
205 utf8_cmp (str
, length
, name
)
210 unsigned char *limit
= str
+ length
;
213 for (i
= 0; name
[i
]; ++i
)
215 int ch
= UTF8_GET (str
, limit
);
223 /* Generate an access control keyword based on FLAGS. Returns 0 if
224 FLAGS matches the saved access information, nonzero otherwise. */
227 generate_access (stream
, flags
)
231 /* FIXME: Java's "protected" and "no access specifier" modes don't
232 actually map to C++ "protected". That's how we map them for now,
235 if (! (flags
& ACC_VISIBILITY
))
236 flags
= ACC_PROTECTED
;
238 if ((flags
& ACC_VISIBILITY
) == last_access
)
240 last_access
= (flags
& ACC_VISIBILITY
);
245 fputs ("public:\n", stream
);
248 fputs ("private:\n", stream
);
251 fputs ("protected:\n", stream
);
255 fprintf (stream
, "#error unrecognized visibility %d\n",
256 (flags
& ACC_VISIBILITY
));
261 /* See if NAME is already the name of a method. */
263 name_is_method_p (name
, length
)
267 struct method_name
*p
;
269 for (p
= method_name_list
; p
!= NULL
; p
= p
->next
)
271 if (p
->length
== length
&& ! memcmp (p
->name
, name
, length
))
278 DEFUN(print_field_info
, (stream
, jcf
, name_index
, sig_index
, flags
),
279 FILE *stream AND JCF
* jcf
280 AND
int name_index AND
int sig_index AND JCF_u2 flags
)
282 char *override
= NULL
;
284 if (flags
& ACC_FINAL
)
286 if (current_field_value
> 0)
291 generate_access (stream
, flags
);
292 switch (JPOOL_TAG (jcf
, current_field_value
))
294 case CONSTANT_Integer
:
295 fputs (" static const jint ", out
);
296 print_name (out
, jcf
, name_index
);
298 num
= JPOOL_INT (jcf
, current_field_value
);
299 format_int (buffer
, num
, 10);
300 fprintf (out
, "%sL;\n", buffer
);
303 fputs (" static const jlong ", out
);
304 print_name (out
, jcf
, name_index
);
306 num
= JPOOL_LONG (jcf
, current_field_value
);
307 format_int (buffer
, num
, 10);
308 fprintf (out
, "%sLL;\n", buffer
);
312 jfloat fnum
= JPOOL_FLOAT (jcf
, current_field_value
);
313 fputs (" static const jfloat ", out
);
314 print_name (out
, jcf
, name_index
);
315 if (! java_float_finite (fnum
))
318 fprintf (out
, " = %.10g;\n", fnum
);
321 case CONSTANT_Double
:
323 jdouble dnum
= JPOOL_DOUBLE (jcf
, current_field_value
);
324 fputs (" static const jdouble ", out
);
325 print_name (out
, jcf
, name_index
);
326 if (! java_double_finite (dnum
))
329 fprintf (out
, " = %.17g;\n", dnum
);
333 fprintf(out
, " <<inappropriate constant type>>\n");
340 generate_access (stream
, flags
);
342 if ((flags
& ACC_STATIC
))
343 fputs ("static ", out
);
345 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
347 fprintf (stream
, "<not a UTF8 constant>");
352 unsigned char *name
= JPOOL_UTF_DATA (jcf
, name_index
);
353 int length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
355 if (name_is_method_p (name
, length
))
357 /* This field name matches a method. So override the name
358 with a dummy name. This is yucky, but it isn't clear
359 what else to do. FIXME: if the field is static, then
360 we'll be in real trouble. */
361 if ((flags
& ACC_STATIC
))
363 fprintf (stderr
, "static field has same name as method\n");
367 override
= (char *) malloc (length
+ 3);
368 memcpy (override
, name
, length
);
369 strcpy (override
+ length
, "__");
373 print_c_decl (out
, jcf
, name_index
, sig_index
, flags
, 0, override
);
381 DEFUN(print_method_info
, (stream
, jcf
, name_index
, sig_index
, flags
),
382 FILE *stream AND JCF
* jcf
383 AND
int name_index AND
int sig_index AND JCF_u2 flags
)
386 int length
, is_init
= 0;
387 char *override
= NULL
;
389 if (JPOOL_TAG (jcf
, name_index
) != CONSTANT_Utf8
)
390 fprintf (stream
, "<not a UTF8 constant>");
391 str
= JPOOL_UTF_DATA (jcf
, name_index
);
392 length
= JPOOL_UTF_LENGTH (jcf
, name_index
);
395 /* Ignore internally generated methods like <clinit>. However,
396 treat <init> as a constructor. */
397 if (! utf8_cmp (str
, length
, "<init>"))
404 struct method_name
*nn
;
406 nn
= (struct method_name
*) malloc (sizeof (struct method_name
));
407 nn
->name
= (char *) malloc (length
);
408 memcpy (nn
->name
, str
, length
);
410 nn
->next
= method_name_list
;
411 method_name_list
= nn
;
414 /* We can't generate a method whose name is a C++ reserved word.
415 For now the only problem has been `delete'; add more here as
416 required. We can't just ignore the function, because that will
417 cause incorrect code to be generated if the function is virtual
418 (not only for calls to this function for for other functions
419 after it in the vtbl). So we give it a dummy name instead. */
420 if (! utf8_cmp (str
, length
, "delete"))
422 /* If the method is static, we can safely skip it. If we don't
423 skip it then we'll have problems since the mangling will be
425 if ((flags
& ACC_STATIC
))
427 override
= "__dummy_delete";
430 generate_access (stream
, flags
);
433 if ((flags
& ACC_STATIC
))
434 fputs ("static ", out
);
435 else if (! (flags
& ACC_FINAL
) && ! (jcf
->access_flags
& ACC_FINAL
))
437 /* Don't print `virtual' if we have a constructor. */
439 fputs ("virtual ", out
);
441 print_c_decl (out
, jcf
, name_index
, sig_index
, flags
, is_init
, override
);
443 /* FIXME: it would be nice to decompile small methods here. That
444 would allow for inlining. */
449 /* Print one piece of a signature. Returns pointer to next parseable
450 character on success, NULL on error. */
451 static unsigned char *
452 decode_signature_piece (stream
, signature
, limit
, need_space
)
454 unsigned char *signature
, *limit
;
459 switch (signature
[0])
462 for (signature
++; (signature
< limit
464 && *signature
<= '9'); signature
++)
468 case 'B': ctype
= "jbyteArray"; goto printit
;
469 case 'C': ctype
= "jcharArray"; goto printit
;
470 case 'D': ctype
= "jdoubleArray"; goto printit
;
471 case 'F': ctype
= "jfloatArray"; goto printit
;
472 case 'I': ctype
= "jintArray"; goto printit
;
473 case 'S': ctype
= "jshortArray"; goto printit
;
474 case 'J': ctype
= "jlongArray"; goto printit
;
475 case 'Z': ctype
= "jbooleanArray"; goto printit
;
476 case '[': ctype
= "jobjectArray"; goto printit
;
478 /* We have to generate a reference to JArray here,
479 so that our output matches what the compiler
482 fputs ("JArray<", stream
);
483 while (signature
< limit
&& *signature
!= ';')
485 int ch
= UTF8_GET (signature
, limit
);
487 fputs ("::", stream
);
489 jcf_print_char (stream
, ch
);
491 fputs (" *> *", stream
);
496 /* Unparseable signature. */
503 /* This shouldn't happen. */
506 case 'B': ctype
= "jbyte"; goto printit
;
507 case 'C': ctype
= "jchar"; goto printit
;
508 case 'D': ctype
= "jdouble"; goto printit
;
509 case 'F': ctype
= "jfloat"; goto printit
;
510 case 'I': ctype
= "jint"; goto printit
;
511 case 'J': ctype
= "jlong"; goto printit
;
512 case 'S': ctype
= "jshort"; goto printit
;
513 case 'Z': ctype
= "jboolean"; goto printit
;
514 case 'V': ctype
= "void"; goto printit
;
517 while (*signature
&& *signature
!= ';')
519 int ch
= UTF8_GET (signature
, limit
);
521 fputs ("::", stream
);
523 jcf_print_char (stream
, ch
);
525 fputs (" *", stream
);
526 if (*signature
== ';')
532 jcf_print_char (stream
, *signature
++);
537 fputs (ctype
, stream
);
545 DEFUN(print_c_decl
, (stream
, jcf
, name_index
, signature_index
, flags
, is_init
,
547 FILE* stream AND JCF
* jcf
548 AND
int name_index AND
int signature_index AND JCF_u2 flags
549 AND
int is_init AND
char *name_override
)
551 if (JPOOL_TAG (jcf
, signature_index
) != CONSTANT_Utf8
)
553 fprintf (stream
, "<not a UTF8 constant>");
558 int length
= JPOOL_UTF_LENGTH (jcf
, signature_index
);
559 unsigned char *str0
= JPOOL_UTF_DATA (jcf
, signature_index
);
560 register unsigned char *str
= str0
;
561 unsigned char *limit
= str
+ length
;
563 int is_method
= str
[0] == '(';
566 /* If printing a method, skip to the return signature and print
567 that first. However, there is no return value if this is a
569 if (is_method
&& ! is_init
)
579 /* If printing a field or an ordinary method, then print the
580 "return value" now. */
581 if (! is_method
|| ! is_init
)
583 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
586 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
592 /* Now print the name of the thing. */
596 fputs (name_override
, stream
);
599 /* Declare constructors specially. */
601 print_base_classname (stream
, jcf
, jcf
->this_class
);
603 print_name (stream
, jcf
, name_index
);
608 /* Have a method or a constructor. Print signature pieces
610 fputs (" (", stream
);
612 while (str
< limit
&& *str
!= ')')
614 next
= decode_signature_piece (stream
, str
, limit
, &need_space
);
617 fprintf (stderr
, "unparseable signature: `%s'\n", str0
);
622 if (next
< limit
&& *next
!= ')')
623 fputs (", ", stream
);
633 DEFUN(print_mangled_classname
, (stream
, jcf
, prefix
, index
),
634 FILE *stream AND JCF
*jcf AND
char *prefix AND
int index
)
636 int name_index
= JPOOL_USHORT1 (jcf
, index
);
637 fputs (prefix
, stream
);
638 jcf_print_utf8_replace (out
,
639 JPOOL_UTF_DATA (jcf
, name_index
),
640 JPOOL_UTF_LENGTH (jcf
, name_index
),
644 /* Print PREFIX, then a class name in C++ format. If the name refers
645 to an array, ignore it and don't print PREFIX. Returns 1 if
646 something was printed, 0 otherwise. */
648 print_cxx_classname (stream
, prefix
, jcf
, index
)
654 int name_index
= JPOOL_USHORT1 (jcf
, index
);
656 unsigned char *s
, *p
, *limit
;
658 s
= JPOOL_UTF_DATA (jcf
, name_index
);
659 len
= JPOOL_UTF_LENGTH (jcf
, name_index
);
662 /* Explicitly omit arrays here. */
664 c
= UTF8_GET (p
, limit
);
668 fputs (prefix
, stream
);
671 c
= UTF8_GET (s
, limit
);
673 fputs ("::", stream
);
675 jcf_print_char (stream
, c
);
681 int written_class_count
= 0;
683 /* Return name of superclass. If LEN is not NULL, fill it with length
685 static unsigned char *
686 super_class_name (derived_jcf
, len
)
690 int supername_index
= JPOOL_USHORT1 (derived_jcf
, derived_jcf
->super_class
);
691 int supername_length
= JPOOL_UTF_LENGTH (derived_jcf
, supername_index
);
692 unsigned char *supername
= JPOOL_UTF_DATA (derived_jcf
, supername_index
);
695 *len
= supername_length
;
700 /* Print declarations for all classes required by this class. FIXME:
701 the current implementation just prints every class name from the
702 constant pool. This is too much. We really only need to print a
703 declaration for each class which is the type of a return value, a
704 field, or an argument. */
706 print_class_decls (out
, jcf
)
712 for (i
= 1; i
< JPOOL_SIZE (jcf
); ++i
)
714 int kind
= JPOOL_TAG (jcf
, i
);
715 if (kind
== CONSTANT_Class
)
717 if (print_cxx_classname (out
, "class ", jcf
, i
))
728 DEFUN(process_file
, (jcf
, out
),
729 JCF
*jcf AND
FILE *out
)
732 uint32 field_start
, method_end
;
734 current_jcf
= main_jcf
= jcf
;
738 if (jcf_parse_preamble (jcf
) != 0)
740 fprintf (stderr
, "Not a valid Java .class file.\n");
745 /* Parse and possibly print constant pool */
746 code
= jcf_parse_constant_pool (jcf
);
749 fprintf (stderr
, "error while parsing constant pool\n");
753 code
= verify_constant_pool (jcf
);
756 fprintf (stderr
, "error in constant pool entry #%d\n", code
);
761 jcf_parse_class (jcf
);
763 if (written_class_count
++ == 0 && out
)
764 fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
769 print_mangled_classname (out
, jcf
, "#ifndef __", jcf
->this_class
);
770 fprintf (out
, "__\n");
772 print_mangled_classname (out
, jcf
, "#define __", jcf
->this_class
);
773 fprintf (out
, "__\n\n");
776 if (jcf
->super_class
&& out
)
779 unsigned char *supername
= super_class_name (jcf
, &super_length
);
781 fputs ("#include <", out
);
782 jcf_print_utf8 (out
, supername
, super_length
);
783 fputs (".h>\n", out
);
785 /* FIXME: If our superclass is Object, then we include
786 java-array.h. The right thing to do here is look at all the
787 methods and fields and see if an array is in use. Only then
788 would we need to include java-array.h. */
789 if (! utf8_cmp (supername
, super_length
, "java/lang/Object"))
790 fputs ("#include <java-array.h>\n", out
);
797 print_class_decls (out
, jcf
);
799 for (i
= 0; i
< prepend_count
; ++i
)
800 fprintf (out
, "%s\n", prepend_specs
[i
]);
801 if (prepend_count
> 0)
805 if (out
&& ! print_cxx_classname (out
, "class ", jcf
, jcf
->this_class
))
807 fprintf (stderr
, "class is of array type\n");
811 if (out
&& jcf
->super_class
)
813 if (! print_cxx_classname (out
, " : public ", jcf
, jcf
->super_class
))
815 fprintf (stderr
, "base class is of array type\n");
821 fputs ("\n{\n", out
);
823 /* We make a single pass over the file, printing methods and fields
824 as we see them. We have to list the methods in the same order
825 that they appear in the class file, so that the Java and C++
826 vtables have the same layout. */
827 /* We want to parse the methods first. But we need to find where
828 they start. So first we skip the fields, then parse the
829 methods. Then we parse the fields and skip the methods. FIXME:
832 field_start
= JCF_TELL (jcf
);
833 jcf_parse_fields (jcf
);
835 jcf_parse_methods (jcf
);
836 method_end
= JCF_TELL (jcf
);
839 JCF_SEEK (jcf
, field_start
);
840 jcf_parse_fields (jcf
);
841 JCF_SEEK (jcf
, method_end
);
843 jcf_parse_final_attributes (jcf
);
847 /* Generate friend decl if we still must. */
848 for (i
= 0; i
< friend_count
; ++i
)
849 fprintf (out
, " friend %s\n", friend_specs
[i
]);
851 /* Generate extra declarations. */
854 for (i
= 0; i
< add_count
; ++i
)
855 fprintf (out
, " %s\n", add_specs
[i
]);
859 if (append_count
> 0)
861 for (i
= 0; i
< append_count
; ++i
)
862 fprintf (out
, "%s\n", append_specs
[i
]);
864 print_mangled_classname (out
, jcf
, "\n#endif /* __", jcf
->this_class
);
865 fprintf (out
, "__ */\n");
872 fprintf (stderr
, "gcjh: no classes specified\n");
879 printf ("Usage: gcjh [OPTION]... CLASS...\n\n");
880 printf ("Generate C++ header files from .class files\n\n");
881 printf (" --classpath PATH Set path to find .class files\n");
882 printf (" --CLASSPATH PATH Set path to find .class files\n");
883 printf (" -IDIR Append directory to class path\n");
884 printf (" -d DIRECTORY Set output directory name\n");
885 printf (" --help Print this help, then exit\n");
886 printf (" -o FILE Set output file name\n");
887 printf (" -td DIRECTORY Set temporary directory name\n");
888 printf (" -v, --verbose Print extra information while running\n");
889 printf (" --version Print version number, then exit\n");
890 /* FIXME: print bug-report information. */
895 java_no_argument (opt
)
898 fprintf (stderr
, "gcjh: no argument given for option `%s'\n", opt
);
905 /* FIXME: use version.c? */
906 printf ("gcjh (GNU gcc) 0.0\n\n");
907 printf ("Copyright (C) 1998 Free Software Foundation, Inc.\n");
908 printf ("This is free software; see the source for copying conditions. There is NO\n");
909 printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
914 DEFUN(main
, (argc
, argv
),
915 int argc AND
char** argv
)
919 char *output_file
= NULL
;
920 int emit_dependencies
= 0, suppress_output
= 0;
927 for (argi
= 1; argi
< argc
; argi
++)
929 char *arg
= argv
[argi
];
931 if (arg
[0] != '-' || ! strcmp (arg
, "--"))
934 /* Just let all arguments be given in either "-" or "--" form. */
938 if (strcmp (arg
, "-o") == 0)
941 output_file
= argv
[++argi
];
943 java_no_argument (argv
[argi
]);
945 else if (strcmp (arg
, "-d") == 0)
948 output_directory
= argv
[++argi
];
950 java_no_argument (argv
[argi
]);
952 else if (strcmp (arg
, "-td") == 0)
955 temp_directory
= argv
[++argi
];
957 java_no_argument (argv
[argi
]);
959 else if (strcmp (arg
, "-prepend") == 0)
963 if (prepend_count
== 0)
964 prepend_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
965 prepend_specs
[prepend_count
++] = argv
[++argi
];
968 java_no_argument (argv
[argi
]);
970 else if (strcmp (arg
, "-friend") == 0)
974 if (friend_count
== 0)
975 friend_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
976 friend_specs
[friend_count
++] = argv
[++argi
];
979 java_no_argument (argv
[argi
]);
981 else if (strcmp (arg
, "-add") == 0)
986 add_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
987 add_specs
[add_count
++] = argv
[++argi
];
990 java_no_argument (argv
[argi
]);
992 else if (strcmp (arg
, "-append") == 0)
996 if (append_count
== 0)
997 append_specs
= (char**) ALLOC ((argc
-argi
) * sizeof (char*));
998 append_specs
[append_count
++] = argv
[++argi
];
1001 java_no_argument (argv
[argi
]);
1003 else if (strcmp (arg
, "-classpath") == 0)
1005 if (argi
+ 1 < argc
)
1006 jcf_path_classpath_arg (argv
[++argi
]);
1008 java_no_argument (argv
[argi
]);
1010 else if (strcmp (arg
, "-CLASSPATH") == 0)
1012 if (argi
+ 1 < argc
)
1013 jcf_path_CLASSPATH_arg (argv
[++argi
]);
1015 java_no_argument (argv
[argi
]);
1017 else if (strncmp (arg
, "-I", 2) == 0)
1018 jcf_path_include_arg (arg
+ 2);
1019 else if (strcmp (arg
, "-verbose") == 0 || strcmp (arg
, "-v") == 0)
1021 else if (strcmp (arg
, "-stubs") == 0)
1023 else if (strcmp (arg
, "-help") == 0)
1025 else if (strcmp (arg
, "-version") == 0)
1027 else if (strcmp (arg
, "-M") == 0)
1029 emit_dependencies
= 1;
1030 suppress_output
= 1;
1031 jcf_dependency_init (1);
1033 else if (strcmp (arg
, "-MM") == 0)
1035 emit_dependencies
= 1;
1036 suppress_output
= 1;
1037 jcf_dependency_init (0);
1039 else if (strcmp (arg
, "-MG") == 0)
1041 fprintf (stderr
, "gcjh: `%s' option is unimplemented\n", argv
[argi
]);
1044 else if (strcmp (arg
, "-MD") == 0)
1046 emit_dependencies
= 1;
1047 jcf_dependency_init (1);
1049 else if (strcmp (arg
, "-MMD") == 0)
1051 emit_dependencies
= 1;
1052 jcf_dependency_init (0);
1056 fprintf (stderr
, "%s: illegal argument\n", argv
[argi
]);
1066 if (output_file
&& emit_dependencies
)
1068 fprintf (stderr
, "gcjh: can't specify both -o and -MD\n");
1072 for (; argi
< argc
; argi
++)
1074 char *classname
= argv
[argi
];
1075 char *classfile_name
, *current_output_file
;
1078 fprintf (stderr
, "Processing %s\n", classname
);
1080 jcf_dependency_reset ();
1081 classfile_name
= find_class (classname
, strlen (classname
), &jcf
, 1);
1082 if (classfile_name
== NULL
)
1084 fprintf (stderr
, "%s: no such class\n", classname
);
1088 fprintf (stderr
, "Found in %s\n", classfile_name
);
1091 if (strcmp (output_file
, "-") == 0)
1093 else if (out
== NULL
)
1095 out
= fopen (output_file
, "w");
1099 perror (output_file
);
1102 current_output_file
= output_file
;
1106 int dir_len
= strlen (output_directory
);
1107 int i
, classname_length
= strlen (classname
);
1108 current_output_file
= (char*) ALLOC (dir_len
+ classname_length
+ 4);
1109 strcpy (current_output_file
, output_directory
);
1110 if (dir_len
> 0 && output_directory
[dir_len
-1] != '/')
1111 current_output_file
[dir_len
++] = '/';
1112 for (i
= 0; classname
[i
] != '\0'; i
++)
1114 char ch
= classname
[i
];
1117 current_output_file
[dir_len
++] = ch
;
1119 if (emit_dependencies
)
1121 if (suppress_output
)
1123 jcf_dependency_set_dep_file ("-");
1128 /* We use `.hd' and not `.d' to avoid clashes with
1129 dependency tracking from straight compilation. */
1130 strcpy (current_output_file
+ dir_len
, ".hd");
1131 jcf_dependency_set_dep_file (current_output_file
);
1134 strcpy (current_output_file
+ dir_len
, ".h");
1135 jcf_dependency_set_target (current_output_file
);
1136 if (! suppress_output
)
1138 out
= fopen (current_output_file
, "w");
1141 perror (current_output_file
);
1146 process_file (&jcf
, out
);
1148 if (current_output_file
!= output_file
)
1149 free (current_output_file
);
1150 jcf_dependency_write ();
1153 if (out
!= NULL
&& out
!= stdout
)
1161 * Do whatever the javah -stubs flag does.
1163 * Emit "structure forward declarations" when needed.
1165 * Generate C headers, like javah