aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/gjavah.c
diff options
context:
space:
mode:
authorAnthony Green <green@cygnus.com>1999-07-25 10:12:49 +0000
committerAnthony Green <green@gcc.gnu.org>1999-07-25 10:12:49 +0000
commit6c9c5c1f7aa85d8e21108406ea507dfcb0d5c831 (patch)
tree0984a5702f9f86b72f2fe325183cb944d50fa044 /gcc/java/gjavah.c
parenta08b508225e8b9194328642001208bf0170e969a (diff)
downloadgcc-6c9c5c1f7aa85d8e21108406ea507dfcb0d5c831.zip
gcc-6c9c5c1f7aa85d8e21108406ea507dfcb0d5c831.tar.gz
gcc-6c9c5c1f7aa85d8e21108406ea507dfcb0d5c831.tar.bz2
gjavah.c (print_stub): New function.
* gjavah.c (print_stub): New function. (METHOD_IS_NATIVE): New macro. (print_mangled_classname): Make static. (HANDLE_END_FIELD): Don't emit fields during stub generation. (process_file): Perform stub generation. (HANDLE_METHOD): Don't emit class decls during stub generation. (HANDLE_END_METHOD): Take into account stub generation. (print_method_info): Handle stub generation. (print_stub): New function. (print_cxx_classname): Make signature consistant with others. (help): Describe -stubs option. (main): Create stub file. (version): Use version.c. (print_full_cxx_name): New function. (print_c_decl): Use print_full_cxx_name. From-SVN: r28236
Diffstat (limited to 'gcc/java/gjavah.c')
-rw-r--r--gcc/java/gjavah.c329
1 files changed, 232 insertions, 97 deletions
diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c
index f99ad5b..500aa2c 100644
--- a/gcc/java/gjavah.c
+++ b/gcc/java/gjavah.c
@@ -33,6 +33,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "java-tree.h"
#include "java-opcodes.h"
+#include "version.c"
+
/* The output file. */
FILE *out = NULL;
@@ -88,6 +90,11 @@ static JCF_u2 last_access;
#define METHOD_IS_FINAL(Class, Method) \
(((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
+/* Pass this macro the flags for a method. It will return true if the
+ method is native. */
+#define METHOD_IS_NATIVE(Method) \
+ ((Method) & ACC_NATIVE)
+
/* We keep a linked list of all method names we have seen. This lets
us determine if a method name and a field name are in conflict. */
struct method_name
@@ -100,11 +107,15 @@ struct method_name
/* List of method names we've seen. */
static struct method_name *method_name_list;
-static void print_field_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
-static void print_method_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
+static void print_field_info PROTO ((FILE*, JCF*, int, int, JCF_u2));
+static void print_mangled_classname PROTO ((FILE*, JCF*, const char*, int));
+static int print_cxx_classname PROTO ((FILE*, const char*, JCF*, int));
+static void print_method_info PROTO ((FILE*, JCF*, int, int, JCF_u2));
static void print_c_decl PROTO ((FILE*, JCF*, int, int, int, const char *));
-static void decompile_method PROTO ((FILE *, JCF *, int));
-static void add_class_decl PROTO ((FILE *, JCF *, JCF_u2));
+static void print_stub PROTO ((FILE*, JCF*, int, int, int, const char *));
+static void print_full_cxx_name PROTO ((FILE*, JCF*, int, int, int, const char *));
+static void decompile_method PROTO ((FILE*, JCF*, int));
+static void add_class_decl PROTO ((FILE*, JCF*, JCF_u2));
static int java_float_finite PROTO ((jfloat));
static int java_double_finite PROTO ((jdouble));
@@ -130,13 +141,13 @@ static int method_pass;
#define HANDLE_END_FIELD() \
if (field_pass) \
{ \
- if (out) \
+ if (out && ! stubs) \
print_field_info (out, jcf, current_field_name, \
current_field_signature, \
current_field_flags); \
} \
else \
- add_class_decl (out, jcf, current_field_signature);
+ if (! stubs) add_class_decl (out, jcf, current_field_signature);
#define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
@@ -151,14 +162,14 @@ static int method_printed = 0;
print_method_info (out, jcf, NAME, SIGNATURE, ACCESS_FLAGS); \
} \
else \
- add_class_decl (out, jcf, SIGNATURE);
+ 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);
static int decompiled = 0;
#define HANDLE_END_METHOD() \
- if (out && method_printed) fputs (decompiled ? "\n" : ";\n", out);
+ if (out && method_printed) fputs (decompiled || stubs ? "\n" : ";\n", out);
#include "jcf-reader.c"
@@ -562,24 +573,36 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
return;
}
- method_printed = 1;
- generate_access (stream, flags);
-
- fputs (" ", out);
- if ((flags & ACC_STATIC))
- fputs ("static ", out);
- else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
+ if (! stubs)
{
- /* Don't print `virtual' if we have a constructor. */
- if (! is_init)
- fputs ("virtual ", out);
- }
- print_c_decl (out, jcf, name_index, sig_index, is_init, override);
+ method_printed = 1;
- if ((flags & ACC_ABSTRACT))
- fputs (" = 0", out);
+ generate_access (stream, flags);
+
+ fputs (" ", out);
+ if ((flags & ACC_STATIC))
+ fputs ("static ", out);
+ else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
+ {
+ /* Don't print `virtual' if we have a constructor. */
+ if (! is_init)
+ fputs ("virtual ", out);
+ }
+ print_c_decl (out, jcf, name_index, sig_index, is_init, override);
+
+ if ((flags & ACC_ABSTRACT))
+ fputs (" = 0", out);
+ else
+ method_declared = 1;
+ }
else
- method_declared = 1;
+ {
+ if (METHOD_IS_NATIVE(flags))
+ {
+ method_printed = 1;
+ print_stub (out, jcf, name_index, sig_index, is_init, override);
+ }
+ }
}
/* Try to decompile a method body. Right now we just try to handle a
@@ -791,40 +814,121 @@ DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, is_init,
/* Now print the name of the thing. */
if (need_space)
fputs (" ", stream);
- if (name_override)
- fputs (name_override, stream);
- else if (name_index)
+ print_full_cxx_name (stream, jcf, name_index,
+ signature_index, is_init, name_override);
+ }
+}
+
+// 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),
+ FILE* stream AND JCF* jcf
+ AND int name_index AND int signature_index AND int is_init
+ AND const char *name_override)
+{
+ int length = JPOOL_UTF_LENGTH (jcf, signature_index);
+ unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
+ register unsigned char *str = str0;
+ unsigned char *limit = str + length;
+ int need_space = 0;
+ int is_method = str[0] == '(';
+ unsigned char *next;
+
+ if (name_override)
+ fputs (name_override, stream);
+ else if (name_index)
+ {
+ /* Declare constructors specially. */
+ if (is_init)
+ print_base_classname (stream, jcf, jcf->this_class);
+ else
+ print_name (stream, jcf, name_index);
+ }
+
+ if (is_method)
+ {
+ /* Have a method or a constructor. Print signature pieces
+ until done. */
+ fputs (" (", stream);
+ str = str0 + 1;
+ while (str < limit && *str != ')')
{
- /* Declare constructors specially. */
- if (is_init)
- print_base_classname (stream, jcf, jcf->this_class);
- else
- print_name (stream, jcf, name_index);
+ next = decode_signature_piece (stream, str, limit, &need_space);
+ if (! next)
+ {
+ fprintf (stderr, "unparseable signature: `%s'\n", str0);
+ found_error = 1;
+ return;
+ }
+
+ if (next < limit && *next != ')')
+ fputs (", ", stream);
+ str = next;
}
+
+ fputs (")", stream);
+ }
+}
+
+static void
+DEFUN(print_stub, (stream, jcf, name_index, signature_index, is_init,
+ name_override),
+ FILE* stream AND JCF* jcf
+ AND int name_index AND int signature_index
+ AND int is_init AND const char *name_override)
+{
+ if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
+ {
+ fprintf (stream, "<not a UTF8 constant>");
+ found_error = 1;
+ }
+ else
+ {
+ int length = JPOOL_UTF_LENGTH (jcf, signature_index);
+ unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
+ register unsigned char *str = str0;
+ unsigned char *limit = str + length;
+ int need_space = 0;
+ int is_method = str[0] == '(';
+ unsigned char *next;
- if (is_method)
+ /* If printing a method, skip to the return signature and print
+ that first. However, there is no return value if this is a
+ constructor. */
+ if (is_method && ! is_init)
{
- /* Have a method or a constructor. Print signature pieces
- until done. */
- fputs (" (", stream);
- str = str0 + 1;
- while (str < limit && *str != ')')
+ while (str < limit)
{
- next = decode_signature_piece (stream, str, limit, &need_space);
- if (! next)
- {
- fprintf (stderr, "unparseable signature: `%s'\n", str0);
- found_error = 1;
- return;
- }
-
- if (next < limit && *next != ')')
- fputs (", ", stream);
- str = next;
+ int ch = *str++;
+ if (ch == ')')
+ break;
}
+ }
- fputs (")", stream);
+ /* If printing a field or an ordinary method, then print the
+ "return value" now. */
+ if (! is_method || ! is_init)
+ {
+ next = decode_signature_piece (stream, str, limit, &need_space);
+ if (! next)
+ {
+ fprintf (stderr, "unparseable signature: `%s'\n", str0);
+ found_error = 1;
+ return;
+ }
}
+
+ /* 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);
}
}
@@ -846,7 +950,7 @@ DEFUN(print_mangled_classname, (stream, jcf, prefix, index),
static int
print_cxx_classname (stream, prefix, jcf, index)
FILE *stream;
- char *prefix;
+ const char *prefix;
JCF *jcf;
int index;
{
@@ -1204,30 +1308,49 @@ DEFUN(process_file, (jcf, out),
jcf_parse_class (jcf);
if (written_class_count++ == 0 && out)
- fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
- out);
+ if (! stubs)
+ fputs ("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-\n\n",
+ out);
+ else
+ {
+ fputs ("// This file was created by `gcjh -stubs'. It is -*- c++ -*-.
+//
+// This file is intended to give you a head start on implementing native
+// methods using CNI.
+// Be aware: running `gcjh -stubs' once more for this class may overwrite any
+// edits you have made to this file.\n\n", out);
+ }
if (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 && out)
- {
- int super_length;
- unsigned char *supername = super_class_name (jcf, &super_length);
-
- fputs ("\n", out);
- print_include (out, supername, super_length);
+ if (! stubs)
+ {
+ 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)
+ {
+ int super_length;
+ 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);
+ }
}
/* We want to parse the methods first. But we need to find where
@@ -1246,31 +1369,37 @@ DEFUN(process_file, (jcf, out),
if (out)
{
fputs ("\n", out);
- print_class_decls (out, jcf, jcf->this_class);
+
+ if (! stubs)
+ print_class_decls (out, jcf, jcf->this_class);
for (i = 0; i < prepend_count; ++i)
fprintf (out, "%s\n", prepend_specs[i]);
if (prepend_count > 0)
fputc ('\n', out);
- }
-
- if (out && ! print_cxx_classname (out, "class ", jcf, jcf->this_class))
- {
- fprintf (stderr, "class is of array type\n");
- found_error = 1;
- return;
- }
- if (out && jcf->super_class)
- {
- if (! print_cxx_classname (out, " : public ", jcf, jcf->super_class))
+
+ if (! stubs)
{
- fprintf (stderr, "base class is of array type\n");
- found_error = 1;
- return;
+ if (! print_cxx_classname (out, "class ", jcf, jcf->this_class))
+ {
+ fprintf (stderr, "class is of array type\n");
+ found_error = 1;
+ return;
+ }
+ if (jcf->super_class)
+ {
+ if (! print_cxx_classname (out, " : public ",
+ jcf, jcf->super_class))
+ {
+ fprintf (stderr, "base class is of array type\n");
+ found_error = 1;
+ return;
+ }
+ }
+
+ fputs ("\n{\n", out);
}
}
- if (out)
- fputs ("\n{\n", out);
/* Now go back for second pass over methods and fields. */
JCF_SEEK (jcf, method_start);
@@ -1297,15 +1426,20 @@ DEFUN(process_file, (jcf, out),
for (i = 0; i < add_count; ++i)
fprintf (out, " %s\n", add_specs[i]);
- fputs ("};\n", out);
+ 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");
+ if (!stubs)
+ {
+ print_mangled_classname (out, jcf,
+ "\n#endif /* __", jcf->this_class);
+ fprintf (out, "__ */\n");
+ }
}
}
@@ -1327,6 +1461,7 @@ help ()
printf (" -d DIRECTORY Set output directory name\n");
printf (" --help Print this help, then exit\n");
printf (" -o FILE Set output file name\n");
+ printf (" -stubs Generate a C++ implementation stub file\n");
printf (" -td DIRECTORY Set temporary directory name\n");
printf (" -v, --verbose Print extra information while running\n");
printf (" --version Print version number, then exit\n");
@@ -1346,8 +1481,8 @@ static void
version ()
{
/* FIXME: use version.c? */
- printf ("gcjh (GNU gcc) 0.0\n\n");
- printf ("Copyright (C) 1998 Free Software Foundation, Inc.\n");
+ printf ("gcjh (%s)\n\n", version_string);
+ printf ("Copyright (C) 1998, 1999 Free Software Foundation, Inc.\n");
printf ("This is free software; see the source for copying conditions. There is NO\n");
printf ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
exit (0);
@@ -1548,7 +1683,7 @@ DEFUN(main, (argc, argv),
{
int dir_len = strlen (output_directory);
int i, classname_length = strlen (classname);
- current_output_file = (char*) ALLOC (dir_len + classname_length + 4);
+ current_output_file = (char*) ALLOC (dir_len + classname_length + 5);
strcpy (current_output_file, output_directory);
if (dir_len > 0 && output_directory[dir_len-1] != '/')
current_output_file[dir_len++] = '/';
@@ -1574,7 +1709,8 @@ DEFUN(main, (argc, argv),
jcf_dependency_set_dep_file (current_output_file);
}
}
- strcpy (current_output_file + dir_len, ".h");
+ strcpy (current_output_file + dir_len,
+ stubs ? ".cc" : ".h");
jcf_dependency_set_target (current_output_file);
if (! suppress_output)
{
@@ -1601,10 +1737,9 @@ DEFUN(main, (argc, argv),
/* TODO:
- * Do whatever the javah -stubs flag does.
-
* Emit "structure forward declarations" when needed.
* Generate C headers, like javah
*/
+