netscape-revival
sun-java/javah/javah.c
/*
* @(#)javah.c 1.51 95/10/16 James Gosling
*
* Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
/*
* Modified for JRI -- Warren Harris
* Copyright (c) 1996 Netscape Communications Corp. All Rights Reserved.
*/
/*-
* produce C header files from an java object file
* produce C stub files from an java object file
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include "tree.h"
#include "oobj.h"
#include "interpreter.h"
#include "signature.h"
#include "io_md.h" /* sysOpen() */
#include "prarena.h"
#ifndef RELEASE
# define RELEASE "Unknown version"
#endif
static int renameIfDiff(char *tempfn, char *newfn, char *newdir);
struct fieldblock **makeslottable(ClassClass *);
long stubmode = 0;
long stubtable[2];
static FILE *outfp = 0;
static char *out = 0;
static char *dir = ".";
static char *tempfn = 0;
static char *tempdir = "/tmp";
static char *currentclassname;
static int jriMode = 0;
static int macMode = 0;
static int componentMode = 0;
static char* prefixString = NULL;
/*
We will need the class name in two forms -
1) in a form suitable for a file name. To get this we replace
the slashes between package names with F_DELIM.
2) in the form of a C-symbol. To get this we replace the
slashes between package names with C_DELIM.
NOTE - for now we use the same deliminter for both C symbols and
for filenames. It is '_' which does not guarrantee no
conflicts in either case but at least is consistent.
*/
#define DIR_DELIM '/'
#define C_DELIM '_'
#define F_DELIM '_'
struct structdecl {
char *class;
struct structdecl *next;
};
static struct structdecl *structdecls;
static char *
strsub(char *src, char *dst, char sub)
{
char c;
char *d = dst;
while ((c = *src++) != 0)
if (c == DIR_DELIM)
*d++ = sub;
else
*d++ = c;
*d = '\0';
return dst;
}
static char *
strnsub(char *src, char *dst, char sub, int n)
{
char c;
char *d = dst;
while (n-- > 0)
if ((c = *src++) == DIR_DELIM)
*d++ = sub;
else
*d++ = c;
*d = '\0';
return dst;
}
#define MAC_FILE_LENGTH 29 /* 32 - 2 (for the ".h" or ".c") - 1 (for the count) */
static void
GetFileName(char* src, char* hfname, size_t hfsize)
{
strsub(src, hfname, F_DELIM);
if (macMode) {
int len = strlen(hfname);
if (len > MAC_FILE_LENGTH) {
int i = 0, j = 0;
char c;
loop:
/* at least write the first character of each word */
hfname[j++] = src[i++];
if (len - i + j > MAC_FILE_LENGTH) {
/*
** if there's not enough room for all the rest, strip the
** rest of the first package name and try again
*/
int k = i;
while (k < MAC_FILE_LENGTH) {
if (src[k] == DIR_DELIM) {
hfname[j++] = F_DELIM;
i = k+1;
if (i < MAC_FILE_LENGTH)
goto loop;
else
break;
}
k++;
}
}
/*
** if we get here there are no more DIR_DELIMs, or the rest
** fits -- so just copy the rest of whatever's left
*/
while (j < MAC_FILE_LENGTH && (c = src[i++]) != 0) {
if (c == DIR_DELIM)
hfname[j++] = F_DELIM;
else
hfname[j++] = c;
}
hfname[j++] = '\0';
}
}
}
/*
** Open a temporary file
*/
static FILE *open_output(void)
{
if (outfp != 0) {
return outfp;
}
tempfn = tempnam(tempdir, "javah");
if ((outfp = fopen(tempfn, "w")) == 0) {
perror(tempfn);
}
/* fprintf(stderr, "writing to %s\n", tempfn); */
fprintf(outfp, "/* DO NOT EDIT THIS FILE - it is machine generated */\n");
if (jriMode || componentMode) {
fprintf(outfp, "#include \"jri.h\"\n\n");
}
else {
if (stubmode) {
fprintf(outfp, "#include \"StubPreamble.h\"\n");
} else {
fprintf(outfp, "#include \"native.h\"\n");
}
}
return outfp;
}
/* Close the temporary file and rename it
* to the final output file if the content
* has changed. */
static int close_output(void)
{
char fname[300];
if (outfp == 0) {
return 0;
}
fclose(outfp);
outfp = 0;
while (structdecls) {
struct structdecl *p = structdecls;
structdecls = p->next;
free(p->class);
free(p);
}
structdecls = 0;
if (out) {
strncpy(fname, out, sizeof(fname));
} else {
char tempfname[300];
GetFileName(currentclassname, tempfname, sizeof(tempfname));
sprintf(fname, "%s/%s%s", dir, tempfname, stubmode ? ".c" : ".h");
}
/* fprintf(stderr, "rename %s to %s\n", tempfn, fname); */
return renameIfDiff(tempfn, fname, dir);
}
static char*
SprintClassType(char* s, char* buf)
{
register char *tn = buf;
{
register char *sp = (jriMode ? "struct " : "struct H");
while (*sp)
*tn++ = *sp++;
}
for (; *s && *s != SIGNATURE_ENDCLASS;) {
char c = *s++;
if (c == DIR_DELIM)
*tn++ = C_DELIM;
else
*tn++ = c;
}
*tn++ = ' ';
*tn++ = '*';
*tn = 0;
if (*s == SIGNATURE_ENDCLASS)
s++;
return s;
}
static char *
SprintReverseType(char *s, char *fname, char *out)
{
char buf[1000];
register char *tn = "?";
if (fname == 0)
fname = "";
switch (*s++) {
default:
switch (s[-1]) {
case SIGNATURE_ANY:
tn = "void*";
break;
case SIGNATURE_CHAR:
tn = (jriMode ? "jchar" : "unicode");
break;
case SIGNATURE_BYTE:
tn = (jriMode ? "jbyte" : "char");
break;
case SIGNATURE_ENUM:
tn = "enum";
break;
case SIGNATURE_FLOAT:
tn = (jriMode ? "jfloat" : "float");
break;
case SIGNATURE_DOUBLE:
tn = (jriMode ? "jdouble" : "double");
break;
case SIGNATURE_BOOLEAN:
tn = (jriMode ? "jbool" : "/*boolean*/ long");
break;
case SIGNATURE_INT:
tn = (jriMode ? "jint" : "long");
break;
case SIGNATURE_LONG:
tn = (jriMode ? "jlong" : "int64_t");
break;
case SIGNATURE_SHORT:
tn = (jriMode ? "jshort" : "short");
break;
case SIGNATURE_CLASS:
s = SprintClassType(s, buf);
tn = buf;
break;
case SIGNATURE_VOID:
tn = "void";
break;
}
sprintf(out, (*fname
? (tn[strlen(tn) - 1] == '*'
? "%s%s"
: "%s %s")
: "%s"),
tn, fname);
break;
case 0:
strcpy(out, fname);
s--;
break;
case SIGNATURE_ARRAY:
switch (*s++) {
case SIGNATURE_BYTE:
if (jriMode)
sprintf(out, *fname ? "jbyteArray %s" : "jbyteArray ", fname);
else
sprintf(out, *fname ? "HArrayOfByte *%s" : "HArrayOfByte *", fname);
break;
case SIGNATURE_CHAR:
if (jriMode)
sprintf(out, *fname ? "jcharArray %s" : "jcharArray ", fname);
else
sprintf(out, *fname ? "HArrayOfChar *%s" : "HArrayOfChar *", fname);
break;
case SIGNATURE_SHORT:
if (jriMode)
sprintf(out, *fname ?
"jshortArray %s" : "jshortArray ", fname);
else
sprintf(out, *fname ?
"HArrayOfShort *%s" : "HArrayOfShort *", fname);
break;
case SIGNATURE_INT:
if (jriMode)
sprintf(out, *fname ? "jintArray %s" : "jintArray ", fname);
else
sprintf(out, *fname ? "HArrayOfInt *%s" : "HArrayOfInt *", fname);
break;
case SIGNATURE_BOOLEAN:
if (jriMode)
sprintf(out, *fname ? "jbooleanArray %s" :
"jbooleanArray ", fname);
else
sprintf(out, *fname ? "/*boolean*/ HArrayOfInt *%s" :
"HArrayOfInt *", fname);
break;
case SIGNATURE_LONG:
if (jriMode)
sprintf(out, *fname ? "jlongArray %s" : "jlongArray ", fname);
else
sprintf(out, *fname ? "HArrayOfLong *%s" : "HArrayOfLong *", fname);
break;
case SIGNATURE_FLOAT:
if (jriMode)
sprintf(out,
*fname ? "jfloatArray %s" : "jfloatArray ", fname);
else
sprintf(out,
*fname ? "HArrayOfFloat *%s" : "HArrayOfFloat *", fname);
break;
case SIGNATURE_DOUBLE:
if (jriMode)
sprintf(out,
*fname ? "jdoubleArray %s" : "jdoubleArray ", fname);
else
sprintf(out,
*fname ? "HArrayOfDouble *%s" : "HArrayOfDouble *", fname);
break;
case SIGNATURE_CLASS:
if (!strncmp(s,"java/lang/String;", sizeof("java/lang/String;")-1)) {
s += sizeof("java/lang/String;") - 1;
if (jriMode)
sprintf(out, *fname ? "jstringArray %s" : "jstringArray ",
fname);
else
sprintf(out, *fname ? "HArrayOfString *%s" : "HArrayOfString *",
fname);
} else {
while (*s++ != SIGNATURE_ENDCLASS);
if (jriMode)
sprintf(out, *fname ? "jobjectArray %s" : "jobjectArray ",
fname);
else
sprintf(out, *fname ? "HArrayOfObject *%s" : "HArrayOfObject *",
fname);
}
break;
case SIGNATURE_ARRAY:
while (*s == SIGNATURE_ARRAY) s++;
if (*s++ == SIGNATURE_CLASS)
while (*s++ != SIGNATURE_ENDCLASS);
if (jriMode)
sprintf(out,
*fname ? "jarrayArray %s" : "jarrayArray ", fname);
else
sprintf(out,
*fname ? "HArrayOfArray *%s" : "HArrayOfArray *", fname);
break;
}
break;
case SIGNATURE_FUNC:
{
int constructor = strcmp(fname, "<init>") == 0;
char cname[300];
strsub(currentclassname, cname, C_DELIM);
sprintf(buf, (jriMode ? "%s_%s(JRIEnv* env, struct " : "%s_%s(struct H"),
cname,
constructor ? (jriMode ? "new" : "Initializor") : fname);
fname = buf + strlen(buf);
sprintf(fname, "%s* self,", cname);
fname += strlen(fname);
while (*s != SIGNATURE_ENDFUNC && *s) {
s = SprintReverseType(s, (char *) 0, fname);
fname += strlen(fname);
*fname++ = ',';
}
if (fname[-1] == ',') fname--;
*fname++ = SIGNATURE_ENDFUNC;
*fname++ = 0;
s = SprintReverseType(constructor ? "" : *s ? s + 1 : s, buf, out);
}
break;
}
return s;
}
static char *
PrintType(FILE *f, char *s, char *fname)
{
char buf[1000];
char fnb[100];
register char *src, *dst;
dst = fnb;
for (src = fname; *src && dst - fnb < sizeof fnb - 1 &&
*src != SIGNATURE_FUNC;) {
char c = *src++;
if (c == DIR_DELIM)
*dst++ = C_DELIM;
else
*dst++ = c;
}
*dst = 0;
s = SprintReverseType(s, fnb, buf);
fwrite(buf, strlen(buf), 1, f);
return s;
}
static char*
ConsumeArg(char* sig)
{
switch (*sig++) {
case SIGNATURE_CLASS:
while (*sig++ != SIGNATURE_ENDCLASS);
return sig;
case SIGNATURE_ARRAY:
return ConsumeArg(sig);
}
return sig;
}
static void
PrintCallArgs(FILE *f, char* sig)
{
char arg = 'a';
sig++;
while (sig[0] != SIGNATURE_ENDFUNC) {
fputs(", ", f);
sig = ConsumeArg(sig);
fputc(arg++, f);
}
}
static void
PrintDefArgs(FILE *f, char* sig)
{
char buf[300];
char arg[2] = { 'a', '\0' };
char* s = &sig[1]; /* skip SIGNATURE_FUNC */
while (*s != SIGNATURE_ENDFUNC) {
fputs(", ", f);
s = SprintReverseType(s, arg, buf);
fputs(buf, f);
arg[0]++;
}
}
/*
* Returns 1 if diff, 0 if same, -1 if error
*/
static int
renameIfDiff(char *tempfn, char *newfn, char *newdir)
{
FILE *f, *nf;
char buf[1024];
long c;
if ((f = fopen(tempfn, "r")) == 0) {
perror(tempfn);
return -1;
} else if ((nf = fopen(newfn, "r"))) {
while ((c = getc(f)) == getc(nf)) {
if (c == -1) {
fclose(f);
fclose(nf);
unlink(tempfn);
if (verbose)
fprintf(stderr, " (no change)\n");
return 0;
}
}
}
rewind(f);
if (nf) {
fclose(nf);
}
if ((nf = fopen(newfn, "w")) == 0) {
if (mkdir(newdir, 0777) != 0) {
perror(newdir);
return -1;
}
nf = fopen(newfn, "w");
}
if (nf == 0) {
perror(newfn);
return -1;
}
while ((c = fread(buf, sizeof(char), sizeof(buf), f)) > 0) {
fwrite(buf, sizeof(char), c, nf);
}
fclose(f);
fclose(nf);
unlink(tempfn);
if (verbose)
fprintf(stderr, " %s => %s\n", tempfn, newfn);
return 1;
}
static void
generateForwardDeclaration(FILE *f, char *p, int len) {
char buf[128];
struct structdecl *s;
strnsub(p, buf, '_', len);
for (s = structdecls ; s ; s = s->next) {
if (!strcmp(s->class, buf)) {
return;
}
}
if (jriMode)
fprintf(f, "struct %s;\n", strnsub(p, buf, '_', len));
else
fprintf(f, "struct H%s;\n", strnsub(p, buf, '_', len));
s = (struct structdecl *)malloc(sizeof(struct structdecl));
s->next = structdecls;
s->class = strdup(buf);
structdecls = s;
}
static void
forwardDeclare(FILE *f, struct fieldblock *fb)
{
char *fs = fieldsig(fb);
if (*fs == SIGNATURE_FUNC) {
for(fs++ ; *fs != '\0' ; fs++) {
if (*fs == SIGNATURE_CLASS) {
char *p = ++fs;
while (*fs != SIGNATURE_ENDCLASS) fs++;
generateForwardDeclaration(f, p, fs - p);
}
}
} else {
while (*fs == SIGNATURE_ARRAY) fs++;
if (*fs == SIGNATURE_CLASS) {
char *p = ++fs;
while (*fs != SIGNATURE_ENDCLASS) fs++;
generateForwardDeclaration(f, p, fs - p);
}
}
}
static void
GetResultType(char* t, char* typeBuf, char* *suffix, char* *unionField)
{
char* type;
if (*t == SIGNATURE_FUNC) {
t++;
while (*t++ != SIGNATURE_ENDFUNC);
}
switch (t[0]) {
case SIGNATURE_VOID:
type = "void";
*suffix = "";
*unionField = ".r";
break;
case SIGNATURE_BOOLEAN:
type = "jbool";
*suffix = "Boolean";
*unionField = ".z";
break;
case SIGNATURE_BYTE:
type = "jbyte";
*suffix = "Byte";
*unionField = ".b";
break;
case SIGNATURE_CHAR:
type = "jchar";
*suffix = "Char";
*unionField = ".c";
break;
case SIGNATURE_SHORT:
type = "jshort";
*suffix = "Short";
*unionField = ".s";
break;
case SIGNATURE_INT:
type = "jint";
*suffix = "Int";
*unionField = ".i";
break;
case SIGNATURE_LONG:
type = "jlong";
*suffix = "Long";
*unionField = ".l";
break;
case SIGNATURE_FLOAT:
type = "jfloat";
*suffix = "Float";
*unionField = ".f";
break;
case SIGNATURE_DOUBLE:
type = "jdouble";
*suffix = "Double";
*unionField = ".d";
break;
case SIGNATURE_CLASS:
*suffix = "";
*unionField = ".r";
SprintClassType(&t[1], typeBuf);
return;
default:
type = "jref";
*suffix = "";
*unionField = ".r";
break;
}
while ((*typeBuf++ = *type++));
}
void
CPPFieldName(ClassClass* cb, struct fieldblock* fb, int currentSlot, char* buf)
{
char* fn = fieldname(fb);
sprintf(buf, "%s", fn);
}
void
CFieldName(ClassClass* cb, struct fieldblock* fb, int currentSlot, char* buf)
{
char* cname = classname(cb);
char hcname[300]; /* C symbol name. */
char cppname[300];
strsub(cname, hcname, C_DELIM);
CPPFieldName(cb, fb, currentSlot, cppname);
sprintf(buf, "%s_%s", prefixString, cppname);
}
void
CPPMethodName(ClassClass* cb, struct fieldblock* fb, int currentSlot, char* buf)
{
char* fn = fieldname(fb);
if (jriMode) {
char* fn = fieldname(fb);
if (strcmp(fn, "<init>") == 0)
sprintf(buf, "_new");
else
sprintf(buf, "%s", fn);
}
else
sprintf(buf, "%s", fn);
}
void
CMethodName1(ClassClass* cb, struct fieldblock* fb, int currentSlot, char* buf)
{
char* fn = fieldname(fb);
if (jriMode) {
char fname[256];
char suffix[10];
int gensym = 0;
int prevSlots;
char* fn = fieldname(fb);
struct methodblock* prevMb = cbMethods(cb);
for (prevSlots = 0; prevSlots < currentSlot; prevSlots++, prevMb++) {
if (strcmp(fn, fieldname(&prevMb->fb)) == 0)
gensym++;
}
sprintf(suffix, (gensym > 0 ? "_%d" : ""), gensym);
if (strcmp(fn, "<init>") == 0)
sprintf(fname, "_new");
else
mangleUTFString(fn, fname, 256, MangleUTF_Field);
sprintf(buf, "%s%s", fname, suffix);
}
else
sprintf(buf, "%s", fn);
}
void
CMethodName(ClassClass* cb, struct fieldblock* fb, int currentSlot, char* buf)
{
char* cname = classname(cb);
char hcname[300]; /* C symbol name. */
char cppname[300];
strsub(cname, hcname, C_DELIM);
CMethodName1(cb, fb, currentSlot, cppname);
if (strncmp(cppname, "_new", 4) == 0)
sprintf(buf, "%s%s", hcname, cppname);
else
sprintf(buf, "%s_%s", prefixString, cppname);
}
void
PrintPreamble(FILE* f, struct fieldblock* fb)
{
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int access = fb->access;
fprintf(f, "/*** %s%s%s%s%s %s ***/\n",
(access & ACC_PUBLIC ? "public " :
(access & ACC_PROTECTED ? "protected " :
(access & ACC_PRIVATE ? "private " : ""))),
(access & ACC_STATIC ? "static " : ""),
(access & ACC_FINAL ? "final " : ""),
(access & ACC_NATIVE ? "native " : ""),
fn, fs);
}
void
PrintKnownValue(FILE* f, char* cfname, struct fieldblock* fb, char* hcname)
{
char* fn = fb->name;
char namebuf[300];
char* name;
if (jriMode)
name = cfname;
else {
sprintf(namebuf, "%s_%s", hcname, fn);
name = namebuf;
}
if (fb->signature[0] == SIGNATURE_DOUBLE) {
Java8 t1;
double d;
d = GET_DOUBLE(t1, twoword_static_address(fb));
fprintf(f, "#define %s\t%gD\n", name, d);
} else if (fb->signature[0] == SIGNATURE_LONG) {
Java8 t1;
int64_t l;
char buf[40];
l = GET_INT64(t1, twoword_static_address(fb));
ll2str(l, buf, buf + sizeof(buf));
fprintf(f, "#define %s\t%sLL\n", name, buf);
} else if (fb->signature[0] == SIGNATURE_FLOAT) {
fprintf(f, "#define %s\t%gf\n", name,
*normal_static_address(fb));
} else {
fprintf(f, "#define %s\t%dL\n", name,
*normal_static_address(fb));
}
}
static void
PrintBlockComment(FILE* f, char* format, ...)
{
int i;
va_list args;
fprintf(f, "/");
for (i = 0; i < 79; i++)
fprintf(f, "*");
fprintf(f, "\n * ");
va_start(args, format);
vfprintf(f, format, args);
va_end(args);
fprintf(f, "\n ");
for (i = 0; i < 78; i++)
fprintf(f, "*");
fprintf(f, "/\n\n");
}
static void
GenerateFieldAccessor(FILE* f, struct fieldblock* fb, int nslots, ClassClass* cb, char* hcname)
{
char* fs = fieldsig(fb);
char cfname[300];
CFieldName(cb, fb, nslots, cfname);
if ((fb->access & ACC_STATIC) == 0) {
char fieldType[300];
char* suffix;
char* unionType;
PrintPreamble(f, fb);
GetResultType(fs, fieldType, &suffix, &unionType);
fprintf(f, "#define get_%s(env, obj) \\\n\t(", cfname);
if (strcmp(suffix, "") == 0)
fprintf(f, "(%s)", fieldType);
fprintf(f, "JRI_GetField%s(env, obj, fieldID_%s))\n", suffix, cfname);
fprintf(f, "#define set_%s(env, obj, v) \\\n", cfname);
fprintf(f, "\tJRI_SetField%s(env, obj, fieldID_%s, v)\n", suffix, cfname);
} else if (fb->access & ACC_VALKNOWN) {
PrintKnownValue(f, cfname, fb, hcname);
} else {
char fieldType[300];
char* suffix;
char* unionType;
PrintPreamble(f, fb);
GetResultType(fs, fieldType, &suffix, &unionType);
fprintf(f, "#define get_%s(env, clazz) \\\n\t(", cfname);
if (strcmp(suffix, "") == 0)
fprintf(f, "(%s)", fieldType);
fprintf(f, "JRI_GetStaticField%s(env, clazz, fieldID_%s))\n",
suffix, cfname);
fprintf(f, "#define set_%s(env, clazz, v) \\\n", cfname);
fprintf(f, "\tJRI_SetStaticField%s(env, clazz, fieldID_%s, v)\n", suffix, cfname);
}
fprintf(f, "\n");
}
static void
GenerateDEBUGFieldAccessor(FILE* f, struct fieldblock* fb, int nslots, ClassClass* cb, char* hcname)
{
char* fs = fieldsig(fb);
char cfname[300];
CFieldName(cb, fb, nslots, cfname);
if ((fb->access & ACC_STATIC) == 0) {
char fieldType[300];
char* suffix;
char* unionType;
PrintPreamble(f, fb);
GetResultType(fs, fieldType, &suffix, &unionType);
fprintf(f, "extern JRI_PUBLIC_API(%s)\nget_%s(JRIEnv* env, %s* obj);\n",
fieldType, cfname, hcname);
fprintf(f, "extern JRI_PUBLIC_API(void)\nset_%s(JRIEnv* env, %s* obj, %s v);\n",
cfname, hcname, fieldType);
} else if (fb->access & ACC_VALKNOWN) {
PrintKnownValue(f, cfname, fb, hcname);
} else {
char fieldType[300];
char* suffix;
char* unionType;
PrintPreamble(f, fb);
GetResultType(fs, fieldType, &suffix, &unionType);
fprintf(f, "extern JRI_PUBLIC_API(%s)\nget_%s(JRIEnv* env, struct java_lang_Class* clazz);\n",
fieldType, cfname);
fprintf(f, "extern JRI_PUBLIC_API(void)\nset_%s(JRIEnv* env, struct java_lang_Class* clazz, %s v);\n",
cfname, fieldType);
}
fprintf(f, "\n");
}
static void
GenerateFieldAccessorExtras(FILE* f, struct fieldblock* fb, int nslots, ClassClass* cb, char* hcname)
{
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
char cfname[300];
int known = fb->access & ACC_VALKNOWN;
CFieldName(cb, fb, nslots, cfname);
if (!known) {
fprintf(f, "extern JRIFieldID FAR fieldID_%s;\n", cfname);
}
fprintf(f, "#define name_%s\t\"%s\"\n", cfname, fn);
fprintf(f, "#define sig_%s \t\"%s\"\n", cfname, fs);
if (!known) {
fprintf(f, "#define use_%s(env, clazz)\t\\\n", cfname);
fprintf(f, "\t(fieldID_%s =\t\\\n\t\tJRI_Get%sFieldID(env, clazz,\t\\\n\t\t\tname_%s,\t\\\n\t\t\tsig_%s))\n",
cfname, (fb->access & ACC_STATIC ? "Static" : ""), cfname, cfname);
fprintf(f, "#define unuse_%s(env, clazz)\t\\\n", cfname);
fprintf(f, "\t\t(fieldID_%s = JRIUninitialized)\n", cfname);
}
fprintf(f, "\n");
}
static void
GenerateMethodAccessor(FILE* f, struct methodblock* mb, int nslots, ClassClass* cb, char* hcname)
{
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
GetResultType(fs, resultType, &suffix, &unionType);
CMethodName(cb, fb, nslots, cfname);
PrintPreamble(f, fb);
if (strcmp(fn, "<init>") == 0) {
fprintf(f, "#define %s(env, clazz", cfname);
PrintCallArgs(f, fs);
fprintf(f, ")\t\\\n");
fprintf(f, "\t((struct %s*)JRI_NewObject(env)(env, JRI_NewObject_op, clazz, methodID_%s",
hcname, cfname);
PrintCallArgs(f, fs);
fprintf(f, "))\n");
}
else {
int isVoid = strcmp(resultType, "void") == 0;
fprintf(f, "#define %s(env%s", cfname, (isStatic ? ", clazz" : ", obj"));
PrintCallArgs(f, fs);
fprintf(f, ") \\\n");
fprintf(f, "\t(");
if (strlen(suffix) == 0)
fprintf(f, "(%s)", resultType);
fprintf(f, "JRI_Call%sMethod%s(env)(env, JRI_Call%sMethod_op, %s, methodID_%s",
(isStatic ? "Static" : ""),
(isVoid ? "" : suffix),
(isStatic ? "Static" : ""),
(isStatic ? "clazz" : "obj"),
cfname);
PrintCallArgs(f, fs);
fprintf(f, "))\n");
}
fprintf(f, "\n");
}
static void
GenerateMethodAccessorSig(FILE* f, struct methodblock* mb, int nslots,
ClassClass* cb, char* hcname, int isNative)
{
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
GetResultType(fs, resultType, &suffix, &unionType);
CMethodName(cb, fb, nslots, cfname);
if (strcmp(fn, "<init>") == 0) {
fprintf(f, "JRI_PUBLIC_API(struct %s*)\n%s%s(JRIEnv* env, struct java_lang_Class* clazz",
hcname, (isNative ? "native_" : ""), cfname);
if (isNative)
fprintf(f, ", JRIMethodID methodID");
PrintDefArgs(f, fs);
fprintf(f, ")");
}
else {
fprintf(f, "JRI_PUBLIC_API(%s)\n%s%s(JRIEnv* env, ", resultType,
(isNative ? "native_" : ""), cfname);
if (isStatic)
fprintf(f, "struct java_lang_Class* clazz");
else
fprintf(f, "struct %s* self", hcname);
PrintDefArgs(f, fs);
fprintf(f, ")");
}
}
static void
GenerateExternMethodAccessor(FILE* f, struct methodblock* mb, int nslots,
ClassClass* cb, char* hcname, int isNative)
{
struct fieldblock* fb = &mb->fb;
PrintPreamble(f, fb);
fprintf(f, "extern ");
GenerateMethodAccessorSig(f, mb, nslots, cb, hcname, isNative);
fprintf(f, ";\n\n");
}
static void
GenerateMethodAccessorExtras(FILE* f, struct methodblock* mb, int nslots, ClassClass* cb, char* hcname)
{
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
GetResultType(fs, resultType, &suffix, &unionType);
CMethodName(cb, fb, nslots, cfname);
PrintPreamble(f, fb);
fprintf(f, "extern JRIMethodID FAR methodID_%s;\n", cfname);
fprintf(f, "#define name_%s\t\"%s\"\n", cfname, fn);
fprintf(f, "#define sig_%s \t\"%s\"\n", cfname, fs);
fprintf(f, "#define use_%s(env, clazz)\t\\\n", cfname);
fprintf(f, "\t(methodID_%s =\t\\\n\t\tJRI_Get%sMethodID(env, clazz,\t\\\n\t\t\tname_%s,\t\\\n\t\t\tsig_%s))\n",
cfname, (fb->access & ACC_STATIC ? "Static" : ""), cfname, cfname);
fprintf(f, "#define unuse_%s(env, clazz)\t\\\n", cfname);
fprintf(f, "\t(methodID_%s = JRIUninitialized)\n", cfname);
fprintf(f, "\n");
}
static void
GenerateCPPFieldAccessor(FILE* f, struct fieldblock* fb, int nslots, ClassClass* cb, char* hcname)
{
int access = fb->access;
if ((access & ACC_STATIC) == 0) {
char* fs = fieldsig(fb);
char cfname[300];
char cppname[300];
char fieldType[300];
char* suffix;
char* unionType;
CFieldName(cb, fb, nslots, cfname);
CPPFieldName(cb, fb, nslots, cppname);
GetResultType(fs, fieldType, &suffix, &unionType);
fprintf(f, "\n\t");
PrintPreamble(f, fb);
fprintf(f, "\t%s %s(JRIEnv* env) {\n",
fieldType, cppname);
fprintf(f, "\t\treturn get_%s(env, this);\n\t}\n", cfname);
fprintf(f, "\tvoid %s(JRIEnv* env, %s v) {\n",
cppname, fieldType);
fprintf(f, "\t\tset_%s(env, this, v);\n\t}\n", cfname);
}
}
static void
GenerateCPPMethod(FILE* f, struct methodblock* mb, int nslots, ClassClass* cb, char* hcname)
{
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
int isConstr = strcmp(fn, "<init>") == 0;
char cfname[300];
char cppname[300];
char resultType[300];
char* suffix;
char* unionType;
CMethodName(cb, fb, nslots, cfname);
CPPMethodName(cb, fb, nslots, cppname);
GetResultType(fs, resultType, &suffix, &unionType);
fprintf(f, "\n\t");
PrintPreamble(f, fb);
if (isConstr)
fprintf(f, "\tstatic %s* %s(JRIEnv* env, struct java_lang_Class* clazz",
hcname, cppname);
else if (isStatic)
fprintf(f, "\tstatic %s %s(JRIEnv* env, struct java_lang_Class* clazz",
resultType, cppname);
else
fprintf(f, "\t%s %s(JRIEnv* env",
resultType, cppname);
PrintDefArgs(f, fs);
fprintf(f, ") {\n");
if (isConstr) {
fprintf(f, "\t\treturn %s(env, clazz", cfname);
}
else {
fprintf(f, "\t\t%s%s(env, ",
(strcmp(resultType, "void") == 0 ? "" : "return "),
cfname);
fprintf(f, (isStatic ? "clazz" : "this"));
}
PrintCallArgs(f, fs);
fprintf(f, ");\n\t}\n");
}
static int
JRIDumpClassHeader(ClassClass * cb)
{
FILE *f;
register struct methodblock *mb;
register nslots;
char hfname[300]; /* header file name */
char hcname[300]; /* C symbol name. */
int needsComment = TRUE;
currentclassname = classname(cb);
GetFileName(currentclassname, hfname, sizeof(hfname));
strsub(currentclassname, hcname, C_DELIM);
if (prefixString == NULL) {
prefixString = hcname;
}
if ((f = open_output()) == 0) {
return -1;
}
if (verbose)
fprintf(stderr, "=> %s\n", tempfn);
fprintf(f, "/* Header for class %s */\n\n", currentclassname);
fprintf(f, "#ifndef _%s_H_\n#define _%s_H_\n\n",
hcname, hcname);
fprintf(f, "#ifdef __cplusplus\n");
fprintf(f, "extern \"C\" {\n");
fprintf(f, "#endif /* __cplusplus */\n\n");
/* first generate forward declarations */
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if ((fb->access & ACC_STATIC) == 0) {
forwardDeclare(f, fb);
}
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
forwardDeclare(f, fb);
}
fprintf(f, "struct java_lang_Class;\n\n", hcname, hcname);
PrintBlockComment(f, "Class %s", currentclassname);
fprintf(f, "typedef struct %s %s;\n\n", hcname, hcname);
fprintf(f, "#define classname_%s\t\"%s\"\n\n", hcname, currentclassname);
fprintf(f, "#define class_%s(env) \\\n\t((struct java_lang_Class*)JRI_FindClass(env, classname_%s))\n\n",
hcname, hcname);
makeslottable(cb);
/* generate public field accessors */
needsComment = TRUE;
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (fb->access & ACC_PUBLIC) {
if (needsComment) {
PrintBlockComment(f, "Public Field Accessors");
fprintf(f, "#ifdef DEBUG\n\n");
needsComment = FALSE;
}
GenerateDEBUGFieldAccessor(f, fb, nslots, cb, hcname);
}
}
if (!needsComment) {
fprintf(f, "#else /* !DEBUG */\n\n");
}
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (fb->access & ACC_PUBLIC) {
GenerateFieldAccessor(f, fb, nslots, cb, hcname);
}
}
if (!needsComment) {
fprintf(f, "#endif /* !DEBUG*/\n\n");
}
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (fb->access & ACC_PUBLIC) {
GenerateFieldAccessorExtras(f, fb, nslots, cb, hcname);
}
}
/* generate public methods */
needsComment = TRUE;
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_PUBLIC) {
if (needsComment) {
PrintBlockComment(f, "Public Methods");
fprintf(f, "#ifdef DEBUG\n\n");
needsComment = FALSE;
}
GenerateExternMethodAccessor(f, mb, nslots, cb, hcname, FALSE);
}
}
if (!needsComment) {
fprintf(f, "#else /* !DEBUG */\n\n");
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_PUBLIC) {
GenerateMethodAccessor(f, mb, nslots, cb, hcname);
}
}
if (!needsComment) {
fprintf(f, "#endif /* !DEBUG*/\n\n");
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_PUBLIC) {
GenerateMethodAccessorExtras(f, mb, nslots, cb, hcname);
}
}
PrintBlockComment(f, "IMPLEMENTATION SECTION: \n\
* Define the IMPLEMENT_%s symbol \n\
* if you intend to implement the native methods of this class. This \n\
* symbol makes the private and protected methods available. You should \n\
* also call the register_%s routine \n\
* to make your native methods available.",
hcname, hcname);
fprintf(f, "extern JRI_PUBLIC_API(struct java_lang_Class*)\nuse_%s(JRIEnv* env);\n\n", hcname, hcname);
fprintf(f, "extern JRI_PUBLIC_API(void)\nunuse_%s(JRIEnv* env);\n\n", hcname, hcname);
fprintf(f, "extern JRI_PUBLIC_API(struct java_lang_Class*)\nregister_%s(JRIEnv* env);\n\n", hcname, hcname);
fprintf(f, "extern JRI_PUBLIC_API(void)\nunregister_%s(JRIEnv* env);\n\n", hcname, hcname);
fprintf(f, "#ifdef IMPLEMENT_%s\n\n", hcname);
/* generate native declarations */
needsComment = TRUE;
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_NATIVE) {
if (needsComment) {
PrintBlockComment(f, "Native Methods: \n\
* These are the signatures of the native methods which you must implement.");
needsComment = FALSE;
}
GenerateExternMethodAccessor(f, mb, nslots, cb, hcname, TRUE);
}
}
/* generate private/protected field accessors */
needsComment = TRUE;
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (!(fb->access & ACC_PUBLIC)) {
if (needsComment) {
PrintBlockComment(f, "Implementation Field Accessors: \n\
* You should only use these from within the native method definitions.");
fprintf(f, "#ifdef DEBUG\n\n");
needsComment = FALSE;
}
GenerateDEBUGFieldAccessor(f, fb, nslots, cb, hcname);
}
}
if (!needsComment) {
fprintf(f, "#else /* !DEBUG */\n\n");
}
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (!(fb->access & ACC_PUBLIC)) {
GenerateFieldAccessor(f, fb, nslots, cb, hcname);
}
}
if (!needsComment) {
fprintf(f, "#endif /* !DEBUG*/\n\n");
}
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (!(fb->access & ACC_PUBLIC)) {
GenerateFieldAccessorExtras(f, fb, nslots, cb, hcname);
}
}
/* generate private/protected methods */
needsComment = TRUE;
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (!(fb->access & ACC_PUBLIC)) {
if (needsComment) {
PrintBlockComment(f, "Implementation Methods: \n\
* You should only use these from within the native method definitions.");
fprintf(f, "#ifdef DEBUG\n\n");
needsComment = FALSE;
}
GenerateExternMethodAccessor(f, mb, nslots, cb, hcname, FALSE);
}
}
if (!needsComment) {
fprintf(f, "#else /* !DEBUG */\n\n");
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (!(fb->access & ACC_PUBLIC)) {
GenerateMethodAccessor(f, mb, nslots, cb, hcname);
}
}
if (!needsComment) {
fprintf(f, "#endif /* !DEBUG*/\n\n");
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (!(fb->access & ACC_PUBLIC)) {
GenerateMethodAccessorExtras(f, mb, nslots, cb, hcname);
}
}
fprintf(f, "#endif /* IMPLEMENT_%s */\n\n", hcname);
/* be nice to those less fortunate */
{
cp_item_type *constant_pool = cb->constantpool;
int i;
int needsColon = 1;
HClass* super = cbSuperclass(cb);
char sname[300];
fprintf(f, "#ifdef __cplusplus\n");
fprintf(f, "} /* extern \"C\" */\n\n");
PrintBlockComment(f, "C++ Definitions");
for (i = 0; i < cb->implements_count; i++) {
char iname[300];
int interface_index = cb->implements[i];
char *interface_name =
GetClassConstantClassName(constant_pool, interface_index);
GetFileName(interface_name, iname, sizeof(iname));
fprintf(f, "#include \"%s.h\"\n", iname);
}
if (super != NULL) {
GetFileName(classname(unhand(super)), sname, sizeof(sname));
fprintf(f, "#include \"%s.h\"\n", sname);
}
fprintf(f, "\nstruct %s", hcname);
for (i = 0; i < cb->implements_count; i++) {
char iname[300];
int interface_index = cb->implements[i];
char *interface_name =
GetClassConstantClassName(constant_pool, interface_index);
GetFileName(interface_name, iname, sizeof(iname));
fprintf(f, "%s virtual public %s", (needsColon ? " :" : ","), iname);
needsColon = 0;
}
if (super != NULL) {
fprintf(f, "%s virtual public %s", (needsColon ? " :" : ","), sname);
needsColon = 0;
}
fprintf(f, " {\n\n");
fprintf(f, "\tstatic struct java_lang_Class* _use(JRIEnv* env) {\n");
fprintf(f, "\t\treturn use_%s(env);\n\t}\n\n", hcname);
fprintf(f, "\tstatic void _unuse(JRIEnv* env) {\n");
fprintf(f, "\t\tunuse_%s(env);\n\t}\n\n", hcname);
fprintf(f, "\tstatic struct java_lang_Class* _register(JRIEnv* env) {\n");
fprintf(f, "\t\treturn register_%s(env);\n\t}\n\n", hcname);
fprintf(f, "\tstatic void _unregister(JRIEnv* env) {\n");
fprintf(f, "\t\tunregister_%s(env);\n\t}\n\n", hcname);
fprintf(f, "\tstatic struct java_lang_Class* _class(JRIEnv* env) {\n");
fprintf(f, "\t\treturn class_%s(env);\n\t}\n", hcname);
needsComment = TRUE;
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (fb->access & ACC_PUBLIC) {
if (needsComment) {
fprintf(f, "\n\t/* Public Field Accessors */");
needsComment = FALSE;
}
GenerateCPPFieldAccessor(f, fb, nslots, cb, hcname);
}
}
needsComment = TRUE;
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_PUBLIC) {
if (needsComment) {
fprintf(f, "\n\t/* Public Methods */");
needsComment = FALSE;
}
GenerateCPPMethod(f, mb, nslots, cb, hcname);
}
}
fprintf(f, "\n#ifdef IMPLEMENT_%s\n", hcname);
needsComment = TRUE;
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (fb->access & ACC_PROTECTED) {
if (needsComment) {
fprintf(f, "\n\t/* Protected Field Accessors */");
needsComment = FALSE;
}
GenerateCPPFieldAccessor(f, fb, nslots, cb, hcname);
}
}
needsComment = TRUE;
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_PROTECTED) {
if (needsComment) {
fprintf(f, "\n\t/* Protected Methods */");
needsComment = FALSE;
}
GenerateCPPMethod(f, mb, nslots, cb, hcname);
}
}
needsComment = TRUE;
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
if (fb->access & ACC_PRIVATE) {
if (needsComment) {
fprintf(f, "\n\t/* Private Field Accessors */");
needsComment = FALSE;
}
GenerateCPPFieldAccessor(f, fb, nslots, cb, hcname);
}
}
needsComment = TRUE;
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
if (fb->access & ACC_PRIVATE) {
if (needsComment) {
fprintf(f, "\n\t/* Private Methods */");
needsComment = FALSE;
}
GenerateCPPMethod(f, mb, nslots, cb, hcname);
}
}
fprintf(f, "\n#endif /* IMPLEMENT_%s */\n", hcname);
fprintf(f, "};\n\n");
fprintf(f, "#endif /* __cplusplus */\n\n");
}
fprintf(f, "#endif /* Class %s */\n", currentclassname);
return out ? 0 : close_output();
}
static int
DumpClassHeader(ClassClass * cb)
{
FILE *f;
register struct fieldblock *fb;
register struct methodblock *mb;
register nslots;
int offset = 0;
char hfname[300]; /* header file name */
char hcname[300]; /* C symbol name. */
currentclassname = classname(cb);
GetFileName(currentclassname, hfname, sizeof(hfname));
strsub(currentclassname, hcname, C_DELIM);
if (prefixString == NULL) {
prefixString = hcname;
}
if ((f = open_output()) == 0) {
return -1;
}
if (verbose)
fprintf(stderr, "=> %s\n", tempfn);
fprintf(f, "/* Header for class %s */\n\n", hfname);
fprintf(f, "#ifndef _Included_%s\n#define _Included_%s\n",
hcname, hcname);
makeslottable(cb);
if (strcmp(currentclassname, "java/lang/Object") != 0
&& strcmp(currentclassname, "java/lang/Class")) {
int NumFieldsWritten = 0;
/* first generate forward declarations */
for (nslots = 0; (unsigned)nslots < cbSlotTableSize(cb); nslots++) {
fb = (cbSlotTable(cb))[nslots];
if ((fb->access & ACC_STATIC) == 0) {
forwardDeclare(f, fb);
}
}
fprintf(f, "\ntypedef struct Class%s {\n",
hcname);
for (nslots = 0; (unsigned)nslots < cbSlotTableSize(cb); nslots++) {
fb = (cbSlotTable(cb))[nslots];
if ((fb->access & ACC_STATIC) == 0) {
char *fs = fieldsig(fb);
NumFieldsWritten++;
if (fb->u.offset != offset) {
fprintf(f, " char _PAD%d_[%d];\n",
fb->u.offset, fb->u.offset - offset);
offset = fb->u.offset;
}
fprintf(f, " ");
switch (fs[0]) {
case SIGNATURE_ARRAY:
switch (fs[1]) {
case SIGNATURE_BYTE:
fprintf(f, "struct HArrayOfByte *%s;\n", fieldname(fb));
break;
case SIGNATURE_CHAR:
fprintf(f, "struct HArrayOfChar *%s;\n", fieldname(fb));
break;
case SIGNATURE_BOOLEAN:
fprintf(f, "struct HArrayOfInt *%s;\n", fieldname(fb));
break;
case SIGNATURE_SHORT:
fprintf(f, "struct HArrayOfShort *%s;\n", fieldname(fb));
break;
case SIGNATURE_INT:
fprintf(f, "struct HArrayOfInt *%s;\n", fieldname(fb));
break;
case SIGNATURE_LONG:
fprintf(f, "struct HArrayOfLong *%s;\n", fieldname(fb));
break;
case SIGNATURE_FLOAT:
fprintf(f, "struct HArrayOfFloat *%s;\n", fieldname(fb));
break;
case SIGNATURE_DOUBLE:
fprintf(f, "struct HArrayOfDouble *%s;\n", fieldname(fb));
break;
case SIGNATURE_ARRAY:
fprintf(f, "struct HArrayOfArray *%s;\n", fieldname(fb));
break;
case SIGNATURE_CLASS:
fprintf(f, "struct HArrayOfObject *%s;\n", fieldname(fb));
break;
default:
fprintf(f, "void *%s;\n", fieldname(fb));
break;
}
break;
case SIGNATURE_BYTE:
case SIGNATURE_CHAR:
case SIGNATURE_SHORT:
fprintf(f, "long %s;\n", fieldname(fb));
break;
default:
PrintType(f, fs, fieldname(fb));
fprintf(f, ";\n");
}
switch (fs[0]) {
case SIGNATURE_ANY:
offset = fb->u.offset + sizeof(void *);
break;
case SIGNATURE_BYTE:
offset = fb->u.offset + sizeof(/*char*/long);
break;
case SIGNATURE_CHAR:
offset = fb->u.offset + sizeof(/*unicode*/long);
break;
case SIGNATURE_DOUBLE:
offset = fb->u.offset + sizeof(double);
break;
case SIGNATURE_ENUM:
offset = fb->u.offset + sizeof(/*enum*/long);
break;
case SIGNATURE_FLOAT:
offset = fb->u.offset + sizeof(float);
break;
case SIGNATURE_INT:
offset = fb->u.offset + sizeof(long);
break;
case SIGNATURE_LONG:
offset = fb->u.offset + sizeof(int64_t);
break;
case SIGNATURE_SHORT:
offset = fb->u.offset + sizeof(/*short*/long);
break;
case SIGNATURE_VOID:
offset = fb->u.offset + sizeof(/*void*/long);
break;
case SIGNATURE_BOOLEAN:
offset = fb->u.offset + sizeof(long);
break;
default:
offset = fb->u.offset + sizeof(OBJECT);
break;
}
} else if (fb->access & ACC_VALKNOWN) {
char cfname[300];
CFieldName(cb, fb, nslots, cfname);
PrintKnownValue(f, cfname, fb, hcname);
} else {
fprintf(f, "/* Inaccessible static: %s */\n", fieldname(fb));
}
}
if (NumFieldsWritten == 0)
fprintf(f, " char PAD;\t/* ANSI C requires structures to have a least one member */\n");
fprintf(f, "} Class%s;\n", hcname);
fprintf(f, "HandleTo(%s);\n\n", hcname);
}
for (nslots = cb->methods_count, mb = cbMethods(cb); --nslots >= 0; mb++) {
fb = &mb->fb;
if (fb->access & ACC_NATIVE) {
forwardDeclare(f, fb);
fprintf(f, "extern ");
PrintType(f, fieldsig(fb), fieldname(fb));
fprintf(f, ";\n");
}
}
fprintf(f, "#endif\n");
return out ? 0 : close_output();
}
/*
* Just decode those sigs that are meaningful to stubs. We don't
* support lots of things.
*/
static char *
SprintReverseArgs(char *sig, char *header, char *proto, char *call,
int argn, int *arg_size_p)
{
int arg_size = 1;
char *type;
switch(*sig++) {
case SIGNATURE_CLASS:
while (*sig++ != SIGNATURE_ENDCLASS);
type = "void *";
sprintf(call, ",((_P_[%d].p))", argn);
break;
case SIGNATURE_BOOLEAN:
type = (jriMode ? "jbool" : "long");
sprintf(call, ",((_P_[%d].i))", argn);
break;
case SIGNATURE_BYTE:
type = (jriMode ? "jbyte" : "long");
sprintf(call, ",((_P_[%d].i))", argn);
break;
case SIGNATURE_SHORT:
type = (jriMode ? "jshort" : "long");
sprintf(call, ",((_P_[%d].i))", argn);
break;
case SIGNATURE_CHAR:
type = (jriMode ? "jchar" : "long");
sprintf(call, ",((_P_[%d].i))", argn);
break;
case SIGNATURE_INT:
type = (jriMode ? "jint" : "long");
sprintf(call, ",((_P_[%d].i))", argn);
break;
case SIGNATURE_FLOAT:
type = (jriMode ? "jfloat" : "float");
sprintf(call, ",((_P_[%d].f))", argn);
break;
case SIGNATURE_LONG:
type = (jriMode ? "jlong" : "int64_t");
sprintf(call, (jriMode ? ",JRI_GET_INT64(_t%d, _P_+%d)"
: ",GET_INT64(_t%d, _P_+%d)"), argn, argn);
arg_size = 2;
break;
case SIGNATURE_DOUBLE:
type = (jriMode ? "jdouble" : "double");
sprintf(call, (jriMode ? ",JRI_GET_DOUBLE(_t%d, _P_+%d)"
: ",GET_DOUBLE(_t%d, _P_+%d)"), argn, argn);
arg_size = 2;
break;
case SIGNATURE_VOID:
type = "void *";
sprintf(call, ",((_P_[%d].p))", argn);
break;
case SIGNATURE_ARRAY:
for (; *sig == SIGNATURE_ARRAY ; sig++);
if (*sig++ == SIGNATURE_CLASS) {
while (*sig++ != SIGNATURE_ENDCLASS);
}
type = "void *";
sprintf(call, ",((_P_[%d].p))", argn);
break;
default:
fprintf(stderr, "%s: illegal signature\n", currentclassname);
return 0;
}
sprintf(proto, ", %s", type);
if (arg_size == 2)
sprintf(header, (jriMode ? "\tJRI_JDK_Java8 _t%d;\n" : "\tJava8 _t%d;\n"),
argn);
*arg_size_p = arg_size;
return sig;
}
static int
PrintStub(FILE *f, char *cfname, char *cname, struct methodblock *mb)
{
struct fieldblock *fb = &mb->fb;
char *s;
char proto[1024], funcall[1024], header[1024];
char *proto_p, *funcall_p, *header_p;
int argn;
char jriname[300];
if (!(fb->access & ACC_NATIVE))
return 0;
mangleMethodName(mb, funcall, 1024, "_stub");
fprintf(f, "/* SYMBOL: \"%s/%s%s\", %s */\n",
currentclassname, fieldname(fb), fieldsig(fb), funcall);
if (jriMode) {
fprintf(f, "JRI_PUBLIC_API(JRI_JDK_stack_item*)\n%s(JRI_JDK_stack_item* _P_, JRIEnv* _EE_) {\n",
funcall);
}
else {
/* We are using a JRI macro here in the non JRI case to get the
correct external linkage on windows. This makes us source incompatible
with JDK stubs */
fprintf(f, "JRI_PUBLIC_API(stack_item*)\n%s(stack_item* _P_, struct execenv* _EE_) {\n",
funcall);
}
/* Generate function prototype args */
s = fieldsig(fb) + 1; /* first char is SIGNATURE_FUNC */
proto_p = proto;
header_p = header;
*proto_p = *header_p = '\0';
if (fb->access & ACC_STATIC) {
argn = 0; /* first argument is _P_[0] */
strcpy(funcall, (jriMode ? "_EE_,NULL" : "NULL"));
} else {
argn = 1;
strcpy(funcall, (jriMode ? "_EE_,_P_[0].p" : "_P_[0].p"));
}
funcall_p = funcall + strlen(funcall);
while (s && *s != SIGNATURE_ENDFUNC) {
int argsize;
s = SprintReverseArgs(s, header_p, proto_p, funcall_p, argn, &argsize);
if (s == 0) return -1;
header_p += strlen(header_p);
proto_p += strlen(proto_p);
funcall_p += strlen(funcall_p);
argn += argsize;
if ( header_p >= header + sizeof(header) ||
proto_p >= proto + sizeof(proto) ||
funcall_p >= funcall + sizeof(funcall)) {
fprintf(stderr, "out of buffer space!\n");
return -1;
}
}
if (jriMode) {
sprintf(jriname, "native_%s", cfname);
cfname = jriname;
}
switch(*++s) {
case SIGNATURE_VOID:
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern void %s(void *%s);\n", cfname, proto);
}
fprintf(f, "\t(void) %s(%s);\n",
cfname, funcall);
fprintf(f, "\treturn _P_;\n}\n");
break;
case SIGNATURE_FLOAT:
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern float %s(void *%s);\n",
cfname, proto);
}
fprintf(f, "\t_P_[0].f = %s(%s);\n",
cfname, funcall);
fprintf(f, "\treturn _P_ + 1;\n}\n");
break;
case SIGNATURE_DOUBLE:
fprintf(f, (jriMode ? "\tJRI_JDK_Java8 _tval;\n" : "\tJava8 _tval;\n"));
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern double %s(void *%s);\n",
cfname, proto);
}
fprintf(f, (jriMode ? "\tJRI_SET_DOUBLE(_tval, _P_, %s(%s));\n"
: "\tSET_DOUBLE(_tval, _P_, %s(%s));\n"),
cfname, funcall);
fprintf(f, "\treturn _P_ + 2;\n}\n");
break;
case SIGNATURE_CLASS:
case SIGNATURE_ARRAY:
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern void* %s(void *%s);\n",
cfname, proto);
}
fprintf(f, "\t_P_[0].p = %s(%s);\n",
cfname, funcall);
fprintf(f, "\treturn _P_ + 1;\n}\n");
break;
case SIGNATURE_BYTE:
case SIGNATURE_SHORT:
case SIGNATURE_CHAR:
case SIGNATURE_INT:
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern long %s(void *%s);\n",
cfname, proto);
}
fprintf(f, "\t_P_[0].i = %s(%s);\n",
cfname, funcall);
fprintf(f, "\treturn _P_ + 1;\n}\n");
break;
case SIGNATURE_BOOLEAN:
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern long %s(void *%s);\n",
cfname, proto);
}
fprintf(f, "\t_P_[0].i = (%s(%s) ? 1 : 0);\n",
cfname, funcall);
fprintf(f, "\treturn _P_ + 1;\n}\n");
break;
case SIGNATURE_LONG:
fprintf(f, (jriMode ? "\tJRI_JDK_Java8 _tval;\n" : "\tJava8 _tval;\n"));
fprintf(f, "%s", header);
if (!jriMode) {
fprintf(f, "\textern int64_t %s(void *%s);\n",
cfname, proto);
}
fprintf(f, (jriMode ? "\tJRI_SET_INT64(_tval, _P_, %s(%s));\n"
: "\tSET_INT64(_tval, _P_, %s(%s));\n"),
cfname, funcall);
fprintf(f, "\treturn _P_ + 2;\n}\n");
break;
default:
fprintf(stderr, "%s: unsupported function return type: %c\n",
currentclassname, *s);
return -1;
}
return 0;
}
int
DumpClassStub(ClassClass * cb)
{
FILE *f;
register struct methodblock *mb;
register nslots;
char fname[300]; /* stub file name */
char cname[300]; /* C symbol name. */
currentclassname = classname(cb);
GetFileName(currentclassname, fname, sizeof(fname));
strsub(currentclassname, cname, C_DELIM);
if (prefixString == NULL) {
prefixString = cname;
}
if ((f = open_output()) == 0) {
return -1;
}
if (verbose)
fprintf(stderr, "=> %s\n", tempfn);
fprintf(f, "/* Stubs for class %s */\n\n", currentclassname);
makeslottable(cb);
if (jriMode) {
fprintf(f, "#ifdef IMPLEMENT_%s\n", cname);
fprintf(f, "#define _implementing_%s\n", cname);
fprintf(f, "#endif /* IMPLEMENT_%s */\n", cname);
fprintf(f, "#define IMPLEMENT_%s\n", cname);
fprintf(f, "#include \"%s.h\"\n\n", fname);
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
int isStatic = (fb->access & ACC_STATIC);
char fieldType[300];
char* suffix;
char* unionType;
char cfname[300];
CFieldName(cb, fb, nslots, cfname);
GetResultType(fb->signature, fieldType, &suffix, &unionType);
if (fb->access & ACC_VALKNOWN) continue;
fprintf(f, "#ifndef UNUSED_%s\n", cfname);
fprintf(f, "JRIFieldID FAR fieldID_%s = JRIUninitialized;\n", cfname)
;
fprintf(f, "#ifdef DEBUG\n");
forwardDeclare(f, fb);
if (isStatic) {
fprintf(f, "JRI_PUBLIC_API(%s)\nget_%s(JRIEnv* env, struct java_lang_Class* clazz) {\n", fieldType, cfname);
fprintf(f, "\tif (fieldID_%s == JRIUninitialized) {\n", cfname);
fprintf(f, "\t\tassert(!\"Forgot to call use_%s(env) before accessing field %s %s\");\n\t}\n",
cname, fb->name, fb->signature);
fprintf(f, "\treturn ");
if (strcmp(suffix, "") == 0)
fprintf(f, "(%s)\n\t\t", fieldType);
fprintf(f, "JRI_GetStaticField%s(env, clazz, fieldID_%s);\n}\n", suffix, cfname);
fprintf(f, "JRI_PUBLIC_API(void)\nset_%s(JRIEnv* env, struct java_lang_Class* clazz, %s v) {\n",
cfname, fieldType);
fprintf(f, "\tif (fieldID_%s == JRIUninitialized) {\n", cfname);
fprintf(f, "\t\tassert(!\"Forgot to call use_%s(env) before accessing field %s %s\");\n\t}\n",
cname, fb->name, fb->signature);
fprintf(f, "\tJRI_SetStaticField%s(env, clazz, fieldID_%s, v);\n}\n", suffix, cfname);
} else {
fprintf(f, "JRI_PUBLIC_API(%s)\nget_%s(JRIEnv* env, struct %s* obj) {\n", fieldType, cfname, cname);
fprintf(f, "\tif (fieldID_%s == JRIUninitialized) {\n", cfname);
fprintf(f, "\t\tassert(!\"Forgot to call use_%s(env) before accessing field %s %s\");\n\t}\n",
cname, fb->name, fb->signature);
fprintf(f, "\treturn ");
if (strcmp(suffix, "") == 0)
fprintf(f, "(%s)\n\t\t", fieldType);
fprintf(f, "JRI_GetField%s(env, obj, fieldID_%s);\n}\n", suffix, cfname);
fprintf(f, "JRI_PUBLIC_API(void)\nset_%s(JRIEnv* env, struct %s* obj, %s v) {\n",
cfname, cname, fieldType);
fprintf(f, "\tif (fieldID_%s == JRIUninitialized) {\n", cfname);
fprintf(f, "\t\tassert(!\"Forgot to call use_%s(env) before accessing field %s %s\");\n\t}\n",
cname, fb->name, fb->signature);
fprintf(f, "\tJRI_SetField%s(env, obj, fieldID_%s, v);\n}\n", suffix, cfname);
}
fprintf(f, "#endif /* DEBUG */\n");
fprintf(f, "#endif /* UNUSED_%s */\n\n", cfname);
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
int isConstr = strcmp(fn, "<init>") == 0;
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
CMethodName(cb, fb, nslots, cfname);
GetResultType(fs, resultType, &suffix, &unionType);
fprintf(f, "#ifndef UNUSED_%s\n", cfname);
fprintf(f, "JRIMethodID FAR methodID_%s = JRIUninitialized;\n", cfname);
fprintf(f, "#ifdef DEBUG\n");
GenerateMethodAccessorSig(f, mb, nslots, cb, cname, FALSE);
fprintf(f, " {\n");
fprintf(f, "\tif (methodID_%s == JRIUninitialized) {\n", cfname);
fprintf(f, "\t\tassert(!\"Forgot to call use_%s(env) before calling method %s %s\");\n\t}\n",
cname, fb->name, fb->signature);
if (isConstr) {
fprintf(f, "\treturn (struct %s*)JRI_NewObject(env)(env, JRI_NewObject_op, clazz, methodID_%s",
cname, cfname);
PrintCallArgs(f, fs);
fprintf(f, ");\n}\n");
}
else {
int isVoid = strcmp(resultType, "void") == 0;
fprintf(f, "\t%s", (isVoid ? "" : "return "));
if (strlen(suffix) == 0)
fprintf(f, "(%s)", resultType);
fprintf(f, "JRI_Call%sMethod%s(env)(env, JRI_Call%sMethod_op, %s, methodID_%s",
(isStatic ? "Static" : ""),
(isVoid ? "" : suffix),
(isStatic ? "Static" : ""),
(isStatic ? "clazz" : "self"),
cfname);
PrintCallArgs(f, fs);
fprintf(f, ");\n}\n");
}
fprintf(f, "#endif /* DEBUG */\n");
fprintf(f, "#endif /* UNUSED_%s */\n\n", cfname);
}
fprintf(f, "#ifndef UNUSED_use_%s\n\n", cname);
fprintf(f, "static jglobal _globalclass_%s = NULL;\n\n", cname);
/************************************************************/
/* Generate the class initializer */
fprintf(f, "JRI_PUBLIC_API(struct java_lang_Class*)\nuse_%s(JRIEnv* env)\n{\n", cname);
fprintf(f, "\tif (_globalclass_%s == NULL) {\n", cname);
fprintf(f, "\t\tstruct java_lang_Class* clazz = JRI_FindClass(env, classname_%s);\n",
cname);
fprintf(f, "\t\tif (clazz == NULL) {\n");
fprintf(f, "\t\t\tJRI_ThrowNew(env, JRI_FindClass(env, \"java/lang/ClassNotFoundException\"), classname_%s);\n",
cname);
fprintf(f, "\t\t\treturn NULL;\n");
fprintf(f, "\t\t}\n");
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
char cfname[300];
CFieldName(cb, fb, nslots, cfname);
if (!(fb->access & ACC_VALKNOWN)) {
fprintf(f, "\t\tuse_%s(env, clazz);\n", cfname);
}
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char cfname[300];
CMethodName(cb, fb, nslots, cfname);
fprintf(f, "\t\tuse_%s(env, clazz);\n", cfname);
}
fprintf(f, "\t\t_globalclass_%s = JRI_NewGlobalRef(env, clazz);\n", cname);
fprintf(f, "\t\treturn clazz;\n");
fprintf(f, "\t}\n\telse {\n");
fprintf(f, "\t\treturn (struct java_lang_Class*)JRI_GetGlobalRef(env, _globalclass_%s);\n", cname);
fprintf(f, "\t}\n");
fprintf(f, "}\n\n");
/************************************************************/
/* Generate the class finalizer */
fprintf(f, "JRI_PUBLIC_API(void)\nunuse_%s(JRIEnv* env)\n{\n", cname);
fprintf(f, "\tif (_globalclass_%s != NULL) {\n", cname);
fprintf(f, "\t\tstruct java_lang_Class* clazz = (struct java_lang_Class*)JRI_GetGlobalRef(env, _globalclass_%s);\n",
cname, cname);
for (nslots = 0; (unsigned)nslots < cb->fields_count; nslots++) {
struct fieldblock* fb = &cb->fields[nslots];
char cfname[300];
CFieldName(cb, fb, nslots, cfname);
if (!(fb->access & ACC_VALKNOWN)) {
fprintf(f, "\t\tunuse_%s(env, clazz);\n", cfname);
}
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char cfname[300];
CMethodName(cb, fb, nslots, cfname);
fprintf(f, "\t\tunuse_%s(env, clazz);\n", cfname);
}
fprintf(f, "\t\tJRI_DisposeGlobalRef(env, _globalclass_%s);\n", cname);
fprintf(f, "\t\t_globalclass_%s = NULL;\n", cname);
fprintf(f, "\t\tclazz = NULL; /* prevent unused variable 'clazz' warning */\n", cname);
fprintf(f, "\t}\n");
fprintf(f, "}\n\n");
fprintf(f, "#endif /* UNUSED_use_%s */\n\n", cname);
/************************************************************/
/* Generate the function to register natives */
fprintf(f, "#ifdef _implementing_%s\n\n", cname);
fprintf(f, "JRI_PUBLIC_API(struct java_lang_Class*)\nregister_%s(JRIEnv* env)\n{\n", cname);
fprintf(f, "\tchar* nativeNamesAndSigs[] = {\n");
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char cfname[300];
CMethodName(cb, fb, nslots, cfname);
if (fb->access & ACC_NATIVE) {
fprintf(f, "\t\t\"%s%s\",\n", fieldname(fb), fieldsig(fb));
}
}
fprintf(f, "\t\tNULL\n"); /* trailing terminator */
fprintf(f, "\t};\n");
fprintf(f, "\tvoid* nativeProcs[] = {\n");
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char cfname[300];
CMethodName(cb, fb, nslots, cfname);
if (fb->access & ACC_NATIVE) {
fprintf(f, "\t\t(void*)native_%s,\n", cfname);
}
}
fprintf(f, "\t\tNULL\n"); /* trailing terminator */
fprintf(f, "\t};\n");
fprintf(f, "\tstruct java_lang_Class* clazz = JRI_FindClass(env, classname_%s);\n",
cname);
fprintf(f, "\tif (clazz == NULL) {\n");
fprintf(f, "\t\tJRI_ThrowNew(env, JRI_FindClass(env, \"java/lang/ClassNotFoundException\"), classname_%s);\n",
cname);
fprintf(f, "\t\treturn NULL;\n");
fprintf(f, "\t}\n");
fprintf(f, "\tJRI_RegisterNatives(env, clazz, nativeNamesAndSigs, nativeProcs);\n");
fprintf(f, "\tuse_%s(env);\n", cname);
fprintf(f, "\treturn clazz;\n");
fprintf(f, "}\n\n");
/************************************************************/
/* Generate the function to unregister natives */
fprintf(f, "JRI_PUBLIC_API(void)\nunregister_%s(JRIEnv* env)\n{\n", cname);
fprintf(f, "\tstruct java_lang_Class* clazz = JRI_FindClass(env, classname_%s);\n",
cname);
fprintf(f, "\tJRI_UnregisterNatives(env, clazz);\n");
fprintf(f, "\tunuse_%s(env);\n", cname);
fprintf(f, "}\n\n");
fprintf(f, "#endif /* _implementing_%s */\n\n", cname);
/************************************************************/
fprintf(f, "/* These stub routines are generated for compatibility with the JDK: */\n\n");
fprintf(f, "#ifndef NO_JDK\n\n");
}
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
char cfname[300];
if (jriMode)
CMethodName(cb, &mb->fb, nslots, cfname);
else
sprintf(cfname, "%s_%s", cname, fieldname(&mb->fb));
if (mb->code == 0) {
if (PrintStub(f, cfname, cname, mb)) {
fclose(f);
unlink(tempfn);
sysExit(-1);
}
fprintf(f, "\n");
}
}
if (jriMode)
fprintf(f, "#endif /* NO_JDK */\n\n");
return out ? 0 : close_output();
}
int
DumpComponentHeader(ClassClass * cb)
{
FILE *f;
register struct methodblock *mb;
register nslots;
char fname[300]; /* stub file name */
char cname[300]; /* C symbol name. */
currentclassname = classname(cb);
GetFileName(currentclassname, fname, sizeof(fname));
strsub(currentclassname, cname, C_DELIM);
if (prefixString == NULL) {
prefixString = cname;
}
if ((f = open_output()) == 0) {
return -1;
}
if (verbose)
fprintf(stderr, "=> %s\n", tempfn);
makeslottable(cb);
fprintf(f, "/* Component interface for %s */\n\n", currentclassname);
fprintf(f, "#ifndef _Component_%s_\n#define _Component_%s_\n\n",
cname, cname);
fprintf(f, "#ifdef __cplusplus\n");
fprintf(f, "extern \"C\" {\n");
fprintf(f, "#endif /* __cplusplus */\n\n");
PrintBlockComment(f, "Component Types");
fprintf(f, "typedef struct Interface_%s\n\tInterface_%s;\n\n",
cname, cname);
fprintf(f, "typedef const Interface_%s*\n\tComponent_%s;\n\n",
cname, cname);
PrintBlockComment(f, "Component Methods");
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
int isConstr = strcmp(fn, "<init>") == 0;
if (fb->access & ACC_PUBLIC && !isStatic && !isConstr) {
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
CMethodName(cb, fb, nslots, cfname);
GetResultType(fs, resultType, &suffix, &unionType);
fprintf(f, "#define %s(comp", cfname);
PrintCallArgs(f, fs);
fprintf(f, ")\t\\\n");
fprintf(f, "\t((*(comp))->%s(comp", fn);
PrintCallArgs(f, fs);
fprintf(f, "))\n\n");
}
}
PrintBlockComment(f, "Component Interface Definition");
fprintf(f, "struct Interface_%s {\n", cname);
fprintf(f, "\tint (*getComponent)(Component_%s* comp, ComponentID* id, void** result);\n", cname);
fprintf(f, "\tvoid*\treserved1;\n");
fprintf(f, "\tvoid*\treserved2;\n");
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
int isConstr = strcmp(fn, "<init>") == 0;
if (fb->access & ACC_PUBLIC && !isStatic && !isConstr) {
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
CMethodName(cb, fb, nslots, cfname);
GetResultType(fs, resultType, &suffix, &unionType);
fprintf(f, "\t%s\t(*%s)(Component_%s* comp",
resultType, fn, cname);
PrintDefArgs(f, fs);
fprintf(f, ");\n");
}
}
fprintf(f, "};\n\n");
fprintf(f, "#ifdef __cplusplus\n");
fprintf(f, "} /* extern \"C\" */\n");
fprintf(f, "#endif /* __cplusplus */\n\n");
fprintf(f, "#endif /* _Component_%s_ */\n", cname);
return out ? 0 : close_output();
}
int
DumpComponentStub(ClassClass * cb)
{
FILE *f;
register struct methodblock *mb;
register nslots;
char fname[300]; /* stub file name */
char cname[300]; /* C symbol name */
currentclassname = classname(cb);
GetFileName(currentclassname, fname, sizeof(fname));
strsub(currentclassname, cname, C_DELIM);
if (prefixString == NULL) {
prefixString = cname;
}
if ((f = open_output()) == 0) {
return -1;
}
if (verbose)
fprintf(stderr, "=> %s\n", tempfn);
fprintf(f, "/* Component Java stubs for %s */\n\n", currentclassname);
makeslottable(cb);
fprintf(f, "#include \"%s.h\"\n\n", fname);
PrintBlockComment(f, "Component Types");
fprintf(f, "typedef struct JavaComponent_%s {\n", cname);
fprintf(f, "\tInterface_%s*\tinterface;\n", cname);
fprintf(f, "\tJRIEnv*\tenv;\n");
fprintf(f, "\tjref\tobj;\n");
fprintf(f, "} JavaComponent_%s;\n\n", cname);
PrintBlockComment(f, "Component Methods");
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
char* fs = fieldsig(fb);
int isStatic = fb->access & ACC_STATIC;
int isConstr = strcmp(fn, "<init>") == 0;
if (fb->access & ACC_PUBLIC && !isStatic && !isConstr) {
char cfname[300];
char resultType[300];
char* suffix;
char* unionType;
int isVoid;
CMethodName(cb, fb, nslots, cfname);
GetResultType(fs, resultType, &suffix, &unionType);
isVoid = strcmp(resultType, "void") == 0;
fprintf(f, "%s\nmethod_%s(JavaComponent_%s* comp",
resultType, cfname, cname);
PrintDefArgs(f, fs);
fprintf(f, ") {\n");
fprintf(f, "\t%s", (isVoid ? "" : "return "));
if (strlen(suffix) == 0)
fprintf(f, "(%s)", resultType);
fprintf(f, "JRI_CallMethod(env)(comp->env, comp->obj, methodID_%s", cfname);
PrintCallArgs(f, fs);
fprintf(f, ")%s;\n", unionType);
fprintf(f, "}\n\n");
}
}
fprintf(f, "int\nmethod_%s_getComponent(JavaComponent_%s* comp, ComponentID* id, void** result) {\n", cname, cname);
fprintf(f, "\treturn 0;\n");
fprintf(f, "}\n\n");
PrintBlockComment(f, "Component Interface Definition");
fprintf(f, "const Interface_%s interface_%s = {\n", cname, cname);
fprintf(f, "\tmethod_%s_getComponent,\n", cname);
fprintf(f, "\tNULL,\n");
fprintf(f, "\tNULL");
for (nslots = 0, mb = cbMethods(cb); nslots < cb->methods_count; nslots++, mb++) {
struct fieldblock* fb = &mb->fb;
char* fn = fieldname(fb);
int isStatic = fb->access & ACC_STATIC;
int isConstr = strcmp(fn, "<init>") == 0;
if (fb->access & ACC_PUBLIC && !isStatic && !isConstr) {
char cfname[300];
CMethodName(cb, fb, nslots, cfname);
fprintf(f, ",\n\tmethod_%s", cfname);
}
}
fprintf(f, "\n};\n\n");
PrintBlockComment(f, "Component Constructor");
fprintf(f, "Component_%s*\nmake_%s(JRIEnv* env, jref obj) {\n", cname, cname);
fprintf(f, "\tJavaComponent_%s* comp = (JavaComponent_%s)\n\t\tmalloc(sizeof(JavaComponent_%s));\n",
cname, cname, cname);
fprintf(f, "\tif (comp == NULL)\n\t\treturn NULL;\n");
fprintf(f, "\tcomp->interface = interface_%s;\n", cname);
fprintf(f, "\tcomp->env = env;\n");
fprintf(f, "\tcomp->obj = obj;\n");
fprintf(f, "\treturn comp;\n");
fprintf(f, "};");
return out ? 0 : close_output();
}
int DumpNatives(ClassClass *cb)
{
struct methodblock *mb;
int nslots;
for (nslots = cb->methods_count, mb = cbMethods(cb); --nslots >= 0; mb++) {
if (mb->fb.access & ACC_NATIVE) {
char funcall[1024];
mangleMethodName(mb, funcall, sizeof(funcall), "_stub");
fprintf(stdout, "%s\n", funcall);
}
}
return 0;
}
static void
InitializeClassPath(int argc, char **argv)
{
int i;
const char *cp = getenv("CLASSPATH");
if (cp) cp = strdup(cp);
for (i = 1; i < argc; i++) {
if (argv[i] && strcmp(argv[i], "-classpath") == 0) {
if (i+1 == argc || argv[i+1] == 0) {
fprintf(stderr,
"Missing destination directory name after "
"'-classpath'\n");
sysExit(1);
}
if (cp) free((char*)cp);
cp = strdup(argv[i+1]);
}
}
setCLASSPATH(cp);
return;
}
#include <path_md.h> /* For LOCAL_DIR_SEPARATOR */
int
main(int argc, char **argv)
{
int retcode = 0;
int donesomething = 0;
int natives = 0;
SkipSourceChecks = 1;
if ((progname = strrchr(argv[0], LOCAL_DIR_SEPARATOR)) != 0) {
progname++;
} else {
progname = argv[0];
}
InhibitExecute = 1;
PR_Init("javah", 16, 0, 0);
InitializeClassPath(argc, argv);
if (!DoImport("java/lang/Object", 0)) {
fprintf(stderr, "java.lang.Object not found: aborting\n");
sysExit(1);
}
while (--argc > 0) {
if ((++argv)[0][0] == '-') {
if ((strcmp(*argv, "-d") == 0) && (argc > 1)) {
dir = *++argv;
argc--;
} else if ((strcmp(*argv, "-o") == 0) && (argc > 1)) {
out = *++argv;
argc--;
} else if ((strcmp(*argv, "-td") == 0) && (argc > 1)) {
tempdir = *++argv;
argc--;
} else if (strcmp(*argv, "-stubs") == 0) {
stubmode++;
} else if (strcmp(*argv, "-v") == 0) {
verbose++;
} else if (strcmp(*argv, "-classpath") == 0) {
argc--;
argv++;
} else if (strcmp(*argv, "-version") == 0) {
fprintf(stderr, "%s version \"%s\"\n", progname, RELEASE);
donesomething++;
} else if (strcmp(*argv, "-natives") == 0) {
natives++;
} else if (strcmp(*argv, "-jri") == 0) {
jriMode = 1;
} else if (strcmp(*argv, "-component") == 0) {
componentMode = 1;
jriMode = 1;
} else if (strcmp(*argv, "-mac") == 0) {
macMode = 1;
} else if (strcmp(*argv, "-prefix") == 0) {
prefixString = *++argv;
argc--;
} else{
fprintf(stderr, "%s: illegal argument\n", *argv);
close_output();
return 1;
}
} else if (strchr(*argv, '/')) {
fprintf(stderr, "Invalid class name: %s\n", *argv);
close_output();
return 1;
} else {
ClassClass *cb;
char *classcopy = strdup(*argv), *p;
/* Convert all periods in the classname to slashes */
for (p = classcopy; ((p = strchr(p, '.')) != 0); *p++ = '/');
cb = FindClass(0, classcopy, TRUE);
donesomething++;
if (cb == 0) {
retcode = 1;
fprintf(stderr, "%s: no such class\n", classcopy);
continue;
}
if (natives) {
if (DumpNatives(cb) < 0) {
retcode = 1;
}
} else if (componentMode && stubmode) {
if (DumpComponentStub(cb) < 0) {
retcode = 1;
}
} else if (componentMode) {
if (DumpComponentHeader(cb) < 0) {
retcode = 1;
}
} else if (stubmode) {
if (DumpClassStub(cb) < 0) {
retcode = 1;
}
} else if (jriMode) {
if (JRIDumpClassHeader(cb) < 0) {
retcode = 1;
}
} else {
if (DumpClassHeader(cb) < 0) {
retcode = 1;
}
}
prefixString = NULL; /* reset it */
}
}
if (!donesomething) {
retcode = 1;
fprintf(stderr,
"Usage: %s [-v] [-version] [-l filename] classes...\n", progname);
}
if (close_output() < 0) {
retcode = 1;
}
return retcode;
}
int
OpenCode(char *fn, char *sfn, char *dir, struct stat * st)
{
long codefd;
if (fn == 0 || (codefd = sysOpen(fn, 0, 0400)) < 0
|| stat(fn, st) < 0)
return -2;
return codefd;
}
HObject *
AllocHandle(struct methodtable *mptr, ClassObject *p)
{
JHandle *h = malloc(sizeof(JHandle));
h->methods = mptr;
h->obj = (ClassObject *) p;
return (HObject *) h;
}
ClassClass *AllocClass(void)
{
ClassClass *cb = NULL;
cb = (ClassClass*) calloc(sizeof(ClassClass), 1);
if (cb != NULL) {
cb->classStorageArena = (ClassArena*) calloc(sizeof(ClassArena), 1);
PR_InitArenaPool(&(cb->classStorageArena->pool), "class pool", 2 * 1024, 4);
}
return cb;
}
/* Dummies */
#undef DumpThreads
void
DumpThreads()
{
}
char *
vramalloc(int n)
{
return malloc(n);
}
long
CallInterpreted(struct methodblock *mb, void *obj, ...) {
return 0;
}
/* ResolveClassStringConstant is called by the classloader to resolve the
* constant pool entry, before assigning a value to a final [i.e. constant]
* String.
*
* For javah, we don't care.
*/
bool_t
ResolveClassStringConstant(ClassClass *cb, cp_index_type index, struct execenv *ee)
{
return TRUE;
}