diff options
Diffstat (limited to 'codegen/generator.cpp')
-rw-r--r-- | codegen/generator.cpp | 109 |
1 files changed, 96 insertions, 13 deletions
diff --git a/codegen/generator.cpp b/codegen/generator.cpp index 2d1033a..eb4bccb 100644 --- a/codegen/generator.cpp +++ b/codegen/generator.cpp @@ -1,5 +1,7 @@ /* - Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com> + Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com> + Copyright (C) 2010 Collabora Ltd. + @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -24,6 +26,8 @@ extern int yylineno; int yyparse(CodeGen *codegen); void yyrestart(FILE *file); +QHash<QByteArray, QList<QByteArray> > CodeGen::s_wrapperDefinitions; + int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); @@ -36,16 +40,18 @@ int main(int argc, char *argv[]) if (fileName.startsWith("-I")) { outStream << "#include <" << fileName.remove(0, 2) << ">" << endl; } else if (fileName.endsWith(".h") && QFile::exists(fileName)) { - CodeGen::parse(fileName); + CodeGen::parse(fileName, outStream); } else { QTextStream(stderr) << "Skipping " << fileName << ": Not an existing header" << endl; } } + CodeGen::printGlobalWrapperDefinitions(outStream); + return 0; } -void CodeGen::parse(const QString & fileName) +void CodeGen::parse(const QString & fileName, QTextStream & outStream) { CodeGen codegen(fileName); @@ -61,19 +67,23 @@ void CodeGen::parse(const QString & fileName) yyparse(&codegen); std::fclose(fp); - codegen.generateOutput(); + codegen.generateOutput(outStream); } -void CodeGen::generateOutput() +void CodeGen::generateOutput(QTextStream & outStream) { - QTextStream outStream(stdout); outStream << "#include \"" << m_fileName << "\"" << endl << endl; - foreach(const TypeRegistration & typeReg, m_typeRegistrations) { + foreach(const QByteArrayHash & typeReg, m_typeRegistrations) { printTypeRegistration(outStream, typeReg); outStream << endl; } + foreach(const QByteArrayHash & def, m_wrapperDefinitions) { + printWrapperDefinition(outStream, def); + outStream << endl; + } + foreach(const Enum & enumDef, m_enums) { if (!enumDef.options.contains("skip")) { printEnumAssertions(outStream, enumDef); @@ -82,7 +92,7 @@ void CodeGen::generateOutput() } } -void CodeGen::printTypeRegistration(QTextStream & outStream, const TypeRegistration & typeReg) +void CodeGen::printTypeRegistration(QTextStream & outStream, const QByteArrayHash & typeReg) { outStream << "QGLIB_REGISTER_TYPE_IMPLEMENTATION("; @@ -96,7 +106,7 @@ void CodeGen::printTypeRegistration(QTextStream & outStream, const TypeRegistrat if (typeReg.contains("GType")) { outStream << typeReg["GType"]; } else { - outStream << (typeReg["namespace"] == "QGst" ? "GST_TYPE_" : "G_TYPE_"); + outStream << namespaceToGstStyle(typeReg["namespace"]) << "_TYPE_"; outStream << toGstStyle(typeReg["enum"].isEmpty() ? typeReg["class"] : typeReg["enum"]); } outStream << ")" << endl; @@ -117,7 +127,7 @@ void CodeGen::printEnumAssertions(QTextStream& outStream, const Enum & enumDef) if (enumDef.options.contains("prefix")) { outStream << enumDef.options["prefix"]; } else { - outStream << (enumDef.options["namespace"] == "QGst" ? "GST_" : "G_"); + outStream << namespaceToGstStyle(enumDef.options["namespace"]) << "_"; if (enumDef.options.contains("class") && !enumDef.options["class"].isEmpty()) { outStream << toGstStyle(enumDef.options["class"]) << "_"; } @@ -133,6 +143,59 @@ void CodeGen::printEnumAssertions(QTextStream& outStream, const Enum & enumDef) outStream << "}" << endl; } +void CodeGen::printWrapperDefinition(QTextStream& outStream, const QByteArrayHash & def) +{ + outStream << "namespace " << def["namespace"] << " {" << endl; + outStream << " QGlib::RefCountedObject *" << def["class"] << "_new(void *instance)" << endl; + outStream << " {" << endl; + + QByteArrayPair index = qMakePair(def["namespace"], def["class"]); + if (m_wrapperSubclasses.contains(index)) { + outStream << " switch(" << namespaceToGstStyle(def["namespace"]) + << "_" << toGstStyle(def["class"]) << "_" + << "TYPE(instance)) {" << endl; + + Q_FOREACH(const QByteArrayHash & subclass, m_wrapperSubclasses[index]) { + outStream << " case " << def["namespace"] << "::" + << def["class"] << subclass["prefix"] << ":" << endl; + outStream << " return new " << def["namespace"] << "::" + << subclass["prefix"] << def["class"] << ";" << endl; + } + + outStream << " default:" << endl; + outStream << " return new " << def["namespace"] << "::" << def["class"] << ";" << endl; + outStream << " }" << endl; + } else { + outStream << " Q_UNUSED(instance);" << endl; + outStream << " return new " << def["namespace"] << "::" << def["class"] << ";" << endl; + } + + outStream << " }" << endl; + outStream << "} //namespace " << def["namespace"] << endl; + + s_wrapperDefinitions[def["namespace"]].append(def["class"]); +} + +void CodeGen::printGlobalWrapperDefinitions(QTextStream & outStream) +{ + QHashIterator<QByteArray, QList<QByteArray> > it(s_wrapperDefinitions); + while (it.hasNext()) { + it.next(); + outStream << "namespace " << it.key() << " {" << endl; + outStream << " void registerWrapperConstructors()" << endl; + outStream << " {" << endl; + outStream << " QGlib::Quark q = g_quark_from_static_string(\"QGlib__wrapper_constructor\");" << endl; + + Q_FOREACH(const QByteArray & classId, it.value()) { + outStream << " QGlib::GetType<" << classId << ">()" + << ".setQuarkData(q, reinterpret_cast<void*>(&" << classId << "_new));" << endl; + } + outStream << " }" << endl; + outStream << "} //namespace " << it.key() << endl << endl; + } + s_wrapperDefinitions.clear(); +} + QByteArray CodeGen::toGstStyle(const QByteArray & str) { QByteArray output; @@ -149,8 +212,12 @@ QByteArray CodeGen::toGstStyle(const QByteArray & str) return output; } +QByteArray CodeGen::namespaceToGstStyle(const QByteArray & ns) +{ + return ns == "QGst" ? "GST" : "G"; +} -void CodeGen::addEnum(const QList<QByteArray> & values, const QHash<QByteArray, QByteArray> & options) +void CodeGen::addEnum(const QList<QByteArray> & values, const QByteArrayHash & options) { Enum e; e.values = values; @@ -161,15 +228,31 @@ void CodeGen::addEnum(const QList<QByteArray> & values, const QHash<QByteArray, } void CodeGen::addTypeRegistration(const QByteArray& namespaceId, const QByteArray& classId, - const QByteArray& enumId, const QHash<QByteArray, QByteArray>& options) + const QByteArray& enumId, const QByteArrayHash & options) { - TypeRegistration typeReg(options); + QByteArrayHash typeReg(options); typeReg["namespace"] = namespaceId; typeReg["class"] = classId; typeReg["enum"] = enumId; m_typeRegistrations.append(typeReg); } +void CodeGen::addWrapperDefinition(const QByteArray & classId, const QByteArrayHash & options) +{ + QByteArrayHash def(options); + def["namespace"] = m_currentNamespace; + def["class"] = classId; + m_wrapperDefinitions.append(def); +} + +void CodeGen::addWrapperFakeSubclass(const QByteArray & prefix, const QByteArray & classId, + const QByteArrayHash & options) +{ + QByteArrayHash sub(options); + sub["prefix"] = prefix; + m_wrapperSubclasses[qMakePair(m_currentNamespace, classId)].append(sub); +} + //called by yyerror() void CodeGen::fatalError(const char* msg) { |