diff options
Diffstat (limited to 'unoidl/source/unoidl-read.cxx')
-rw-r--r-- | unoidl/source/unoidl-read.cxx | 1139 |
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 0000000000..721fdabe9c --- /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, Concat2View(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: */ |