Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/gen.c URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/gen.c?rev=294974&view=auto ============================================================================== --- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/gen.c (added) +++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/gen.c Tue Oct 4 19:19:16 2005 @@ -0,0 +1,474 @@ + +/* + * Copyright 2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: gen.c,v 1.3 2005/05/08 21:12:07 archiecobbs Exp $ + */ + +#include "javah.h" + +struct flag_name { + uint16_t flag; + const char *name; +}; + +struct jni_name { + const char *name; + const char *ctype; +}; + +static const struct flag_name flag_names[] = { + { _JC_ACC_PUBLIC, "public" }, + { _JC_ACC_PROTECTED, "protected" }, + { _JC_ACC_PRIVATE, "private" }, + { _JC_ACC_ABSTRACT, "abstract" }, + { _JC_ACC_STATIC, "static" }, + { _JC_ACC_FINAL, "final" }, + { _JC_ACC_TRANSIENT, "transient" }, + { _JC_ACC_VOLATILE, "volatile" }, + { _JC_ACC_SYNCHRONIZED, "synchronized" }, + { _JC_ACC_NATIVE, "native" }, + { _JC_ACC_STRICT, "strictfp" }, + { 0, NULL } +}; + +static const struct jni_name jni_names[] = { + { "Ljava/lang/Class;", "jclass" }, + { "Ljava/lang/String;", "jstring" }, + { "Ljava/lang/Throwable;", "jthrowable" }, + { "Ljava/lang/ref/WeakReference;", "jweak" }, + { NULL, NULL } +}; + +static const char hexdig[] = "0123456789abcdef"; + +static const char *flagstr(int flags, jboolean with_class); +static const char *jtypestr(const char **sp); +static const char *ctypestr(const char **sp, jboolean jni, int pnum); +static void print_comment(FILE *fp, _jc_cf_method *method); +static void print_export(FILE *fp, _jc_cf_method *method, + jboolean jni, jboolean hdr); +static void print_name(FILE *fp, _jc_classfile *cfile, + _jc_cf_method *method, jboolean jni); +static void print_decl(FILE *fp, _jc_cf_method *method, + jboolean jni, jboolean with_names); +static void encode(const char *s, char *buf, size_t bmax); + +void +javah_header(_jc_classfile *cfile, const char *dir, jboolean jni) +{ + char pathname[MAXPATHLEN]; + char namebuf[MAXPATHLEN]; + char *filename; + int ivs = 0; + FILE *fp; + int i; + + /* Open file */ + encode(cfile->name, namebuf, sizeof(namebuf)); + snprintf(pathname, sizeof(pathname), "%s/%s.h", dir, namebuf); + filename = pathname + strlen(dir) + 1; + if ((fp = fopen(pathname, "w")) == NULL) + err(1, "%s", pathname); + + /* Do header */ + fprintf(fp, "// generated file -- do not edit\n"); + fprintf(fp, "// %s %s\n", + flagstr(cfile->access_flags, JNI_TRUE), cfile->name); + fprintf(fp, "\n"); + filename[strlen(filename) - 2] = '_'; + fprintf(fp, "#ifndef _Included_%s\n", filename); + fprintf(fp, "#define _Included_%s\n", filename); + fprintf(fp, "\n"); + fprintf(fp, "#include <%s.h>\n", jni ? "jni" : "jc_defs"); + fprintf(fp, "\n"); + fprintf(fp, "#ifdef __cplusplus\n"); + fprintf(fp, "extern \"C\" {\n"); + fprintf(fp, "#endif\n"); + fprintf(fp, "\n"); + + /* Spit out static final fields */ + for (i = 0; i < cfile->num_fields; i++) { + _jc_cf_field *const field = &cfile->fields[i]; + const u_char ptype = _jc_sig_types[(u_char)*field->descriptor]; + _jc_cf_constant *value = field->initial_value; + char buf[256]; + + if (!_JC_ACC_TEST(field, STATIC) + || ptype == _JC_TYPE_REFERENCE + || value == NULL) + continue; + encode(field->name, buf, sizeof(buf)); + fprintf(fp, "#define %s_%s ", namebuf, buf); + switch (ptype) { + case _JC_TYPE_BOOLEAN: + case _JC_TYPE_BYTE: + case _JC_TYPE_CHAR: + case _JC_TYPE_SHORT: + case _JC_TYPE_INT: + fprintf(fp, "%d", value->u.Integer); + break; + case _JC_TYPE_LONG: + fprintf(fp, "%ld", (long)value->u.Long); + break; + case _JC_TYPE_FLOAT: + fprintf(fp, "%g", (double)value->u.Float); + break; + case _JC_TYPE_DOUBLE: + fprintf(fp, "%g", (double)value->u.Double); + break; + default: + assert(0); + } + fprintf(fp, "\n"); + ivs = 1; + } + if (ivs) + printf("\n"); + + /* Spit out native method declarations */ + for (i = 0; i < cfile->num_methods; i++) { + _jc_cf_method *const method = &cfile->methods[i]; + + if ((method->access_flags & _JC_ACC_NATIVE) == 0) + continue; + print_comment(fp, method); + print_export(fp, method, jni, JNI_TRUE); + fprintf(fp, " "); + print_name(fp, cfile, method, jni); + fprintf(fp, "\n "); + print_decl(fp, method, jni, JNI_FALSE); + if (!jni) + fprintf(fp, " _JC_JCNI_ATTR"); + fprintf(fp, ";\n\n"); + } + fprintf(fp, "#ifdef __cplusplus\n"); + fprintf(fp, "}\n"); + fprintf(fp, "#endif\n"); + fprintf(fp, "\n"); + fprintf(fp, "#endif\t/* _Included_%s */\n", filename); + fprintf(fp, "\n"); +} + +void +javah_source(_jc_classfile *cfile, const char *dir, jboolean jni) +{ + char pathname[MAXPATHLEN]; + char *filename; + char *s; + FILE *fp; + int i; + + /* Open file */ + snprintf(pathname, sizeof(pathname), "%s/%s.c", dir, cfile->name); + filename = pathname + strlen(dir) + 1; + for (s = filename; *s != '\0'; s++) { + if (*s == '/') + *s = '_'; + } + if ((fp = fopen(pathname, "w")) == NULL) + err(1, "%s", pathname); + + /* Do header */ + fprintf(fp, "// generated file -- please edit\n"); + fprintf(fp, "// %s %s\n", + flagstr(cfile->access_flags, JNI_TRUE), cfile->name); + fprintf(fp, "\n"); + filename[strlen(filename) - 1] = 'h'; + fprintf(fp, "#include %s\n", jni ? "" : "\"libjc.h\""); + fprintf(fp, "#include \"%s\"\n", filename); + fprintf(fp, "\n"); + + /* Spit out native method declarations */ + for (i = 0; i < cfile->num_methods; i++) { + _jc_cf_method *const method = &cfile->methods[i]; + + if ((method->access_flags & _JC_ACC_NATIVE) == 0) + continue; + print_comment(fp, method); + print_export(fp, method, jni, JNI_FALSE); + fprintf(fp, "\n"); + print_name(fp, cfile, method, jni); + print_decl(fp, method, jni, JNI_TRUE); + fprintf(fp, "\n{\n}\n\n"); + } +} + +static void +print_decl(FILE *fp, _jc_cf_method *method, jboolean jni, jboolean with_names) +{ + const char *parm = strchr(method->descriptor, '(') + 1; + const char *s; + int i; + + if (jni) + fprintf(fp, "(JNIEnv *%s", with_names ? "jenv" : ""); /*)*/ + else + fprintf(fp, "(_jc_env *%s", with_names ? "env" : ""); /*)*/ + if ((method->access_flags & _JC_ACC_STATIC) != 0) { + if (jni) { + fprintf(fp, ", jclass"); + if (with_names) + fprintf(fp, " clazz"); + } + } else { + fprintf(fp, ", %s", jni ? "jobject" : "_jc_object *"); + if (with_names) + fprintf(fp, " this"); + } + for (i = 0, s = parm; *s != /*(*/ ')'; i++) + fprintf(fp, ", %s", ctypestr(&s, jni, with_names ? i + 1 : -1)); + fprintf(fp, /*(*/ ")"); +} + +static void +print_name(FILE *fp, _jc_classfile *cfile, _jc_cf_method *method, jboolean jni) +{ + char *buf; + char *s; + + fprintf(fp, "%s_", jni ? "Java" : "JCNI"); + if ((buf = alloca(_jc_jni_encode_length(cfile->name) + 1 + + _jc_jni_encode_length(method->name) + 1)) == NULL) + err(1, "alloca"); + s = buf; + _jc_jni_encode(&s, cfile->name); + _jc_jni_encode(&s, "/"); + _jc_jni_encode(&s, method->name); + *s = '\0'; + fprintf(fp, "%s", buf); +} + +static void +print_export(FILE *fp, _jc_cf_method *method, jboolean jni, jboolean hdr) +{ + const char *ret = strchr(method->descriptor, /*(*/ ')') + 1; + + if (jni) + fprintf(fp, "JNIEXPORT "); + else if (hdr) + fprintf(fp, "extern "); + fprintf(fp, "%s", ctypestr(&ret, jni, -1)); + if (jni) + fprintf(fp, " JNICALL"); +} + +static void +print_comment(FILE *fp, _jc_cf_method *method) +{ + const char *parm = strchr(method->descriptor, '(') + 1; + const char *ret = strchr(method->descriptor, ')') + 1; + _jc_cf_attr *eattr = NULL; + const char *s; + int i; + + fprintf(fp, "/*\n"); + fprintf(fp, " * %s %s %s(", /*)*/ + flagstr(method->access_flags, JNI_FALSE), + jtypestr(&ret), method->name); + for (s = parm; *s != ')'; ) { + fprintf(fp, "%s", jtypestr(&s)); + if (*s != /*(*/ ')') + fprintf(fp, ", "); + } + fprintf(fp, ")\n"); + for (i = 0; i < method->num_attributes; i++) { + _jc_cf_attr *const attr = &method->attributes[i]; + + if (strcmp(attr->name, "Exceptions") == 0) { + eattr = attr; + break; + } + } + if (eattr != NULL) { + const int num = eattr->u.Exceptions.num_exceptions; + int j; + + fprintf(fp, " *\tthrows "); + for (j = 0; j < num; j++) { + fprintf(fp, "%s%s", eattr->u.Exceptions.exceptions[j], + j == num - 1 ? "\n" : ", "); + } + } + fprintf(fp, " */\n"); +} + +static const char * +ctypestr(const char **sp, jboolean jni, int pnum) +{ + static char buf[1024]; + const char *s = *sp; + jboolean star = JNI_FALSE; + int dims = 0; + u_char type; + + if ((type = _jc_sig_types[(u_char)*s]) != _JC_TYPE_REFERENCE) { + snprintf(buf, sizeof(buf), "%s%s", + (type == _JC_TYPE_VOID) ? "" : "j", _jc_prim_names[type]); + s++; + goto done; + } + while (s[dims] == '[') + dims++; + s += dims; + if ((type = _jc_sig_types[(u_char)*s]) == _JC_TYPE_INVALID) + errx(1, "bogus type \"%s\"", *sp); + if (type != _JC_TYPE_REFERENCE && dims == 1) { + if (jni) { + snprintf(buf, sizeof(buf), + "j%sArray", _jc_prim_names[type]); + } else { + snprintf(buf, sizeof(buf), + "_jc_%s_array *", _jc_prim_names[type]); + star = JNI_TRUE; + } + s++; + } else if (dims > 0) { + if (jni) + snprintf(buf, sizeof(buf), "jobjectArray"); + else { + snprintf(buf, sizeof(buf), "_jc_object_array *"); + star = JNI_TRUE; + } + while (*s != ';') + s++; + s++; + } else { + const char *semi = strchr(s, ';'); + size_t len; + + if (semi == NULL) + errx(1, "bogus type \"%s\"", *sp); + len = (semi + 1) - s; + if (jni) { + int j; + + /* Check for specially named classes */ + for (j = 0; jni_names[j].name != NULL; j++) { + if (strncmp(s, jni_names[j].name, len) == 0) { + snprintf(buf, sizeof(buf), + "%s", jni_names[j].ctype); + goto objdone; + } + } + } + snprintf(buf, sizeof(buf), jni ? "jobject" : "_jc_object *"); + star = !jni; + objdone: + s += len; + } +done: + if (pnum != -1) { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "%sparam%d", star ? "" : " ", pnum); + } + *sp = s; + return buf; +} + +static const char * +jtypestr(const char **sp) +{ + static char buf[1024]; + const char *s = *sp; + int dims = 0; + u_char type; + +again: + type = _jc_sig_types[(u_char)*s]; + if (type == _JC_TYPE_INVALID) + goto bogus; + if (type != _JC_TYPE_REFERENCE) { + snprintf(buf, sizeof(buf), "%s", _jc_prim_names[type]); + s++; + } else if (*s == 'L') { + const char *t = strchr(s, ';'); + size_t len; + + if (t == NULL) + goto bogus; + for (len = 0; t > s && t[-1] != '/'; t--, len++); + if (len == 0) + goto bogus; + memcpy(buf, t, len); + buf[len] = '\0'; + s = t + len + 1; + } else if (*s == '[') { + while (s[dims] == '[') + dims++; + s += dims; + goto again; + } else +bogus: errx(1, "invalid type \"%s\"", *sp); + while (dims-- > 0) + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "[]"); + *sp = s; + return buf; +} + +static const char * +flagstr(int flags, jboolean with_class) +{ + static char buf[128]; + int i; + + *buf = '\0'; + for (i = 0; flag_names[i].flag != 0; i++) { + if ((flags & flag_names[i].flag) != 0) { + if (with_class && flag_names[i].flag == _JC_ACC_SUPER) + continue; + if (*buf != '\0') { + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), " "); + } + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "%s", flag_names[i].name); + } + } + if (with_class) { + if (*buf != '\0') { + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + " "); + } + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + (flags & _JC_ACC_INTERFACE) != 0 ? "interface" : "class"); + } + return buf; +} + +static void +encode(const char *s, char *buf, size_t bmax) +{ + char ch; + int i; + + for (i = 0; i < bmax - 3 && (ch = s[i]) != '\0'; i++) { + if (ch == '/' || ch == '_') { + *buf++ = '_'; + continue; + } + if (isalnum(ch)) { + *buf++ = ch; + continue; + } + *buf++ = '_'; + *buf++ = '_'; + *buf++ = hexdig[(ch >> 4) & 0x0f]; + *buf++ = hexdig[ch & 0x0f]; + } + *buf++ = '\0'; +} + Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/javah.h URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/javah.h?rev=294974&view=auto ============================================================================== --- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/javah.h (added) +++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/javah.h Tue Oct 4 19:19:16 2005 @@ -0,0 +1,43 @@ + +/* + * Copyright 2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: javah.h,v 1.1 2005/01/08 23:25:06 archiecobbs Exp $ + */ + +#ifndef _JAVAH_H_ +#define _JAVAH_H_ + +#include "libjc.h" +#include +#include +#include + +#define EXCEPTION_MSG_MAX 128 + +extern int exception; +extern char exception_msg[EXCEPTION_MSG_MAX]; + +extern _jc_env *_jc_support_init(void); + +extern void javah_header(_jc_classfile *cfile, + const char *dir, jboolean jni); +extern void javah_source(_jc_classfile *cfile, + const char *dir, jboolean jni); +extern _jc_classbytes *read_classbytes(_jc_env *env, + const char *dir, const char *name); + +#endif /* _JAVAH_H_ */ Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/main.c URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/main.c?rev=294974&view=auto ============================================================================== --- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/main.c (added) +++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/tools/jcjavah/main.c Tue Oct 4 19:19:16 2005 @@ -0,0 +1,111 @@ + +/* + * Copyright 2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: main.c,v 1.3 2005/03/28 15:13:09 archiecobbs Exp $ + */ + +#include "javah.h" + +int +main(int ac, char **av) +{ + jboolean jni = JNI_FALSE; + jboolean c_files = JNI_FALSE; + const char *output_dir = "."; + const char *classpath = "."; + _jc_classbytes *cb; + _jc_classfile *cf; + _jc_env *env; + _jc_jvm *vm; + + /* Initialize */ + env = _jc_support_init(); + vm = env->vm; + + /* Parse command line */ + for (av++, ac--; ac > 0 && **av == '-'; av++, ac--) { + if (strcmp(av[0], "-jni") == 0) + jni = JNI_TRUE; + else if (strcmp(*av, "-c") == 0) + c_files = JNI_TRUE; + else if (strcmp(*av, "-classpath") == 0 + || strcmp(*av, "-cp") == 0) { + av++, ac--; + if (ac == 0) + goto usage; + classpath = *av; + } else if (strcmp(*av, "-d") == 0) { + av++, ac--; + if (ac == 0) + goto usage; + output_dir = *av; + } else + goto usage; + } + if (ac == 0) { +usage: fprintf(stderr, "Usage: jcjavah [-classpath path]" + " [-d output-dir] [-c] [-jni] class ...\n"); + fprintf(stderr, "Options:\n" + " -classpath\tSpecify search path for class files\n" + " -cp\t\tAlias for -classpath\n" + " -d dir\tOutput directory for generated files\n" + " -c\t\tAlso generate C source file stubs\n" + " -jni\tGenerate JNI sources instead of JCNI\n"); + exit(1); + } + + /* Parse classpath */ + if (_jc_parse_classpath(env, classpath, + &vm->boot.class_path, &vm->boot.class_path_len) != JNI_OK) + errx(1, "%s: %s", _jc_vmex_names[env->ex.num], env->ex.msg); + + /* Process files */ + while (ac-- > 0) { + char *const classname = *av++; + int i; + + /* Get class name */ + for (i = 0; classname[i] != '\0'; i++) { + if (classname[i] == '.') + classname[i] = '/'; + } + + /* Read in classfile */ + if ((cb = _jc_bootcl_find_classbytes(env, + classname, NULL)) == NULL) { + errx(1, "can't load class `%s': %s: %s", classname, + _jc_vmex_names[env->ex.num], env->ex.msg); + } + + /* Parse classfile */ + if ((cf = _jc_parse_classfile(env, cb, 2)) == NULL) { + errx(1, "can't parse class `%s': %s: %s", classname, + _jc_vmex_names[env->ex.num], env->ex.msg); + } + _jc_free_classbytes(&cb); + + /* Output files */ + javah_header(cf, output_dir, jni); + if (c_files) + javah_source(cf, output_dir, jni); + _jc_destroy_classfile(&cf); + } + + /* Done */ + return 0; +} +