1
|
1 /****************************************************************************
|
|
2 **
|
|
3 ** Copyright (C) 1992-2008 Nokia. All rights reserved.
|
|
4 **
|
|
5 ** This file is part of Qt Jambi.
|
|
6 **
|
|
7 ** * Commercial Usage
|
|
8 * Licensees holding valid Qt Commercial licenses may use this file in
|
|
9 * accordance with the Qt Commercial License Agreement provided with the
|
|
10 * Software or, alternatively, in accordance with the terms contained in
|
|
11 * a written agreement between you and Nokia.
|
|
12 *
|
|
13 *
|
|
14 * GNU General Public License Usage
|
|
15 * Alternatively, this file may be used under the terms of the GNU
|
|
16 * General Public License versions 2.0 or 3.0 as published by the Free
|
|
17 * Software Foundation and appearing in the file LICENSE.GPL included in
|
|
18 * the packaging of this file. Please review the following information
|
|
19 * to ensure GNU General Public Licensing requirements will be met:
|
|
20 * http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
|
21 * http://www.gnu.org/copyleft/gpl.html. In addition, as a special
|
|
22 * exception, Nokia gives you certain additional rights. These rights
|
|
23 * are described in the Nokia Qt GPL Exception version 1.2, included in
|
|
24 * the file GPL_EXCEPTION.txt in this package.
|
|
25 *
|
|
26 * Qt for Windows(R) Licensees
|
|
27 * As a special exception, Nokia, as the sole copyright holder for Qt
|
|
28 * Designer, grants users of the Qt/Eclipse Integration plug-in the
|
|
29 * right for the Qt/Eclipse Integration to link to functionality
|
|
30 * provided by Qt Designer and its related libraries.
|
|
31 *
|
|
32 *
|
|
33 * If you are unsure which license is appropriate for your use, please
|
|
34 * contact the sales department at qt-sales@nokia.com.
|
|
35
|
|
36 **
|
|
37 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
38 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
39 **
|
|
40 ****************************************************************************/
|
|
41
|
|
42 #include "jumptable.h"
|
|
43 #include "cppimplgenerator.h"
|
|
44 #include "reporthandler.h"
|
|
45 #include "fileout.h"
|
|
46
|
|
47
|
|
48 static QHash<QString, QString> shortNames;
|
|
49 static QHash<char, QString> expandNamesJNI;
|
|
50 static QHash<char, QString> expandNamesJava;
|
|
51
|
|
52 bool JumpTableGenerator::active = false;
|
|
53
|
|
54 static QString simplifyName(const QString &name, const QString &context, const QString &funcName)
|
|
55 {
|
|
56 if (shortNames.size() == 0) {
|
|
57 shortNames.insert("jboolean", "Z");
|
|
58 shortNames.insert("jbyte", "B");
|
|
59 shortNames.insert("jchar", "C");
|
|
60 shortNames.insert("jshort", "S");
|
|
61 shortNames.insert("jint", "I");
|
|
62 shortNames.insert("jlong", "J");
|
|
63 shortNames.insert("jfloat", "F");
|
|
64 shortNames.insert("jdouble", "D");
|
|
65 shortNames.insert("jobject", "L");
|
|
66 shortNames.insert("void", "V");
|
|
67
|
|
68 // Because QBool is specialcased in the typesystem to do
|
|
69 // automatic conversions from between bool and jboolean, we
|
|
70 // need to handle bool specially here.
|
|
71 shortNames.insert("bool", "Z");
|
|
72 }
|
|
73
|
|
74 QString sn = ((const QHash<QString, QString> &) shortNames).value(name);
|
|
75 if (sn.isEmpty()) {
|
|
76 printf("Failed to translate to shortname: %s in %s :: %s\n",
|
|
77 qPrintable(name),
|
|
78 qPrintable(context),
|
|
79 qPrintable(funcName));
|
|
80 }
|
|
81
|
|
82 return shortNames.value(name);
|
|
83 }
|
|
84
|
|
85 static QString expandNameJNI(const QChar &c) {
|
|
86 if (expandNamesJNI.size() == 0) {
|
|
87 expandNamesJNI.insert('Z', "jboolean");
|
|
88 expandNamesJNI.insert('B', "jbyte");
|
|
89 expandNamesJNI.insert('C', "jchar");
|
|
90 expandNamesJNI.insert('S', "jshort");
|
|
91 expandNamesJNI.insert('I', "jint");
|
|
92 expandNamesJNI.insert('J', "jlong");
|
|
93 expandNamesJNI.insert('F', "jfloat");
|
|
94 expandNamesJNI.insert('D', "jdouble");
|
|
95 expandNamesJNI.insert('L', "jobject");
|
|
96 expandNamesJNI.insert('V', "void");
|
|
97 }
|
|
98
|
|
99 QString n = ((const QHash<char, QString> &) expandNamesJNI).value(c.toLatin1());
|
|
100 if (n.isEmpty())
|
|
101 printf("Failed to translate to expanded names: %c\n", c.toLatin1());
|
|
102
|
|
103 return n;
|
|
104 }
|
|
105
|
|
106 static QString expandNameJava(const QChar &c) {
|
|
107 if (expandNamesJava.size() == 0) {
|
|
108 expandNamesJava.insert('Z', "boolean");
|
|
109 expandNamesJava.insert('B', "byte");
|
|
110 expandNamesJava.insert('C', "char");
|
|
111 expandNamesJava.insert('S', "short");
|
|
112 expandNamesJava.insert('I', "int");
|
|
113 expandNamesJava.insert('J', "long");
|
|
114 expandNamesJava.insert('F', "float");
|
|
115 expandNamesJava.insert('D', "double");
|
|
116 expandNamesJava.insert('L', "Object");
|
|
117 expandNamesJava.insert('V', "void");
|
|
118 }
|
|
119
|
|
120 QString n = ((const QHash<char, QString> &) expandNamesJava).value(c.toLatin1());
|
|
121 if (n.isEmpty())
|
|
122 printf("Failed to translate to expanded names: %c\n", c.toLatin1());
|
|
123
|
|
124 return n;
|
|
125 }
|
|
126
|
|
127
|
|
128 void JumpTablePreprocessor::generate()
|
|
129 {
|
|
130 ReportHandler::setContext("JumpTablePreprocessor");
|
|
131 foreach (AbstractMetaClass *cl, m_classes) {
|
|
132 process(cl);
|
|
133 }
|
|
134 }
|
|
135
|
|
136 void JumpTablePreprocessor::process(AbstractMetaClass *cls)
|
|
137 {
|
|
138 // Skip generate=no classes, such as QFutureIterator
|
|
139 if (cls->typeEntry()->codeGeneration() != TypeEntry::GenerateAll) {
|
|
140 // printf("skipping class: %s, generation is : %x vs %x\n",
|
|
141 // qPrintable(cls->name()),
|
|
142 // cls->typeEntry()->codeGeneration(),
|
|
143 // TypeEntry::GenerateAll);
|
|
144 return;
|
|
145 }
|
|
146
|
|
147 QString package = cls->package();
|
|
148
|
|
149 if (!m_table.contains(package))
|
|
150 m_table[package] = SignatureTable();
|
|
151
|
|
152
|
|
153 SignatureTable &signatureList = m_table[package];
|
|
154
|
|
155 // Native callbacks (all java functions require native callbacks)
|
|
156 AbstractMetaFunctionList class_funcs = cls->functionsInTargetLang();
|
|
157 foreach (AbstractMetaFunction *function, class_funcs) {
|
|
158 if (!function->isEmptyFunction())
|
|
159 process(function, &signatureList);
|
|
160 }
|
|
161
|
|
162
|
|
163 class_funcs = cls->queryFunctions(AbstractMetaClass::NormalFunctions
|
|
164 | AbstractMetaClass::AbstractFunctions
|
|
165 | AbstractMetaClass::NotRemovedFromTargetLang);
|
|
166 foreach (AbstractMetaFunction *function, class_funcs) {
|
|
167 if (function->implementingClass() != cls) {
|
|
168 process(function, &signatureList);
|
|
169 }
|
|
170 }
|
|
171 }
|
|
172
|
|
173
|
|
174 QString JumpTablePreprocessor::signature(const AbstractMetaFunction *func)
|
|
175 {
|
|
176 QString signature;
|
|
177 QString context = func->implementingClass()->name();
|
|
178 QString functionSignature = func->signature();
|
|
179
|
|
180 if (func->argumentRemoved(0))
|
|
181 signature = "V";
|
|
182 else
|
|
183 signature = simplifyName(CppImplGenerator::jniReturnName(func), context, functionSignature);
|
|
184
|
|
185 AbstractMetaArgumentList args = func->arguments();
|
|
186 foreach (const AbstractMetaArgument *a, args) {
|
|
187 if (!func->argumentRemoved(a->argumentIndex() + 1)) {
|
|
188 if (!a->type()->hasNativeId())
|
|
189 signature += simplifyName(CppImplGenerator::translateType(a->type(), EnumAsInts),
|
|
190 context, functionSignature);
|
|
191 else
|
|
192 signature += "J";
|
|
193 }
|
|
194 }
|
|
195
|
|
196 return signature;
|
|
197 }
|
|
198
|
|
199
|
|
200 void JumpTablePreprocessor::process(AbstractMetaFunction *func, SignatureTable *table)
|
|
201 {
|
|
202 if (!func->needsCallThrough())
|
|
203 return;
|
|
204
|
|
205
|
|
206 if (func->jumpTableId() >= 0) {
|
|
207 // printf("%s::%s already has an ID=%d, for declaring=%s, owner=%s\n",
|
|
208 // qPrintable(func->implementingClass()->name()),
|
|
209 // qPrintable(func->signature()),
|
|
210 // func->jumpTableId(),
|
|
211 // qPrintable(func->declaringClass()->name()),
|
|
212 // qPrintable(func->ownerClass()->name()));
|
|
213 return;
|
|
214 }
|
|
215
|
|
216 QString sig = signature(func);
|
|
217
|
|
218 AbstractMetaFunctionList &list = (*table)[sig];
|
|
219 list.append(func);
|
|
220 func->setJumpTableId(list.size());
|
|
221 }
|
|
222
|
|
223
|
|
224 JumpTableGenerator::JumpTableGenerator(JumpTablePreprocessor *pp, PriGenerator *pri)
|
|
225 : m_preprocessor(pp),
|
|
226 m_prigenerator(pri)
|
|
227 {
|
|
228 active = true;
|
|
229 }
|
|
230
|
|
231
|
|
232 void JumpTableGenerator::generate()
|
|
233 {
|
|
234 for (PackageJumpTable::const_iterator it = m_preprocessor->table()->constBegin();
|
|
235 it != m_preprocessor->table()->constEnd(); ++it) {
|
|
236 QString package = it.key();
|
|
237 generatePackage(package, it.value());
|
|
238 }
|
|
239 }
|
|
240
|
|
241
|
|
242 void JumpTableGenerator::generatePackage(const QString &packageName, const SignatureTable &table)
|
|
243 {
|
|
244 generateNativeTable(packageName, table);
|
|
245 generateJavaTable(packageName, table);
|
|
246 }
|
|
247
|
|
248
|
|
249 void JumpTableGenerator::generateJavaTable(const QString &packageName,
|
|
250 const SignatureTable &table)
|
|
251 {
|
|
252 QString tableFile = QString("%1/%2/JTbl.java")
|
|
253 .arg(outputDirectory())
|
|
254 .arg(QString(packageName).replace(".", "/"));
|
|
255
|
|
256 printf("Generating jump table (.java): %s\n", qPrintable(tableFile));
|
|
257
|
|
258 FileOut file(tableFile);
|
|
259
|
|
260 QTextStream &s = file.stream;
|
|
261
|
|
262 s << "package " << packageName << ";" << endl << endl;
|
|
263 s << "class JTbl {" << endl;
|
|
264
|
|
265
|
|
266 for (SignatureTable::const_iterator sit = table.constBegin(); sit != table.constEnd(); ++sit) {
|
|
267 QString signature = sit.key();
|
|
268
|
|
269 QString ret = expandNameJava(signature.at(0));
|
|
270
|
|
271 s << " static native " << ret << " " << signature << "(int id, long nid";
|
|
272
|
|
273 for (int i=1; i<signature.size(); ++i) {
|
|
274 s << ", " << expandNameJava(signature.at(i)) << " a" << i;
|
|
275 }
|
|
276
|
|
277 s << ", Object _this);" << endl;
|
|
278 }
|
|
279
|
|
280 s << "}" << endl;
|
|
281 }
|
|
282
|
|
283
|
|
284 void JumpTableGenerator::generateNativeTable(const QString &packageName,
|
|
285 const SignatureTable &table)
|
|
286 {
|
|
287 QString tableFile = QString("%1/%2/nativejumptable.cpp")
|
|
288 .arg(outputDirectory())
|
|
289 .arg(CppGenerator::subDirectoryForPackage(packageName));
|
|
290
|
|
291 FileOut file(tableFile);
|
|
292
|
|
293 QString pkgSubDir = QString(packageName).replace(".", "_");
|
238
|
294 m_prigenerator->addSource(packageName, "nativejumptable.cpp");
|
1
|
295
|
|
296 printf("Generating jump table (.cpp): %s\n", qPrintable(tableFile));
|
|
297
|
|
298 QTextStream &s = file.stream;
|
|
299
|
|
300 s << "#include <qtjambi_global.h>" << endl;
|
|
301
|
|
302 for (SignatureTable::const_iterator sit = table.constBegin(); sit != table.constEnd(); ++sit) {
|
|
303 QString signature = sit.key();
|
|
304
|
|
305 QString ret = expandNameJNI(signature.at(0));
|
|
306
|
|
307 s << endl << endl
|
|
308 << "extern \"C\" Q_DECL_EXPORT " << ret << " JNICALL QTJAMBI_FUNCTION_PREFIX(Java_"
|
|
309 << QString(packageName).replace("_", "_1").replace(".", "_") << "_JTbl_" << signature << ")" << endl
|
|
310 << "(JNIEnv *e, jclass, jint id, jlong nid";
|
|
311
|
|
312 for (int i=1; i<signature.size(); ++i) {
|
|
313 s << ", " << expandNameJNI(signature.at(i)) << " a" << i;
|
|
314 }
|
|
315
|
|
316 s << ", jobject __this)" << endl
|
|
317 << "{" << endl
|
|
318 << "Q_UNUSED(__this);" << endl
|
|
319 << "Q_UNUSED(nid);" << endl
|
|
320 << "switch (id) { " << endl;
|
|
321
|
|
322 AbstractMetaFunctionList functions = sit.value();
|
|
323 bool hasReturn = signature.at(0) != 'V';
|
|
324
|
|
325 foreach (AbstractMetaFunction *f, functions) {
|
|
326 const AbstractMetaClass *cls = f->ownerClass();
|
|
327 s << endl
|
|
328 << "// " << cls->name() << "::" << f->signature() << ", declaring=" << f->declaringClass()->name() << ", implementing=" << f->implementingClass()->name() << endl
|
|
329 << "case " << f->jumpTableId() << ":" << endl
|
|
330 << "extern ";
|
|
331 CppImplGenerator::writeFunctionName(s, f, cls, CppImplGenerator::ReturnType);
|
|
332 s << endl;
|
|
333 CppImplGenerator::writeFinalFunctionArguments(s, f);
|
|
334 s << ";" << endl;
|
|
335
|
|
336 if (hasReturn && !f->isConstructor())
|
|
337 s << "return ";
|
|
338
|
|
339 CppImplGenerator::writeFunctionName(s, f, cls, 0);
|
|
340
|
|
341 s << "(e";
|
|
342
|
|
343 if (f->isStatic())
|
|
344 s << ", 0";
|
|
345 else if (f->isConstructor())
|
|
346 s << ", __this";
|
|
347 else
|
|
348 s << ", __this, nid";
|
|
349
|
|
350 for (int i=1; i<signature.size(); ++i) {
|
|
351 s << ", a" << i;
|
|
352 }
|
|
353
|
|
354 s << ");" << endl
|
|
355 << "break;" << endl;
|
|
356 }
|
|
357
|
|
358 s << "} // switch..." << endl;
|
|
359
|
|
360 if (hasReturn)
|
|
361 s << "return 0;" << endl;
|
|
362
|
|
363 s << "} // " << signature << endl;
|
|
364 }
|
|
365 }
|
|
366
|
|
367 bool JumpTableGenerator::isJumpTableActive() {
|
|
368 return active;
|
|
369 }
|