void Generator::generateCode() { bool isQt = (cdef->classname == "Qt"); bool isQObject = (cdef->classname == "QObject"); bool isConstructible = !cdef->constructorList.isEmpty(); // // build the data array // int i = 0; // filter out undeclared enumerators and sets { QList<EnumDef> enumList; for (i = 0; i < cdef->enumList.count(); ++i) { EnumDef def = cdef->enumList.at(i); if (cdef->enumDeclarations.contains(def.name)) { enumList += def; } QByteArray alias = cdef->flagAliases.value(def.name); if (cdef->enumDeclarations.contains(alias)) { def.name = alias; enumList += def; } } cdef->enumList = enumList; } QByteArray qualifiedClassNameIdentifier = cdef->qualified; qualifiedClassNameIdentifier.replace(':', '_'); int index = 12; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); fprintf(out, " %4d, // revision\n", 2); fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0); index += methodCount * 5; fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0); index += cdef->propertyList.count() * 3; if(cdef->notifyableProperties) index += cdef->propertyList.count(); fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0); int enumsIndex = index; for (i = 0; i < cdef->enumList.count(); ++i) index += 4 + (cdef->enumList.at(i).values.count() * 2); fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0, isConstructible ? index : 0); // // Build classinfo array // generateClassInfos(); // // Build signals array first, otherwise the signal indices would be wrong // generateFunctions(cdef->signalList, "signal", MethodSignal); // // Build slots array // generateFunctions(cdef->slotList, "slot", MethodSlot); // // Build method array // generateFunctions(cdef->methodList, "method", MethodMethod); // // Build property array // generateProperties(); // // Build enums array // generateEnums(enumsIndex); // // Build constructors array // if (isConstructible) generateFunctions(cdef->constructorList, "constructor", MethodConstructor); // // Terminate data array // fprintf(out, "\n 0 // eod\n};\n\n"); // // Build stringdata array // fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, " \""); int col = 0; int len = 0; for (i = 0; i < strings.size(); ++i) { QByteArray s = strings.at(i); len = s.length(); if (col && col + len >= 72) { fprintf(out, "\"\n \""); col = 0; } else if (len && s.at(0) >= '0' && s.at(0) <= '9') { fprintf(out, "\"\""); len += 2; } int idx = 0; while (idx < s.length()) { if (idx > 0) { col = 0; fprintf(out, "\"\n \""); } int spanLen = qMin(70, s.length() - idx); // don't cut escape sequences at the end of a line int backSlashPos = s.lastIndexOf('\\', idx + spanLen - 1); if (backSlashPos >= idx) { int escapeLen = lengthOfEscapeSequence(s, backSlashPos); spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, s.length() - idx); } fwrite(s.constData() + idx, 1, spanLen, out); idx += spanLen; col += spanLen; } fputs("\\0", out); col += len + 2; } fprintf(out, "\"\n};\n\n"); // // Generate internal qt_static_metacall() function // if (isConstructible) generateStaticMetacall(qualifiedClassNameIdentifier); // // Build extra array // QList<QByteArray> extraList; for (int i = 0; i < cdef->propertyList.count(); ++i) { const PropertyDef &p = cdef->propertyList.at(i); if (!isVariantType(p.type) && !metaTypes.contains(p.type)) { int s = p.type.lastIndexOf("::"); if (s > 0) { QByteArray scope = p.type.left(s); if (scope != "Qt" && scope != cdef->classname && !extraList.contains(scope)) extraList += scope; } } } if (!extraList.isEmpty()) { fprintf(out, "static const QMetaObject *qt_meta_extradata_%s[] = {\n ", qualifiedClassNameIdentifier.constData()); for (int i = 0; i < extraList.count(); ++i) { if (i) fprintf(out, ",\n "); fprintf(out, " &%s::staticMetaObject", extraList.at(i).constData()); } fprintf(out, ",0\n};\n\n"); } if (isConstructible || !extraList.isEmpty()) { fprintf(out, "static const QMetaObjectExtraData qt_meta_extradata2_%s = {\n ", qualifiedClassNameIdentifier.constData()); if (extraList.isEmpty()) fprintf(out, "0, "); else fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData()); if (!isConstructible) fprintf(out, "0"); else fprintf(out, "%s_qt_static_metacall", qualifiedClassNameIdentifier.constData()); fprintf(out, " \n};\n\n"); } // // Finally create and initialize the static meta object // if (isQt) fprintf(out, "const QMetaObject QObject::staticQtMetaObject = {\n"); else fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData()); if (isQObject) fprintf(out, " { 0, "); else if (cdef->superclassList.size()) fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData()); else fprintf(out, " { 0, "); fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); if (!isConstructible && extraList.isEmpty()) fprintf(out, "0 }\n"); else fprintf(out, "&qt_meta_extradata2_%s }\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "};\n"); if (isQt || !cdef->hasQObject) return; fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n", cdef->qualified.constData()); // // Generate smart cast function // fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData()); fprintf(out, " if (!_clname) return 0;\n"); fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s))\n" " return static_cast<void*>(const_cast< %s*>(this));\n", qualifiedClassNameIdentifier.constData(), cdef->classname.constData()); for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one if (cdef->superclassList.at(i).second == FunctionDef::Private) continue; const char *cname = cdef->superclassList.at(i).first; fprintf(out, " if (!strcmp(_clname, \"%s\"))\n return static_cast< %s*>(const_cast< %s*>(this));\n", cname, cname, cdef->classname.constData()); } for (int i = 0; i < cdef->interfaceList.size(); ++i) { const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i); for (int j = 0; j < iface.size(); ++j) { fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData()); for (int k = j; k >= 0; --k) fprintf(out, "static_cast< %s*>(", iface.at(k).className.constData()); fprintf(out, "const_cast< %s*>(this)%s;\n", cdef->classname.constData(), QByteArray(j+1, ')').constData()); } } if (!purestSuperClass.isEmpty() && !isQObject) { QByteArray superClass = purestSuperClass; // workaround for VC6 if (superClass.contains("::")) { fprintf(out, " typedef %s QMocSuperClass;\n", superClass.constData()); superClass = "QMocSuperClass"; } fprintf(out, " return %s::qt_metacast(_clname);\n", superClass.constData()); } else { fprintf(out, " return 0;\n"); } fprintf(out, "}\n"); // // Generate internal qt_metacall() function // generateMetacall(); // // Generate internal signal functions // for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex) generateSignal(&cdef->signalList[signalindex], signalindex); }
bool generate() { if (!generateEnums()) return false; if (!generateStructs()) return false; return true; }