/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { [[noreturn]] void badUsage() { std::cerr << "Usage:" << std::endl << std::endl << " unoidl-read [--published] [--summary] [] " << std::endl << std::endl << ("where each 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 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 * 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 theEntity, bool theRelevant, Entity * theParent): entity(std::move(theEntity)), relevant(theRelevant), sorted(Sorted::NO), written(Written::NO), parent(theParent) {} rtl::Reference const entity; std::set dependencies; std::set interfaceDependencies; bool relevant; Sorted sorted; Written written; Entity * parent; }; void insertEntityDependency( rtl::Reference const & manager, std::map::iterator const & iterator, OUString const & name, bool weakInterfaceDependency = false) { assert(manager.is()); if (name == iterator->first) return; bool ifc = false; if (weakInterfaceDependency) { rtl::Reference 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 const & manager, std::map::iterator const & iterator, std::vector const & names) { for (auto & i: names) { insertEntityDependency(manager, iterator, i); } } void insertEntityDependencies( rtl::Reference const & manager, std::map::iterator const & iterator, std::vector const & references) { for (auto & i: references) { insertEntityDependency(manager, iterator, i.name); } } void insertTypeDependency( rtl::Reference const & manager, std::map::iterator const & iterator, std::u16string_view type) { std::size_t rank; std::vector 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 const & manager, rtl::Reference const & cursor, bool modules, bool published, std::u16string_view prefix, Entity * parent, std::map & entities) { assert(cursor.is()); for (;;) { OUString id; rtl::Reference 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(ent.get())->createCursor(), modules, published, Concat2View(name + "."), p, entities); } else { auto const pub = static_cast(ent.get())->isPublished(); std::map::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 ent2( static_cast( 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 ent2( static_cast( ent.get())); for (auto & j: ent2->getMembers()) { if (!j.parameterized) { insertTypeDependency(manager, i, j.type); } } break; } case unoidl::Entity::SORT_EXCEPTION_TYPE: { rtl::Reference ent2( static_cast(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 ent2( static_cast( 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 ent2( static_cast(ent.get())); insertTypeDependency(manager, i, ent2->getType()); break; } case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE: { rtl::Reference ent2( static_cast( 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 ent2( static_cast( 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 ent2( static_cast( ent.get())); insertEntityDependency(manager, i, ent2->getBase()); break; } case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON: { rtl::Reference ent2( static_cast( ent.get())); insertEntityDependency(manager, i, ent2->getBase()); break; } case unoidl::Entity::SORT_MODULE: assert(false && "this cannot happen"); } } } } void propagateRelevant(std::map & entities, Entity & entity) { if (!entity.relevant) { entity.relevant = true; if (entity.sorted != Entity::Sorted::YES) { for (auto & i: entity.dependencies) { std::map::iterator j(entities.find(i)); if (j != entities.end()) { propagateRelevant(entities, j->second); } } } } } void visit( std::map & entities, std::map::iterator const & iterator, std::vector & result) { switch (iterator->second.sorted) { case Entity::Sorted::NO: iterator->second.sorted = Entity::Sorted::ACTIVE; for (auto & i: iterator->second.dependencies) { std::map::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 sort(std::map & entities) { std::vector res; for (auto i(entities.begin()); i != entities.end(); ++i) { visit(entities, i, res); } return res; } void indent(std::vector const & modules, unsigned int extra = 0) { for (std::vector::size_type i = 0; i != modules.size(); ++i) { std::cout << ' '; } for (unsigned int i = 0; i != extra; ++i) { std::cout << ' '; } } void closeModules( std::vector & modules, std::vector::size_type n) { for (std::vector::size_type i = 0; i != n; ++i) { assert(!modules.empty()); modules.pop_back(); indent(modules); std::cout << "};\n"; } } OUString openModulesFor(std::vector & modules, std::u16string_view name) { std::vector::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::size_type >( modules.end() - i)); indent(modules); return id; } if (i != modules.end()) { if (id == *i) { ++i; continue; } closeModules( modules, static_cast< std::vector::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 const & annotations) { if (!annotations.empty()) { std::cout << "/**"; for (auto & i: annotations) { //TODO: i.indexOf("*/") == -1 std::cout << " @" << i; } std::cout << " */ "; } } void writePublished(rtl::Reference const & entity) { assert(entity.is()); if (entity->isPublished()) { std::cout << "published "; } } void writeAnnotationsPublished( rtl::Reference const & entity) { assert(entity.is()); writeAnnotations(entity->getAnnotations()); writePublished(entity); } void writeType(std::u16string_view type) { std::size_t rank; std::vector 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 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 & entities, std::vector & modules, OUString const & name) { std::map::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::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( k->second.entity.get())); std::cout << "interface " << id << ";\n"; } } OUString id(openModulesFor(modules, name)); rtl::Reference ent( static_cast(i->second.entity.get())); switch (ent->getSort()) { case unoidl::Entity::SORT_ENUM_TYPE: { rtl::Reference ent2( static_cast(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 ent2( static_cast(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 ent2( static_cast( 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 ent2( static_cast(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 ent2( static_cast( 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 ent2( static_cast(ent.get())); writeAnnotationsPublished(ent); std::cout << "typedef "; writeType(ent2->getType()); std::cout << ' ' << id << ";\n"; break; } case unoidl::Entity::SORT_CONSTANT_GROUP: { rtl::Reference ent2( static_cast(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 ent2( static_cast( 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 ent2( static_cast( 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 ent2( static_cast( ent.get())); writeAnnotationsPublished(ent); std::cout << "singleton " << id << ": "; writeName(ent2->getBase()); std::cout << ";\n"; break; } case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON: { rtl::Reference ent2( static_cast( 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 mgr(new unoidl::Manager); rtl::Reference 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 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 sorted(sort(ents)); std::vector 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: */