📄 gjavah.c
字号:
{ struct method_name *nn; nn = (struct method_name *) malloc (sizeof (struct method_name)); nn->name = (char *) malloc (length); memcpy (nn->name, str, length); nn->length = length; nn->next = method_name_list; method_name_list = nn; } /* 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 calls to this function for for other functions after it in the vtbl). So we give it a dummy name instead. */ override = cxx_keyword_subst (str, length); if (override) { /* If the method is static or final, we can safely skip it. If we don't skip it then we'll have problems since the mangling will be wrong. FIXME. */ if (METHOD_IS_FINAL (jcf->access_flags, flags) || (flags & ACC_STATIC)) 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)) { /* 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;}/* Try to decompile a method body. Right now we just try to handle a simple case that we can do. Expand as desired. */static voiddecompile_method (out, jcf, code_len) FILE *out; JCF *jcf; int code_len;{ unsigned char *codes = jcf->read_ptr; int index; uint16 name_and_type, name; /* If the method is synchronized, don't touch it. */ if ((method_access & ACC_SYNCHRONIZED)) return; if (code_len == 5 && codes[0] == OPCODE_aload_0 && codes[1] == OPCODE_getfield && (codes[4] == OPCODE_areturn || codes[4] == OPCODE_dreturn || codes[4] == OPCODE_freturn || codes[4] == OPCODE_ireturn || codes[4] == OPCODE_lreturn)) { /* Found code like `return FIELD'. */ fputs (" { return ", out); index = (codes[2] << 8) | codes[3]; /* FIXME: ensure that tag is CONSTANT_Fieldref. */ /* FIXME: ensure that the field's class is this class. */ name_and_type = JPOOL_USHORT2 (jcf, index); /* FIXME: ensure that tag is CONSTANT_NameAndType. */ name = JPOOL_USHORT1 (jcf, name_and_type); print_name (out, jcf, name); fputs ("; }", out); decompiled = 1; } else if (code_len == 2 && codes[0] == OPCODE_aload_0 && codes[1] == OPCODE_areturn) { /* Found `return this'. */ fputs (" { return this; }", out); decompiled = 1; } else if (code_len == 1 && codes[0] == OPCODE_return) { /* Found plain `return'. */ fputs (" { }", out); decompiled = 1; } else if (code_len == 2 && codes[0] == OPCODE_aconst_null && codes[1] == OPCODE_areturn) { /* Found `return null'. We don't want to depend on NULL being defined. */ fputs (" { return 0; }", out); decompiled = 1; }}/* Print one piece of a signature. Returns pointer to next parseable character on success, NULL on error. */static unsigned char *decode_signature_piece (stream, signature, limit, need_space) FILE *stream; unsigned char *signature, *limit; int *need_space;{ const char *ctype; switch (signature[0]) { case '[': for (signature++; (signature < limit && *signature >= '0' && *signature <= '9'); signature++) ; 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 '[': ctype = "jobjectArray"; goto printit; case 'L': /* We have to generate a reference to JArray here, so that our output matches what the compiler does. */ ++signature; fputs ("JArray<", stream); while (signature < limit && *signature != ';') { int ch = UTF8_GET (signature, limit); if (ch == '/') fputs ("::", stream); else jcf_print_char (stream, ch); } fputs (" *> *", stream); *need_space = 0; ++signature; break; default: /* Unparseable signature. */ return NULL; } break; case '(': case ')': /* This shouldn't happen. */ return NULL; case 'B': ctype = "jbyte"; goto printit; case 'C': ctype = "jchar"; goto printit; case 'D': ctype = "jdouble"; goto printit; case 'F': ctype = "jfloat"; goto printit; case 'I': ctype = "jint"; goto printit; case 'J': ctype = "jlong"; goto printit; case 'S': ctype = "jshort"; goto printit; case 'Z': ctype = "jboolean"; goto printit; case 'V': ctype = "void"; goto printit; case 'L': ++signature; while (*signature && *signature != ';') { int ch = UTF8_GET (signature, limit); /* `$' is the separator for an inner class. */ if (ch == '/' || ch == '$') fputs ("::", stream); else jcf_print_char (stream, ch); } fputs (" *", stream); if (*signature == ';') signature++; *need_space = 0; break; default: *need_space = 1; jcf_print_char (stream, *signature++); break; printit: signature++; *need_space = 1; fputs (ctype, stream); break; } return signature;}static voidDEFUN(print_c_decl, (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 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) { while (str < limit) { int ch = *str++; if (ch == ')') break; } } /* 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. */ if (need_space) fputs (" ", stream); 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 != ')') { 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); } }}voidDEFUN(print_mangled_classname, (stream, jcf, prefix, index), FILE *stream AND JCF *jcf AND const char *prefix AND int index){ int name_index = JPOOL_USHORT1 (jcf, index); fputs (prefix, stream); jcf_print_utf8_replace (out, JPOOL_UTF_DATA (jcf, name_index), JPOOL_UTF_LENGTH (jcf, name_index), '/', '_');}/* Print PREFIX, then a class name in C++ format. If the name refers to an array, ignore it and don't print PREFIX. Returns 1 if something was printed, 0 otherwise. */static intprint_cxx_classname (stream, prefix, jcf, index) FILE *stream; char *prefix; JCF *jcf; int index;{ int name_index = JPOOL_USHORT1 (jcf, index); int len, c; unsigned char *s, *p, *limit; s = JPOOL_UTF_DATA (jcf, name_index); len = JPOOL_UTF_LENGTH (jcf, name_index); limit = s + len; /* Explicitly omit arrays here. */ p = s; c = UTF8_GET (p, limit); if (c == '[') return 0; fputs (prefix, stream); while (s < limit) { c = UTF8_GET (s, limit); if (c == '/') fputs ("::", stream); else jcf_print_char (stream, c); } return 1;}int written_class_count = 0;/* Return name of superclass. If LEN is not NULL, fill it with length of name. */static unsigned char *super_class_name (derived_jcf, len) JCF *derived_jcf; int *len;{ int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class); int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index); unsigned char *supername = JPOOL_UTF_DATA (derived_jcf, supername_index); if (len) *len = supername_length; return supername;}/* We keep track of all the `#include's we generate, so we can avoid duplicates. */struct include{ char *name; struct include *next;};/* List of all includes. */static struct include *all_includes = NULL;/* Generate a #include. */static voidprint_include (out, utf8, len) FILE *out; unsigned char *utf8; int len;{ struct include *incl; if (! out) return; if (len == -1) len = strlen (utf8); for (incl = all_includes; incl; incl = incl->next) { /* We check the length because we might have a proper prefix. */ if (len == (int) strlen (incl->name) && ! strncmp (incl->name, utf8, len)) return; } incl = (struct include *) malloc (sizeof (struct include)); incl->name = malloc (len + 1); strncpy (incl->name, utf8, len); incl->name[len] = '\0'; incl->next = all_includes; all_includes = incl; fputs ("#include <", out); jcf_print_utf8 (out, utf8, len); fputs (".h>\n", out);}/* This is used to represent part of a package or class name. */struct namelet{ /* The text of this part of the name. */ char *name; /* True if this represents a class. */ int is_class; /* Linked list of all classes and packages inside this one. */ struct namelet *subnamelets; /* Pointer to next sibling. */ struct namelet *next;};/* The special root namelet. */static struct namelet root ={ NULL, 0, NULL, NULL};/* This extracts the next name segment from the full UTF-8 encoded package or class name and links it into the tree. It does this recursively. */static voidadd_namelet (name, name_limit, parent) unsigned char *name, *name_limit; struct namelet *parent;{ unsigned char *p; struct namelet *n = NULL, *np; /* We want to skip the standard namespaces that we assume the runtime already knows about. We only do this at the top level, though, hence the check for `root'. */ if (parent == &root) {#define JAVALANG "java/lang/"#define JAVAIO "java/io/"#define JAVAUTIL "java/util/" if ((name_limit - name >= (int) sizeof (JAVALANG) - 1 && ! strncmp (name, JAVALANG, sizeof (JAVALANG) - 1)) || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1 && ! strncmp (name, JAVAUTIL, sizeof (JAVAUTIL) - 1)) || (name_limit - name >= (int) sizeof (JAVAIO) - 1 && ! strncmp (name, JAVAIO, sizeof (JAVAIO) - 1))) return; } for (p = name; p < name_limit && *p != '/' && *p != '$'; ++p) ; /* Search for this name beneath the PARENT node. */ for (np = parent->subnamelets; np != NULL; np = np->next) { /* We check the length because we might have a proper prefix. */ if ((int) strlen (np->name) == p - name && ! strncmp (name, np->name, p - name)) { n = np; break; } } if (n == NULL) { n = (struct namelet *) malloc (sizeof (struct namelet)); n->name = malloc (p - name + 1); strncpy (n->name, name, p - name); n->name[p - name] = '\0'; n->is_class = (p == name_limit || *p == '$'); n->subnamelets = NULL; n->next = parent->subnamelets; parent->subnamelets = n; } /* We recurse if there is more text, and if the trailing piece does not represent an inner class. */ if (p < name_limit && *p != '$') add_namelet (p + 1, name_limit, n);}/* Print a single namelet. Destroys namelets while printing. */static voidprint_namelet (out, name, depth) FILE *out; struct namelet *name; int depth;{ int i, term = 0; struct namelet *c; if (name->name) { for (i = 0; i < depth; ++i) fputc (' ', out); fprintf (out, "%s %s", name->is_class ? "class" : "namespace", name->name); if (name->is_class && name->subnamelets == NULL) fputs (";\n", out); else { term = 1; fputs ("\n", out); for (i = 0; i < depth; ++i) fputc (' ', out); fputs ("{\n", out); } } c = name->subnamelets; while (c != NULL) { struct namelet *next = c->next; print_namelet (out, c, depth + 2); c = next; } if (name->name) { if (term) { for (i = 0; i < depth; ++i) fputc (' ', out); fputs ("};\n", out);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -