summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-08-20 21:24:45 -0300
committerHugo Lima <hugo.lima@openbossa.org>2009-08-25 16:23:11 -0300
commit425c1eba27766b4382ace8f10daeaa548c9eb0d6 (patch)
treedfdf37ebca0fd2b1b26f8e598410f35eb1e6c12e
parent252ff87489c02fe1b26d650ad855d111042c6490 (diff)
downloadgeneratorrunner-425c1eba27766b4382ace8f10daeaa548c9eb0d6.tar.gz
generatorrunner-425c1eba27766b4382ace8f10daeaa548c9eb0d6.tar.xz
generatorrunner-425c1eba27766b4382ace8f10daeaa548c9eb0d6.zip
The current generators will be just plugins and all generator stuff in APIExtractor were moved
to this project. So we need to re-think if boostpythongenerator still a good name for the project, because boostpythongenerator will be the name of the plugin to generate bindings for boost::python. Also the generators were just moved to a subdirectory (generators) and the boostpython generators to a sub-subdirectory (generators/boostpython), transform them in plugins will be a second milestone.
-rw-r--r--CMakeLists.txt15
-rw-r--r--generator.cpp143
-rw-r--r--generator.h334
-rw-r--r--generators/boostpython/boostpythongenerator.cpp (renamed from boostpythongenerator.cpp)0
-rw-r--r--generators/boostpython/boostpythongenerator.h (renamed from boostpythongenerator.h)0
-rw-r--r--generators/boostpython/convertergenerator.cpp (renamed from convertergenerator.cpp)0
-rw-r--r--generators/boostpython/convertergenerator.h (renamed from convertergenerator.h)0
-rw-r--r--generators/boostpython/cppgenerator.cpp (renamed from cppgenerator.cpp)0
-rw-r--r--generators/boostpython/cppgenerator.h (renamed from cppgenerator.h)0
-rw-r--r--generators/boostpython/hppgenerator.cpp (renamed from hppgenerator.cpp)0
-rw-r--r--generators/boostpython/hppgenerator.h (renamed from hppgenerator.h)0
-rw-r--r--main.cpp200
12 files changed, 662 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e38549..2eeb84c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,11 +12,8 @@ configure_file(boostpythongeneratorversion.h.in ${CMAKE_CURRENT_BINARY_DIR}/boos
set(CMAKE_BUILD_TYPE Debug)
set(boostpythongenerator_SRC
-boostpythongenerator.cpp
-convertergenerator.cpp
-docgenerator.cpp
-hppgenerator.cpp
-cppgenerator.cpp
+main.cpp
+generator.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
@@ -26,13 +23,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${QT_INCLUDE_DIR}
${QT_QTCORE_INCLUDE_DIR})
-add_library(libboostpythongenerator STATIC ${boostpythongenerator_SRC})
-target_link_libraries(libboostpythongenerator
+add_executable(boostpythongenerator ${boostpythongenerator_SRC})
+target_link_libraries(boostpythongenerator
${APIEXTRACTOR_LIBRARY}
${QT_QTCORE_LIBRARY}
${QT_QTXML_LIBRARY})
-add_executable(boostpythongenerator main.cpp)
-target_link_libraries(boostpythongenerator libboostpythongenerator)
# uninstall target
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake"
@@ -58,5 +53,5 @@ install(TARGETS boostpythongenerator DESTINATION bin)
enable_testing()
#add_subdirectory(libbindgen)
-add_subdirectory(tests)
+# add_subdirectory(tests)
diff --git a/generator.cpp b/generator.cpp
new file mode 100644
index 0000000..343ebc6
--- /dev/null
+++ b/generator.cpp
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "generator.h"
+#include "reporthandler.h"
+#include "fileout.h"
+#include "apiextractor.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QDebug>
+
+Generator::Generator() : m_numGenerated(0), m_numGeneratedWritten(0)
+{}
+
+Generator::~Generator()
+{
+}
+
+bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args)
+{
+ m_globalEnums = extractor.globalEnums();
+ m_globalFunctions = extractor.globalFunctions();
+ m_classes = extractor.classes();
+ m_primitiveTypes = extractor.primitiveTypes();
+ m_containerTypes = extractor.containerTypes();
+
+ // FIXME: Avoid this ugly hack to get the package name.. and... why the name "package"!?
+ foreach (const AbstractMetaClass* cppClass, m_classes) {
+ if (m_packageName.isEmpty()
+ && cppClass->typeEntry()->generateCode()
+ && !cppClass->package().isEmpty()) {
+ m_packageName = cppClass->package();
+ break;
+ }
+ }
+ // does anyone use this?
+ m_qmetatypeDeclaredTypenames = extractor.qtMetaTypeDeclaredTypeNames();
+ return doSetup(args);
+}
+
+void Generator::generate()
+{
+ foreach (AbstractMetaClass *cls, m_classes) {
+ if (!shouldGenerate(cls))
+ continue;
+
+ QString fileName = fileNameForClass(cls);
+ if (fileName.isNull())
+ continue;
+ ReportHandler::debugSparse(QString("generating: %1").arg(fileName));
+
+ FileOut fileOut(outputDirectory() + '/' + subDirectoryForClass(cls) + '/' + fileName);
+ generateClass(fileOut.stream, cls);
+
+ if (fileOut.done())
+ ++m_numGeneratedWritten;
+ ++m_numGenerated;
+ }
+ finishGeneration();
+}
+
+bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const
+{
+ return metaClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang;
+}
+
+void Generator::verifyDirectoryFor(const QFile &file)
+{
+ QDir dir = QFileInfo(file).dir();
+ if (!dir.exists()) {
+ if (!dir.mkpath(dir.absolutePath()))
+ ReportHandler::warning(QString("unable to create directory '%1'")
+ .arg(dir.absolutePath()));
+ }
+}
+
+bool Generator::hasDefaultConstructor(const AbstractMetaType *type)
+{
+ QString full_name = type->typeEntry()->qualifiedTargetLangName();
+ QString class_name = type->typeEntry()->targetLangName();
+
+ foreach (const AbstractMetaClass *cls, m_classes) {
+ if (cls->typeEntry()->qualifiedTargetLangName() == full_name) {
+ AbstractMetaFunctionList functions = cls->functions();
+ foreach (const AbstractMetaFunction *function, functions) {
+ if (function->arguments().isEmpty() && function->name() == class_name)
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func)
+{
+ const AbstractMetaClass *cpp_class = func->ownerClass();
+ code.replace("%TYPE", cpp_class->name());
+
+ foreach (AbstractMetaArgument *arg, func->arguments())
+ code.replace("%" + QString::number(arg->argumentIndex() + 1), arg->argumentName());
+
+ //template values
+ code.replace("%RETURN_TYPE", translateType(func->type(), cpp_class));
+ code.replace("%FUNCTION_NAME", func->originalName());
+
+ if (code.contains("%ARGUMENT_NAMES")) {
+ QString str;
+ QTextStream aux_stream(&str);
+ writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments);
+ code.replace("%ARGUMENT_NAMES", str);
+ }
+
+ if (code.contains("%ARGUMENTS")) {
+ QString str;
+ QTextStream aux_stream(&str);
+ writeFunctionArguments(aux_stream, func, Generator::SkipDefaultValues | Generator::SkipRemovedArguments);
+ code.replace("%ARGUMENTS", str);
+ }
+}
+
diff --git a/generator.h b/generator.h
new file mode 100644
index 0000000..14526d7
--- /dev/null
+++ b/generator.h
@@ -0,0 +1,334 @@
+/*
+ * This file is part of the API Extractor project.
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef GENERATOR_H
+#define GENERATOR_H
+
+#include <QtCore/QObject>
+#include <QtCore/QDir>
+#include "abstractmetalang.h"
+
+class ApiExtractor;
+class AbstractMetaBuilder;
+class QFile;
+
+/**
+ * Base class for all generators. The default implementations does nothing,
+ * you must subclass this to create your own generators.
+ */
+class Generator
+{
+public:
+ /// Optiosn used around the generator code
+ enum Option {
+ NoOption = 0x00000000,
+ BoxedPrimitive = 0x00000001,
+ ExcludeConst = 0x00000002,
+ ExcludeReference = 0x00000004,
+ UseNativeIds = 0x00000008,
+
+ EnumAsInts = 0x00000010,
+ SkipName = 0x00000020,
+ NoCasts = 0x00000040,
+ SkipReturnType = 0x00000080,
+ OriginalName = 0x00000100,
+ ShowStatic = 0x00000200,
+ UnderscoreSpaces = 0x00000400,
+ ForceEnumCast = 0x00000800,
+ ArrayAsPointer = 0x00001000,
+ VirtualCall = 0x00002000,
+ SkipTemplateParameters = 0x00004000,
+ SkipAttributes = 0x00008000,
+ OriginalTypeDescription = 0x00010000,
+ SkipRemovedArguments = 0x00020000,
+ IncludeDefaultExpression = 0x00040000,
+ NoReturnStatement = 0x00080000,
+ NoBlockedSlot = 0x00100000,
+
+ SuperCall = 0x00200000,
+
+ GlobalRefJObject = 0x00100000,
+
+ SkipDefaultValues = 0x00400000,
+
+ WriteSelf = 0x00800000,
+ ExcludeMethodConst = 0x01000000,
+
+ ForceValueType = ExcludeReference | ExcludeConst
+ };
+
+ Generator();
+ virtual ~Generator();
+
+ bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args);
+
+ virtual QMap<QString, QString> options() const
+ {
+ return QMap<QString, QString>();
+ }
+
+ /// Returns the classes used to generate the binding code.
+ AbstractMetaClassList classes() const
+ {
+ return m_classes;
+ }
+
+ AbstractMetaFunctionList globalFunctions() const
+ {
+ return m_globalFunctions;
+ }
+
+ AbstractMetaEnumList globalEnums() const
+ {
+ return m_globalEnums;
+ }
+
+ QList<const PrimitiveTypeEntry*> primitiveTypes() const
+ {
+ return m_primitiveTypes;
+ }
+
+ QList<const ContainerTypeEntry*> containerTypes() const
+ {
+ return m_containerTypes;
+ }
+
+ /// Returns the output directory
+ QString outputDirectory() const
+ {
+ return m_outDir;
+ }
+
+ /// Set the output directory
+ void setOutputDirectory(const QString &outDir)
+ {
+ m_outDir = outDir;
+ }
+
+ /**
+ * Start the code generation, be sure to call setClasses before callign this method.
+ * For each class it creates a QTextStream, call the write method with the current
+ * class and the associated text stream, then write the text stream contents if needed.
+ * \see #write
+ */
+ void generate();
+
+ /// Returns the number of generated items
+ int numGenerated()
+ {
+ return m_numGenerated;
+ }
+
+ /// Returns the number of generated items written
+ int numGeneratedAndWritten()
+ {
+ return m_numGeneratedWritten;
+ }
+
+ virtual const char* name() const = 0;
+
+ /// Returns true if the generator should generate any code for the AbstractMetaClass
+ virtual bool shouldGenerate(const AbstractMetaClass *) const;
+
+ /// Returns the subdirectory used to write the binding code of an AbstractMetaClass.
+ virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) const = 0;
+
+ /**
+ * Translate metatypes to binding source format.
+ * \param metatype a pointer to metatype
+ * \param context the current meta class
+ * \param option some extra options
+ * \return the metatype translated to binding source format
+ */
+ virtual QString translateType(const AbstractMetaType *metatype,
+ const AbstractMetaClass *context,
+ int option = NoOption) const = 0;
+
+ /**
+ * Function used to write the fucntion arguments on the class buffer.
+ * \param s the class output buffer
+ * \param metafunction the pointer to metafunction information
+ * \param count the number of function arguments
+ * \param options some extra options used during the parser
+ */
+ virtual void writeFunctionArguments(QTextStream &s,
+ const AbstractMetaFunction *metafunction,
+ uint options = 0) const = 0;
+
+ virtual void writeArgumentNames(QTextStream &s,
+ const AbstractMetaFunction *metafunction,
+ uint options = 0) const = 0;
+
+ void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func);
+
+ bool hasDefaultConstructor(const AbstractMetaType *type);
+
+ // QtScript
+ QSet<QString> qtMetaTypeDeclaredTypeNames() const
+ {
+ return m_qmetatypeDeclaredTypenames;
+ }
+
+ /**
+ * Returns the license comment to be prepended to each source file generated.
+ */
+ QString licenseComment()
+ {
+ return m_licenseComment;
+ }
+
+ /**
+ * Sets the license comment to be prepended to each source file generated.
+ */
+ void setLicenseComment(const QString &licenseComment)
+ {
+ m_licenseComment = licenseComment;
+ }
+
+ /**
+ * Returns the package name.
+ */
+ QString packageName()
+ {
+ return m_packageName;
+ }
+
+ /**
+ * Sets the package name.
+ */
+ void setPackageName(const QString &packageName)
+ {
+ m_packageName = packageName;
+ }
+
+ /**
+ * Retrieves the name of the currently processed module. While package name
+ * is a complete package idetification, e.g. 'PySide.QtCore', a module name
+ * represents the last part of the package, e.g. 'QtCore'.
+ * If the target language separates the modules with characters other than
+ * dots ('.') the generator subclass must overload this method.
+ * /return a string representing the last part of a package name
+ */
+ virtual QString moduleName()
+ {
+ return QString(m_packageName).remove(0, m_packageName.lastIndexOf('.') + 1);
+ }
+
+protected:
+ QString m_packageName;
+
+ /**
+ * Returns the file name used to write the binding code of an AbstractMetaClass.
+ * /param metaClass the AbstractMetaClass for which the file name must be
+ * returned
+ * /return the file name used to write the binding code for the class
+ */
+ virtual QString fileNameForClass(const AbstractMetaClass* metaClass) const = 0;
+
+ virtual bool doSetup(QMap<QString, QString> args) = 0;
+
+ /**
+ * Returns the subdirectory path for a given package
+ * (aka module, aka library) name.
+ * If the target language separates the package modules with characters other
+ * than dots ('.') the generator subclass must overload this method.
+ * /param packageName complete package name for which to return the subdirectory path
+ * or nothing the use the name of the currently processed package
+ * /return a string representing the subdirectory path for the given package
+ */
+ virtual QString subDirectoryForPackage(QString packageName = QString()) const
+ {
+ if (packageName.isEmpty())
+ packageName = m_packageName;
+ return QString(packageName).replace(".", QDir::separator());
+ }
+
+ /**
+ * Write the bindding code for an AbstractMetaClass.
+ * This is called by the default implementation of generate method.
+ * \param s text stream to write the generated output
+ * \param metaClass the class that should be generated
+ */
+ virtual void generateClass(QTextStream& s, const AbstractMetaClass* metaClass) = 0;
+ virtual void finishGeneration() = 0;
+
+ void verifyDirectoryFor(const QFile &file);
+
+ int m_numGenerated;
+ int m_numGeneratedWritten;
+
+private:
+ AbstractMetaClassList m_classes;
+ AbstractMetaFunctionList m_globalFunctions;
+ AbstractMetaEnumList m_globalEnums;
+ QString m_outDir;
+
+ QList<const PrimitiveTypeEntry*> m_primitiveTypes;
+ QList<const ContainerTypeEntry*> m_containerTypes;
+
+ // QtScript
+ QSet<QString> m_qmetatypeDeclaredTypenames;
+
+ // License comment
+ QString m_licenseComment;
+};
+
+/**
+* Utility class to store the identation level, use it in a QTextStream.
+*/
+class Indentor
+{
+public:
+ Indentor():
+ indent(0) {}
+ int indent;
+};
+
+/**
+* Class that use the RAII idiom to set and unset the identation level.
+*/
+class Indentation
+{
+public:
+ Indentation(Indentor &indentor) : indentor(indentor)
+ {
+ indentor.indent++;
+ }
+ ~Indentation()
+ {
+ indentor.indent--;
+ }
+
+private:
+ Indentor &indentor;
+};
+
+inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor)
+{
+ for (int i = 0; i < indentor.indent; ++i)
+ s << " ";
+ return s;
+}
+
+#endif // GENERATOR_H
+
diff --git a/boostpythongenerator.cpp b/generators/boostpython/boostpythongenerator.cpp
index 70ce4a5..70ce4a5 100644
--- a/boostpythongenerator.cpp
+++ b/generators/boostpython/boostpythongenerator.cpp
diff --git a/boostpythongenerator.h b/generators/boostpython/boostpythongenerator.h
index 4ad191b..4ad191b 100644
--- a/boostpythongenerator.h
+++ b/generators/boostpython/boostpythongenerator.h
diff --git a/convertergenerator.cpp b/generators/boostpython/convertergenerator.cpp
index ea52b91..ea52b91 100644
--- a/convertergenerator.cpp
+++ b/generators/boostpython/convertergenerator.cpp
diff --git a/convertergenerator.h b/generators/boostpython/convertergenerator.h
index 8f91377..8f91377 100644
--- a/convertergenerator.h
+++ b/generators/boostpython/convertergenerator.h
diff --git a/cppgenerator.cpp b/generators/boostpython/cppgenerator.cpp
index 36bd067..36bd067 100644
--- a/cppgenerator.cpp
+++ b/generators/boostpython/cppgenerator.cpp
diff --git a/cppgenerator.h b/generators/boostpython/cppgenerator.h
index bd41fe1..bd41fe1 100644
--- a/cppgenerator.h
+++ b/generators/boostpython/cppgenerator.h
diff --git a/hppgenerator.cpp b/generators/boostpython/hppgenerator.cpp
index f6d576d..f6d576d 100644
--- a/hppgenerator.cpp
+++ b/generators/boostpython/hppgenerator.cpp
diff --git a/hppgenerator.h b/generators/boostpython/hppgenerator.h
index 8e0f5f0..8e0f5f0 100644
--- a/hppgenerator.h
+++ b/generators/boostpython/hppgenerator.h
diff --git a/main.cpp b/main.cpp
index 9560eff..af6d9d1 100644
--- a/main.cpp
+++ b/main.cpp
@@ -21,32 +21,192 @@
*
*/
-#include <QtCore/QCoreApplication>
+#include <QCoreApplication>
+#include <QLinkedList>
+#include <QLibrary>
+#include <iostream>
#include <apiextractor/apiextractor.h>
-#include "hppgenerator.h"
-#include "cppgenerator.h"
-#include "hppgenerator.h"
-#include "convertergenerator.h"
-#include "docgenerator.h"
#include "boostpythongeneratorversion.h"
-#include <iostream>
+#include "generator.h"
-void showVersion(const char* apiextractor_version) {
- using namespace std;
+#if defined(Q_OS_WIN32)
+ #define PATH_SPLITTER ";"
+#else
+ #define PATH_SPLITTER ":"
+#endif
- cout << "BoostPythonGenerator v" BOOSTPYTHONGENERATOR_VERSION << " using " << apiextractor_version << endl;
- cout << "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)" << endl;
+
+static void printOptions(QTextStream& s, const QMap<QString, QString>& options) {
+ QMap<QString, QString>::const_iterator it = options.constBegin();
+ s.setFieldAlignment(QTextStream::AlignLeft);
+ for (; it != options.constEnd(); ++it) {
+ s << " --";
+ s.setFieldWidth(38);
+ s << it.key() << it.value();
+ s.setFieldWidth(0);
+ s << endl;
+ }
+}
+
+typedef QLinkedList<Generator*> (*getGeneratorsFunc)();
+typedef QLinkedList<Generator*> GeneratorList;
+
+QMap<QString, QString> getCommandLineArgs(int argc, char** argv)
+{
+ QMap<QString, QString> args;
+ int argNum = 0;
+ for (int i = 1; i < argc; ++i) {
+ QString arg(argv[i]);
+ arg = arg.trimmed();
+ if (arg.startsWith("--")) {
+ int split = arg.indexOf("=");
+ if (split > 0)
+ args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed();
+ else
+ args[arg.mid(2)] = QString();
+ } else if (arg.startsWith("-")) {
+ args[arg.mid(1)] = QString();
+ } else {
+ argNum++;
+ args[QString("arg-%1").arg(argNum)] = arg;
+ }
+ }
+ return args;
+}
+
+void printUsage(const GeneratorList& generators)
+{
+ #if defined(Q_OS_WIN32)
+ #define PATHSPLITTER ";"
+ #else
+ #define PATHSPLITTER ":"
+ #endif
+ QTextStream s(stdout);
+ s << "Usage:\n "
+ << "generator [options] header-file typesystem-file\n\n"
+ "General options:\n";
+ QMap<QString, QString> generalOptions;
+ generalOptions.insert("debug-level=[sparse|medium|full]", "Set the debug level");
+ generalOptions.insert("silent", "Avoid printing any message");
+ generalOptions.insert("help", "Display this help and exit");
+ generalOptions.insert("no-suppress-warnings", "Show all warnings");
+ generalOptions.insert("output-directory=[dir]", "The directory where the generated files will be written");
+ generalOptions.insert("include-paths=<path>[" PATHSPLITTER "<path>" PATHSPLITTER "...]", "Include paths used by the C++ parser");
+ generalOptions.insert("typesystem-paths=<path>[" PATHSPLITTER "<path>" PATHSPLITTER "...]", "Paths used when searching for typesystems");
+ generalOptions.insert("documentation-only", "Do not generates any code, just the documentation");
+ generalOptions.insert("license-file=[licensefile]", "File used for copyright headers of generated files");
+ generalOptions.insert("version", "Output version information and exit");
+ generalOptions.insert("generatorSet", "generatorSet to be used. e.g. boostpython");
+ printOptions(s, generalOptions);
+
+ foreach (Generator* generator, generators) {
+ QMap<QString, QString> options = generator->options();
+ if (!options.isEmpty()) {
+ s << endl << generator->name() << " options:\n";
+ printOptions(s, generator->options());
+ }
+ }
}
int main(int argc, char *argv[])
{
- QCoreApplication app(argc, argv); // needed by qxmlpatterns
-
- ApiExtractor extractor(argc, argv);
- extractor.addGenerator(new HppGenerator);
- extractor.addGenerator(new CppGenerator);
- extractor.addGenerator(new ConverterGenerator);
- extractor.addGenerator(new DocGenerator);
- extractor.setVersionHandler(&showVersion);
- return extractor.exec();
+ // needed by qxmlpatterns
+ QCoreApplication app(argc, argv);
+
+ // Store command arguments in a map
+ QMap<QString, QString> args = getCommandLineArgs(argc, argv);
+ GeneratorList generators;
+
+ if (args.contains("version")) {
+ std::cout << "generator v" BOOSTPYTHONGENERATOR_VERSION << std::endl;
+ std::cout << "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)" << std::endl;
+ return EXIT_SUCCESS;
+ }
+
+ // Try to load a generator
+ QString generatorSet = args.value("generatorSet");
+ if (!generatorSet.isEmpty()) {
+ QLibrary plugin(generatorSet);
+ getGeneratorsFunc getGenerators = reinterpret_cast<getGeneratorsFunc>(plugin.resolve("getGenerators"));
+ if (getGenerators)
+ generators = getGenerators();
+ else {
+ std::cerr << argv[0] << ": Error loading generatorset plugin: " << qPrintable(plugin.errorString()) << std::endl;
+ return EXIT_FAILURE;
+ }
+ } else if (!args.contains("help")) {
+ std::cerr << argv[0] << ": You need to specify a generator with --generatorSet=GENERATOR_NAME" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (args.contains("help")) {
+ printUsage(generators);
+ return EXIT_SUCCESS;
+ }
+
+
+ QString licenseComment;
+ if (args.contains("license-file") && !args.value("license-file").isEmpty()) {
+ QString licenseFileName = args.value("license-file");
+ if (QFile::exists(licenseFileName)) {
+ QFile licenseFile(licenseFileName);
+ if (licenseFile.open(QIODevice::ReadOnly))
+ licenseComment = licenseFile.readAll();
+ } else {
+ std::cerr << "Couldn't find the file containing the license heading: ";
+ std::cerr << qPrintable(licenseFileName) << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ // Create and set-up API Extractor
+ ApiExtractor extractor;
+
+ if (args.contains("silent")) {
+ extractor.setSilent(true);
+ } else if (args.contains("debug-level")) {
+ QString level = args.value("debug-level");
+ if (level == "sparse")
+ extractor.setDebugLevel(ReportHandler::SparseDebug);
+ else if (level == "medium")
+ extractor.setDebugLevel(ReportHandler::MediumDebug);
+ else if (level == "full")
+ extractor.setDebugLevel(ReportHandler::FullDebug);
+ }
+ if (args.contains("no-suppress-warnings"))
+ extractor.setSuppressWarnings(false);
+
+ if (args.contains("typesystem-paths"))
+ extractor.addTypesystemSearchPath(args.value("typesystem-paths").split(PATH_SPLITTER));
+ if (!args.value("include-paths").isEmpty())
+ extractor.addIncludePath(args.value("include-paths").split(PATH_SPLITTER));
+
+
+ QString cppFileName = args.value("arg-1");
+ QString typeSystemFileName = args.value("arg-2");
+ if (args.contains("arg-3")) {
+ std::cerr << "Too many arguments!" << std::endl;
+ return EXIT_FAILURE;
+ }
+ extractor.setCppFileName(cppFileName);
+ extractor.setTypeSystem(typeSystemFileName);
+ extractor.run();
+
+ if (!extractor.classCount()) {
+ std::cerr << "No C++ classes found!" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+
+ QString outputDirectory = args.contains("output-directory") ? args["output-directory"] : "out";
+ foreach (Generator* g, generators) {
+ g->setOutputDirectory(outputDirectory);
+ g->setLicenseComment(licenseComment);
+ if (g->setup(extractor, args))
+ g->generate();
+ }
+
+ std::cout << "Done, " << ReportHandler::warningCount();
+ std::cout << " warnings (" << ReportHandler::suppressedCount() << " known issues)";
+ std::cout << std::endl;
}