Mercurial > projects > qtd
view generator/jumptable.cpp @ 8:c0c94c0066fa
missing files
author | eldar |
---|---|
date | Thu, 14 May 2009 11:02:22 +0000 |
parents | e78566595089 |
children | 1349940724eb |
line wrap: on
line source
/**************************************************************************** ** ** Copyright (C) 1992-2008 Nokia. All rights reserved. ** ** This file is part of Qt Jambi. ** ** * Commercial Usage * Licensees holding valid Qt Commercial licenses may use this file in * accordance with the Qt Commercial License Agreement provided with the * Software or, alternatively, in accordance with the terms contained in * a written agreement between you and Nokia. * * * GNU General Public License Usage * Alternatively, this file may be used under the terms of the GNU * General Public License versions 2.0 or 3.0 as published by the Free * Software Foundation and appearing in the file LICENSE.GPL included in * the packaging of this file. Please review the following information * to ensure GNU General Public Licensing requirements will be met: * http://www.fsf.org/licensing/licenses/info/GPLv2.html and * http://www.gnu.org/copyleft/gpl.html. In addition, as a special * exception, Nokia gives you certain additional rights. These rights * are described in the Nokia Qt GPL Exception version 1.2, included in * the file GPL_EXCEPTION.txt in this package. * * Qt for Windows(R) Licensees * As a special exception, Nokia, as the sole copyright holder for Qt * Designer, grants users of the Qt/Eclipse Integration plug-in the * right for the Qt/Eclipse Integration to link to functionality * provided by Qt Designer and its related libraries. * * * If you are unsure which license is appropriate for your use, please * contact the sales department at qt-sales@nokia.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "jumptable.h" #include "cppimplgenerator.h" #include "reporthandler.h" #include "fileout.h" static QHash<QString, QString> shortNames; static QHash<char, QString> expandNamesJNI; static QHash<char, QString> expandNamesJava; bool JumpTableGenerator::active = false; static QString simplifyName(const QString &name, const QString &context, const QString &funcName) { if (shortNames.size() == 0) { shortNames.insert("jboolean", "Z"); shortNames.insert("jbyte", "B"); shortNames.insert("jchar", "C"); shortNames.insert("jshort", "S"); shortNames.insert("jint", "I"); shortNames.insert("jlong", "J"); shortNames.insert("jfloat", "F"); shortNames.insert("jdouble", "D"); shortNames.insert("jobject", "L"); shortNames.insert("void", "V"); // Because QBool is specialcased in the typesystem to do // automatic conversions from between bool and jboolean, we // need to handle bool specially here. shortNames.insert("bool", "Z"); } QString sn = ((const QHash<QString, QString> &) shortNames).value(name); if (sn.isEmpty()) { printf("Failed to translate to shortname: %s in %s :: %s\n", qPrintable(name), qPrintable(context), qPrintable(funcName)); } return shortNames.value(name); } static QString expandNameJNI(const QChar &c) { if (expandNamesJNI.size() == 0) { expandNamesJNI.insert('Z', "jboolean"); expandNamesJNI.insert('B', "jbyte"); expandNamesJNI.insert('C', "jchar"); expandNamesJNI.insert('S', "jshort"); expandNamesJNI.insert('I', "jint"); expandNamesJNI.insert('J', "jlong"); expandNamesJNI.insert('F', "jfloat"); expandNamesJNI.insert('D', "jdouble"); expandNamesJNI.insert('L', "jobject"); expandNamesJNI.insert('V', "void"); } QString n = ((const QHash<char, QString> &) expandNamesJNI).value(c.toLatin1()); if (n.isEmpty()) printf("Failed to translate to expanded names: %c\n", c.toLatin1()); return n; } static QString expandNameJava(const QChar &c) { if (expandNamesJava.size() == 0) { expandNamesJava.insert('Z', "boolean"); expandNamesJava.insert('B', "byte"); expandNamesJava.insert('C', "char"); expandNamesJava.insert('S', "short"); expandNamesJava.insert('I', "int"); expandNamesJava.insert('J', "long"); expandNamesJava.insert('F', "float"); expandNamesJava.insert('D', "double"); expandNamesJava.insert('L', "Object"); expandNamesJava.insert('V', "void"); } QString n = ((const QHash<char, QString> &) expandNamesJava).value(c.toLatin1()); if (n.isEmpty()) printf("Failed to translate to expanded names: %c\n", c.toLatin1()); return n; } void JumpTablePreprocessor::generate() { ReportHandler::setContext("JumpTablePreprocessor"); foreach (AbstractMetaClass *cl, m_classes) { process(cl); } } void JumpTablePreprocessor::process(AbstractMetaClass *cls) { // Skip generate=no classes, such as QFutureIterator if (cls->typeEntry()->codeGeneration() != TypeEntry::GenerateAll) { // printf("skipping class: %s, generation is : %x vs %x\n", // qPrintable(cls->name()), // cls->typeEntry()->codeGeneration(), // TypeEntry::GenerateAll); return; } QString package = cls->package(); if (!m_table.contains(package)) m_table[package] = SignatureTable(); SignatureTable &signatureList = m_table[package]; // Native callbacks (all java functions require native callbacks) AbstractMetaFunctionList class_funcs = cls->functionsInTargetLang(); foreach (AbstractMetaFunction *function, class_funcs) { if (!function->isEmptyFunction()) process(function, &signatureList); } class_funcs = cls->queryFunctions(AbstractMetaClass::NormalFunctions | AbstractMetaClass::AbstractFunctions | AbstractMetaClass::NotRemovedFromTargetLang); foreach (AbstractMetaFunction *function, class_funcs) { if (function->implementingClass() != cls) { process(function, &signatureList); } } } QString JumpTablePreprocessor::signature(const AbstractMetaFunction *func) { QString signature; QString context = func->implementingClass()->name(); QString functionSignature = func->signature(); if (func->argumentRemoved(0)) signature = "V"; else signature = simplifyName(CppImplGenerator::jniReturnName(func), context, functionSignature); AbstractMetaArgumentList args = func->arguments(); foreach (const AbstractMetaArgument *a, args) { if (!func->argumentRemoved(a->argumentIndex() + 1)) { if (!a->type()->hasNativeId()) signature += simplifyName(CppImplGenerator::translateType(a->type(), EnumAsInts), context, functionSignature); else signature += "J"; } } return signature; } void JumpTablePreprocessor::process(AbstractMetaFunction *func, SignatureTable *table) { if (!func->needsCallThrough()) return; if (func->jumpTableId() >= 0) { // printf("%s::%s already has an ID=%d, for declaring=%s, owner=%s\n", // qPrintable(func->implementingClass()->name()), // qPrintable(func->signature()), // func->jumpTableId(), // qPrintable(func->declaringClass()->name()), // qPrintable(func->ownerClass()->name())); return; } QString sig = signature(func); AbstractMetaFunctionList &list = (*table)[sig]; list.append(func); func->setJumpTableId(list.size()); } JumpTableGenerator::JumpTableGenerator(JumpTablePreprocessor *pp, PriGenerator *pri) : m_preprocessor(pp), m_prigenerator(pri) { active = true; } void JumpTableGenerator::generate() { for (PackageJumpTable::const_iterator it = m_preprocessor->table()->constBegin(); it != m_preprocessor->table()->constEnd(); ++it) { QString package = it.key(); generatePackage(package, it.value()); } } void JumpTableGenerator::generatePackage(const QString &packageName, const SignatureTable &table) { generateNativeTable(packageName, table); generateJavaTable(packageName, table); } void JumpTableGenerator::generateJavaTable(const QString &packageName, const SignatureTable &table) { QString tableFile = QString("%1/%2/JTbl.java") .arg(outputDirectory()) .arg(QString(packageName).replace(".", "/")); printf("Generating jump table (.java): %s\n", qPrintable(tableFile)); FileOut file(tableFile); QTextStream &s = file.stream; s << "package " << packageName << ";" << endl << endl; s << "class JTbl {" << endl; for (SignatureTable::const_iterator sit = table.constBegin(); sit != table.constEnd(); ++sit) { QString signature = sit.key(); QString ret = expandNameJava(signature.at(0)); s << " static native " << ret << " " << signature << "(int id, long nid"; for (int i=1; i<signature.size(); ++i) { s << ", " << expandNameJava(signature.at(i)) << " a" << i; } s << ", Object _this);" << endl; } s << "}" << endl; } void JumpTableGenerator::generateNativeTable(const QString &packageName, const SignatureTable &table) { QString tableFile = QString("%1/%2/nativejumptable.cpp") .arg(outputDirectory()) .arg(CppGenerator::subDirectoryForPackage(packageName)); FileOut file(tableFile); QString pkgSubDir = QString(packageName).replace(".", "_"); m_prigenerator->addSource(pkgSubDir + "/" + pkgSubDir + ".pri", "nativejumptable.cpp"); printf("Generating jump table (.cpp): %s\n", qPrintable(tableFile)); QTextStream &s = file.stream; s << "#include <qtjambi_global.h>" << endl; for (SignatureTable::const_iterator sit = table.constBegin(); sit != table.constEnd(); ++sit) { QString signature = sit.key(); QString ret = expandNameJNI(signature.at(0)); s << endl << endl << "extern \"C\" Q_DECL_EXPORT " << ret << " JNICALL QTJAMBI_FUNCTION_PREFIX(Java_" << QString(packageName).replace("_", "_1").replace(".", "_") << "_JTbl_" << signature << ")" << endl << "(JNIEnv *e, jclass, jint id, jlong nid"; for (int i=1; i<signature.size(); ++i) { s << ", " << expandNameJNI(signature.at(i)) << " a" << i; } s << ", jobject __this)" << endl << "{" << endl << "Q_UNUSED(__this);" << endl << "Q_UNUSED(nid);" << endl << "switch (id) { " << endl; AbstractMetaFunctionList functions = sit.value(); bool hasReturn = signature.at(0) != 'V'; foreach (AbstractMetaFunction *f, functions) { const AbstractMetaClass *cls = f->ownerClass(); s << endl << "// " << cls->name() << "::" << f->signature() << ", declaring=" << f->declaringClass()->name() << ", implementing=" << f->implementingClass()->name() << endl << "case " << f->jumpTableId() << ":" << endl << "extern "; CppImplGenerator::writeFunctionName(s, f, cls, CppImplGenerator::ReturnType); s << endl; CppImplGenerator::writeFinalFunctionArguments(s, f); s << ";" << endl; if (hasReturn && !f->isConstructor()) s << "return "; CppImplGenerator::writeFunctionName(s, f, cls, 0); s << "(e"; if (f->isStatic()) s << ", 0"; else if (f->isConstructor()) s << ", __this"; else s << ", __this, nid"; for (int i=1; i<signature.size(); ++i) { s << ", a" << i; } s << ");" << endl << "break;" << endl; } s << "} // switch..." << endl; if (hasReturn) s << "return 0;" << endl; s << "} // " << signature << endl; } } bool JumpTableGenerator::isJumpTableActive() { return active; }