diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-02-03 06:13:46 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-02-03 06:13:46 +0000 |
commit | efa33969fe00fd80b6d74f81bac4a08ab30afad3 (patch) | |
tree | 5df2046d6ef1586cc3a1275a5aea8d35e0a255d3 | |
parent | 1d656f74b6fd314426cd80d41f753acb2221fb94 (diff) | |
download | gcc-efa33969fe00fd80b6d74f81bac4a08ab30afad3.tar.gz |
* gjavah.c (options): Added `jni' entry.
(help): Document -jni.
(flag_jni): New global.
(process_file): Handle JNI output. Don't print text from
-prepend, -add, etc, when generating stubs. Only remove `.class'
suffix if it actually exists.
(main): Create a `.c' file when run with `--jni --stubs'. Create
correct output file name with `--jni'.
(print_include): Mangle header name differently in JNI case.
(HANDLE_METHOD): In JNI mode, call print_method_info to generate
method list.
(print_method_info): Handle JNI case. Put signature info into
method name. Handle case when STREAM is NULL.
(print_name_for_stub_or_jni): New function.
(print_stub_or_jni): Renamed from `print_stub'. Handle JNI.
(print_cxx_classname): Handle JNI.
(print_full_cxx_name): Likewise.
(decode_signature_piece): Likewise.
(overloaded_jni_method_exists_p): New function.
(struct method_name): Added `signature' and `sig_length' fields.
(HANDLE_END_FIELD): Do nothing in JNI mode.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@31767 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/java/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/java/gjavah.c | 480 |
2 files changed, 397 insertions, 107 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 40ac69c6f45..3e41ae56cf6 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,5 +1,29 @@ 2000-02-02 Tom Tromey <tromey@cygnus.com> + * gjavah.c (options): Added `jni' entry. + (help): Document -jni. + (flag_jni): New global. + (process_file): Handle JNI output. Don't print text from + -prepend, -add, etc, when generating stubs. Only remove `.class' + suffix if it actually exists. + (main): Create a `.c' file when run with `--jni --stubs'. Create + correct output file name with `--jni'. + (print_include): Mangle header name differently in JNI case. + (HANDLE_METHOD): In JNI mode, call print_method_info to generate + method list. + (print_method_info): Handle JNI case. Put signature info into + method name. Handle case when STREAM is NULL. + (print_name_for_stub_or_jni): New function. + (print_stub_or_jni): Renamed from `print_stub'. Handle JNI. + (print_cxx_classname): Handle JNI. + (print_full_cxx_name): Likewise. + (decode_signature_piece): Likewise. + (overloaded_jni_method_exists_p): New function. + (struct method_name): Added `signature' and `sig_length' fields. + (HANDLE_END_FIELD): Do nothing in JNI mode. + +2000-02-02 Tom Tromey <tromey@cygnus.com> + * jv-scan.c: Include version.c, <getopt.h>. (LONG_OPT, OPT_HELP, OPT_VERSION): New macros. (options): New array. diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c index 8233c924df2..a9d3ae92033 100644 --- a/gcc/java/gjavah.c +++ b/gcc/java/gjavah.c @@ -45,6 +45,9 @@ FILE *out = NULL; /* Nonzero on failure. */ static int found_error = 0; +/* Nonzero if we're generating JNI output. */ +static int flag_jni = 0; + /* Directory to place resulting files in. Set by -d option. */ const char *output_directory = ""; @@ -105,6 +108,8 @@ struct method_name { unsigned char *name; int length; + unsigned char *signature; + int sig_length; struct method_name *next; }; @@ -115,9 +120,12 @@ static void print_field_info PARAMS ((FILE*, JCF*, int, int, JCF_u2)); static void print_mangled_classname PARAMS ((FILE*, JCF*, const char*, int)); static int print_cxx_classname PARAMS ((FILE*, const char*, JCF*, int)); static void print_method_info PARAMS ((FILE*, JCF*, int, int, JCF_u2)); -static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *)); -static void print_stub PARAMS ((FILE*, JCF*, int, int, int, const char *)); -static void print_full_cxx_name PARAMS ((FILE*, JCF*, int, int, int, const char *)); +static void print_c_decl PARAMS ((FILE*, JCF*, int, int, int, const char *, + int)); +static void print_stub_or_jni PARAMS ((FILE*, JCF*, int, int, int, + const char *, int)); +static void print_full_cxx_name PARAMS ((FILE*, JCF*, int, int, int, + const char *, int)); static void decompile_method PARAMS ((FILE*, JCF*, int)); static void add_class_decl PARAMS ((FILE*, JCF*, JCF_u2)); @@ -161,13 +169,13 @@ static int method_pass; #define HANDLE_END_FIELD() \ if (field_pass) \ { \ - if (out && ! stubs) \ + if (out && ! stubs && ! flag_jni) \ print_field_info (out, jcf, current_field_name, \ current_field_signature, \ current_field_flags); \ } \ - else \ - if (! stubs) add_class_decl (out, jcf, current_field_signature); + else if (! stubs && ! flag_jni) \ + add_class_decl (out, jcf, current_field_signature); #define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX) @@ -181,8 +189,9 @@ static int method_printed = 0; if (out) \ print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \ } \ - else \ - if (! stubs) add_class_decl (out, jcf, SIGNATURE); + else if (flag_jni) \ + print_method_info (NULL, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \ + else if (! stubs) add_class_decl (out, jcf, SIGNATURE); #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \ if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH); @@ -312,8 +321,7 @@ cxx_keyword_subst (str, length) return NULL; } -/* Generate an access control keyword based on FLAGS. Returns 0 if - FLAGS matches the saved access information, nonzero otherwise. */ +/* Generate an access control keyword based on FLAGS. */ static void generate_access (stream, flags) @@ -362,6 +370,28 @@ name_is_method_p (name, length) return 0; } +/* If there is already a method named NAME, whose signature is not + SIGNATURE, then return true. Otherwise return false. */ +static int +overloaded_jni_method_exists_p (name, length, signature, sig_length) + const unsigned char *name; + int length; + const char *signature; + int sig_length; +{ + struct method_name *p; + + for (p = method_name_list; p != NULL; p = p->next) + { + if (p->length == length + && ! memcmp (p->name, name, length) + && (p->sig_length != sig_length + || memcmp (p->signature, signature, sig_length))) + return 1; + } + return 0; +} + /* Get name of a field. This handles renamings due to C++ clash. */ static char * get_field_name (jcf, name_index, flags) @@ -525,7 +555,7 @@ DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags), } override = get_field_name (jcf, name_index, flags); - print_c_decl (out, jcf, name_index, sig_index, 0, override); + print_c_decl (out, jcf, name_index, sig_index, 0, override, flags); fputs (";\n", out); if (override) @@ -543,7 +573,7 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), method_declared = 0; method_access = flags; - if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8) + if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8) fprintf (stream, "<not a UTF8 constant>"); str = JPOOL_UTF_DATA (jcf, name_index); length = JPOOL_UTF_LENGTH (jcf, name_index); @@ -576,9 +606,19 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), memcpy (nn->name, str, length); nn->length = length; nn->next = method_name_list; + nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index); + nn->signature = (char *) xmalloc (nn->sig_length); + memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index), + nn->sig_length); method_name_list = nn; } + /* If we're not printing, then the rest of this function doesn't + matter. This happens during the first method pass in JNI mode. + Eww. */ + if (! stream) + return; + /* We can't generate a method whose name is a C++ reserved word. We can't just ignore the function, because that will cause incorrect code to be generated if the function is virtual (not only for @@ -595,7 +635,7 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), return; } - if (! stubs) + if (! stubs && ! flag_jni) { method_printed = 1; @@ -610,7 +650,7 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), if (! is_init) fputs ("virtual ", out); } - print_c_decl (out, jcf, name_index, sig_index, is_init, override); + print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags); if ((flags & ACC_ABSTRACT)) fputs (" = 0", out); @@ -619,10 +659,11 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags), } else { - if (METHOD_IS_NATIVE(flags)) + if (METHOD_IS_NATIVE (flags)) { method_printed = 1; - print_stub (out, jcf, name_index, sig_index, is_init, override); + print_stub_or_jni (out, jcf, name_index, sig_index, + is_init, override, flags); } } } @@ -704,6 +745,7 @@ decode_signature_piece (stream, signature, limit, need_space) { case '[': /* More spaghetti. */ + array_loop: for (signature++; (signature < limit && *signature >= '0' @@ -711,18 +753,35 @@ decode_signature_piece (stream, signature, limit, need_space) ; switch (*signature) { - case 'B': ctype = "jbyteArray"; goto printit; - case 'C': ctype = "jcharArray"; goto printit; - case 'D': ctype = "jdoubleArray"; goto printit; - case 'F': ctype = "jfloatArray"; goto printit; - case 'I': ctype = "jintArray"; goto printit; - case 'S': ctype = "jshortArray"; goto printit; - case 'J': ctype = "jlongArray"; goto printit; - case 'Z': ctype = "jbooleanArray"; goto printit; + case 'B': + ctype = "jbyteArray"; + break; + case 'C': + ctype = "jcharArray"; + break; + case 'D': + ctype = "jdoubleArray"; + break; + case 'F': + ctype = "jfloatArray"; + break; + case 'I': + ctype = "jintArray"; + break; + case 'S': + ctype = "jshortArray"; + break; + case 'J': + ctype = "jlongArray"; + break; + case 'Z': + ctype = "jbooleanArray"; + break; case '[': /* We have a nested array. */ ++array_depth; - fputs ("JArray<", stream); + if (! flag_jni) + fputs ("JArray<", stream); goto array_loop; case 'L': @@ -730,23 +789,42 @@ decode_signature_piece (stream, signature, limit, need_space) our output matches what the compiler does. */ ++signature; /* Space between `<' and `:' to avoid C++ digraphs. */ - fputs ("JArray< ::", stream); + if (! flag_jni) + fputs ("JArray< ::", stream); while (signature < limit && *signature != ';') { int ch = UTF8_GET (signature, limit); - if (ch == '/') - fputs ("::", stream); - else - jcf_print_char (stream, ch); + if (! flag_jni) + { + if (ch == '/') + fputs ("::", stream); + else + jcf_print_char (stream, ch); + } } - fputs (" *> *", stream); + if (! flag_jni) + fputs (" *> *", stream); *need_space = 0; - ++signature; + ctype = NULL; break; default: /* Unparseable signature. */ return NULL; } + + /* If the previous iterations left us with something to print, + print it. For JNI, we always print `jobjectArray' in the + nested cases. */ + if (flag_jni && ctype == NULL) + { + ctype = "jobjectArray"; + *need_space = 1; + } + /* The `printit' case will advance SIGNATURE for us. If we + don't go there, we must advance past the `;' ourselves. */ + if (ctype != NULL) + goto printit; + ++signature; break; case '(': @@ -764,6 +842,34 @@ decode_signature_piece (stream, signature, limit, need_space) case 'Z': ctype = "jboolean"; goto printit; case 'V': ctype = "void"; goto printit; case 'L': + if (flag_jni) + { + /* We know about certain types and special-case their + names. + FIXME: something like java.lang.Exception should be + printed as `jthrowable', because it is a subclass. This + means that gcjh must read the entire hierarchy and + comprehend it. */ + if (! strncmp (signature, "Ljava/lang/String;", + sizeof ("Ljava/lang/String;") -1)) + ctype = "jstring"; + else if (! strncmp (signature, "Ljava/lang/Class;", + sizeof ("Ljava/lang/Class;") - 1)) + ctype = "jclass"; + else if (! strncmp (signature, "Ljava/lang/Throwable;", + sizeof ("Ljava/lang/Throwable;") - 1)) + ctype = "jthrowable"; + else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;", + sizeof ("Ljava/lang/ref/WeakReference;") - 1)) + ctype = "jweak"; + else + ctype = "jobject"; + + while (*signature && *signature != ';') + ++signature; + + goto printit; + } /* Print a leading "::" so we look in the right namespace. */ fputs ("::", stream); ++signature; @@ -792,18 +898,21 @@ decode_signature_piece (stream, signature, limit, need_space) break; } - while (array_depth-- > 0) - fputs ("> *", stream); + if (! flag_jni) + { + while (array_depth-- > 0) + fputs ("> *", stream); + } return signature; } static void DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init, - name_override), + name_override, flags), FILE* stream AND JCF* jcf AND int name_index AND int signature_index - AND int is_init AND const char *name_override) + AND int is_init AND const char *name_override AND int flags) { if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8) { @@ -850,16 +959,18 @@ DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init, if (need_space) fputs (" ", stream); print_full_cxx_name (stream, jcf, name_index, - signature_index, is_init, name_override); + signature_index, is_init, name_override, + flags); } } /* Print the unqualified method name followed by the signature. */ static void -DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, is_init, name_override), +DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, + is_init, name_override, flags), FILE* stream AND JCF* jcf AND int name_index AND int signature_index AND int is_init - AND const char *name_override) + AND const char *name_override AND int flags) { int length = JPOOL_UTF_LENGTH (jcf, signature_index); const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index); @@ -879,13 +990,75 @@ DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, is_init, n else print_name (stream, jcf, name_index); } - + + if (flag_jni) + { + unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index); + int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index); + if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index), + JPOOL_UTF_LENGTH (jcf, name_index), + signature, sig_len)) + { + /* If this method is overloaded by another native method, + then include the argument information in the mangled + name. */ + unsigned char *limit = signature + sig_len; + fputs ("__", stream); + while (signature < limit) + { + int ch = UTF8_GET (signature, limit); + if (ch == '(') + { + /* Ignore. */ + } + else if (ch == ')') + { + /* Done. */ + break; + } + else if (ch == '_') + fputs ("_1", stream); + else if (ch == ';') + fputs ("_2", stream); + else if (ch == '[') + fputs ("_3", stream); + else if (ch == '/') + fputs ("_", stream); + else if ((ch >= '0' && ch <= '9') + || (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z')) + fputc (ch, stream); + else + { + /* "Unicode" character. FIXME: upper or lower case + letters? */ + fprintf (stream, "_0%04x", ch); + } + } + } + } + if (is_method) { /* Have a method or a constructor. Print signature pieces until done. */ fputs (" (", stream); + str = str0 + 1; + + /* In JNI mode, add extra arguments. */ + if (flag_jni) + { + /* FIXME: it would be nice to know if we are printing a decl + or a definition, and only print `env' for the latter. */ + fputs ("JNIEnv *env", stream); + + fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream); + + if (*str != ')') + fputs (", ", stream); + } + while (str < limit && *str != ')') { next = decode_signature_piece (stream, str, limit, &need_space); @@ -905,12 +1078,28 @@ DEFUN(print_full_cxx_name, (stream, jcf, name_index, signature_index, is_init, n } } +/* This is a helper for print_stub_or_jni. */ static void -DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init, - name_override), +DEFUN (print_name_for_stub_or_jni, (stream, jcf, name_index, signature_index, + is_init, name_override, flags), + FILE *stream AND JCF *jcf + AND int name_index AND int signature_index + AND int is_init AND const char *name_override AND int flags) +{ + char *prefix = flag_jni ? "Java_" : "\n"; + print_cxx_classname (stream, prefix, jcf, jcf->this_class); + fputs (flag_jni ? "_" : "::", stream); + print_full_cxx_name (stream, jcf, name_index, + signature_index, is_init, name_override, + flags); +} + +static void +DEFUN(print_stub_or_jni, (stream, jcf, name_index, signature_index, is_init, + name_override, flags), FILE* stream AND JCF* jcf AND int name_index AND int signature_index - AND int is_init AND const char *name_override) + AND int is_init AND const char *name_override AND int flags) { if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8) { @@ -927,6 +1116,13 @@ DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init, int is_method = str[0] == '('; const unsigned char *next; + /* Don't print fields in the JNI case. */ + if (! is_method && flag_jni) + return; + + if (flag_jni && ! stubs) + fputs ("extern ", stream); + /* If printing a method, skip to the return signature and print that first. However, there is no return value if this is a constructor. */ @@ -941,7 +1137,8 @@ DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init, } /* If printing a field or an ordinary method, then print the - "return value" now. */ + "return value" now. Note that a constructor can't be native, + so we don't bother checking this in the JNI case. */ if (! is_method || ! is_init) { next = decode_signature_piece (stream, str, limit, &need_space); @@ -953,17 +1150,29 @@ DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init, } } + /* When printing a JNI header we need to respect the space. In + other cases we're just going to insert a newline anyway. */ + if (flag_jni) + fputs (need_space && ! stubs ? " " : "\n", stream); + /* Now print the name of the thing. */ - print_cxx_classname (stream, "\n", jcf, jcf->this_class); - fputs ("::", stream); - print_full_cxx_name (stream, jcf, name_index, - signature_index, is_init, name_override); - fputs ("\n{\n JvFail (\"", stream); - print_cxx_classname (stream, "", jcf, jcf->this_class); - fputs ("::", stream); - print_full_cxx_name (stream, jcf, name_index, - signature_index, is_init, name_override); - fputs (" not implemented\");\n}\n\n", stream); + print_name_for_stub_or_jni (stream, jcf, name_index, + signature_index, is_init, name_override, + flags); + + /* Print the body. */ + if (stubs) + { + if (flag_jni) + fputs ("\n{\n (*env)->FatalError (\"", stream); + else + fputs ("\n{\n JvFail (\"", stream); + print_name_for_stub_or_jni (stream, jcf, name_index, + signature_index, is_init, + name_override, + flags); + fputs (" not implemented\");\n}\n\n", stream); + } } } @@ -1006,13 +1215,14 @@ print_cxx_classname (stream, prefix, jcf, index) fputs (prefix, stream); /* Print a leading "::" so we look in the right namespace. */ - fputs ("::", stream); + if (! flag_jni) + fputs ("::", stream); while (s < limit) { c = UTF8_GET (s, limit); if (c == '/') - fputs ("::", stream); + fputs (flag_jni ? "_" : "::", stream); else jcf_print_char (stream, c); } @@ -1084,7 +1294,9 @@ print_include (out, utf8, len) all_includes = incl; fputs ("#include <", out); - jcf_print_utf8 (out, utf8, len); + jcf_print_utf8_replace (out, utf8, len, + '/', + flag_jni ? '_' : '/'); fputs (".h>\n", out); } @@ -1356,17 +1568,46 @@ DEFUN(process_file, (jcf, out), if (written_class_count++ == 0 && out) { + char *cstart, *cstart2, *mode, *cend, *what, *jflag; + if (flag_jni) + { + cstart = "/*"; + cstart2 = " "; + cend = " */"; + mode = ""; + what = "JNI"; + jflag = " -jni"; + } + else + { + cstart = "//"; + cstart2 = "//"; + cend = ""; + mode = " -*- c++ -*-"; + what = "CNI"; + jflag = ""; + } + if (! stubs) - fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n", - out); + fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n", + cstart, mode, cend); else { - fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.\n\ -//\n\ -// This file is intended to give you a head start on implementing native\n\ -// methods using CNI.\n\ -// Be aware: running `gcjh -stubs' once more for this class may overwrite any\n\ -// edits you have made to this file.\n\n", out); + fprintf (out, "%s This file was created by `gcjh -stubs%s'.%s\n\ +%s\n\ +%s This file is intended to give you a head start on implementing native\n\ +%s methods using %s.\n\ +%s Be aware: running `gcjh -stubs %s' once more for this class may\n\ +%s overwrite any edits you have made to this file.%s\n\n", + cstart, jflag, mode, + cstart2, + cstart2, + cstart2, + what, + cstart2, + jflag, + cstart2, + cend); } } @@ -1376,30 +1617,44 @@ DEFUN(process_file, (jcf, out), { print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class); fprintf (out, "__\n"); - + print_mangled_classname (out, jcf, "#define __", jcf->this_class); fprintf (out, "__\n\n"); - - /* We do this to ensure that inline methods won't be `outlined' - by g++. This works as long as method and fields are not - added by the user. */ - fprintf (out, "#pragma interface\n"); - - if (jcf->super_class) + + if (flag_jni) { - int super_length; - const unsigned char *supername = - super_class_name (jcf, &super_length); - - fputs ("\n", out); - print_include (out, supername, super_length); + fprintf (out, "#include <jni.h>\n\n"); + fprintf (out, "#ifdef __cplusplus\n"); + fprintf (out, "extern \"C\"\n"); + fprintf (out, "{\n"); + fprintf (out, "#endif\n"); + } + else + { + /* We do this to ensure that inline methods won't be + `outlined' by g++. This works as long as method and + fields are not added by the user. */ + fprintf (out, "#pragma interface\n"); + + if (jcf->super_class) + { + int super_length; + const unsigned char *supername = + super_class_name (jcf, &super_length); + + fputs ("\n", out); + print_include (out, supername, super_length); + } } } else { /* Strip off the ".class" portion of the name when printing the include file name. */ - print_include (out, jcf->classname, strlen (jcf->classname) - 6); + int len = strlen (jcf->classname); + if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class")) + len -= 6; + print_include (out, jcf->classname, len); } } @@ -1417,9 +1672,10 @@ DEFUN(process_file, (jcf, out), jcf_parse_methods (jcf); if (out) - { - fputs ("\n", out); + fputs ("\n", out); + if (out && ! flag_jni) + { if (! stubs) print_class_decls (out, jcf, jcf->this_class); @@ -1427,7 +1683,7 @@ DEFUN(process_file, (jcf, out), fprintf (out, "%s\n", prepend_specs[i]); if (prepend_count > 0) fputc ('\n', out); - + if (! stubs) { if (! print_cxx_classname (out, "class ", jcf, jcf->this_class)) @@ -1464,32 +1720,38 @@ DEFUN(process_file, (jcf, out), jcf_parse_final_attributes (jcf); - if (out) + if (out && ! stubs) { - /* Generate friend decl if we still must. */ - for (i = 0; i < friend_count; ++i) - fprintf (out, " friend %s\n", friend_specs[i]); - - /* Generate extra declarations. */ - if (add_count > 0) - fputc ('\n', out); - for (i = 0; i < add_count; ++i) - fprintf (out, " %s\n", add_specs[i]); - - if (! stubs) - fputs ("};\n", out); - - if (append_count > 0) - fputc ('\n', out); - for (i = 0; i < append_count; ++i) - fprintf (out, "%s\n", append_specs[i]); - - if (!stubs) + if (flag_jni) { - print_mangled_classname (out, jcf, - "\n#endif /* __", jcf->this_class); - fprintf (out, "__ */\n"); + fprintf (out, "\n#ifdef __cplusplus\n"); + fprintf (out, "}\n"); + fprintf (out, "#endif\n"); } + else + { + /* Generate friend decl if we still must. */ + for (i = 0; i < friend_count; ++i) + fprintf (out, " friend %s\n", friend_specs[i]); + + /* Generate extra declarations. */ + if (add_count > 0) + fputc ('\n', out); + for (i = 0; i < add_count; ++i) + fprintf (out, " %s\n", add_specs[i]); + + if (! stubs) + fputs ("};\n", out); + + if (append_count > 0) + fputc ('\n', out); + for (i = 0; i < append_count; ++i) + fprintf (out, "%s\n", append_specs[i]); + } + + print_mangled_classname (out, jcf, + "\n#endif /* __", jcf->this_class); + fprintf (out, "__ */\n"); } } @@ -1531,6 +1793,7 @@ static struct option options[] = { "MG", no_argument, NULL, OPT_MG }, { "MD", no_argument, NULL, OPT_MD }, { "MMD", no_argument, NULL, OPT_MMD }, + { "jni", no_argument, &flag_jni, 1 }, { NULL, no_argument, NULL, 0 } }; @@ -1547,6 +1810,7 @@ help () printf ("Usage: gcjh [OPTION]... CLASS...\n\n"); printf ("Generate C++ header files from .class files\n\n"); printf (" -stubs Generate an implementation stub file\n"); + printf (" -jni Generate a JNI header or stub\n"); printf ("\n"); printf (" -add TEXT Insert TEXT into class body\n"); printf (" -append TEXT Insert TEXT after class declaration\n"); @@ -1767,6 +2031,8 @@ DEFUN(main, (argc, argv), char ch = classname[i]; if (ch == '.') ch = '/'; + if (flag_jni && ch == '/') + ch = '_'; current_output_file[dir_len++] = ch; } if (emit_dependencies) @@ -1785,7 +2051,7 @@ DEFUN(main, (argc, argv), } } strcpy (current_output_file + dir_len, - stubs ? ".cc" : ".h"); + stubs ? (flag_jni ? ".c" : ".cc") : ".h"); jcf_dependency_set_target (current_output_file); if (! suppress_output) { |