summaryrefslogtreecommitdiffstats
path: root/unoidl/source/unoidl-read.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--unoidl/source/unoidl-read.cxx1139
1 files changed, 1139 insertions, 0 deletions
diff --git a/unoidl/source/unoidl-read.cxx b/unoidl/source/unoidl-read.cxx
new file mode 100644
index 000000000..283c660ce
--- /dev/null
+++ b/unoidl/source/unoidl-read.cxx
@@ -0,0 +1,1139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <set>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <osl/file.hxx>
+#include <osl/process.h>
+#include <rtl/process.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/main.h>
+#include <sal/types.h>
+#include <unoidl/unoidl.hxx>
+#include <o3tl/string_view.hxx>
+
+namespace {
+
+void badUsage() {
+ std::cerr
+ << "Usage:" << std::endl << std::endl
+ << " unoidl-read [--published] [--summary] [<extra registries>] <registry>"
+ << std::endl << std::endl
+ << ("where each <registry> is either a new- or legacy-format .rdb file,"
+ " a single .idl")
+ << std::endl
+ << ("file, or a root directory of an .idl file tree. The complete"
+ " content of the")
+ << std::endl
+ << ("last <registry> is written to stdout; if --published is specified,"
+ " only the")
+ << std::endl
+ << ("published entities (plus any non-published entities referenced"
+ " from published")
+ << std::endl
+ << "via any unpublished optional bases) are written out. If --summary is specified,"
+ << std::endl
+ << "only a short summary is written, with the type and name of one entity per line."
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+}
+
+OUString getArgumentUri(sal_uInt32 argument) {
+ OUString arg;
+ rtl_getAppCommandArg(argument, &arg.pData);
+ OUString url;
+ osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
+ if (e1 != osl::FileBase::E_None) {
+ std::cerr
+ << "Cannot convert \"" << arg << "\" to file URL, error code "
+ << +e1 << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ OUString cwd;
+ oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
+ if (e2 != osl_Process_E_None) {
+ std::cerr
+ << "Cannot obtain working directory, error code " << +e2
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ OUString abs;
+ e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
+ if (e1 != osl::FileBase::E_None) {
+ std::cerr
+ << "Cannot make \"" << url
+ << "\" into an absolute file URL, error code " << +e1 << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ return abs;
+}
+
+std::u16string_view decomposeType(
+ std::u16string_view type, std::size_t * rank,
+ std::vector<OUString> * typeArguments, bool * entity)
+{
+ assert(rank != nullptr);
+ assert(typeArguments != nullptr);
+ assert(entity != nullptr);
+ std::u16string_view nucl(type);
+ *rank = 0;
+ typeArguments->clear();
+ while (o3tl::starts_with(nucl, u"[]", &nucl)) {
+ ++*rank;
+ }
+ size_t i = nucl.find('<');
+ if (i != std::u16string_view::npos) {
+ std::u16string_view tmpl(nucl.substr(0, i));
+ do {
+ ++i; // skip '<' or ','
+ size_t j = i;
+ for (size_t level = 0; j != nucl.size(); ++j) {
+ sal_Unicode c = nucl[j];
+ if (c == ',') {
+ if (level == 0) {
+ break;
+ }
+ } else if (c == '<') {
+ ++level;
+ } else if (c == '>') {
+ if (level == 0) {
+ break;
+ }
+ --level;
+ }
+ }
+ if (j != nucl.size()) {
+ typeArguments->push_back(OUString(nucl.substr(i, j - i)));
+ }
+ i = j;
+ } while (i != nucl.size() && nucl[i] != '>');
+ assert(i == nucl.size() - 1 && nucl[i] == '>');
+ assert(!typeArguments->empty());
+ nucl = tmpl;
+ }
+ assert(!nucl.empty());
+ *entity = nucl != u"void" && nucl != u"boolean" && nucl != u"byte"
+ && nucl != u"short" && nucl != u"unsigned short" && nucl != u"long"
+ && nucl != u"unsigned long" && nucl != u"hyper"
+ && nucl != u"unsigned hyper" && nucl != u"float" && nucl != u"double"
+ && nucl != u"char" && nucl != u"string" && nucl != u"type"
+ && nucl != u"any";
+ assert(*entity || typeArguments->empty());
+ return nucl;
+}
+
+struct Entity {
+ enum class Sorted { NO, ACTIVE, YES };
+ enum class Written { NO, DECLARATION, DEFINITION };
+
+ explicit Entity(
+ rtl::Reference<unoidl::Entity> theEntity, bool theRelevant, Entity * theParent):
+ entity(std::move(theEntity)), relevant(theRelevant), sorted(Sorted::NO),
+ written(Written::NO), parent(theParent)
+ {}
+
+ rtl::Reference<unoidl::Entity> const entity;
+ std::set<OUString> dependencies;
+ std::set<OUString> interfaceDependencies;
+ bool relevant;
+ Sorted sorted;
+ Written written;
+ Entity * parent;
+};
+
+void insertEntityDependency(
+ rtl::Reference<unoidl::Manager> const & manager,
+ std::map<OUString, Entity>::iterator const & iterator,
+ OUString const & name, bool weakInterfaceDependency = false)
+{
+ assert(manager.is());
+ if (name == iterator->first)
+ return;
+
+ bool ifc = false;
+ if (weakInterfaceDependency) {
+ rtl::Reference<unoidl::Entity> ent(manager->findEntity(name));
+ if (!ent.is()) {
+ std::cerr << "Unknown entity " << name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ ifc = ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE;
+ }
+ (ifc
+ ? iterator->second.interfaceDependencies
+ : iterator->second.dependencies)
+ .insert(name);
+}
+
+void insertEntityDependencies(
+ rtl::Reference<unoidl::Manager> const & manager,
+ std::map<OUString, Entity>::iterator const & iterator,
+ std::vector<OUString> const & names)
+{
+ for (auto & i: names) {
+ insertEntityDependency(manager, iterator, i);
+ }
+}
+
+void insertEntityDependencies(
+ rtl::Reference<unoidl::Manager> const & manager,
+ std::map<OUString, Entity>::iterator const & iterator,
+ std::vector<unoidl::AnnotatedReference> const & references)
+{
+ for (auto & i: references) {
+ insertEntityDependency(manager, iterator, i.name);
+ }
+}
+
+void insertTypeDependency(
+ rtl::Reference<unoidl::Manager> const & manager,
+ std::map<OUString, Entity>::iterator const & iterator,
+ std::u16string_view type)
+{
+ std::size_t rank;
+ std::vector<OUString> args;
+ bool entity;
+ OUString nucl(decomposeType(type, &rank, &args, &entity));
+ if (entity) {
+ insertEntityDependency(manager, iterator, nucl, true);
+ for (const auto & i: args) {
+ insertTypeDependency(manager, iterator, i);
+ }
+ }
+}
+
+void scanMap(
+ rtl::Reference<unoidl::Manager> const & manager,
+ rtl::Reference<unoidl::MapCursor> const & cursor, bool modules, bool published,
+ std::u16string_view prefix, Entity * parent, std::map<OUString, Entity> & entities)
+{
+ assert(cursor.is());
+ for (;;) {
+ OUString id;
+ rtl::Reference<unoidl::Entity> ent(cursor->getNext(&id));
+ if (!ent.is()) {
+ break;
+ }
+ OUString name(prefix + id);
+ if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
+ Entity * p = nullptr;
+ if (modules) {
+ p = &entities.insert(std::make_pair(name, Entity(ent, !published, parent))).first
+ ->second;
+ }
+ scanMap(
+ manager,
+ static_cast<unoidl::ModuleEntity *>(ent.get())->createCursor(), modules,
+ published, OUStringConcatenation(name + "."), p, entities);
+ } else {
+ auto const pub = static_cast<unoidl::PublishableEntity *>(ent.get())->isPublished();
+ std::map<OUString, Entity>::iterator i(
+ entities.insert(
+ std::make_pair(
+ name,
+ Entity(
+ ent,
+ (!published
+ || pub),
+ parent)))
+ .first);
+ if (modules && published && pub) {
+ for (auto j = parent; j; j = j->parent) {
+ j->relevant = true;
+ }
+ }
+ switch (ent->getSort()) {
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ break;
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ {
+ rtl::Reference<unoidl::PlainStructTypeEntity> ent2(
+ static_cast<unoidl::PlainStructTypeEntity *>(
+ ent.get()));
+ if (!ent2->getDirectBase().isEmpty()) {
+ insertEntityDependency(
+ manager, i, ent2->getDirectBase());
+ }
+ for (auto & j: ent2->getDirectMembers()) {
+ insertTypeDependency(manager, i, j.type);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ {
+ rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
+ ent2(
+ static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
+ ent.get()));
+ for (auto & j: ent2->getMembers()) {
+ if (!j.parameterized) {
+ insertTypeDependency(manager, i, j.type);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ {
+ rtl::Reference<unoidl::ExceptionTypeEntity> ent2(
+ static_cast<unoidl::ExceptionTypeEntity *>(ent.get()));
+ if (!ent2->getDirectBase().isEmpty()) {
+ insertEntityDependency(
+ manager, i, ent2->getDirectBase());
+ }
+ for (auto & j: ent2->getDirectMembers()) {
+ insertTypeDependency(manager, i, j.type);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ {
+ rtl::Reference<unoidl::InterfaceTypeEntity> ent2(
+ static_cast<unoidl::InterfaceTypeEntity *>(
+ ent.get()));
+ insertEntityDependencies(
+ manager, i, ent2->getDirectMandatoryBases());
+ insertEntityDependencies(
+ manager, i, ent2->getDirectOptionalBases());
+ for (auto & j: ent2->getDirectAttributes()) {
+ insertTypeDependency(manager, i, j.type);
+ }
+ for (auto & j: ent2->getDirectMethods()) {
+ insertTypeDependency(manager, i, j.returnType);
+ for (auto & k: j.parameters) {
+ insertTypeDependency(manager, i, k.type);
+ }
+ insertEntityDependencies(manager, i, j.exceptions);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_TYPEDEF:
+ {
+ rtl::Reference<unoidl::TypedefEntity> ent2(
+ static_cast<unoidl::TypedefEntity *>(ent.get()));
+ insertTypeDependency(manager, i, ent2->getType());
+ break;
+ }
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ {
+ rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
+ ent2(
+ static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
+ ent.get()));
+ insertEntityDependency(manager, i, ent2->getBase());
+ for (auto & j: ent2->getConstructors()) {
+ for (auto & k: j.parameters) {
+ insertTypeDependency(manager, i, k.type);
+ }
+ insertEntityDependencies(manager, i, j.exceptions);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ {
+ rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2(
+ static_cast<unoidl::AccumulationBasedServiceEntity *>(
+ ent.get()));
+ insertEntityDependencies(
+ manager, i, ent2->getDirectMandatoryBaseServices());
+ insertEntityDependencies(
+ manager, i, ent2->getDirectOptionalBaseServices());
+ insertEntityDependencies(
+ manager, i, ent2->getDirectMandatoryBaseInterfaces());
+ insertEntityDependencies(
+ manager, i, ent2->getDirectOptionalBaseInterfaces());
+ for (auto & j: ent2->getDirectProperties()) {
+ insertTypeDependency(manager, i, j.type);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ {
+ rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2(
+ static_cast<unoidl::InterfaceBasedSingletonEntity *>(
+ ent.get()));
+ insertEntityDependency(manager, i, ent2->getBase());
+ break;
+ }
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ {
+ rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2(
+ static_cast<unoidl::ServiceBasedSingletonEntity *>(
+ ent.get()));
+ insertEntityDependency(manager, i, ent2->getBase());
+ break;
+ }
+ case unoidl::Entity::SORT_MODULE:
+ assert(false && "this cannot happen");
+ }
+ }
+ }
+}
+
+void propagateRelevant(std::map<OUString, Entity> & entities, Entity & entity) {
+ if (!entity.relevant) {
+ entity.relevant = true;
+ if (entity.sorted != Entity::Sorted::YES) {
+ for (auto & i: entity.dependencies) {
+ std::map<OUString, Entity>::iterator j(entities.find(i));
+ if (j != entities.end()) {
+ propagateRelevant(entities, j->second);
+ }
+ }
+ }
+ }
+}
+
+void visit(
+ std::map<OUString, Entity> & entities,
+ std::map<OUString, Entity>::iterator const & iterator,
+ std::vector<OUString> & result)
+{
+ switch (iterator->second.sorted) {
+ case Entity::Sorted::NO:
+ iterator->second.sorted = Entity::Sorted::ACTIVE;
+ for (auto & i: iterator->second.dependencies) {
+ std::map<OUString, Entity>::iterator j(entities.find(i));
+ if (j != entities.end()) {
+ if (iterator->second.relevant) {
+ propagateRelevant(entities, j->second);
+ }
+ visit(entities, j, result);
+ }
+ }
+ iterator->second.sorted = Entity::Sorted::YES;
+ result.push_back(iterator->first);
+ break;
+ case Entity::Sorted::ACTIVE:
+ std::cerr
+ << "Entity " << iterator->first << " recursively depends on itself"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ // fall-through avoids warnings
+ default:
+ break;
+ }
+}
+
+std::vector<OUString> sort(std::map<OUString, Entity> & entities) {
+ std::vector<OUString> res;
+ for (auto i(entities.begin()); i != entities.end(); ++i) {
+ visit(entities, i, res);
+ }
+ return res;
+}
+
+void indent(std::vector<OUString> const & modules, unsigned int extra = 0) {
+ for (std::vector<OUString>::size_type i = 0; i != modules.size(); ++i) {
+ std::cout << ' ';
+ }
+ for (unsigned int i = 0; i != extra; ++i) {
+ std::cout << ' ';
+ }
+}
+
+void closeModules(
+ std::vector<OUString> & modules, std::vector<OUString>::size_type n)
+{
+ for (std::vector<OUString>::size_type i = 0; i != n; ++i) {
+ assert(!modules.empty());
+ modules.pop_back();
+ indent(modules);
+ std::cout << "};\n";
+ }
+}
+
+OUString openModulesFor(std::vector<OUString> & modules, std::u16string_view name)
+{
+ std::vector<OUString>::iterator i(modules.begin());
+ for (sal_Int32 j = 0;;) {
+ OUString id(o3tl::getToken(name, 0, '.', j));
+ if (j == -1) {
+ closeModules(
+ modules,
+ static_cast< std::vector<OUString>::size_type >(
+ modules.end() - i));
+ indent(modules);
+ return id;
+ }
+ if (i != modules.end()) {
+ if (id == *i) {
+ ++i;
+ continue;
+ }
+ closeModules(
+ modules,
+ static_cast< std::vector<OUString>::size_type >(
+ modules.end() - i));
+ i = modules.end();
+ }
+ indent(modules);
+ std::cout << "module " << id << " {\n";
+ modules.push_back(id);
+ i = modules.end();
+ }
+}
+
+void writeName(OUString const & name) {
+ std::cout << "::" << name.replaceAll(".", "::");
+}
+
+void writeAnnotations(std::vector<OUString> const & annotations) {
+ if (!annotations.empty()) {
+ std::cout << "/**";
+ for (auto & i: annotations) {
+ //TODO: i.indexOf("*/") == -1
+ std::cout << " @" << i;
+ }
+ std::cout << " */ ";
+ }
+}
+
+void writePublished(rtl::Reference<unoidl::PublishableEntity> const & entity) {
+ assert(entity.is());
+ if (entity->isPublished()) {
+ std::cout << "published ";
+ }
+}
+
+void writeAnnotationsPublished(
+ rtl::Reference<unoidl::PublishableEntity> const & entity)
+{
+ assert(entity.is());
+ writeAnnotations(entity->getAnnotations());
+ writePublished(entity);
+}
+
+void writeType(std::u16string_view type) {
+ std::size_t rank;
+ std::vector<OUString> args;
+ bool entity;
+ OUString nucl(decomposeType(type, &rank, &args, &entity));
+ for (std::size_t i = 0; i != rank; ++i) {
+ std::cout << "sequence< ";
+ }
+ if (entity) {
+ writeName(nucl);
+ } else {
+ std::cout << nucl;
+ }
+ if (!args.empty()) {
+ std::cout << "< ";
+ for (auto i(args.begin()); i != args.end(); ++i) {
+ if (i != args.begin()) {
+ std::cout << ", ";
+ }
+ writeType(*i);
+ }
+ std::cout << " >";
+ }
+ for (std::size_t i = 0; i != rank; ++i) {
+ std::cout << " >";
+ }
+}
+
+void writeExceptionSpecification(std::vector<OUString> const & exceptions) {
+ if (!exceptions.empty()) {
+ std::cout << " raises (";
+ for (auto i(exceptions.begin()); i != exceptions.end(); ++i) {
+ if (i != exceptions.begin()) {
+ std::cout << ", ";
+ }
+ writeName(*i);
+ }
+ std::cout << ')';
+ }
+}
+
+void writeEntity(
+ std::map<OUString, Entity> & entities, std::vector<OUString> & modules,
+ OUString const & name)
+{
+ std::map<OUString, Entity>::iterator i(entities.find(name));
+ if (i == entities.end() || !i->second.relevant)
+ return;
+
+ assert(i->second.written != Entity::Written::DEFINITION);
+ i->second.written = Entity::Written::DEFINITION;
+ for (auto & j: i->second.interfaceDependencies) {
+ std::map<OUString, Entity>::iterator k(entities.find(j));
+ if (k != entities.end() && k->second.written == Entity::Written::NO) {
+ k->second.written = Entity::Written::DECLARATION;
+ OUString id(openModulesFor(modules, j));
+ if (k->second.entity->getSort()
+ != unoidl::Entity::SORT_INTERFACE_TYPE)
+ {
+ std::cerr
+ << "Entity " << j << " should be an interface type"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ writePublished(
+ static_cast<unoidl::PublishableEntity *>(
+ k->second.entity.get()));
+ std::cout << "interface " << id << ";\n";
+ }
+ }
+ OUString id(openModulesFor(modules, name));
+ rtl::Reference<unoidl::PublishableEntity> ent(
+ static_cast<unoidl::PublishableEntity *>(i->second.entity.get()));
+ switch (ent->getSort()) {
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ {
+ rtl::Reference<unoidl::EnumTypeEntity> ent2(
+ static_cast<unoidl::EnumTypeEntity *>(ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "enum " << id << " {\n";
+ for (auto j(ent2->getMembers().begin());
+ j != ent2->getMembers().end(); ++j)
+ {
+ indent(modules, 1);
+ writeAnnotations(j->annotations);
+ std::cout << j->name << " = " << j->value;
+ if (j + 1 != ent2->getMembers().end()) {
+ std::cout << ',';
+ }
+ std::cout << '\n';
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ {
+ rtl::Reference<unoidl::PlainStructTypeEntity> ent2(
+ static_cast<unoidl::PlainStructTypeEntity *>(ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "struct " << id;
+ if (!ent2->getDirectBase().isEmpty()) {
+ std::cout << ": ";
+ writeName(ent2->getDirectBase());
+ }
+ std::cout << " {\n";
+ for (auto & j: ent2->getDirectMembers()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ writeType(j.type);
+ std::cout << ' ' << j.name << ";\n";
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ {
+ rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
+ ent2(
+ static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
+ ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "struct " << id << '<';
+ for (auto j(ent2->getTypeParameters().begin());
+ j != ent2->getTypeParameters().end(); ++j)
+ {
+ if (j != ent2->getTypeParameters().begin()) {
+ std::cout << ", ";
+ }
+ std::cout << *j;
+ }
+ std::cout << "> {\n";
+ for (auto & j: ent2->getMembers()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ if (j.parameterized) {
+ std::cout << j.type;
+ } else {
+ writeType(j.type);
+ }
+ std::cout << ' ' << j.name << ";\n";
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ {
+ rtl::Reference<unoidl::ExceptionTypeEntity> ent2(
+ static_cast<unoidl::ExceptionTypeEntity *>(ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "exception " << id;
+ if (!ent2->getDirectBase().isEmpty()) {
+ std::cout << ": ";
+ writeName(ent2->getDirectBase());
+ }
+ std::cout << " {\n";
+ for (auto & j: ent2->getDirectMembers()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ writeType(j.type);
+ std::cout << ' ' << j.name << ";\n";
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ {
+ rtl::Reference<unoidl::InterfaceTypeEntity> ent2(
+ static_cast<unoidl::InterfaceTypeEntity *>(
+ ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "interface " << id << " {\n";
+ for (auto & j: ent2->getDirectMandatoryBases()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "interface ";
+ writeName(j.name);
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectOptionalBases()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "[optional] interface ";
+ writeName(j.name);
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectAttributes()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "[attribute";
+ if (j.bound) {
+ std::cout << ", bound";
+ }
+ if (j.readOnly) {
+ std::cout << ", readonly";
+ }
+ std::cout << "] ";
+ writeType(j.type);
+ std::cout << ' ' << j.name;
+ if (!(j.getExceptions.empty() && j.setExceptions.empty())) {
+ std::cout << " {\n";
+ if (!j.getExceptions.empty()) {
+ indent(modules, 2);
+ std::cout << "get";
+ writeExceptionSpecification(j.getExceptions);
+ std::cout << ";\n";
+ }
+ if (!j.setExceptions.empty()) {
+ indent(modules, 2);
+ std::cout << "set";
+ writeExceptionSpecification(j.setExceptions);
+ std::cout << ";\n";
+ }
+ std::cout << " }";
+ }
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectMethods()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ writeType(j.returnType);
+ std::cout << ' ' << j.name << '(';
+ for (auto k(j.parameters.begin()); k != j.parameters.end();
+ ++k)
+ {
+ if (k != j.parameters.begin()) {
+ std::cout << ", ";
+ }
+ switch (k->direction) {
+ case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN:
+ std::cout << "[in] ";
+ break;
+ case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT:
+ std::cout << "[out] ";
+ break;
+ case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT:
+ std::cout << "[inout] ";
+ break;
+ }
+ writeType(k->type);
+ std::cout << ' ' << k->name;
+ }
+ std::cout << ')';
+ writeExceptionSpecification(j.exceptions);
+ std::cout << ";\n";
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_TYPEDEF:
+ {
+ rtl::Reference<unoidl::TypedefEntity> ent2(
+ static_cast<unoidl::TypedefEntity *>(ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "typedef ";
+ writeType(ent2->getType());
+ std::cout << ' ' << id << ";\n";
+ break;
+ }
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ {
+ rtl::Reference<unoidl::ConstantGroupEntity> ent2(
+ static_cast<unoidl::ConstantGroupEntity *>(ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "constants " << id << " {\n";
+ for (auto & j: ent2->getMembers()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "const ";
+ switch (j.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ std::cout << "boolean";
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ std::cout << "byte";
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ std::cout << "short";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ std::cout << "unsigned short";
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ std::cout << "long";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ std::cout << "unsigned long";
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ std::cout << "hyper";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ std::cout << "unsigned hyper";
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ std::cout << "float";
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ std::cout << "double";
+ break;
+ }
+ std::cout << ' ' << j.name << " = ";
+ switch (j.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ std::cout << (j.value.booleanValue ? "TRUE" : "FALSE");
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ std::cout << int(j.value.byteValue);
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ std::cout << j.value.shortValue;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ std::cout << j.value.unsignedShortValue;
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ std::cout << j.value.longValue;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ std::cout << j.value.unsignedLongValue;
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ std::cout << j.value.hyperValue;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ std::cout << j.value.unsignedHyperValue;
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ std::cout << j.value.floatValue;
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ std::cout << j.value.doubleValue;
+ break;
+ }
+ std::cout << ";\n";
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ {
+ rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity> ent2(
+ static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
+ ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "service " << id << ": ";
+ writeName(ent2->getBase());
+ if (ent2->getConstructors().size() != 1
+ || !ent2->getConstructors().front().defaultConstructor)
+ {
+ std::cout << " {\n";
+ for (auto & j: ent2->getConstructors()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << j.name << '(';
+ for (auto k(j.parameters.begin());
+ k != j.parameters.end(); ++k)
+ {
+ if (k != j.parameters.begin()) {
+ std::cout << ", ";
+ }
+ std::cout << "[in] ";
+ writeType(k->type);
+ if (k->rest) {
+ std::cout << "...";
+ }
+ std::cout << ' ' << k->name;
+ }
+ std::cout << ')';
+ writeExceptionSpecification(j.exceptions);
+ std::cout << ";\n";
+ }
+ indent(modules);
+ std::cout << '}';
+ }
+ std::cout << ";\n";
+ break;
+ }
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ {
+ rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2(
+ static_cast<unoidl::AccumulationBasedServiceEntity *>(
+ ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "service " << id << " {\n";
+ for (auto & j: ent2->getDirectMandatoryBaseServices()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "service ";
+ writeName(j.name);
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectOptionalBaseServices()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "[optional] service ";
+ writeName(j.name);
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectMandatoryBaseInterfaces()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "interface ";
+ writeName(j.name);
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectOptionalBaseInterfaces()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "[optional] interface ";
+ writeName(j.name);
+ std::cout << ";\n";
+ }
+ for (auto & j: ent2->getDirectProperties()) {
+ indent(modules, 1);
+ writeAnnotations(j.annotations);
+ std::cout << "[property";
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_BOUND)
+ != 0)
+ {
+ std::cout << ", bound";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_CONSTRAINED)
+ != 0)
+ {
+ std::cout << ", constrained";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_AMBIGUOUS)
+ != 0)
+ {
+ std::cout << ", maybeambiguous";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_DEFAULT)
+ != 0)
+ {
+ std::cout << ", maybedefault";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_VOID)
+ != 0)
+ {
+ std::cout << ", maybevoid";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL)
+ != 0)
+ {
+ std::cout << ", optional";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_READ_ONLY)
+ != 0)
+ {
+ std::cout << ", readonly";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_REMOVABLE)
+ != 0)
+ {
+ std::cout << ", removable";
+ }
+ if ((j.attributes
+ & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_TRANSIENT)
+ != 0)
+ {
+ std::cout << ", transient";
+ }
+ std::cout << "] ";
+ writeType(j.type);
+ std::cout << ' ' << j.name << ";\n";
+ }
+ indent(modules);
+ std::cout << "};\n";
+ break;
+ }
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ {
+ rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2(
+ static_cast<unoidl::InterfaceBasedSingletonEntity *>(
+ ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "singleton " << id << ": ";
+ writeName(ent2->getBase());
+ std::cout << ";\n";
+ break;
+ }
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ {
+ rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2(
+ static_cast<unoidl::ServiceBasedSingletonEntity *>(
+ ent.get()));
+ writeAnnotationsPublished(ent);
+ std::cout << "singleton " << id << " { service ";
+ writeName(ent2->getBase());
+ std::cout << "; };";
+ break;
+ }
+ case unoidl::Entity::SORT_MODULE:
+ assert(false && "this cannot happen");
+ }
+}
+
+void writeSummary(OUString const & name, Entity const & entity) {
+ if (!entity.relevant) {
+ return;
+ }
+ switch (entity.entity->getSort()) {
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ std::cout << "enum";
+ break;
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ std::cout << "struct";
+ break;
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ std::cout << "exception";
+ break;
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ std::cout << "interface";
+ break;
+ case unoidl::Entity::SORT_TYPEDEF:
+ std::cout << "typedef";
+ break;
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ std::cout << "constants";
+ break;
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ std::cout << "service";
+ break;
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ std::cout << "singleton";
+ break;
+ case unoidl::Entity::SORT_MODULE:
+ std::cout << "module";
+ break;
+ }
+ std::cout << ' ' << name << '\n';
+}
+
+}
+
+SAL_IMPLEMENT_MAIN() {
+ try {
+ sal_uInt32 args = rtl_getAppCommandArgCount();
+ sal_uInt32 i = 0;
+ bool published = false;
+ bool summary = false;
+ for (;; ++i) {
+ if (i == args) {
+ badUsage();
+ }
+ OUString arg;
+ rtl_getAppCommandArg(i, &arg.pData);
+ if (arg == "--published") {
+ if (published) {
+ badUsage();
+ }
+ published = true;
+ } else if (arg == "--summary") {
+ if (summary) {
+ badUsage();
+ }
+ summary = true;
+ } else {
+ break;
+ }
+ }
+ rtl::Reference<unoidl::Manager> mgr(new unoidl::Manager);
+ rtl::Reference<unoidl::Provider> prov;
+ for (; i != args; ++i) {
+ OUString uri(getArgumentUri(i));
+ try {
+ prov = mgr->addProvider(uri);
+ } catch (unoidl::NoSuchFileException &) {
+ std::cerr
+ << "Input <" << uri << "> does not exist" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ std::map<OUString, Entity> ents;
+ scanMap(mgr, prov->createRootCursor(), summary, published, u"", nullptr, ents);
+ if (summary) {
+ for (auto const & j: ents) {
+ writeSummary(j.first, j.second);
+ }
+ } else {
+ std::vector<OUString> sorted(sort(ents));
+ std::vector<OUString> mods;
+ for (const auto & j: sorted) {
+ writeEntity(ents, mods, j);
+ }
+ closeModules(mods, mods.size());
+ }
+ return EXIT_SUCCESS;
+ } catch (unoidl::FileFormatException & e1) {
+ std::cerr
+ << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ } catch (std::exception & e1) {
+ std::cerr << "Failure: " << e1.what() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */