зеркало из https://github.com/mozilla/gecko-dev.git
252 строки
6.3 KiB
C++
252 строки
6.3 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (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.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
#include "JNIHeaderGenerator.h"
|
|
#include "prprf.h"
|
|
#include "plstr.h"
|
|
#include "CUtils.h"
|
|
#include "StringUtils.h"
|
|
#include "JavaObject.h"
|
|
#include "FieldOrMethod.h"
|
|
#include "JNIManglers.h"
|
|
|
|
#ifdef USE_PR_IO
|
|
#define PR_fprintf fprintf
|
|
#define PR_Write fwrite
|
|
#define PRFileDesc FILE
|
|
#endif
|
|
|
|
bool JNIHeaderGenerator::genHeaderFile(ClassFileSummary &summ,
|
|
PRFileDesc *fp)
|
|
{
|
|
Uint32 i;
|
|
const ClassFileReader &reader = *summ.getReader();
|
|
const char *className = reader.getThisClass()->getUtf()->getUtfString();
|
|
|
|
PR_fprintf(fp, "/* This file is machine-generated. Do not edit!! */\n");
|
|
|
|
PR_fprintf(fp, "\n/* Header for class %s */\n\n", className);
|
|
|
|
PR_fprintf(fp, "#include <jni.h>\n\n");
|
|
|
|
const Method **methods = summ.getMethods();
|
|
Uint32 methodCount = summ.getMethodCount();
|
|
|
|
/* Now go through each method and see if it is overloaded. */
|
|
TemporaryBuffer overbuf(methodCount*sizeof(bool));
|
|
bool *overloadedMethods = (bool *) (char *) overbuf;
|
|
|
|
for (i = 0; i < methodCount; i++) {
|
|
const char *methodName = methods[i]->getName();
|
|
|
|
overloadedMethods[i] = false;
|
|
for (Uint32 j = 0; j < methodCount; ++j)
|
|
if (i != j && strcmp(methodName, methods[j]->getName()) == 0)
|
|
overloadedMethods[i] = true;
|
|
}
|
|
|
|
/* Go through each native method and generate a declaration for it */
|
|
|
|
JNILongMangler lmangler;
|
|
JNIShortMangler smangler;
|
|
|
|
/* extern "C" the generated method headers */
|
|
PR_fprintf(fp, "#ifdef __cplusplus\n");
|
|
PR_fprintf(fp, "extern \"C\" {\n");
|
|
PR_fprintf(fp, "#endif\n");
|
|
|
|
for (i = 0; i < methodCount; i++) {
|
|
Method *m = (Method *) methods[i];
|
|
const Signature &sig = m->getSignature();
|
|
|
|
if ((m->getModifiers() & CR_METHOD_NATIVE)) {
|
|
/* Generate the return type */
|
|
char *retString = getArgString(*sig.resultType);
|
|
const char *methodName = m->getName();
|
|
const char *signature = const_cast<Method *>(m)->getSignatureString();
|
|
|
|
if (!retString)
|
|
return false;
|
|
|
|
int32 len = PL_strlen(methodName) + PL_strlen(className)*2 +
|
|
PL_strlen(signature)*2 + sizeof("Java___");
|
|
|
|
TemporaryBuffer copy(len);
|
|
char *mangledMethodName = copy;
|
|
|
|
if (overloadedMethods[i]) {
|
|
if (!lmangler.mangle(className, methodName, signature,
|
|
mangledMethodName, len))
|
|
continue;
|
|
}
|
|
else {
|
|
if (!smangler.mangle(className, methodName, signature,
|
|
mangledMethodName, len))
|
|
continue;
|
|
}
|
|
|
|
PR_fprintf(fp, "\n/*\n");
|
|
PR_fprintf(fp, " * Class : %s\n", className);
|
|
PR_fprintf(fp, " * Method : %s\n", methodName);
|
|
PR_fprintf(fp, " * Signature : %s\n", signature);
|
|
PR_fprintf(fp, " */\n");
|
|
|
|
PR_fprintf(fp, "JNIEXPORT JNICALL(%s)\n%s(",
|
|
retString, mangledMethodName);
|
|
|
|
// Kills the release build since NSPR needs to give us a clean way to
|
|
// free strings that it allocates
|
|
#ifdef DEBUG
|
|
//free(retString);
|
|
#endif
|
|
|
|
/* The first argument is always a (JNIEnv *) */
|
|
PR_fprintf(fp, "JNIEnv *");
|
|
|
|
/* For static methods, the second argument is a jclass */
|
|
if (m->getModifiers() & CR_METHOD_STATIC)
|
|
PR_fprintf(fp, ", jclass");
|
|
|
|
for (uint32 j = 0; j < sig.nArguments; j++) {
|
|
char *typeString = getArgString(*sig.argumentTypes[j]);
|
|
|
|
if (!typeString)
|
|
return false;
|
|
|
|
PR_fprintf(fp, ", %s", typeString);
|
|
|
|
// Currently does not work with the release build since NSPR needs to
|
|
// give us a clean way of freeing strings that it allocates
|
|
#ifdef DEBUG
|
|
//free(typeString);
|
|
#endif
|
|
|
|
}
|
|
|
|
PR_fprintf(fp, ");\n\n");
|
|
}
|
|
}
|
|
|
|
PR_fprintf(fp, "#ifdef __cplusplus\n");
|
|
PR_fprintf(fp, "}\n"); /* Matches the extern "C" declaration generated earlier */
|
|
PR_fprintf(fp, "#endif \n\n"); /* Matches the #ifdef __cplusplus */
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
char *JNIHeaderGenerator::getArgString(const Type &type)
|
|
{
|
|
switch (type.typeKind) {
|
|
case tkChar:
|
|
return PL_strdup("jchar");
|
|
break;
|
|
|
|
case tkShort:
|
|
return PL_strdup("jshort");
|
|
break;
|
|
|
|
case tkInt:
|
|
return PL_strdup("jint");
|
|
break;
|
|
|
|
case tkByte:
|
|
return PL_strdup("jbyte");
|
|
break;
|
|
|
|
case tkBoolean:
|
|
return PL_strdup("jbool");
|
|
break;
|
|
|
|
case tkLong:
|
|
return PL_strdup("jlong");
|
|
break;
|
|
|
|
case tkFloat:
|
|
return PL_strdup("jfloat");
|
|
break;
|
|
|
|
case tkDouble:
|
|
return PL_strdup("jdouble");
|
|
break;
|
|
|
|
case tkVoid:
|
|
return PL_strdup("void");
|
|
break;
|
|
|
|
case tkObject: {
|
|
const Class &clazz = *static_cast<const Class *>(&type);
|
|
|
|
/* Special-case certain objects XXX Need to do throwable here */
|
|
if (!PL_strcmp(clazz.getName(), "java.lang.String"))
|
|
return PL_strdup("jstring");
|
|
else
|
|
return PL_strdup("jobject");
|
|
}
|
|
|
|
case tkInterface:
|
|
return PL_strdup("jobject");
|
|
|
|
case tkArray: {
|
|
const Array &atype = *static_cast<const Array *>(&type);
|
|
|
|
switch (atype.componentType.typeKind) {
|
|
case tkChar:
|
|
return PL_strdup("jcharArray");
|
|
|
|
case tkShort:
|
|
return PL_strdup("jshortArray");
|
|
|
|
case tkInt:
|
|
return PL_strdup("jintArray");
|
|
|
|
case tkByte:
|
|
return PL_strdup("jbyteArray");
|
|
|
|
case tkBoolean:
|
|
return PL_strdup("jboolArray");
|
|
|
|
case tkLong:
|
|
return PL_strdup("jlongArray");
|
|
|
|
case tkFloat:
|
|
return PL_strdup("jfloatArray");
|
|
|
|
case tkDouble:
|
|
return PL_strdup("jdoubleArray");
|
|
|
|
case tkObject:
|
|
case tkInterface:
|
|
case tkArray:
|
|
return PL_strdup("jobjectArray");
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
}
|