1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the tools applications of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "generator.h"
43 #include "outputrevision.h"
45 #include <QtCore/qmetatype.h>
46 #include <QtCore/qjsondocument.h>
47 #include <QtCore/qjsonobject.h>
48 #include <QtCore/qjsonvalue.h>
49 #include <QtCore/qjsonarray.h>
50 #include <QtCore/qplugin.h>
53 #include <private/qmetaobject_p.h> //for the flags.
57 uint nameToBuiltinType(const QByteArray &name)
62 uint tp = QMetaType::type(name.constData());
63 return tp < uint(QMetaType::User) ? tp : QMetaType::UnknownType;
67 Returns true if the type is a built-in type.
69 bool isBuiltinType(const QByteArray &type)
71 int id = QMetaType::type(type.constData());
72 if (id == QMetaType::UnknownType)
74 return (id < QMetaType::User);
77 static const char *metaTypeEnumValueString(int type)
79 #define RETURN_METATYPENAME_STRING(MetaTypeName, MetaTypeId, RealType) \
80 case QMetaType::MetaTypeName: return #MetaTypeName;
83 QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
85 #undef RETURN_METATYPENAME_STRING
89 Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile)
90 : out(outfile), cdef(classDef), metaTypes(metaTypes)
92 if (cdef->superclassList.size())
93 purestSuperClass = cdef->superclassList.first().first;
96 static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
98 if (s.at(i) != '\\' || i >= s.length() - 1)
100 const int startPos = i;
105 while (i < s.length() && is_hex_char(s.at(i)))
107 } else if (is_octal_char(ch)) {
108 while (i < startPos + 4
110 && is_octal_char(s.at(i))) {
113 } else { // single character escape sequence
114 i = qMin(i + 1, s.length());
119 void Generator::strreg(const QByteArray &s)
121 if (!strings.contains(s))
125 int Generator::stridx(const QByteArray &s)
127 int i = strings.indexOf(s);
128 Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings");
132 // Returns the sum of all parameters (including return type) for the given
133 // \a list of methods. This is needed for calculating the size of the methods'
134 // parameter type/name meta-data.
135 static int aggregateParameterCount(const QList<FunctionDef> &list)
138 for (int i = 0; i < list.count(); ++i)
139 sum += list.at(i).arguments.count() + 1; // +1 for return type
143 void Generator::generateCode()
145 bool isQt = (cdef->classname == "Qt");
146 bool isQObject = (cdef->classname == "QObject");
147 bool isConstructible = !cdef->constructorList.isEmpty();
149 // filter out undeclared enumerators and sets
151 QList<EnumDef> enumList;
152 for (int i = 0; i < cdef->enumList.count(); ++i) {
153 EnumDef def = cdef->enumList.at(i);
154 if (cdef->enumDeclarations.contains(def.name)) {
157 QByteArray alias = cdef->flagAliases.value(def.name);
158 if (cdef->enumDeclarations.contains(alias)) {
163 cdef->enumList = enumList;
167 // Register all strings used in data section
169 strreg(cdef->qualified);
170 registerClassInfoStrings();
171 registerFunctionStrings(cdef->signalList);
172 registerFunctionStrings(cdef->slotList);
173 registerFunctionStrings(cdef->methodList);
174 registerFunctionStrings(cdef->constructorList);
175 registerPropertyStrings();
176 registerEnumStrings();
178 QByteArray qualifiedClassNameIdentifier = cdef->qualified;
179 qualifiedClassNameIdentifier.replace(':', '_');
182 // Build stringdata struct
184 fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
185 fprintf(out, " QByteArrayData data[%d];\n", strings.size());
188 for (int i = 0; i < strings.size(); ++i)
189 len += strings.at(i).length() + 1;
190 fprintf(out, " char stringdata[%d];\n", len + 1);
192 fprintf(out, "};\n");
194 // Macro that expands into a QByteArrayData. The offset member is
195 // calculated from 1) the offset of the actual characters in the
196 // stringdata.stringdata member, and 2) the stringdata.data index of the
197 // QByteArrayData being defined. This calculation relies on the
198 // QByteArrayData::data() implementation returning simply "this + offset".
199 fprintf(out, "#define QT_MOC_LITERAL(idx, ofs, len) { \\\n"
200 " Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \\\n"
201 " offsetof(qt_meta_stringdata_%s_t, stringdata) + ofs \\\n"
202 " - idx * sizeof(QByteArrayData) \\\n"
204 qualifiedClassNameIdentifier.constData());
206 fprintf(out, "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n",
207 qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
208 fprintf(out, " {\n");
211 for (int i = 0; i < strings.size(); ++i) {
214 const QByteArray &str = strings.at(i);
215 fprintf(out, "QT_MOC_LITERAL(%d, %d, %d)", i, idx, str.length());
216 idx += str.length() + 1;
217 for (int j = 0; j < str.length(); ++j) {
218 if (str.at(j) == '\\') {
219 int cnt = lengthOfEscapeSequence(str, j) - 1;
225 fprintf(out, "\n },\n");
229 // Build stringdata array
234 for (int i = 0; i < strings.size(); ++i) {
235 QByteArray s = strings.at(i);
237 if (col && col + len >= 72) {
238 fprintf(out, "\"\n \"");
240 } else if (len && s.at(0) >= '0' && s.at(0) <= '9') {
241 fprintf(out, "\"\"");
245 while (idx < s.length()) {
248 fprintf(out, "\"\n \"");
250 int spanLen = qMin(70, s.length() - idx);
251 // don't cut escape sequences at the end of a line
252 int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1);
253 if (backSlashPos >= idx) {
254 int escapeLen = lengthOfEscapeSequence(s, backSlashPos);
255 spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx);
257 fwrite(s.constData() + idx, 1, spanLen, out);
266 // Terminate stringdata struct
267 fprintf(out, "\"\n};\n");
268 fprintf(out, "#undef QT_MOC_LITERAL\n\n");
271 // build the data array
274 int index = MetaObjectPrivateFieldCount;
275 fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
276 fprintf(out, "\n // content:\n");
277 fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision));
278 fprintf(out, " %4d, // classname\n", stridx(cdef->qualified));
279 fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
280 index += cdef->classInfoList.count() * 2;
282 int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
283 fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
284 index += methodCount * 5;
285 if (cdef->revisionedMethods)
286 index += methodCount;
287 int paramsIndex = index;
288 int totalParameterCount = aggregateParameterCount(cdef->signalList)
289 + aggregateParameterCount(cdef->slotList)
290 + aggregateParameterCount(cdef->methodList)
291 + aggregateParameterCount(cdef->constructorList);
292 index += totalParameterCount * 2 // types and parameter names
293 - methodCount // return "parameters" don't have names
294 - cdef->constructorList.count(); // "this" parameters don't have names
296 fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0);
297 index += cdef->propertyList.count() * 3;
298 if(cdef->notifyableProperties)
299 index += cdef->propertyList.count();
300 if (cdef->revisionedProperties)
301 index += cdef->propertyList.count();
302 fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0);
304 int enumsIndex = index;
305 for (int i = 0; i < cdef->enumList.count(); ++i)
306 index += 4 + (cdef->enumList.at(i).values.count() * 2);
307 fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
308 isConstructible ? index : 0);
310 fprintf(out, " %4d, // flags\n", 0);
311 fprintf(out, " %4d, // signalCount\n", cdef->signalList.count());
315 // Build classinfo array
317 generateClassInfos();
320 // Build signals array first, otherwise the signal indices would be wrong
322 generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex);
327 generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex);
330 // Build method array
332 generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex);
335 // Build method version arrays
337 if (cdef->revisionedMethods) {
338 generateFunctionRevisions(cdef->signalList, "signal");
339 generateFunctionRevisions(cdef->slotList, "slot");
340 generateFunctionRevisions(cdef->methodList, "method");
344 // Build method parameters array
346 generateFunctionParameters(cdef->signalList, "signal");
347 generateFunctionParameters(cdef->slotList, "slot");
348 generateFunctionParameters(cdef->methodList, "method");
350 generateFunctionParameters(cdef->constructorList, "constructor");
353 // Build property array
355 generateProperties();
360 generateEnums(enumsIndex);
363 // Build constructors array
366 generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex);
369 // Terminate data array
371 fprintf(out, "\n 0 // eod\n};\n\n");
374 // Generate internal qt_static_metacall() function
376 if (cdef->hasQObject && !isQt)
377 generateStaticMetacall();
382 QList<QByteArray> extraList;
383 for (int i = 0; i < cdef->propertyList.count(); ++i) {
384 const PropertyDef &p = cdef->propertyList.at(i);
385 if (!isBuiltinType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
386 !p.type.contains('<') && !p.type.contains('>')) {
387 int s = p.type.lastIndexOf("::");
389 QByteArray scope = p.type.left(s);
390 if (scope != "Qt" && scope != cdef->classname && !extraList.contains(scope))
396 // QTBUG-20639 - Accept non-local enums for QML signal/slot parameters.
397 // Look for any scoped enum declarations, and add those to the list
398 // of extra/related metaobjects for this object.
399 QList<QByteArray> enumKeys = cdef->enumDeclarations.keys();
400 for (int i = 0; i < enumKeys.count(); ++i) {
401 const QByteArray &enumKey = enumKeys[i];
402 int s = enumKey.lastIndexOf("::");
404 QByteArray scope = enumKey.left(s);
405 if (scope != "Qt" && scope != cdef->classname && !extraList.contains(scope))
410 if (!extraList.isEmpty()) {
411 fprintf(out, "static const QMetaObject *qt_meta_extradata_%s[] = {\n ", qualifiedClassNameIdentifier.constData());
412 for (int i = 0; i < extraList.count(); ++i) {
413 fprintf(out, " &%s::staticMetaObject,\n", extraList.at(i).constData());
415 fprintf(out, " 0\n};\n\n");
418 bool hasExtraData = (cdef->hasQObject && !isQt) || !extraList.isEmpty();
420 fprintf(out, "const QMetaObjectExtraData %s::staticMetaObjectExtraData = {\n ",
421 cdef->qualified.constData());
422 if (extraList.isEmpty())
425 fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData());
427 if (cdef->hasQObject && !isQt)
428 fprintf(out, " qt_static_metacall");
431 fprintf(out, " \n};\n\n");
435 // Finally create and initialize the static meta object
438 fprintf(out, "const QMetaObject QObject::staticQtMetaObject = {\n");
440 fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData());
443 fprintf(out, " { 0, ");
444 else if (cdef->superclassList.size())
445 fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData());
447 fprintf(out, " { 0, ");
448 fprintf(out, "qt_meta_stringdata_%s.data,\n"
449 " qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(),
450 qualifiedClassNameIdentifier.constData());
452 fprintf(out, "0 }\n");
454 fprintf(out, "&staticMetaObjectExtraData }\n");
455 fprintf(out, "};\n");
461 if (!cdef->hasQObject)
464 fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;\n}\n",
465 cdef->qualified.constData());
468 // Generate smart cast function
470 fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
471 fprintf(out, " if (!_clname) return 0;\n");
472 fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n"
473 " return static_cast<void*>(const_cast< %s*>(this));\n",
474 qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
475 for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
476 if (cdef->superclassList.at(i).second == FunctionDef::Private)
478 const char *cname = cdef->superclassList.at(i).first.constData();
479 fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(const_cast< %s*>(this));\n",
480 cname, cname, cdef->classname.constData());
482 for (int i = 0; i < cdef->interfaceList.size(); ++i) {
483 const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i);
484 for (int j = 0; j < iface.size(); ++j) {
485 fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData());
486 for (int k = j; k >= 0; --k)
487 fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData());
488 fprintf(out, "const_cast< %s*>(this)%s;\n",
489 cdef->classname.constData(), QByteArray(j+1, ')').constData());
492 if (!purestSuperClass.isEmpty() && !isQObject) {
493 QByteArray superClass = purestSuperClass;
494 // workaround for VC6
495 if (superClass.contains("::")) {
496 fprintf(out, " typedef %s QMocSuperClass;\n", superClass.constData());
497 superClass = "QMocSuperClass";
499 fprintf(out, " return %s::qt_metacast(_clname);\n", superClass.constData());
501 fprintf(out, " return 0;\n");
506 // Generate internal qt_metacall() function
511 // Generate internal signal functions
513 for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
514 generateSignal(&cdef->signalList[signalindex], signalindex);
517 // Generate plugin meta data
519 generatePluginMetaData();
523 void Generator::registerClassInfoStrings()
525 for (int i = 0; i < cdef->classInfoList.size(); ++i) {
526 const ClassInfoDef &c = cdef->classInfoList.at(i);
532 void Generator::generateClassInfos()
534 if (cdef->classInfoList.isEmpty())
537 fprintf(out, "\n // classinfo: key, value\n");
539 for (int i = 0; i < cdef->classInfoList.size(); ++i) {
540 const ClassInfoDef &c = cdef->classInfoList.at(i);
541 fprintf(out, " %4d, %4d,\n", stridx(c.name), stridx(c.value));
545 void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
547 for (int i = 0; i < list.count(); ++i) {
548 const FunctionDef &f = list.at(i);
551 if (!isBuiltinType(f.normalizedType))
552 strreg(f.normalizedType);
555 for (int j = 0; j < f.arguments.count(); ++j) {
556 const ArgumentDef &a = f.arguments.at(j);
557 if (!isBuiltinType(a.normalizedType))
558 strreg(a.normalizedType);
564 void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type, int ¶msIndex)
568 fprintf(out, "\n // %ss: name, argc, parameters, tag, flags\n", functype);
570 for (int i = 0; i < list.count(); ++i) {
571 const FunctionDef &f = list.at(i);
573 unsigned char flags = type;
574 if (f.access == FunctionDef::Private)
575 flags |= AccessPrivate;
576 else if (f.access == FunctionDef::Public)
577 flags |= AccessPublic;
578 else if (f.access == FunctionDef::Protected)
579 flags |= AccessProtected;
580 if (f.access == FunctionDef::Private)
581 flags |= AccessPrivate;
582 else if (f.access == FunctionDef::Public)
583 flags |= AccessPublic;
584 else if (f.access == FunctionDef::Protected)
585 flags |= AccessProtected;
587 flags |= MethodCompatibility;
589 flags |= MethodCloned;
591 flags |= MethodScriptable;
593 flags |= MethodRevisioned;
595 int argc = f.arguments.count();
596 fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n",
597 stridx(f.name), argc, paramsIndex, stridx(f.tag), flags);
599 paramsIndex += 1 + argc * 2;
603 void Generator::generateFunctionRevisions(const QList<FunctionDef>& list, const char *functype)
606 fprintf(out, "\n // %ss: revision\n", functype);
607 for (int i = 0; i < list.count(); ++i) {
608 const FunctionDef &f = list.at(i);
609 fprintf(out, " %4d,\n", f.revision);
613 void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const char *functype)
617 fprintf(out, "\n // %ss: parameters\n", functype);
618 for (int i = 0; i < list.count(); ++i) {
619 const FunctionDef &f = list.at(i);
623 for (int j = -1; j < f.arguments.count(); ++j) {
626 const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
627 if (isBuiltinType(typeName)) {
628 int type = nameToBuiltinType(typeName);
629 const char *valueString = metaTypeEnumValueString(type);
631 fprintf(out, "QMetaType::%s", valueString);
633 fprintf(out, "%4d", type);
635 Q_ASSERT(!typeName.isEmpty() || f.isConstructor);
636 fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(typeName));
642 for (int j = 0; j < f.arguments.count(); ++j) {
643 const ArgumentDef &arg = f.arguments.at(j);
644 fprintf(out, " %4d,", stridx(arg.name));
651 void Generator::registerPropertyStrings()
653 for (int i = 0; i < cdef->propertyList.count(); ++i) {
654 const PropertyDef &p = cdef->propertyList.at(i);
656 if (!isBuiltinType(p.type))
661 void Generator::generateProperties()
667 if (cdef->propertyList.count())
668 fprintf(out, "\n // properties: name, type, flags\n");
669 for (int i = 0; i < cdef->propertyList.count(); ++i) {
670 const PropertyDef &p = cdef->propertyList.at(i);
671 uint flags = Invalid;
672 if (!isBuiltinType(p.type))
674 if (!p.read.isEmpty())
676 if (!p.write.isEmpty()) {
681 if (!p.reset.isEmpty())
685 // flags |= Override;
687 if (p.designable.isEmpty())
688 flags |= ResolveDesignable;
689 else if (p.designable != "false")
692 if (p.scriptable.isEmpty())
693 flags |= ResolveScriptable;
694 else if (p.scriptable != "false")
697 if (p.stored.isEmpty())
698 flags |= ResolveStored;
699 else if (p.stored != "false")
702 if (p.editable.isEmpty())
703 flags |= ResolveEditable;
704 else if (p.editable != "false")
707 if (p.user.isEmpty())
708 flags |= ResolveUser;
709 else if (p.user != "false")
712 if (p.notifyId != -1)
723 fprintf(out, " %4d, ", stridx(p.name));
725 if (isBuiltinType(p.type)) {
726 int type = nameToBuiltinType(p.type);
727 const char *valueString = metaTypeEnumValueString(type);
729 fprintf(out, "QMetaType::%s", valueString);
731 fprintf(out, "%4d", type);
733 fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(p.type));
736 fprintf(out, ", 0x%.8x,\n", flags);
739 if(cdef->notifyableProperties) {
740 fprintf(out, "\n // properties: notify_signal_id\n");
741 for (int i = 0; i < cdef->propertyList.count(); ++i) {
742 const PropertyDef &p = cdef->propertyList.at(i);
744 fprintf(out, " %4d,\n",
747 fprintf(out, " %4d,\n",
751 if (cdef->revisionedProperties) {
752 fprintf(out, "\n // properties: revision\n");
753 for (int i = 0; i < cdef->propertyList.count(); ++i) {
754 const PropertyDef &p = cdef->propertyList.at(i);
755 fprintf(out, " %4d,\n", p.revision);
760 void Generator::registerEnumStrings()
762 for (int i = 0; i < cdef->enumList.count(); ++i) {
763 const EnumDef &e = cdef->enumList.at(i);
765 for (int j = 0; j < e.values.count(); ++j)
766 strreg(e.values.at(j));
770 void Generator::generateEnums(int index)
772 if (cdef->enumDeclarations.isEmpty())
775 fprintf(out, "\n // enums: name, flags, count, data\n");
776 index += 4 * cdef->enumList.count();
778 for (i = 0; i < cdef->enumList.count(); ++i) {
779 const EnumDef &e = cdef->enumList.at(i);
780 fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n",
782 cdef->enumDeclarations.value(e.name) ? 1 : 0,
785 index += e.values.count() * 2;
788 fprintf(out, "\n // enum data: key, value\n");
789 for (i = 0; i < cdef->enumList.count(); ++i) {
790 const EnumDef &e = cdef->enumList.at(i);
791 for (int j = 0; j < e.values.count(); ++j) {
792 const QByteArray &val = e.values.at(j);
793 QByteArray code = cdef->qualified.constData();
795 code += "::" + e.name;
797 fprintf(out, " %4d, uint(%s),\n",
798 stridx(val), code.constData());
803 void Generator::generateMetacall()
805 bool isQObject = (cdef->classname == "QObject");
807 fprintf(out, "\nint %s::qt_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n",
808 cdef->qualified.constData());
810 if (!purestSuperClass.isEmpty() && !isQObject) {
811 QByteArray superClass = purestSuperClass;
812 // workaround for VC6
813 if (superClass.contains("::")) {
814 fprintf(out, " typedef %s QMocSuperClass;\n", superClass.constData());
815 superClass = "QMocSuperClass";
817 fprintf(out, " _id = %s::qt_metacall(_c, _id, _a);\n", superClass.constData());
820 fprintf(out, " if (_id < 0)\n return _id;\n");
823 bool needElse = false;
824 QList<FunctionDef> methodList;
825 methodList += cdef->signalList;
826 methodList += cdef->slotList;
827 methodList += cdef->methodList;
829 if (methodList.size()) {
831 fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n");
832 fprintf(out, " if (_id < %d)\n", methodList.size());
833 fprintf(out, " qt_static_metacall(this, _c, _id, _a);\n");
834 fprintf(out, " _id -= %d;\n }", methodList.size());
837 if (cdef->propertyList.size()) {
838 bool needGet = false;
839 bool needTempVarForGet = false;
840 bool needSet = false;
841 bool needReset = false;
842 bool needDesignable = false;
843 bool needScriptable = false;
844 bool needStored = false;
845 bool needEditable = false;
846 bool needUser = false;
847 for (int i = 0; i < cdef->propertyList.size(); ++i) {
848 const PropertyDef &p = cdef->propertyList.at(i);
849 needGet |= !p.read.isEmpty();
850 if (!p.read.isEmpty())
851 needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
852 && p.gspec != PropertyDef::ReferenceSpec);
854 needSet |= !p.write.isEmpty();
855 needReset |= !p.reset.isEmpty();
856 needDesignable |= p.designable.endsWith(')');
857 needScriptable |= p.scriptable.endsWith(')');
858 needStored |= p.stored.endsWith(')');
859 needEditable |= p.editable.endsWith(')');
860 needUser |= p.user.endsWith(')');
862 fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
865 fprintf(out, " else ");
866 fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
868 if (needTempVarForGet)
869 fprintf(out, " void *_v = _a[0];\n");
870 fprintf(out, " switch (_id) {\n");
871 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
872 const PropertyDef &p = cdef->propertyList.at(propindex);
873 if (p.read.isEmpty())
876 if (p.inPrivateClass.size()) {
877 prefix = p.inPrivateClass;
880 if (p.gspec == PropertyDef::PointerSpec)
881 fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
882 propindex, prefix.constData(), p.read.constData());
883 else if (p.gspec == PropertyDef::ReferenceSpec)
884 fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
885 propindex, prefix.constData(), p.read.constData());
886 else if (cdef->enumDeclarations.value(p.type, false))
887 fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
888 propindex, prefix.constData(), p.read.constData());
890 fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
891 propindex, p.type.constData(), prefix.constData(), p.read.constData());
893 fprintf(out, " }\n");
898 " }", cdef->propertyList.count());
900 fprintf(out, " else ");
901 fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
904 fprintf(out, " void *_v = _a[0];\n");
905 fprintf(out, " switch (_id) {\n");
906 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
907 const PropertyDef &p = cdef->propertyList.at(propindex);
908 if (p.write.isEmpty())
911 if (p.inPrivateClass.size()) {
912 prefix = p.inPrivateClass;
915 if (cdef->enumDeclarations.value(p.type, false)) {
916 fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
917 propindex, prefix.constData(), p.write.constData());
919 fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
920 propindex, prefix.constData(), p.write.constData(), p.type.constData());
923 fprintf(out, " }\n");
928 " }", cdef->propertyList.count());
930 fprintf(out, " else ");
931 fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
933 fprintf(out, " switch (_id) {\n");
934 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
935 const PropertyDef &p = cdef->propertyList.at(propindex);
936 if (!p.reset.endsWith(')'))
939 if (p.inPrivateClass.size()) {
940 prefix = p.inPrivateClass;
943 fprintf(out, " case %d: %s%s; break;\n",
944 propindex, prefix.constData(), p.reset.constData());
946 fprintf(out, " }\n");
950 " }", cdef->propertyList.count());
952 fprintf(out, " else ");
953 fprintf(out, "if (_c == QMetaObject::QueryPropertyDesignable) {\n");
954 if (needDesignable) {
955 fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
956 fprintf(out, " switch (_id) {\n");
957 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
958 const PropertyDef &p = cdef->propertyList.at(propindex);
959 if (!p.designable.endsWith(')'))
961 fprintf(out, " case %d: *_b = %s; break;\n",
962 propindex, p.designable.constData());
964 fprintf(out, " }\n");
968 " }", cdef->propertyList.count());
970 fprintf(out, " else ");
971 fprintf(out, "if (_c == QMetaObject::QueryPropertyScriptable) {\n");
972 if (needScriptable) {
973 fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
974 fprintf(out, " switch (_id) {\n");
975 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
976 const PropertyDef &p = cdef->propertyList.at(propindex);
977 if (!p.scriptable.endsWith(')'))
979 fprintf(out, " case %d: *_b = %s; break;\n",
980 propindex, p.scriptable.constData());
982 fprintf(out, " }\n");
986 " }", cdef->propertyList.count());
988 fprintf(out, " else ");
989 fprintf(out, "if (_c == QMetaObject::QueryPropertyStored) {\n");
991 fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
992 fprintf(out, " switch (_id) {\n");
993 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
994 const PropertyDef &p = cdef->propertyList.at(propindex);
995 if (!p.stored.endsWith(')'))
997 fprintf(out, " case %d: *_b = %s; break;\n",
998 propindex, p.stored.constData());
1000 fprintf(out, " }\n");
1004 " }", cdef->propertyList.count());
1006 fprintf(out, " else ");
1007 fprintf(out, "if (_c == QMetaObject::QueryPropertyEditable) {\n");
1009 fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
1010 fprintf(out, " switch (_id) {\n");
1011 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
1012 const PropertyDef &p = cdef->propertyList.at(propindex);
1013 if (!p.editable.endsWith(')'))
1015 fprintf(out, " case %d: *_b = %s; break;\n",
1016 propindex, p.editable.constData());
1018 fprintf(out, " }\n");
1022 " }", cdef->propertyList.count());
1025 fprintf(out, " else ");
1026 fprintf(out, "if (_c == QMetaObject::QueryPropertyUser) {\n");
1028 fprintf(out, " bool *_b = reinterpret_cast<bool*>(_a[0]);\n");
1029 fprintf(out, " switch (_id) {\n");
1030 for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
1031 const PropertyDef &p = cdef->propertyList.at(propindex);
1032 if (!p.user.endsWith(')'))
1034 fprintf(out, " case %d: *_b = %s; break;\n",
1035 propindex, p.user.constData());
1037 fprintf(out, " }\n");
1041 " }", cdef->propertyList.count());
1044 fprintf(out, "\n#endif // QT_NO_PROPERTIES");
1046 if (methodList.size() || cdef->signalList.size() || cdef->propertyList.size())
1047 fprintf(out, "\n ");
1048 fprintf(out,"return _id;\n}\n");
1051 void Generator::generateStaticMetacall()
1053 fprintf(out, "void %s::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)\n{\n",
1054 cdef->qualified.constData());
1056 bool needElse = false;
1057 bool isUsed_a = false;
1059 if (!cdef->constructorList.isEmpty()) {
1060 fprintf(out, " if (_c == QMetaObject::CreateInstance) {\n");
1061 fprintf(out, " switch (_id) {\n");
1062 for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) {
1063 fprintf(out, " case %d: { %s *_r = new %s(", ctorindex,
1064 cdef->classname.constData(), cdef->classname.constData());
1065 const FunctionDef &f = cdef->constructorList.at(ctorindex);
1067 for (int j = 0; j < f.arguments.count(); ++j) {
1068 const ArgumentDef &a = f.arguments.at(j);
1071 fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++);
1073 fprintf(out, ");\n");
1074 fprintf(out, " if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n");
1076 fprintf(out, " }\n");
1082 QList<FunctionDef> methodList;
1083 methodList += cdef->signalList;
1084 methodList += cdef->slotList;
1085 methodList += cdef->methodList;
1087 if (!methodList.isEmpty()) {
1089 fprintf(out, " else ");
1092 fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n");
1094 fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
1096 fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
1097 fprintf(out, " switch (_id) {\n");
1098 for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
1099 const FunctionDef &f = methodList.at(methodindex);
1100 Q_ASSERT(!f.normalizedType.isEmpty());
1101 fprintf(out, " case %d: ", methodindex);
1102 if (f.normalizedType != "void")
1103 fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData());
1104 fprintf(out, "_t->");
1105 if (f.inPrivateClass.size())
1106 fprintf(out, "%s->", f.inPrivateClass.constData());
1107 fprintf(out, "%s(", f.name.constData());
1109 for (int j = 0; j < f.arguments.count(); ++j) {
1110 const ArgumentDef &a = f.arguments.at(j);
1113 fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++);
1117 if (f.normalizedType != "void") {
1118 fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
1119 noRef(f.normalizedType).constData());
1122 fprintf(out, " break;\n");
1124 fprintf(out, " default: ;\n");
1125 fprintf(out, " }\n");
1129 if (!cdef->signalList.isEmpty()) {
1130 Q_ASSERT(needElse); // if there is signal, there was method.
1131 fprintf(out, " else if (_c == QMetaObject::IndexOfMethod) {\n");
1132 fprintf(out, " int *result = reinterpret_cast<int *>(_a[0]);\n");
1133 fprintf(out, " void **func = reinterpret_cast<void **>(_a[1]);\n");
1134 bool anythingUsed = false;
1135 for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) {
1136 const FunctionDef &f = cdef->signalList.at(methodindex);
1137 if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
1139 anythingUsed = true;
1140 fprintf(out, " {\n");
1141 fprintf(out, " typedef %s (%s::*_t)(",f.type.rawName.constData() , cdef->classname.constData());
1142 for (int j = 0; j < f.arguments.count(); ++j) {
1143 const ArgumentDef &a = f.arguments.at(j);
1146 fprintf(out, "%s", QByteArray(a.type.name + ' ' + a.rightType).constData());
1149 fprintf(out, ") const;\n");
1151 fprintf(out, ");\n");
1152 fprintf(out, " if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&%s::%s)) {\n",
1153 cdef->classname.constData(), f.name.constData());
1154 fprintf(out, " *result = %d;\n", methodindex);
1155 fprintf(out, " }\n }\n");
1158 fprintf(out, " Q_UNUSED(result);\n Q_UNUSED(func);\n");
1166 if (methodList.isEmpty()) {
1167 fprintf(out, " Q_UNUSED(_o);\n");
1168 if (cdef->constructorList.isEmpty()) {
1169 fprintf(out, " Q_UNUSED(_id);\n");
1170 fprintf(out, " Q_UNUSED(_c);\n");
1174 fprintf(out, " Q_UNUSED(_a);\n");
1176 fprintf(out, "}\n\n");
1179 void Generator::generateSignal(FunctionDef *def,int index)
1181 if (def->wasCloned || def->isAbstract)
1183 fprintf(out, "\n// SIGNAL %d\n%s %s::%s(",
1184 index, def->type.name.constData(), cdef->qualified.constData(), def->name.constData());
1186 QByteArray thisPtr = "this";
1187 const char *constQualifier = "";
1190 thisPtr = "const_cast< ";
1191 thisPtr += cdef->qualified;
1192 thisPtr += " *>(this)";
1193 constQualifier = "const";
1196 Q_ASSERT(!def->normalizedType.isEmpty());
1197 if (def->arguments.isEmpty() && def->normalizedType == "void") {
1198 fprintf(out, ")%s\n{\n"
1199 " QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n"
1200 "}\n", constQualifier, thisPtr.constData(), index);
1205 for (int j = 0; j < def->arguments.count(); ++j) {
1206 const ArgumentDef &a = def->arguments.at(j);
1209 fprintf(out, "%s _t%d%s", a.type.name.constData(), offset++, a.rightType.constData());
1211 fprintf(out, ")%s\n{\n", constQualifier);
1212 if (def->type.name.size() && def->normalizedType != "void")
1213 fprintf(out, " %s _t0 = %s();\n", noRef(def->normalizedType).constData(), noRef(def->normalizedType).constData());
1215 fprintf(out, " void *_a[] = { ");
1216 if (def->normalizedType == "void") {
1219 if (def->returnTypeIsVolatile)
1220 fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(&_t0))");
1222 fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(&_t0))");
1225 for (i = 1; i < offset; ++i)
1226 if (def->arguments.at(i - 1).type.isVolatile)
1227 fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(&_t%d))", i);
1229 fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i);
1230 fprintf(out, " };\n");
1231 fprintf(out, " QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index);
1232 if (def->normalizedType != "void")
1233 fprintf(out, " return _t0;\n");
1234 fprintf(out, "}\n");
1237 static void writePluginMetaData(FILE *out, const QJsonObject &data)
1239 const QJsonDocument doc(data);
1241 fputs("\nQT_PLUGIN_METADATA_SECTION\n"
1242 "static const unsigned char qt_pluginMetaData[] = {\n"
1243 " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',\n ", out);
1245 fprintf(out, "\"%s\";\n", doc.toJson().constData());
1247 const QByteArray binary = doc.toBinaryData();
1248 const int last = binary.size() - 1;
1249 for (int i = 0; i < last; ++i) {
1250 fprintf(out, " 0x%02x,", (uchar)binary.at(i));
1254 fprintf(out, " 0x%02x\n};\n", (uchar)binary.at(last));
1258 void Generator::generatePluginMetaData()
1260 if (cdef->pluginData.iid.isEmpty())
1263 // Write plugin meta data #ifdefed QT_NO_DEBUG with debug=false,
1264 // true, respectively.
1267 const QString debugKey = QStringLiteral("debug");
1268 data.insert(QStringLiteral("IID"), QLatin1String(cdef->pluginData.iid.constData()));
1269 data.insert(QStringLiteral("className"), QLatin1String(cdef->classname.constData()));
1270 data.insert(QStringLiteral("version"), (int)QT_VERSION);
1271 data.insert(debugKey, QJsonValue(false));
1272 data.insert(QStringLiteral("MetaData"), cdef->pluginData.metaData.object());
1274 fputs("\nQT_PLUGIN_METADATA_SECTION const uint qt_section_alignment_dummy = 42;\n\n"
1275 "#ifdef QT_NO_DEBUG\n", out);
1276 writePluginMetaData(out, data);
1278 fputs("\n#else // QT_NO_DEBUG\n", out);
1280 data.remove(debugKey);
1281 data.insert(debugKey, QJsonValue(true));
1282 writePluginMetaData(out, data);
1284 fputs("#endif // QT_NO_DEBUG\n\n", out);
1286 // 'Use' all namespaces.
1287 int pos = cdef->qualified.indexOf("::");
1288 for ( ; pos != -1 ; pos = cdef->qualified.indexOf("::", pos + 2) )
1289 fprintf(out, "using namespace %s;\n", cdef->qualified.left(pos).constData());
1290 fprintf(out, "QT_MOC_EXPORT_PLUGIN(%s)\n\n", cdef->classname.constData());