summaryrefslogtreecommitdiff
path: root/codegen/generator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/generator.cpp')
-rw-r--r--codegen/generator.cpp109
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)
{