1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtScxml module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "generator.h" |
30 | #include "outputrevision.h" |
31 | #include "utils.h" |
32 | #include <QtCore/qmetatype.h> |
33 | #include <QtCore/qjsondocument.h> |
34 | #include <QtCore/qjsonobject.h> |
35 | #include <QtCore/qjsonvalue.h> |
36 | #include <QtCore/qjsonarray.h> |
37 | #include <QtCore/qplugin.h> |
38 | |
39 | #include <private/qmetaobject_p.h> //for the flags. |
40 | #include <stdio.h> |
41 | |
42 | QT_BEGIN_NAMESPACE |
43 | |
44 | void fprintf(QIODevice &out, const char *fmt, ...) |
45 | { |
46 | va_list argp; |
47 | va_start(argp, fmt); |
48 | const int bufSize = 4096; |
49 | char buf[bufSize]; |
50 | vsnprintf(s: buf, maxlen: bufSize, format: fmt, arg: argp); |
51 | va_end(argp); |
52 | out.write(data: buf); |
53 | } |
54 | |
55 | void fputc(char c, QIODevice &out) |
56 | { |
57 | out.write(data: &c, len: 1); |
58 | } |
59 | |
60 | void fputs(const char *s, QIODevice &out) |
61 | { |
62 | out.write(data: s); |
63 | } |
64 | |
65 | uint nameToBuiltinType(const QByteArray &name) |
66 | { |
67 | if (name.isEmpty()) |
68 | return 0; |
69 | |
70 | uint tp = QMetaType::type(typeName: name.constData()); |
71 | return tp < uint(QMetaType::User) ? tp : uint(QMetaType::UnknownType); |
72 | } |
73 | |
74 | /* |
75 | Returns \c true if the type is a built-in type. |
76 | */ |
77 | bool isBuiltinType(const QByteArray &type) |
78 | { |
79 | int id = QMetaType::type(typeName: type.constData()); |
80 | if (id == QMetaType::UnknownType) |
81 | return false; |
82 | return (id < QMetaType::User); |
83 | } |
84 | |
85 | static const char *metaTypeEnumValueString(int type) |
86 | { |
87 | #define RETURN_METATYPENAME_STRING(MetaTypeName, MetaTypeId, RealType) \ |
88 | case QMetaType::MetaTypeName: return #MetaTypeName; |
89 | |
90 | switch (type) { |
91 | QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING) |
92 | } |
93 | #undef RETURN_METATYPENAME_STRING |
94 | return 0; |
95 | } |
96 | |
97 | Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, |
98 | QByteArray> &knownQObjectClasses, const QHash<QByteArray, |
99 | QByteArray> &knownGadgets, QIODevice &outfile) |
100 | : out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses) |
101 | , knownGadgets(knownGadgets) |
102 | { |
103 | if (cdef->superclassList.size()) |
104 | purestSuperClass = cdef->superclassList.first().first; |
105 | } |
106 | |
107 | static inline int lengthOfEscapeSequence(const QByteArray &s, int i) |
108 | { |
109 | if (s.at(i) != '\\' || i >= s.length() - 1) |
110 | return 1; |
111 | const int startPos = i; |
112 | ++i; |
113 | char ch = s.at(i); |
114 | if (ch == 'x') { |
115 | ++i; |
116 | while (i < s.length() && is_hex_char(s: s.at(i))) |
117 | ++i; |
118 | } else if (is_octal_char(s: ch)) { |
119 | while (i < startPos + 4 |
120 | && i < s.length() |
121 | && is_octal_char(s: s.at(i))) { |
122 | ++i; |
123 | } |
124 | } else { // single character escape sequence |
125 | i = qMin(a: i + 1, b: s.length()); |
126 | } |
127 | return i - startPos; |
128 | } |
129 | |
130 | void Generator::strreg(const QByteArray &s) |
131 | { |
132 | if (!strings.contains(t: s)) |
133 | strings.append(t: s); |
134 | } |
135 | |
136 | int Generator::stridx(const QByteArray &s) |
137 | { |
138 | int i = strings.indexOf(t: s); |
139 | Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings" ); |
140 | return i; |
141 | } |
142 | |
143 | // Returns the sum of all parameters (including return type) for the given |
144 | // \a list of methods. This is needed for calculating the size of the methods' |
145 | // parameter type/name meta-data. |
146 | static int aggregateParameterCount(const QList<FunctionDef> &list) |
147 | { |
148 | int sum = 0; |
149 | for (int i = 0; i < list.count(); ++i) |
150 | sum += list.at(i).arguments.count() + 1; // +1 for return type |
151 | return sum; |
152 | } |
153 | |
154 | bool Generator::registerableMetaType(const QByteArray &propertyType) |
155 | { |
156 | if (metaTypes.contains(t: propertyType)) |
157 | return true; |
158 | |
159 | if (propertyType.endsWith(c: '*')) { |
160 | QByteArray objectPointerType = propertyType; |
161 | // The objects container stores class names, such as 'QState', 'QLabel' etc, |
162 | // not 'QState*', 'QLabel*'. The propertyType does contain the '*', so we need |
163 | // to chop it to find the class type in the known QObjects list. |
164 | objectPointerType.chop(n: 1); |
165 | if (knownQObjectClasses.contains(akey: objectPointerType)) |
166 | return true; |
167 | } |
168 | |
169 | static const QVector<QByteArray> smartPointers = QVector<QByteArray>() |
170 | #define STREAM_SMART_POINTER(SMART_POINTER) << #SMART_POINTER |
171 | QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(STREAM_SMART_POINTER) |
172 | #undef STREAM_SMART_POINTER |
173 | ; |
174 | |
175 | for (const QByteArray &smartPointer : smartPointers) |
176 | if (propertyType.startsWith(a: smartPointer + "<" ) && !propertyType.endsWith(c: "&" )) |
177 | return knownQObjectClasses.contains(akey: propertyType.mid(index: smartPointer.size() + 1, len: propertyType.size() - smartPointer.size() - 1 - 1)); |
178 | |
179 | static const QVector<QByteArray> oneArgTemplates = QVector<QByteArray>() |
180 | #define STREAM_1ARG_TEMPLATE(TEMPLATENAME) << #TEMPLATENAME |
181 | QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(STREAM_1ARG_TEMPLATE) |
182 | #undef STREAM_1ARG_TEMPLATE |
183 | ; |
184 | for (const QByteArray &oneArgTemplateType : oneArgTemplates) |
185 | if (propertyType.startsWith(a: oneArgTemplateType + "<" ) && propertyType.endsWith(c: ">" )) { |
186 | const int argumentSize = propertyType.size() - oneArgTemplateType.size() - 1 |
187 | // The closing '>' |
188 | - 1 |
189 | // templates inside templates have an extra whitespace char to strip. |
190 | - (propertyType.at(i: propertyType.size() - 2) == ' ' ? 1 : 0 ); |
191 | const QByteArray templateArg = propertyType.mid(index: oneArgTemplateType.size() + 1, len: argumentSize); |
192 | return isBuiltinType(type: templateArg) || registerableMetaType(propertyType: templateArg); |
193 | } |
194 | return false; |
195 | } |
196 | |
197 | /* returns \c true if name and qualifiedName refers to the same name. |
198 | * If qualified name is "A::B::C", it returns \c true for "C", "B::C" or "A::B::C" */ |
199 | static bool qualifiedNameEquals(const QByteArray &qualifiedName, const QByteArray &name) |
200 | { |
201 | if (qualifiedName == name) |
202 | return true; |
203 | int index = qualifiedName.indexOf(c: "::" ); |
204 | if (index == -1) |
205 | return false; |
206 | return qualifiedNameEquals(qualifiedName: qualifiedName.mid(index: index+2), name); |
207 | } |
208 | |
209 | void Generator::generateCode() |
210 | { |
211 | bool isQt = (cdef->classname == "Qt" ); |
212 | bool isQObject = (cdef->classname == "QObject" ); |
213 | bool isConstructible = !cdef->constructorList.isEmpty(); |
214 | |
215 | // filter out undeclared enumerators and sets |
216 | { |
217 | QList<EnumDef> enumList; |
218 | for (int i = 0; i < cdef->enumList.count(); ++i) { |
219 | EnumDef def = cdef->enumList.at(i); |
220 | if (cdef->enumDeclarations.contains(akey: def.name)) { |
221 | enumList += def; |
222 | } |
223 | QByteArray alias = cdef->flagAliases.value(akey: def.name); |
224 | if (cdef->enumDeclarations.contains(akey: alias)) { |
225 | def.name = alias; |
226 | enumList += def; |
227 | } |
228 | } |
229 | cdef->enumList = enumList; |
230 | } |
231 | |
232 | // |
233 | // Register all strings used in data section |
234 | // |
235 | strreg(s: cdef->qualified); |
236 | registerClassInfoStrings(); |
237 | registerFunctionStrings(list: cdef->signalList); |
238 | registerFunctionStrings(list: cdef->slotList); |
239 | registerFunctionStrings(list: cdef->methodList); |
240 | registerFunctionStrings(list: cdef->constructorList); |
241 | registerPropertyStrings(); |
242 | registerEnumStrings(); |
243 | |
244 | QByteArray qualifiedClassNameIdentifier = cdef->qualified; |
245 | qualifiedClassNameIdentifier.replace(before: ':', after: '_'); |
246 | |
247 | // |
248 | // Build stringdata struct |
249 | // |
250 | const int constCharArraySizeLimit = 65535; |
251 | fprintf(out, fmt: "struct qt_meta_stringdata_%s_t {\n" , qualifiedClassNameIdentifier.constData()); |
252 | fprintf(out, fmt: " QByteArrayData data[%d];\n" , strings.size()); |
253 | { |
254 | int stringDataLength = 0; |
255 | int stringDataCounter = 0; |
256 | for (int i = 0; i < strings.size(); ++i) { |
257 | int thisLength = strings.at(i).length() + 1; |
258 | stringDataLength += thisLength; |
259 | if (stringDataLength / constCharArraySizeLimit) { |
260 | // save previous stringdata and start computing the next one. |
261 | fprintf(out, fmt: " unsigned char stringdata%d[%d];\n" , stringDataCounter++, |
262 | stringDataLength - thisLength); |
263 | stringDataLength = thisLength; |
264 | } |
265 | } |
266 | fprintf(out, fmt: " unsigned char stringdata%d[%d];\n" , stringDataCounter, stringDataLength); |
267 | |
268 | } |
269 | fprintf(out, fmt: "};\n" ); |
270 | |
271 | // Macro that expands into a QByteArrayData. The offset member is |
272 | // calculated from 1) the offset of the actual characters in the |
273 | // stringdata.stringdata member, and 2) the stringdata.data index of the |
274 | // QByteArrayData being defined. This calculation relies on the |
275 | // QByteArrayData::data() implementation returning simply "this + offset". |
276 | fprintf(out, fmt: "#define QT_MOC_LITERAL(idx, ofs, len) \\\n" |
277 | " Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \\\n" |
278 | " qptrdiff(offsetof(qt_meta_stringdata_%s_t, stringdata0) + ofs \\\n" |
279 | " - idx * sizeof(QByteArrayData)) \\\n" |
280 | " )\n" , |
281 | qualifiedClassNameIdentifier.constData()); |
282 | |
283 | fprintf(out, fmt: "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n" , |
284 | qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); |
285 | fprintf(out, fmt: " {\n" ); |
286 | { |
287 | int idx = 0; |
288 | for (int i = 0; i < strings.size(); ++i) { |
289 | const QByteArray &str = strings.at(i); |
290 | fprintf(out, fmt: "QT_MOC_LITERAL(%d, %d, %d)" , i, idx, str.length()); |
291 | if (i != strings.size() - 1) |
292 | fputc(c: ',', out); |
293 | const QByteArray = str.length() > 32 ? str.left(len: 29) + "..." : str; |
294 | fprintf(out, fmt: " // \"%s\"\n" , comment.constData()); |
295 | idx += str.length() + 1; |
296 | for (int j = 0; j < str.length(); ++j) { |
297 | if (str.at(i: j) == '\\') { |
298 | int cnt = lengthOfEscapeSequence(s: str, i: j) - 1; |
299 | idx -= cnt; |
300 | j += cnt; |
301 | } |
302 | } |
303 | } |
304 | fprintf(out, fmt: " },{\n" ); |
305 | } |
306 | |
307 | // |
308 | // Build stringdata array |
309 | // |
310 | for (int i = 0; i < strings.size(); ++i) { |
311 | QByteArray s = strings.at(i); |
312 | int len = s.length(); |
313 | for (int charPos = 0; charPos < len; ++charPos) |
314 | fprintf(out, fmt: "0x%.2x," , static_cast<quint8>(s.at(i: charPos))); |
315 | fprintf(out, fmt: "0%s // %d: %s\n" , i < strings.size() - 1 ? "," : "" , i, s.constData()); |
316 | } |
317 | |
318 | // Terminate stringdata struct |
319 | fprintf(out, fmt: " }};\n" ); |
320 | fprintf(out, fmt: "#undef QT_MOC_LITERAL\n\n" ); |
321 | |
322 | // |
323 | // build the data array |
324 | // |
325 | |
326 | int index = MetaObjectPrivateFieldCount; |
327 | fprintf(out, fmt: "static const uint qt_meta_data_%s[] = {\n" , qualifiedClassNameIdentifier.constData()); |
328 | fprintf(out, fmt: "\n // content:\n" ); |
329 | fprintf(out, fmt: " %4d, // revision\n" , int(QMetaObjectPrivate::OutputRevision)); |
330 | fprintf(out, fmt: " %4d, // classname\n" , stridx(s: cdef->qualified)); |
331 | fprintf(out, fmt: " %4d, %4d, // classinfo\n" , cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); |
332 | index += cdef->classInfoList.count() * 2; |
333 | |
334 | int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); |
335 | fprintf(out, fmt: " %4d, %4d, // methods\n" , methodCount, methodCount ? index : 0); |
336 | index += methodCount * 5; |
337 | if (cdef->revisionedMethods) |
338 | index += methodCount; |
339 | int paramsIndex = index; |
340 | int totalParameterCount = aggregateParameterCount(list: cdef->signalList) |
341 | + aggregateParameterCount(list: cdef->slotList) |
342 | + aggregateParameterCount(list: cdef->methodList) |
343 | + aggregateParameterCount(list: cdef->constructorList); |
344 | index += totalParameterCount * 2 // types and parameter names |
345 | - methodCount // return "parameters" don't have names |
346 | - cdef->constructorList.count(); // "this" parameters don't have names |
347 | |
348 | fprintf(out, fmt: " %4d, %4d, // properties\n" , cdef->propertyList.count(), cdef->propertyList.count() ? index : 0); |
349 | index += cdef->propertyList.count() * 3; |
350 | if(cdef->notifyableProperties) |
351 | index += cdef->propertyList.count(); |
352 | if (cdef->revisionedProperties) |
353 | index += cdef->propertyList.count(); |
354 | fprintf(out, fmt: " %4d, %4d, // enums/sets\n" , cdef->enumList.count(), cdef->enumList.count() ? index : 0); |
355 | |
356 | int enumsIndex = index; |
357 | for (int i = 0; i < cdef->enumList.count(); ++i) |
358 | index += 4 + (cdef->enumList.at(i).values.count() * 2); |
359 | fprintf(out, fmt: " %4d, %4d, // constructors\n" , isConstructible ? cdef->constructorList.count() : 0, |
360 | isConstructible ? index : 0); |
361 | |
362 | int flags = 0; |
363 | if (cdef->hasQGadget) { |
364 | // Ideally, all the classes could have that flag. But this broke classes generated |
365 | // by qdbusxml2cpp which generate code that require that we call qt_metacall for properties |
366 | flags |= PropertyAccessInStaticMetaCall; |
367 | } |
368 | fprintf(out, fmt: " %4d, // flags\n" , flags); |
369 | fprintf(out, fmt: " %4d, // signalCount\n" , cdef->signalList.count()); |
370 | |
371 | |
372 | // |
373 | // Build classinfo array |
374 | // |
375 | generateClassInfos(); |
376 | |
377 | // |
378 | // Build signals array first, otherwise the signal indices would be wrong |
379 | // |
380 | generateFunctions(list: cdef->signalList, functype: "signal" , type: MethodSignal, paramsIndex); |
381 | |
382 | // |
383 | // Build slots array |
384 | // |
385 | generateFunctions(list: cdef->slotList, functype: "slot" , type: MethodSlot, paramsIndex); |
386 | |
387 | // |
388 | // Build method array |
389 | // |
390 | generateFunctions(list: cdef->methodList, functype: "method" , type: MethodMethod, paramsIndex); |
391 | |
392 | // |
393 | // Build method version arrays |
394 | // |
395 | if (cdef->revisionedMethods) { |
396 | generateFunctionRevisions(list: cdef->signalList, functype: "signal" ); |
397 | generateFunctionRevisions(list: cdef->slotList, functype: "slot" ); |
398 | generateFunctionRevisions(list: cdef->methodList, functype: "method" ); |
399 | } |
400 | |
401 | // |
402 | // Build method parameters array |
403 | // |
404 | generateFunctionParameters(list: cdef->signalList, functype: "signal" ); |
405 | generateFunctionParameters(list: cdef->slotList, functype: "slot" ); |
406 | generateFunctionParameters(list: cdef->methodList, functype: "method" ); |
407 | if (isConstructible) |
408 | generateFunctionParameters(list: cdef->constructorList, functype: "constructor" ); |
409 | |
410 | // |
411 | // Build property array |
412 | // |
413 | generateProperties(); |
414 | |
415 | // |
416 | // Build enums array |
417 | // |
418 | generateEnums(index: enumsIndex); |
419 | |
420 | // |
421 | // Build constructors array |
422 | // |
423 | if (isConstructible) |
424 | generateFunctions(list: cdef->constructorList, functype: "constructor" , type: MethodConstructor, paramsIndex); |
425 | |
426 | // |
427 | // Terminate data array |
428 | // |
429 | fprintf(out, fmt: "\n 0 // eod\n};\n\n" ); |
430 | |
431 | // |
432 | // Generate internal qt_static_metacall() function |
433 | // |
434 | const bool hasStaticMetaCall = !isQt && |
435 | (cdef->hasQObject || !cdef->methodList.isEmpty() |
436 | || !cdef->propertyList.isEmpty() || !cdef->constructorList.isEmpty()); |
437 | if (hasStaticMetaCall) |
438 | generateStaticMetacall(); |
439 | |
440 | // |
441 | // Build extra array |
442 | // |
443 | QList<QByteArray> ; |
444 | QHash<QByteArray, QByteArray> = knownGadgets; |
445 | knownExtraMetaObject.insert(hash: knownQObjectClasses); |
446 | |
447 | for (int i = 0; i < cdef->propertyList.count(); ++i) { |
448 | const PropertyDef &p = cdef->propertyList.at(i); |
449 | if (isBuiltinType(type: p.type)) |
450 | continue; |
451 | |
452 | if (p.type.contains(c: '*') || p.type.contains(c: '<') || p.type.contains(c: '>')) |
453 | continue; |
454 | |
455 | int s = p.type.lastIndexOf(c: "::" ); |
456 | if (s <= 0) |
457 | continue; |
458 | |
459 | QByteArray unqualifiedScope = p.type.left(len: s); |
460 | |
461 | // The scope may be a namespace for example, so it's only safe to include scopes that are known QObjects (QTBUG-2151) |
462 | QHash<QByteArray, QByteArray>::ConstIterator scopeIt; |
463 | |
464 | QByteArray thisScope = cdef->qualified; |
465 | do { |
466 | int s = thisScope.lastIndexOf(c: "::" ); |
467 | thisScope = thisScope.left(len: s); |
468 | QByteArray currentScope = thisScope.isEmpty() ? unqualifiedScope : thisScope + "::" + unqualifiedScope; |
469 | scopeIt = knownExtraMetaObject.constFind(akey: currentScope); |
470 | } while (!thisScope.isEmpty() && scopeIt == knownExtraMetaObject.constEnd()); |
471 | |
472 | if (scopeIt == knownExtraMetaObject.constEnd()) |
473 | continue; |
474 | |
475 | const QByteArray &scope = *scopeIt; |
476 | |
477 | if (scope == "Qt" ) |
478 | continue; |
479 | if (qualifiedNameEquals(qualifiedName: cdef->qualified, name: scope)) |
480 | continue; |
481 | |
482 | if (!extraList.contains(t: scope)) |
483 | extraList += scope; |
484 | } |
485 | |
486 | // QTBUG-20639 - Accept non-local enums for QML signal/slot parameters. |
487 | // Look for any scoped enum declarations, and add those to the list |
488 | // of extra/related metaobjects for this object. |
489 | QList<QByteArray> enumKeys = cdef->enumDeclarations.keys(); |
490 | for (int i = 0; i < enumKeys.count(); ++i) { |
491 | const QByteArray &enumKey = enumKeys[i]; |
492 | int s = enumKey.lastIndexOf(c: "::" ); |
493 | if (s > 0) { |
494 | QByteArray scope = enumKey.left(len: s); |
495 | if (scope != "Qt" && !qualifiedNameEquals(qualifiedName: cdef->qualified, name: scope) && !extraList.contains(t: scope)) |
496 | extraList += scope; |
497 | } |
498 | } |
499 | |
500 | if (!extraList.isEmpty()) { |
501 | fprintf(out, fmt: "static const QMetaObject * const qt_meta_extradata_%s[] = {\n " , qualifiedClassNameIdentifier.constData()); |
502 | for (int i = 0; i < extraList.count(); ++i) { |
503 | fprintf(out, fmt: " &%s::staticMetaObject,\n" , extraList.at(i).constData()); |
504 | } |
505 | fprintf(out, fmt: " nullptr\n};\n\n" ); |
506 | } |
507 | |
508 | // |
509 | // Finally create and initialize the static meta object |
510 | // |
511 | if (isQt) |
512 | fprintf(out, fmt: "const QMetaObject QObject::staticQtMetaObject = {\n" ); |
513 | else |
514 | fprintf(out, fmt: "const QMetaObject %s::staticMetaObject = {\n" , cdef->qualified.constData()); |
515 | |
516 | if (isQObject) |
517 | fprintf(out, fmt: " { nullptr, " ); |
518 | else if (cdef->superclassList.size() && (!cdef->hasQGadget || knownGadgets.contains(akey: purestSuperClass))) |
519 | fprintf(out, fmt: " { &%s::staticMetaObject, " , purestSuperClass.constData()); |
520 | else |
521 | fprintf(out, fmt: " { nullptr, " ); |
522 | fprintf(out, fmt: "qt_meta_stringdata_%s.data,\n" |
523 | " qt_meta_data_%s, " , qualifiedClassNameIdentifier.constData(), |
524 | qualifiedClassNameIdentifier.constData()); |
525 | if (hasStaticMetaCall) |
526 | fprintf(out, fmt: " qt_static_metacall, " ); |
527 | else |
528 | fprintf(out, fmt: " nullptr, " ); |
529 | |
530 | if (extraList.isEmpty()) |
531 | fprintf(out, fmt: "nullptr, " ); |
532 | else |
533 | fprintf(out, fmt: "qt_meta_extradata_%s, " , qualifiedClassNameIdentifier.constData()); |
534 | fprintf(out, fmt: "nullptr}\n};\n\n" ); |
535 | |
536 | if(isQt) |
537 | return; |
538 | |
539 | if (!cdef->hasQObject) |
540 | return; |
541 | |
542 | fprintf(out, fmt: "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;\n}\n" , |
543 | cdef->qualified.constData()); |
544 | |
545 | // |
546 | // Generate smart cast function |
547 | // |
548 | fprintf(out, fmt: "\nvoid *%s::qt_metacast(const char *_clname)\n{\n" , cdef->qualified.constData()); |
549 | fprintf(out, fmt: " if (!_clname) return nullptr;\n" ); |
550 | fprintf(out, fmt: " if (!strcmp(_clname, reinterpret_cast<const char *>(\n" |
551 | " qt_meta_stringdata_%s.stringdata0)))\n" |
552 | " return static_cast<void*>(const_cast< %s*>(this));\n" , |
553 | qualifiedClassNameIdentifier.constData(), cdef->classname.constData()); |
554 | for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one |
555 | if (cdef->superclassList.at(i).second == FunctionDef::Private) |
556 | continue; |
557 | const char *cname = cdef->superclassList.at(i).first.constData(); |
558 | fprintf(out, fmt: " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(const_cast< %s*>(this));\n" , |
559 | cname, cname, cdef->classname.constData()); |
560 | } |
561 | for (int i = 0; i < cdef->interfaceList.size(); ++i) { |
562 | const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i); |
563 | for (int j = 0; j < iface.size(); ++j) { |
564 | fprintf(out, fmt: " if (!strcmp(_clname, %s))\n return " , iface.at(i: j).interfaceId.constData()); |
565 | for (int k = j; k >= 0; --k) |
566 | fprintf(out, fmt: "static_cast< %s*>(" , iface.at(i: k).className.constData()); |
567 | fprintf(out, fmt: "const_cast< %s*>(this)%s;\n" , |
568 | cdef->classname.constData(), QByteArray(j+1, ')').constData()); |
569 | } |
570 | } |
571 | if (!purestSuperClass.isEmpty() && !isQObject) { |
572 | QByteArray superClass = purestSuperClass; |
573 | fprintf(out, fmt: " return %s::qt_metacast(_clname);\n" , superClass.constData()); |
574 | } else { |
575 | fprintf(out, fmt: " return nullptr;\n" ); |
576 | } |
577 | fprintf(out, fmt: "}\n" ); |
578 | |
579 | // |
580 | // Generate internal qt_metacall() function |
581 | // |
582 | generateMetacall(); |
583 | |
584 | // |
585 | // Generate internal signal functions |
586 | // |
587 | for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex) |
588 | generateSignal(def: &cdef->signalList[signalindex], index: signalindex); |
589 | |
590 | fprintf(out, fmt: "\n" ); |
591 | // |
592 | // Generate plugin meta data |
593 | // |
594 | // generatePluginMetaData(); |
595 | } |
596 | |
597 | |
598 | void Generator::registerClassInfoStrings() |
599 | { |
600 | for (int i = 0; i < cdef->classInfoList.size(); ++i) { |
601 | const ClassInfoDef &c = cdef->classInfoList.at(i); |
602 | strreg(s: c.name); |
603 | strreg(s: c.value); |
604 | } |
605 | } |
606 | |
607 | void Generator::generateClassInfos() |
608 | { |
609 | if (cdef->classInfoList.isEmpty()) |
610 | return; |
611 | |
612 | fprintf(out, fmt: "\n // classinfo: key, value\n" ); |
613 | |
614 | for (int i = 0; i < cdef->classInfoList.size(); ++i) { |
615 | const ClassInfoDef &c = cdef->classInfoList.at(i); |
616 | fprintf(out, fmt: " %4d, %4d,\n" , stridx(s: c.name), stridx(s: c.value)); |
617 | } |
618 | } |
619 | |
620 | void Generator::registerFunctionStrings(const QList<FunctionDef> &list) |
621 | { |
622 | for (int i = 0; i < list.count(); ++i) { |
623 | const FunctionDef &f = list.at(i); |
624 | |
625 | strreg(s: f.name); |
626 | if (!isBuiltinType(type: f.normalizedType)) |
627 | strreg(s: f.normalizedType); |
628 | strreg(s: f.tag); |
629 | |
630 | int argsCount = f.arguments.count(); |
631 | for (int j = 0; j < argsCount; ++j) { |
632 | const ArgumentDef &a = f.arguments.at(i: j); |
633 | if (!isBuiltinType(type: a.normalizedType)) |
634 | strreg(s: a.normalizedType); |
635 | strreg(s: a.name); |
636 | } |
637 | } |
638 | } |
639 | |
640 | void Generator::generateFunctions(const QList<FunctionDef> &list, const char *functype, int type, int ¶msIndex) |
641 | { |
642 | if (list.isEmpty()) |
643 | return; |
644 | fprintf(out, fmt: "\n // %ss: name, argc, parameters, tag, flags\n" , functype); |
645 | |
646 | for (int i = 0; i < list.count(); ++i) { |
647 | const FunctionDef &f = list.at(i); |
648 | |
649 | QByteArray ; |
650 | unsigned char flags = type; |
651 | if (f.access == FunctionDef::Private) { |
652 | flags |= AccessPrivate; |
653 | comment.append(s: "Private" ); |
654 | } else if (f.access == FunctionDef::Public) { |
655 | flags |= AccessPublic; |
656 | comment.append(s: "Public" ); |
657 | } else if (f.access == FunctionDef::Protected) { |
658 | flags |= AccessProtected; |
659 | comment.append(s: "Protected" ); |
660 | } |
661 | if (f.isCompat) { |
662 | flags |= MethodCompatibility; |
663 | comment.append(s: " | MethodCompatibility" ); |
664 | } |
665 | if (f.wasCloned) { |
666 | flags |= MethodCloned; |
667 | comment.append(s: " | MethodCloned" ); |
668 | } |
669 | if (f.isScriptable) { |
670 | flags |= MethodScriptable; |
671 | comment.append(s: " | isScriptable" ); |
672 | } |
673 | if (f.revision > 0) { |
674 | flags |= MethodRevisioned; |
675 | comment.append(s: " | MethodRevisioned" ); |
676 | } |
677 | |
678 | int argc = f.arguments.count(); |
679 | fprintf(out, fmt: " %4d, %4d, %4d, %4d, 0x%02x /* %s */,\n" , |
680 | stridx(s: f.name), argc, paramsIndex, stridx(s: f.tag), flags, comment.constData()); |
681 | |
682 | paramsIndex += 1 + argc * 2; |
683 | } |
684 | } |
685 | |
686 | void Generator::generateFunctionRevisions(const QList<FunctionDef> &list, const char *functype) |
687 | { |
688 | if (list.count()) |
689 | fprintf(out, fmt: "\n // %ss: revision\n" , functype); |
690 | for (int i = 0; i < list.count(); ++i) { |
691 | const FunctionDef &f = list.at(i); |
692 | fprintf(out, fmt: " %4d,\n" , f.revision); |
693 | } |
694 | } |
695 | |
696 | void Generator::generateFunctionParameters(const QList<FunctionDef> &list, const char *functype) |
697 | { |
698 | if (list.isEmpty()) |
699 | return; |
700 | fprintf(out, fmt: "\n // %ss: parameters\n" , functype); |
701 | for (int i = 0; i < list.count(); ++i) { |
702 | const FunctionDef &f = list.at(i); |
703 | fprintf(out, fmt: " " ); |
704 | |
705 | // Types |
706 | int argsCount = f.arguments.count(); |
707 | for (int j = -1; j < argsCount; ++j) { |
708 | if (j > -1) |
709 | fputc(c: ' ', out); |
710 | const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(i: j).normalizedType; |
711 | generateTypeInfo(typeName, /*allowEmptyName=*/f.isConstructor); |
712 | fputc(c: ',', out); |
713 | } |
714 | |
715 | // Parameter names |
716 | for (int j = 0; j < argsCount; ++j) { |
717 | const ArgumentDef &arg = f.arguments.at(i: j); |
718 | fprintf(out, fmt: " %4d," , stridx(s: arg.name)); |
719 | } |
720 | |
721 | fprintf(out, fmt: "\n" ); |
722 | } |
723 | } |
724 | |
725 | void Generator::generateTypeInfo(const QByteArray &typeName, bool allowEmptyName) |
726 | { |
727 | Q_UNUSED(allowEmptyName); |
728 | if (isBuiltinType(type: typeName)) { |
729 | int type; |
730 | const char *valueString; |
731 | if (typeName == "qreal" ) { |
732 | type = QMetaType::UnknownType; |
733 | valueString = "QReal" ; |
734 | } else { |
735 | type = nameToBuiltinType(name: typeName); |
736 | valueString = metaTypeEnumValueString(type); |
737 | } |
738 | if (valueString) { |
739 | fprintf(out, fmt: "QMetaType::%s" , valueString); |
740 | } else { |
741 | Q_ASSERT(type != QMetaType::UnknownType); |
742 | fprintf(out, fmt: "%4d" , type); |
743 | } |
744 | } else { |
745 | Q_ASSERT(!typeName.isEmpty() || allowEmptyName); |
746 | fprintf(out, fmt: "0x%.8x | %d" , IsUnresolvedType, stridx(s: typeName)); |
747 | } |
748 | } |
749 | |
750 | void Generator::registerPropertyStrings() |
751 | { |
752 | for (int i = 0; i < cdef->propertyList.count(); ++i) { |
753 | const PropertyDef &p = cdef->propertyList.at(i); |
754 | strreg(s: p.name); |
755 | if (!isBuiltinType(type: p.type)) |
756 | strreg(s: p.type); |
757 | } |
758 | } |
759 | |
760 | void Generator::generateProperties() |
761 | { |
762 | // |
763 | // Create meta data |
764 | // |
765 | |
766 | if (cdef->propertyList.count()) |
767 | fprintf(out, fmt: "\n // properties: name, type, flags\n" ); |
768 | for (int i = 0; i < cdef->propertyList.count(); ++i) { |
769 | const PropertyDef &p = cdef->propertyList.at(i); |
770 | uint flags = Invalid; |
771 | if (!isBuiltinType(type: p.type)) |
772 | flags |= EnumOrFlag; |
773 | if (!p.member.isEmpty() && !p.constant) |
774 | flags |= Writable; |
775 | if (!p.read.isEmpty() || !p.member.isEmpty()) |
776 | flags |= Readable; |
777 | if (!p.write.isEmpty()) { |
778 | flags |= Writable; |
779 | if (p.stdCppSet()) |
780 | flags |= StdCppSet; |
781 | } |
782 | if (!p.reset.isEmpty()) |
783 | flags |= Resettable; |
784 | |
785 | // if (p.override) |
786 | // flags |= Override; |
787 | |
788 | if (p.designable.isEmpty()) |
789 | flags |= ResolveDesignable; |
790 | else if (p.designable != "false" ) |
791 | flags |= Designable; |
792 | |
793 | if (p.scriptable.isEmpty()) |
794 | flags |= ResolveScriptable; |
795 | else if (p.scriptable != "false" ) |
796 | flags |= Scriptable; |
797 | |
798 | if (p.stored.isEmpty()) |
799 | flags |= ResolveStored; |
800 | else if (p.stored != "false" ) |
801 | flags |= Stored; |
802 | |
803 | if (p.editable.isEmpty()) |
804 | flags |= ResolveEditable; |
805 | else if (p.editable != "false" ) |
806 | flags |= Editable; |
807 | |
808 | if (p.user.isEmpty()) |
809 | flags |= ResolveUser; |
810 | else if (p.user != "false" ) |
811 | flags |= User; |
812 | |
813 | if (p.notifyId != -1) |
814 | flags |= Notify; |
815 | |
816 | if (p.revision > 0) |
817 | flags |= Revisioned; |
818 | |
819 | if (p.constant) |
820 | flags |= Constant; |
821 | if (p.final) |
822 | flags |= Final; |
823 | |
824 | fprintf(out, fmt: " %4d, " , stridx(s: p.name)); |
825 | generateTypeInfo(typeName: p.type); |
826 | fprintf(out, fmt: ", 0x%.8x,\n" , flags); |
827 | } |
828 | |
829 | if(cdef->notifyableProperties) { |
830 | fprintf(out, fmt: "\n // properties: notify_signal_id\n" ); |
831 | for (int i = 0; i < cdef->propertyList.count(); ++i) { |
832 | const PropertyDef &p = cdef->propertyList.at(i); |
833 | if(p.notifyId == -1) |
834 | fprintf(out, fmt: " %4d,\n" , |
835 | 0); |
836 | else |
837 | fprintf(out, fmt: " %4d,\n" , |
838 | p.notifyId); |
839 | } |
840 | } |
841 | if (cdef->revisionedProperties) { |
842 | fprintf(out, fmt: "\n // properties: revision\n" ); |
843 | for (int i = 0; i < cdef->propertyList.count(); ++i) { |
844 | const PropertyDef &p = cdef->propertyList.at(i); |
845 | fprintf(out, fmt: " %4d,\n" , p.revision); |
846 | } |
847 | } |
848 | } |
849 | |
850 | void Generator::registerEnumStrings() |
851 | { |
852 | for (int i = 0; i < cdef->enumList.count(); ++i) { |
853 | const EnumDef &e = cdef->enumList.at(i); |
854 | strreg(s: e.name); |
855 | for (int j = 0; j < e.values.count(); ++j) |
856 | strreg(s: e.values.at(i: j)); |
857 | } |
858 | } |
859 | |
860 | void Generator::generateEnums(int index) |
861 | { |
862 | if (cdef->enumDeclarations.isEmpty()) |
863 | return; |
864 | |
865 | fprintf(out, fmt: "\n // enums: name, flags, count, data\n" ); |
866 | index += 4 * cdef->enumList.count(); |
867 | int i; |
868 | for (i = 0; i < cdef->enumList.count(); ++i) { |
869 | const EnumDef &e = cdef->enumList.at(i); |
870 | fprintf(out, fmt: " %4d, 0x%.1x, %4d, %4d,\n" , |
871 | stridx(s: e.name), |
872 | cdef->enumDeclarations.value(akey: e.name) ? 1 : 0, |
873 | e.values.count(), |
874 | index); |
875 | index += e.values.count() * 2; |
876 | } |
877 | |
878 | fprintf(out, fmt: "\n // enum data: key, value\n" ); |
879 | for (i = 0; i < cdef->enumList.count(); ++i) { |
880 | const EnumDef &e = cdef->enumList.at(i); |
881 | for (int j = 0; j < e.values.count(); ++j) { |
882 | const QByteArray &val = e.values.at(i: j); |
883 | QByteArray code = cdef->qualified.constData(); |
884 | if (e.isEnumClass) |
885 | code += "::" + e.name; |
886 | code += "::" + val; |
887 | fprintf(out, fmt: " %4d, uint(%s),\n" , |
888 | stridx(s: val), code.constData()); |
889 | } |
890 | } |
891 | } |
892 | |
893 | void Generator::generateMetacall() |
894 | { |
895 | bool isQObject = (cdef->classname == "QObject" ); |
896 | |
897 | fprintf(out, fmt: "\nint %s::qt_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n" , |
898 | cdef->qualified.constData()); |
899 | |
900 | if (!purestSuperClass.isEmpty() && !isQObject) { |
901 | QByteArray superClass = purestSuperClass; |
902 | fprintf(out, fmt: " _id = %s::qt_metacall(_c, _id, _a);\n" , superClass.constData()); |
903 | } |
904 | |
905 | fprintf(out, fmt: " if (_id < 0)\n return _id;\n" ); |
906 | fprintf(out, fmt: " " ); |
907 | |
908 | bool needElse = false; |
909 | QList<FunctionDef> methodList; |
910 | methodList += cdef->signalList; |
911 | methodList += cdef->slotList; |
912 | methodList += cdef->methodList; |
913 | |
914 | if (methodList.size()) { |
915 | needElse = true; |
916 | fprintf(out, fmt: "if (_c == QMetaObject::InvokeMetaMethod) {\n" ); |
917 | fprintf(out, fmt: " if (_id < %d)\n" , methodList.size()); |
918 | fprintf(out, fmt: " qt_static_metacall(this, _c, _id, _a);\n" ); |
919 | fprintf(out, fmt: " _id -= %d;\n }" , methodList.size()); |
920 | |
921 | fprintf(out, fmt: " else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {\n" ); |
922 | fprintf(out, fmt: " if (_id < %d)\n" , methodList.size()); |
923 | |
924 | if (methodsWithAutomaticTypesHelper(methodList).isEmpty()) |
925 | fprintf(out, fmt: " *reinterpret_cast<int*>(_a[0]) = -1;\n" ); |
926 | else |
927 | fprintf(out, fmt: " qt_static_metacall(this, _c, _id, _a);\n" ); |
928 | fprintf(out, fmt: " _id -= %d;\n }" , methodList.size()); |
929 | |
930 | } |
931 | |
932 | if (cdef->propertyList.size()) { |
933 | bool needDesignable = false; |
934 | bool needScriptable = false; |
935 | bool needStored = false; |
936 | bool needEditable = false; |
937 | bool needUser = false; |
938 | for (int i = 0; i < cdef->propertyList.size(); ++i) { |
939 | const PropertyDef &p = cdef->propertyList.at(i); |
940 | needDesignable |= p.designable.endsWith(c: ')'); |
941 | needScriptable |= p.scriptable.endsWith(c: ')'); |
942 | needStored |= p.stored.endsWith(c: ')'); |
943 | needEditable |= p.editable.endsWith(c: ')'); |
944 | needUser |= p.user.endsWith(c: ')'); |
945 | } |
946 | |
947 | fprintf(out, fmt: "\n#ifndef QT_NO_PROPERTIES\n " ); |
948 | if (needElse) |
949 | fprintf(out, fmt: "else " ); |
950 | fprintf(out, |
951 | fmt: "if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty\n" |
952 | " || _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {\n" |
953 | " qt_static_metacall(this, _c, _id, _a);\n" |
954 | " _id -= %d;\n }" , cdef->propertyList.count()); |
955 | |
956 | fprintf(out, fmt: " else " ); |
957 | fprintf(out, fmt: "if (_c == QMetaObject::QueryPropertyDesignable) {\n" ); |
958 | if (needDesignable) { |
959 | fprintf(out, fmt: " bool *_b = reinterpret_cast<bool*>(_a[0]);\n" ); |
960 | fprintf(out, fmt: " switch (_id) {\n" ); |
961 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
962 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
963 | if (!p.designable.endsWith(c: ')')) |
964 | continue; |
965 | fprintf(out, fmt: " case %d: *_b = %s; break;\n" , |
966 | propindex, p.designable.constData()); |
967 | } |
968 | fprintf(out, fmt: " default: break;\n" ); |
969 | fprintf(out, fmt: " }\n" ); |
970 | } |
971 | fprintf(out, |
972 | fmt: " _id -= %d;\n" |
973 | " }" , cdef->propertyList.count()); |
974 | |
975 | fprintf(out, fmt: " else " ); |
976 | fprintf(out, fmt: "if (_c == QMetaObject::QueryPropertyScriptable) {\n" ); |
977 | if (needScriptable) { |
978 | fprintf(out, fmt: " bool *_b = reinterpret_cast<bool*>(_a[0]);\n" ); |
979 | fprintf(out, fmt: " switch (_id) {\n" ); |
980 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
981 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
982 | if (!p.scriptable.endsWith(c: ')')) |
983 | continue; |
984 | fprintf(out, fmt: " case %d: *_b = %s; break;\n" , |
985 | propindex, p.scriptable.constData()); |
986 | } |
987 | fprintf(out, fmt: " default: break;\n" ); |
988 | fprintf(out, fmt: " }\n" ); |
989 | } |
990 | fprintf(out, |
991 | fmt: " _id -= %d;\n" |
992 | " }" , cdef->propertyList.count()); |
993 | |
994 | fprintf(out, fmt: " else " ); |
995 | fprintf(out, fmt: "if (_c == QMetaObject::QueryPropertyStored) {\n" ); |
996 | if (needStored) { |
997 | fprintf(out, fmt: " bool *_b = reinterpret_cast<bool*>(_a[0]);\n" ); |
998 | fprintf(out, fmt: " switch (_id) {\n" ); |
999 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1000 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1001 | if (!p.stored.endsWith(c: ')')) |
1002 | continue; |
1003 | fprintf(out, fmt: " case %d: *_b = %s; break;\n" , |
1004 | propindex, p.stored.constData()); |
1005 | } |
1006 | fprintf(out, fmt: " default: break;\n" ); |
1007 | fprintf(out, fmt: " }\n" ); |
1008 | } |
1009 | fprintf(out, |
1010 | fmt: " _id -= %d;\n" |
1011 | " }" , cdef->propertyList.count()); |
1012 | |
1013 | fprintf(out, fmt: " else " ); |
1014 | fprintf(out, fmt: "if (_c == QMetaObject::QueryPropertyEditable) {\n" ); |
1015 | if (needEditable) { |
1016 | fprintf(out, fmt: " bool *_b = reinterpret_cast<bool*>(_a[0]);\n" ); |
1017 | fprintf(out, fmt: " switch (_id) {\n" ); |
1018 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1019 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1020 | if (!p.editable.endsWith(c: ')')) |
1021 | continue; |
1022 | fprintf(out, fmt: " case %d: *_b = %s; break;\n" , |
1023 | propindex, p.editable.constData()); |
1024 | } |
1025 | fprintf(out, fmt: " default: break;\n" ); |
1026 | fprintf(out, fmt: " }\n" ); |
1027 | } |
1028 | fprintf(out, |
1029 | fmt: " _id -= %d;\n" |
1030 | " }" , cdef->propertyList.count()); |
1031 | |
1032 | |
1033 | fprintf(out, fmt: " else " ); |
1034 | fprintf(out, fmt: "if (_c == QMetaObject::QueryPropertyUser) {\n" ); |
1035 | if (needUser) { |
1036 | fprintf(out, fmt: " bool *_b = reinterpret_cast<bool*>(_a[0]);\n" ); |
1037 | fprintf(out, fmt: " switch (_id) {\n" ); |
1038 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1039 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1040 | if (!p.user.endsWith(c: ')')) |
1041 | continue; |
1042 | fprintf(out, fmt: " case %d: *_b = %s; break;\n" , |
1043 | propindex, p.user.constData()); |
1044 | } |
1045 | fprintf(out, fmt: " default: break;\n" ); |
1046 | fprintf(out, fmt: " }\n" ); |
1047 | } |
1048 | fprintf(out, |
1049 | fmt: " _id -= %d;\n" |
1050 | " }" , cdef->propertyList.count()); |
1051 | |
1052 | fprintf(out, fmt: "\n#endif // QT_NO_PROPERTIES" ); |
1053 | } |
1054 | if (methodList.size() || cdef->signalList.size() || cdef->propertyList.size()) |
1055 | fprintf(out, fmt: "\n " ); |
1056 | fprintf(out,fmt: "return _id;\n}\n" ); |
1057 | } |
1058 | |
1059 | |
1060 | QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper() |
1061 | { |
1062 | QMultiMap<QByteArray, int> automaticPropertyMetaTypes; |
1063 | for (int i = 0; i < cdef->propertyList.size(); ++i) { |
1064 | const QByteArray propertyType = cdef->propertyList.at(i).type; |
1065 | if (registerableMetaType(propertyType) && !isBuiltinType(type: propertyType)) |
1066 | automaticPropertyMetaTypes.insert(akey: propertyType, avalue: i); |
1067 | } |
1068 | return automaticPropertyMetaTypes; |
1069 | } |
1070 | |
1071 | QMap<int, QMultiMap<QByteArray, int> > Generator::methodsWithAutomaticTypesHelper(const QList<FunctionDef> &methodList) |
1072 | { |
1073 | QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypes; |
1074 | for (int i = 0; i < methodList.size(); ++i) { |
1075 | const FunctionDef &f = methodList.at(i); |
1076 | for (int j = 0; j < f.arguments.count(); ++j) { |
1077 | const QByteArray argType = f.arguments.at(i: j).normalizedType; |
1078 | if (registerableMetaType(propertyType: argType) && !isBuiltinType(type: argType)) |
1079 | methodsWithAutomaticTypes[i].insert(akey: argType, avalue: j); |
1080 | } |
1081 | } |
1082 | return methodsWithAutomaticTypes; |
1083 | } |
1084 | |
1085 | void Generator::generateStaticMetacall() |
1086 | { |
1087 | fprintf(out, fmt: "void %s::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)\n{\n" , |
1088 | cdef->qualified.constData()); |
1089 | |
1090 | bool needElse = false; |
1091 | bool isUsed_a = false; |
1092 | |
1093 | if (!cdef->constructorList.isEmpty()) { |
1094 | fprintf(out, fmt: " if (_c == QMetaObject::CreateInstance) {\n" ); |
1095 | fprintf(out, fmt: " switch (_id) {\n" ); |
1096 | for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) { |
1097 | fprintf(out, fmt: " case %d: { %s *_r = new %s(" , ctorindex, |
1098 | cdef->classname.constData(), cdef->classname.constData()); |
1099 | const FunctionDef &f = cdef->constructorList.at(i: ctorindex); |
1100 | int offset = 1; |
1101 | |
1102 | int argsCount = f.arguments.count(); |
1103 | for (int j = 0; j < argsCount; ++j) { |
1104 | const ArgumentDef &a = f.arguments.at(i: j); |
1105 | if (j) |
1106 | fprintf(out, fmt: "," ); |
1107 | fprintf(out, fmt: "(*reinterpret_cast< %s>(_a[%d]))" , a.typeNameForCast.constData(), offset++); |
1108 | } |
1109 | if (f.isPrivateSignal) { |
1110 | if (argsCount > 0) |
1111 | fprintf(out, fmt: ", " ); |
1112 | fprintf(out, fmt: "%s" , QByteArray("QPrivateSignal()" ).constData()); |
1113 | } |
1114 | fprintf(out, fmt: ");\n" ); |
1115 | fprintf(out, fmt: " if (_a[0]) *reinterpret_cast<%s**>(_a[0]) = _r; } break;\n" , |
1116 | cdef->hasQGadget ? "void" : "QObject" ); |
1117 | } |
1118 | fprintf(out, fmt: " default: break;\n" ); |
1119 | fprintf(out, fmt: " }\n" ); |
1120 | fprintf(out, fmt: " }" ); |
1121 | needElse = true; |
1122 | isUsed_a = true; |
1123 | } |
1124 | |
1125 | QList<FunctionDef> methodList; |
1126 | methodList += cdef->signalList; |
1127 | methodList += cdef->slotList; |
1128 | methodList += cdef->methodList; |
1129 | |
1130 | if (!methodList.isEmpty()) { |
1131 | if (needElse) |
1132 | fprintf(out, fmt: " else " ); |
1133 | else |
1134 | fprintf(out, fmt: " " ); |
1135 | fprintf(out, fmt: "if (_c == QMetaObject::InvokeMetaMethod) {\n" ); |
1136 | if (cdef->hasQObject) { |
1137 | #ifndef QT_NO_DEBUG |
1138 | fprintf(out, fmt: " Q_ASSERT(staticMetaObject.cast(_o));\n" ); |
1139 | #endif |
1140 | fprintf(out, fmt: " %s *_t = static_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1141 | } else { |
1142 | fprintf(out, fmt: " %s *_t = reinterpret_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1143 | } |
1144 | fprintf(out, fmt: " Q_UNUSED(_t)\n" ); |
1145 | fprintf(out, fmt: " switch (_id) {\n" ); |
1146 | for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) { |
1147 | const FunctionDef &f = methodList.at(i: methodindex); |
1148 | Q_ASSERT(!f.normalizedType.isEmpty()); |
1149 | fprintf(out, fmt: " case %d: " , methodindex); |
1150 | |
1151 | //---- Changed from the original in moc |
1152 | if (f.implementation) { |
1153 | fprintf(out, fmt: f.implementation, "_o" , methodindex); |
1154 | fprintf(out, fmt: " break;\n" ); |
1155 | continue; |
1156 | } |
1157 | //---- End of change |
1158 | |
1159 | if (f.normalizedType != "void" ) |
1160 | fprintf(out, fmt: "{ %s _r = " , noRef(type: f.normalizedType).constData()); |
1161 | fprintf(out, fmt: "_t->" ); |
1162 | if (f.inPrivateClass.size()) |
1163 | fprintf(out, fmt: "%s->" , f.inPrivateClass.constData()); |
1164 | fprintf(out, fmt: "%s(" , f.name.constData()); |
1165 | int offset = 1; |
1166 | |
1167 | int argsCount = f.arguments.count(); |
1168 | for (int j = 0; j < argsCount; ++j) { |
1169 | const ArgumentDef &a = f.arguments.at(i: j); |
1170 | if (j) |
1171 | fprintf(out, fmt: "," ); |
1172 | fprintf(out, fmt: "(*reinterpret_cast< %s>(_a[%d]))" ,a.typeNameForCast.constData(), offset++); |
1173 | isUsed_a = true; |
1174 | } |
1175 | if (f.isPrivateSignal) { |
1176 | if (argsCount > 0) |
1177 | fprintf(out, fmt: ", " ); |
1178 | fprintf(out, fmt: "%s" , "QPrivateSignal()" ); |
1179 | } |
1180 | fprintf(out, fmt: ");" ); |
1181 | if (f.normalizedType != "void" ) { |
1182 | fprintf(out, fmt: "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } " , |
1183 | noRef(type: f.normalizedType).constData()); |
1184 | isUsed_a = true; |
1185 | } |
1186 | fprintf(out, fmt: " break;\n" ); |
1187 | } |
1188 | fprintf(out, fmt: " default: ;\n" ); |
1189 | fprintf(out, fmt: " }\n" ); |
1190 | fprintf(out, fmt: " }" ); |
1191 | needElse = true; |
1192 | |
1193 | QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypes = methodsWithAutomaticTypesHelper(methodList); |
1194 | |
1195 | if (!methodsWithAutomaticTypes.isEmpty()) { |
1196 | fprintf(out, fmt: " else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {\n" ); |
1197 | fprintf(out, fmt: " switch (_id) {\n" ); |
1198 | fprintf(out, fmt: " default: *reinterpret_cast<int*>(_a[0]) = -1; break;\n" ); |
1199 | QMap<int, QMultiMap<QByteArray, int> >::const_iterator it = methodsWithAutomaticTypes.constBegin(); |
1200 | const QMap<int, QMultiMap<QByteArray, int> >::const_iterator end = methodsWithAutomaticTypes.constEnd(); |
1201 | for ( ; it != end; ++it) { |
1202 | fprintf(out, fmt: " case %d:\n" , it.key()); |
1203 | fprintf(out, fmt: " switch (*reinterpret_cast<int*>(_a[1])) {\n" ); |
1204 | fprintf(out, fmt: " default: *reinterpret_cast<int*>(_a[0]) = -1; break;\n" ); |
1205 | for (const QByteArray &key : it->uniqueKeys()) { |
1206 | for (int argumentID : it->values(akey: key)) |
1207 | fprintf(out, fmt: " case %d:\n" , argumentID); |
1208 | fprintf(out, fmt: " *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< %s >(); break;\n" , key.constData()); |
1209 | } |
1210 | fprintf(out, fmt: " }\n" ); |
1211 | fprintf(out, fmt: " break;\n" ); |
1212 | } |
1213 | fprintf(out, fmt: " }\n" ); |
1214 | fprintf(out, fmt: " }" ); |
1215 | isUsed_a = true; |
1216 | } |
1217 | |
1218 | } |
1219 | if (!cdef->signalList.isEmpty()) { |
1220 | Q_ASSERT(needElse); // if there is signal, there was method. |
1221 | fprintf(out, fmt: " else if (_c == QMetaObject::IndexOfMethod) {\n" ); |
1222 | fprintf(out, fmt: " int *result = reinterpret_cast<int *>(_a[0]);\n" ); |
1223 | fprintf(out, fmt: " void **func = reinterpret_cast<void **>(_a[1]);\n" ); |
1224 | bool anythingUsed = false; |
1225 | for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) { |
1226 | const FunctionDef &f = cdef->signalList.at(i: methodindex); |
1227 | if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic || f.mangledName.isEmpty()) |
1228 | continue; |
1229 | anythingUsed = true; |
1230 | fprintf(out, fmt: " {\n" ); |
1231 | fprintf(out, fmt: " typedef %s (%s::*_t)(" ,f.type.rawName.constData() , cdef->classname.constData()); |
1232 | |
1233 | int argsCount = f.arguments.count(); |
1234 | for (int j = 0; j < argsCount; ++j) { |
1235 | const ArgumentDef &a = f.arguments.at(i: j); |
1236 | if (j) |
1237 | fprintf(out, fmt: ", " ); |
1238 | fprintf(out, fmt: "%s" , QByteArray(a.type.name + ' ' + a.rightType).constData()); |
1239 | } |
1240 | if (f.isPrivateSignal) { |
1241 | if (argsCount > 0) |
1242 | fprintf(out, fmt: ", " ); |
1243 | fprintf(out, fmt: "%s" , "QPrivateSignal" ); |
1244 | } |
1245 | if (f.isConst) |
1246 | fprintf(out, fmt: ") const;\n" ); |
1247 | else |
1248 | fprintf(out, fmt: ");\n" ); |
1249 | fprintf(out, fmt: " if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&%s::%s)) {\n" , |
1250 | cdef->classname.constData(), f.mangledName.constData()); |
1251 | fprintf(out, fmt: " *result = %d;\n" , methodindex); |
1252 | fprintf(out, fmt: " return;\n" ); |
1253 | fprintf(out, fmt: " }\n }\n" ); |
1254 | } |
1255 | if (!anythingUsed) |
1256 | fprintf(out, fmt: " Q_UNUSED(result);\n Q_UNUSED(func);\n" ); |
1257 | fprintf(out, fmt: " }" ); |
1258 | needElse = true; |
1259 | } |
1260 | |
1261 | QMultiMap<QByteArray, int> automaticPropertyMetaTypes = automaticPropertyMetaTypesHelper(); |
1262 | |
1263 | if (!automaticPropertyMetaTypes.isEmpty()) { |
1264 | if (needElse) |
1265 | fprintf(out, fmt: " else " ); |
1266 | else |
1267 | fprintf(out, fmt: " " ); |
1268 | fprintf(out, fmt: "if (_c == QMetaObject::RegisterPropertyMetaType) {\n" ); |
1269 | fprintf(out, fmt: " switch (_id) {\n" ); |
1270 | fprintf(out, fmt: " default: *reinterpret_cast<int*>(_a[0]) = -1; break;\n" ); |
1271 | for (const QByteArray &key : automaticPropertyMetaTypes.uniqueKeys()) { |
1272 | for (int propertyID : automaticPropertyMetaTypes.values(akey: key)) |
1273 | fprintf(out, fmt: " case %d:\n" , propertyID); |
1274 | fprintf(out, fmt: " *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< %s >(); break;\n" , key.constData()); |
1275 | } |
1276 | fprintf(out, fmt: " }\n" ); |
1277 | fprintf(out, fmt: " }\n" ); |
1278 | isUsed_a = true; |
1279 | needElse = true; |
1280 | } |
1281 | |
1282 | if (!cdef->propertyList.empty()) { |
1283 | bool needGet = false; |
1284 | bool needTempVarForGet = false; |
1285 | bool needSet = false; |
1286 | bool needReset = false; |
1287 | for (int i = 0; i < cdef->propertyList.size(); ++i) { |
1288 | const PropertyDef &p = cdef->propertyList.at(i); |
1289 | needGet |= !p.read.isEmpty() || !p.member.isEmpty(); |
1290 | if (!p.read.isEmpty() || !p.member.isEmpty()) |
1291 | needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec |
1292 | && p.gspec != PropertyDef::ReferenceSpec); |
1293 | |
1294 | needSet |= !p.write.isEmpty() || (!p.member.isEmpty() && !p.constant); |
1295 | needReset |= !p.reset.isEmpty(); |
1296 | } |
1297 | fprintf(out, fmt: "\n#ifndef QT_NO_PROPERTIES\n " ); |
1298 | |
1299 | if (needElse) |
1300 | fprintf(out, fmt: "else " ); |
1301 | fprintf(out, fmt: "if (_c == QMetaObject::ReadProperty) {\n" ); |
1302 | if (needGet) { |
1303 | if (cdef->hasQObject) { |
1304 | #ifndef QT_NO_DEBUG |
1305 | fprintf(out, fmt: " Q_ASSERT(staticMetaObject.cast(_o));\n" ); |
1306 | #endif |
1307 | fprintf(out, fmt: " %s *_t = static_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1308 | } else { |
1309 | fprintf(out, fmt: " %s *_t = reinterpret_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1310 | } |
1311 | fprintf(out, fmt: " Q_UNUSED(_t)\n" ); |
1312 | if (needTempVarForGet) |
1313 | fprintf(out, fmt: " void *_v = _a[0];\n" ); |
1314 | fprintf(out, fmt: " switch (_id) {\n" ); |
1315 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1316 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1317 | if (p.read.isEmpty() && p.member.isEmpty()) |
1318 | continue; |
1319 | QByteArray prefix = "_t->" ; |
1320 | if (p.inPrivateClass.size()) { |
1321 | prefix += p.inPrivateClass + "->" ; |
1322 | } |
1323 | if (p.gspec == PropertyDef::PointerSpec) |
1324 | fprintf(out, fmt: " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n" , |
1325 | propindex, prefix.constData(), p.read.constData()); |
1326 | else if (p.gspec == PropertyDef::ReferenceSpec) |
1327 | fprintf(out, fmt: " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n" , |
1328 | propindex, prefix.constData(), p.read.constData()); |
1329 | else if (cdef->enumDeclarations.value(akey: p.type, adefaultValue: false)) |
1330 | fprintf(out, fmt: " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n" , |
1331 | propindex, prefix.constData(), p.read.constData()); |
1332 | else if (!p.read.isEmpty()) |
1333 | //---- Changed from the original in moc |
1334 | { |
1335 | fprintf(out, fmt: " case %d: *reinterpret_cast< %s*>(_v) = %s%s%s; break;\n" , |
1336 | propindex, p.type.constData(), prefix.constData(), p.read.constData(), |
1337 | p.read.endsWith(c: ')') ? "" : "()" ); |
1338 | } |
1339 | //---- End of change |
1340 | else |
1341 | fprintf(out, fmt: " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n" , |
1342 | propindex, p.type.constData(), prefix.constData(), p.member.constData()); |
1343 | } |
1344 | fprintf(out, fmt: " default: break;\n" ); |
1345 | fprintf(out, fmt: " }\n" ); |
1346 | } |
1347 | |
1348 | fprintf(out, fmt: " }" ); |
1349 | |
1350 | fprintf(out, fmt: " else " ); |
1351 | fprintf(out, fmt: "if (_c == QMetaObject::WriteProperty) {\n" ); |
1352 | |
1353 | if (needSet) { |
1354 | if (cdef->hasQObject) { |
1355 | #ifndef QT_NO_DEBUG |
1356 | fprintf(out, fmt: " Q_ASSERT(staticMetaObject.cast(_o));\n" ); |
1357 | #endif |
1358 | fprintf(out, fmt: " %s *_t = static_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1359 | } else { |
1360 | fprintf(out, fmt: " %s *_t = reinterpret_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1361 | } |
1362 | fprintf(out, fmt: " Q_UNUSED(_t)\n" ); |
1363 | fprintf(out, fmt: " void *_v = _a[0];\n" ); |
1364 | fprintf(out, fmt: " switch (_id) {\n" ); |
1365 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1366 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1367 | if (p.constant) |
1368 | continue; |
1369 | if (p.write.isEmpty() && p.member.isEmpty()) |
1370 | continue; |
1371 | QByteArray prefix = "_t->" ; |
1372 | if (p.inPrivateClass.size()) { |
1373 | prefix += p.inPrivateClass + "->" ; |
1374 | } |
1375 | if (cdef->enumDeclarations.value(akey: p.type, adefaultValue: false)) { |
1376 | fprintf(out, fmt: " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n" , |
1377 | propindex, prefix.constData(), p.write.constData()); |
1378 | } else if (!p.write.isEmpty()) { |
1379 | fprintf(out, fmt: " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n" , |
1380 | propindex, prefix.constData(), p.write.constData(), p.type.constData()); |
1381 | } else { |
1382 | fprintf(out, fmt: " case %d:\n" , propindex); |
1383 | fprintf(out, fmt: " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n" , |
1384 | prefix.constData(), p.member.constData(), p.type.constData()); |
1385 | fprintf(out, fmt: " %s%s = *reinterpret_cast< %s*>(_v);\n" , |
1386 | prefix.constData(), p.member.constData(), p.type.constData()); |
1387 | if (!p.notify.isEmpty() && p.notifyId != -1) { |
1388 | const FunctionDef &f = cdef->signalList.at(i: p.notifyId); |
1389 | if (f.arguments.size() == 0) |
1390 | fprintf(out, fmt: " Q_EMIT _t->%s();\n" , p.notify.constData()); |
1391 | else if (f.arguments.size() == 1 && f.arguments.at(i: 0).normalizedType == p.type) |
1392 | fprintf(out, fmt: " Q_EMIT _t->%s(%s%s);\n" , |
1393 | p.notify.constData(), prefix.constData(), p.member.constData()); |
1394 | } |
1395 | fprintf(out, fmt: " }\n" ); |
1396 | fprintf(out, fmt: " break;\n" ); |
1397 | } |
1398 | } |
1399 | fprintf(out, fmt: " default: break;\n" ); |
1400 | fprintf(out, fmt: " }\n" ); |
1401 | } |
1402 | |
1403 | fprintf(out, fmt: " }" ); |
1404 | |
1405 | fprintf(out, fmt: " else " ); |
1406 | fprintf(out, fmt: "if (_c == QMetaObject::ResetProperty) {\n" ); |
1407 | if (needReset) { |
1408 | if (cdef->hasQObject) { |
1409 | #ifndef QT_NO_DEBUG |
1410 | fprintf(out, fmt: " Q_ASSERT(staticMetaObject.cast(_o));\n" ); |
1411 | #endif |
1412 | fprintf(out, fmt: " %s *_t = static_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1413 | } else { |
1414 | fprintf(out, fmt: " %s *_t = reinterpret_cast<%s *>(_o);\n" , cdef->classname.constData(), cdef->classname.constData()); |
1415 | } |
1416 | fprintf(out, fmt: " Q_UNUSED(_t)\n" ); |
1417 | fprintf(out, fmt: " switch (_id) {\n" ); |
1418 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1419 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1420 | if (!p.reset.endsWith(c: ')')) |
1421 | continue; |
1422 | QByteArray prefix = "_t->" ; |
1423 | if (p.inPrivateClass.size()) { |
1424 | prefix += p.inPrivateClass + "->" ; |
1425 | } |
1426 | fprintf(out, fmt: " case %d: %s%s; break;\n" , |
1427 | propindex, prefix.constData(), p.reset.constData()); |
1428 | } |
1429 | fprintf(out, fmt: " default: break;\n" ); |
1430 | fprintf(out, fmt: " }\n" ); |
1431 | } |
1432 | fprintf(out, fmt: " }" ); |
1433 | fprintf(out, fmt: "\n#endif // QT_NO_PROPERTIES" ); |
1434 | needElse = true; |
1435 | } |
1436 | |
1437 | if (needElse) |
1438 | fprintf(out, fmt: "\n" ); |
1439 | |
1440 | if (methodList.isEmpty()) { |
1441 | fprintf(out, fmt: " Q_UNUSED(_o);\n" ); |
1442 | if (cdef->constructorList.isEmpty() && automaticPropertyMetaTypes.isEmpty() && methodsWithAutomaticTypesHelper(methodList).isEmpty()) { |
1443 | fprintf(out, fmt: " Q_UNUSED(_id);\n" ); |
1444 | fprintf(out, fmt: " Q_UNUSED(_c);\n" ); |
1445 | } |
1446 | } |
1447 | if (!isUsed_a) |
1448 | fprintf(out, fmt: " Q_UNUSED(_a);\n" ); |
1449 | |
1450 | fprintf(out, fmt: "}\n\n" ); |
1451 | } |
1452 | |
1453 | void Generator::generateSignal(FunctionDef *def,int index) |
1454 | { |
1455 | if (def->wasCloned || def->isAbstract || def->implementation) |
1456 | return; |
1457 | fprintf(out, fmt: "\n// SIGNAL %d\n%s %s::%s(" , |
1458 | index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData()); |
1459 | |
1460 | QByteArray thisPtr = "this" ; |
1461 | const char *constQualifier = "" ; |
1462 | |
1463 | if (def->isConst) { |
1464 | thisPtr = "const_cast< " ; |
1465 | thisPtr += cdef->qualified; |
1466 | thisPtr += " *>(this)" ; |
1467 | constQualifier = "const" ; |
1468 | } |
1469 | |
1470 | Q_ASSERT(!def->normalizedType.isEmpty()); |
1471 | if (def->arguments.isEmpty() && def->normalizedType == "void" ) { |
1472 | if (def->isPrivateSignal) |
1473 | fprintf(out, fmt: "QPrivateSignal" ); |
1474 | |
1475 | fprintf(out, fmt: ")%s\n{\n" |
1476 | " QMetaObject::activate(%s, &staticMetaObject, %d, nullptr);\n" |
1477 | "}\n" , constQualifier, thisPtr.constData(), index); |
1478 | return; |
1479 | } |
1480 | |
1481 | int offset = 1; |
1482 | for (int j = 0; j < def->arguments.count(); ++j) { |
1483 | const ArgumentDef &a = def->arguments.at(i: j); |
1484 | if (j) |
1485 | fprintf(out, fmt: ", " ); |
1486 | fprintf(out, fmt: "%s _t%d%s" , a.type.name.constData(), offset++, a.rightType.constData()); |
1487 | } |
1488 | if (def->isPrivateSignal) { |
1489 | if (!def->arguments.isEmpty()) |
1490 | fprintf(out, fmt: ", " ); |
1491 | fprintf(out, fmt: "QPrivateSignal" ); |
1492 | } |
1493 | |
1494 | fprintf(out, fmt: ")%s\n{\n" , constQualifier); |
1495 | if (def->type.name.size() && def->normalizedType != "void" ) { |
1496 | QByteArray returnType = noRef(type: def->normalizedType); |
1497 | if (returnType.endsWith(c: '*')) { |
1498 | fprintf(out, fmt: " %s _t0 = 0;\n" , returnType.constData()); |
1499 | } else { |
1500 | fprintf(out, fmt: " %s _t0 = %s();\n" , returnType.constData(), returnType.constData()); |
1501 | } |
1502 | } |
1503 | |
1504 | fprintf(out, fmt: " void *_a[] = { " ); |
1505 | if (def->normalizedType == "void" ) { |
1506 | fprintf(out, fmt: "nullptr" ); |
1507 | } else { |
1508 | fprintf(out, fmt: "const_cast<void*>(reinterpret_cast<const void*>(&_t0))" ); |
1509 | } |
1510 | int i; |
1511 | for (i = 1; i < offset; ++i) |
1512 | if (def->arguments.at(i: i - 1).type.isVolatile) |
1513 | fprintf(out, fmt: ", const_cast<void*>(reinterpret_cast<const volatile void*>(&_t%d))" , i); |
1514 | else |
1515 | fprintf(out, fmt: ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))" , i); |
1516 | fprintf(out, fmt: " };\n" ); |
1517 | fprintf(out, fmt: " QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n" , thisPtr.constData(), index); |
1518 | if (def->normalizedType != "void" ) |
1519 | fprintf(out, fmt: " return _t0;\n" ); |
1520 | fprintf(out, fmt: "}\n" ); |
1521 | } |
1522 | |
1523 | void Generator::generateAccessorDefs() |
1524 | { |
1525 | for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) { |
1526 | const PropertyDef &p = cdef->propertyList.at(i: propindex); |
1527 | if (p.read.isEmpty() || p.mangledName.isEmpty()) |
1528 | continue; |
1529 | |
1530 | fprintf(out, fmt: "bool %s::%s() const\n{\n return %s;\n}\n\n" , cdef->classname.constData(), |
1531 | p.mangledName.constData(), p.read.constData()); |
1532 | } |
1533 | } |
1534 | |
1535 | void Generator::generateSignalDefs() |
1536 | { |
1537 | for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) { |
1538 | const FunctionDef &f = cdef->signalList.at(i: methodindex); |
1539 | if (!f.implementation || f.mangledName.isEmpty()) |
1540 | continue; |
1541 | |
1542 | fprintf(out, fmt: "void %s::%s(bool _t1)\n{\n" , cdef->classname.constData(), |
1543 | f.mangledName.constData()); |
1544 | fprintf(out, fmt: " void *_a[] = { nullptr, " |
1545 | "const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };\n " ); |
1546 | fprintf(out, fmt: f.implementation, "this" , methodindex); |
1547 | fprintf(out, fmt: "\n}\n\n" ); |
1548 | } |
1549 | } |
1550 | |
1551 | #if 0 |
1552 | static void writePluginMetaData(FILE *out, const QJsonObject &data) |
1553 | { |
1554 | const QJsonDocument doc(data); |
1555 | |
1556 | fputs("\nQT_PLUGIN_METADATA_SECTION\n" |
1557 | "static const unsigned char qt_pluginMetaData[] = {\n" |
1558 | " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',\n " , out); |
1559 | #if 0 |
1560 | fprintf(out, "\"%s\";\n" , doc.toJson().constData()); |
1561 | #else |
1562 | const QByteArray binary = doc.toBinaryData(); |
1563 | const int last = binary.size() - 1; |
1564 | for (int i = 0; i < last; ++i) { |
1565 | uchar c = (uchar)binary.at(i); |
1566 | if (c < 0x20 || c >= 0x7f) |
1567 | fprintf(out, " 0x%02x," , c); |
1568 | else if (c == '\'' || c == '\\') |
1569 | fprintf(out, " '\\%c'," , c); |
1570 | else |
1571 | fprintf(out, " '%c', " , c); |
1572 | if (!((i + 1) % 8)) |
1573 | fputs("\n " , out); |
1574 | } |
1575 | fprintf(out, " 0x%02x\n};\n" , (uchar)binary.at(last)); |
1576 | #endif |
1577 | } |
1578 | |
1579 | void Generator::generatePluginMetaData() |
1580 | { |
1581 | if (cdef->pluginData.iid.isEmpty()) |
1582 | return; |
1583 | |
1584 | // Write plugin meta data #ifdefed QT_NO_DEBUG with debug=false, |
1585 | // true, respectively. |
1586 | |
1587 | QJsonObject data; |
1588 | const QString debugKey = QStringLiteral("debug" ); |
1589 | data.insert(QStringLiteral("IID" ), QLatin1String(cdef->pluginData.iid.constData())); |
1590 | data.insert(QStringLiteral("className" ), QLatin1String(cdef->classname.constData())); |
1591 | data.insert(QStringLiteral("version" ), (int)QT_VERSION); |
1592 | data.insert(debugKey, QJsonValue(false)); |
1593 | data.insert(QStringLiteral("MetaData" ), cdef->pluginData.metaData.object()); |
1594 | |
1595 | // Add -M args from the command line: |
1596 | for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) |
1597 | data.insert(it.key(), it.value()); |
1598 | |
1599 | fputs("\nQT_PLUGIN_METADATA_SECTION const uint qt_section_alignment_dummy = 42;\n\n" |
1600 | "#ifdef QT_NO_DEBUG\n" , out); |
1601 | writePluginMetaData(out, data); |
1602 | |
1603 | fputs("\n#else // QT_NO_DEBUG\n" , out); |
1604 | |
1605 | data.remove(debugKey); |
1606 | data.insert(debugKey, QJsonValue(true)); |
1607 | writePluginMetaData(out, data); |
1608 | |
1609 | fputs("#endif // QT_NO_DEBUG\n\n" , out); |
1610 | |
1611 | // 'Use' all namespaces. |
1612 | int pos = cdef->qualified.indexOf("::" ); |
1613 | for ( ; pos != -1 ; pos = cdef->qualified.indexOf("::" , pos + 2) ) |
1614 | fprintf(out, "using namespace %s;\n" , cdef->qualified.left(pos).constData()); |
1615 | fprintf(out, "QT_MOC_EXPORT_PLUGIN(%s, %s)\n\n" , |
1616 | cdef->qualified.constData(), cdef->classname.constData()); |
1617 | } |
1618 | #endif |
1619 | |
1620 | QT_END_NAMESPACE |
1621 | |