void Generator::_generateClassInfos() { for (int i = 0; i < cdef->classInfoList.size(); ++i) { const ClassInfoDef &c = cdef->classInfoList.at(i); meta_data << strreg(c.name) << strreg(c.value); } }
void Generator::generateEnums(int index) { if (cdef->enumDeclarations.isEmpty()) return; fprintf(out, "\n // enums: name, flags, count, data\n"); index += 4 * cdef->enumList.count(); int i; for (i = 0; i < cdef->enumList.count(); ++i) { const EnumDef &e = cdef->enumList.at(i); fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n", strreg(e.name), cdef->enumDeclarations.value(e.name) ? 1 : 0, e.values.count(), index); index += e.values.count() * 2; } fprintf(out, "\n // enum data: key, value\n"); for (i = 0; i < cdef->enumList.count(); ++i) { const EnumDef &e = cdef->enumList.at(i); for (int j = 0; j < e.values.count(); ++j) { const QByteArray &val = e.values.at(j); fprintf(out, " %4d, uint(%s::%s),\n", strreg(val), cdef->qualified.constData(), val.constData()); } } }
void Generator::generateClassInfos() { if (cdef->classInfoList.isEmpty()) return; fprintf(out, "\n // classinfo: key, value\n"); for (int i = 0; i < cdef->classInfoList.size(); ++i) { const ClassInfoDef &c = cdef->classInfoList.at(i); fprintf(out, " %4d, %4d,\n", strreg(c.name), strreg(c.value)); } }
void Generator::generateFunctions(QList<FunctionDef>& list, const char *functype, int type) { if (list.isEmpty()) return; fprintf(out, "\n // %ss: signature, parameters, type, tag, flags\n", functype); for (int i = 0; i < list.count(); ++i) { const FunctionDef &f = list.at(i); QByteArray sig = f.name + '('; QByteArray arguments; for (int j = 0; j < f.arguments.count(); ++j) { const ArgumentDef &a = f.arguments.at(j); if (j) { sig += ","; arguments += ","; } sig += a.normalizedType; arguments += a.name; } sig += ')'; char flags = type; if (f.access == FunctionDef::Private) flags |= AccessPrivate; else if (f.access == FunctionDef::Public) flags |= AccessPublic; else if (f.access == FunctionDef::Protected) flags |= AccessProtected; if (f.access == FunctionDef::Private) flags |= AccessPrivate; else if (f.access == FunctionDef::Public) flags |= AccessPublic; else if (f.access == FunctionDef::Protected) flags |= AccessProtected; if (f.isCompat) flags |= MethodCompatibility; if (f.wasCloned) flags |= MethodCloned; if (f.isScriptable) flags |= MethodScriptable; fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig), strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags); } }
void Generator::_generateFunctions(QList<FunctionDef> &list, int type) { for (int i = 0; i < list.count(); ++i) { const FunctionDef &f = list.at(i); QByteArray sig = f.name + '('; QByteArray arguments; for (int j = 0; j < f.arguments.count(); ++j) { const ArgumentDef &a = f.arguments.at(j); if (j) { sig += ","; arguments += ","; } sig += a.normalizedType; arguments += a.name; } sig += ')'; char flags = type; if (f.access == FunctionDef::Private) flags |= AccessPrivate; else if (f.access == FunctionDef::Public) flags |= AccessPublic; else if (f.access == FunctionDef::Protected) flags |= AccessProtected; if (f.access == FunctionDef::Private) flags |= AccessPrivate; else if (f.access == FunctionDef::Public) flags |= AccessPublic; else if (f.access == FunctionDef::Protected) flags |= AccessProtected; if (f.isCompat) flags |= MethodCompatibility; if (f.wasCloned) flags |= MethodCloned; if (f.isScriptable) flags |= MethodScriptable; meta_data << strreg(sig) << strreg(arguments) << strreg(f.normalizedType) << strreg(f.tag) << flags; } }
void Generator::_generateEnums(int index) { index += 4 * cdef->enumList.count(); int i; for (i = 0; i < cdef->enumList.count(); ++i) { const EnumDef &e = cdef->enumList.at(i); meta_data << strreg(e.name) << (cdef->enumDeclarations.value(e.name) ? 1 : 0) << e.values.count() << index; index += e.values.count() * 2; } for (i = 0; i < cdef->enumList.count(); ++i) { const EnumDef &e = cdef->enumList.at(i); for (int j = 0; j < e.values.count(); ++j) { const QByteArray &val = e.values.at(j); meta_data << strreg(val) << 0; // we don't know the value itself } } }
static char *is_section(const void *ctx, const char *line, char **value) { char *secname; /* Any number of upper case words separated by spaces, ending in : */ if (!strreg(ctx, line, "^([A-Z][a-zA-Z0-9_]*( [A-Z][a-zA-Z0-9_]*)*):[ \t\n]*(.*)", &secname, NULL, value)) return NULL; return secname; }
void Generator::generateProperties() { // // specify get function, for compatibiliy we accept functions // returning pointers, or const char * for QByteArray. // for (int i = 0; i < cdef->propertyList.count(); ++i) { PropertyDef &p = cdef->propertyList[i]; if (p.read.isEmpty()) continue; for (int j = 0; j < cdef->publicList.count(); ++j) { const FunctionDef &f = cdef->publicList.at(j); if (f.name != p.read) continue; if (!f.isConst) // get functions must be const continue; if (f.arguments.size()) // and must not take any arguments continue; PropertyDef::Specification spec = PropertyDef::ValueSpec; QByteArray tmp = f.normalizedType; if (p.type == "QByteArray" && tmp == "const char *") tmp = "QByteArray"; if (tmp.left(6) == "const ") tmp = tmp.mid(6); if (p.type != tmp && tmp.endsWith('*')) { tmp.chop(1); spec = PropertyDef::PointerSpec; } else if (f.type.name.endsWith('&')) { // raw type, not normalized type spec = PropertyDef::ReferenceSpec; } if (p.type != tmp) continue; p.gspec = spec; break; } if(!p.notify.isEmpty()) { int notifyId = -1; for (int j = 0; j < cdef->signalList.count(); ++j) { const FunctionDef &f = cdef->signalList.at(j); if(f.name != p.notify) { continue; } else { notifyId = j /* Signal indexes start from 0 */; break; } } p.notifyId = notifyId; } } // // Create meta data // if (cdef->propertyList.count()) fprintf(out, "\n // properties: name, type, flags\n"); for (int i = 0; i < cdef->propertyList.count(); ++i) { const PropertyDef &p = cdef->propertyList.at(i); uint flags = Invalid; if (!isVariantType(p.type)) { flags |= EnumOrFlag; } else { flags |= qvariant_nameToType(p.type) << 24; } if (!p.read.isEmpty()) flags |= Readable; if (!p.write.isEmpty()) { flags |= Writable; if (p.stdCppSet()) flags |= StdCppSet; } if (!p.reset.isEmpty()) flags |= Resettable; // if (p.override) // flags |= Override; if (p.designable.isEmpty()) flags |= ResolveDesignable; else if (p.designable != "false") flags |= Designable; if (p.scriptable.isEmpty()) flags |= ResolveScriptable; else if (p.scriptable != "false") flags |= Scriptable; if (p.stored.isEmpty()) flags |= ResolveStored; else if (p.stored != "false") flags |= Stored; if (p.editable.isEmpty()) flags |= ResolveEditable; else if (p.editable != "false") flags |= Editable; if (p.user.isEmpty()) flags |= ResolveUser; else if (p.user != "false") flags |= User; if (p.notifyId != -1) flags |= Notify; fprintf(out, " %4d, %4d, 0x%.8x,\n", strreg(p.name), strreg(p.type), flags); } if(cdef->notifyableProperties) { fprintf(out, "\n // properties: notify_signal_id\n"); for (int i = 0; i < cdef->propertyList.count(); ++i) { const PropertyDef &p = cdef->propertyList.at(i); if(p.notifyId == -1) fprintf(out, " %4d,\n", 0); else fprintf(out, " %4d,\n", p.notifyId); } } }
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); }
QMetaObject *Generator::generateMetaObject(bool ignoreProperties) { // // build the data array // // filter out undeclared enumerators and sets { QList<EnumDef> enumList; for (int 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; } int index = 10; meta_data << 1 // revision << strreg(cdef->qualified) // classname << cdef->classInfoList.count() << (cdef->classInfoList.count() ? index : 0) // classinfo ; index += cdef->classInfoList.count() * 2; int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); meta_data << methodCount << (methodCount ? index : 0); // methods index += methodCount * 5; if (!ignoreProperties) { meta_data << cdef->propertyList.count() << (cdef->propertyList.count() ? index : 0); // properties index += cdef->propertyList.count() * 3; } else { meta_data << 0 << 0; // properties } meta_data << cdef->enumList.count() << (cdef->enumList.count() ? index : 0); // enums/sets // // Build classinfo array // _generateClassInfos(); // // Build signals array first, otherwise the signal indices would be wrong // _generateFunctions(cdef->signalList, MethodSignal); // // Build slots array // _generateFunctions(cdef->slotList, MethodSlot); // // Build method array // _generateFunctions(cdef->methodList, MethodMethod); // // Build property array // if (!ignoreProperties) _generateProperties(); // // Build enums array // _generateEnums(index); // // Terminate data array // meta_data << 0; // // Build stringdata array // QVector<char> string_data; for (int i = 0; i < strings.size(); ++i) { const char *s = strings.at(i).constData(); char c; do { c = *(s++); string_data << c; } while (c != '\0'); } // // Finally create and initialize the static meta object // const int meta_object_offset = 0; const int meta_object_size = sizeof(QMetaObject); const int meta_data_offset = meta_object_offset + meta_object_size; const int meta_data_size = meta_data.count() * sizeof(uint); const int string_data_offset = meta_data_offset + meta_data_size; const int string_data_size = string_data.count(); const int total_size = string_data_offset + string_data_size; char *blob = new char[total_size]; char *string_data_output = blob + string_data_offset; const char *string_data_src = string_data.constData(); for (int i = 0; i < string_data.count(); ++i) string_data_output[i] = string_data_src[i]; uint *meta_data_output = reinterpret_cast<uint *>(blob + meta_data_offset); const uint *meta_data_src = meta_data.constData(); for (int i = 0; i < meta_data.count(); ++i) meta_data_output[i] = meta_data_src[i]; QMetaObject *meta_object = new (blob + meta_object_offset)QMetaObject; meta_object->d.superdata = 0; meta_object->d.stringdata = string_data_output; meta_object->d.data = meta_data_output; meta_object->d.extradata = 0; return meta_object; }