21#include <osl/file.hxx>
22#include <osl/process.h>
23#include <rtl/process.h>
25#include <rtl/ustring.hxx>
35 <<
"Usage:" << std::endl << std::endl
36 <<
" unoidl-read [--published] [--summary] [<extra registries>] <registry>"
37 << std::endl << std::endl
38 << (
"where each <registry> is either a new- or legacy-format .rdb file,"
41 << (
"file, or a root directory of an .idl file tree. The complete"
44 << (
"last <registry> is written to stdout; if --published is specified,"
47 << (
"published entities (plus any non-published entities referenced"
50 <<
"via any unpublished optional bases) are written out. If --summary is specified,"
52 <<
"only a short summary is written, with the type and name of one entity per line."
54 std::exit(EXIT_FAILURE);
57OUString getArgumentUri(sal_uInt32 argument) {
59 rtl_getAppCommandArg(argument, &arg.pData);
61 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
62 if (e1 != osl::FileBase::E_None) {
64 <<
"Cannot convert \"" << arg <<
"\" to file URL, error code "
66 std::exit(EXIT_FAILURE);
69 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
70 if (e2 != osl_Process_E_None) {
72 <<
"Cannot obtain working directory, error code " << +e2
74 std::exit(EXIT_FAILURE);
77 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
78 if (e1 != osl::FileBase::E_None) {
80 <<
"Cannot make \"" << url
81 <<
"\" into an absolute file URL, error code " << +e1 << std::endl;
82 std::exit(EXIT_FAILURE);
87std::u16string_view decomposeType(
88 std::u16string_view type, std::size_t * rank,
89 std::vector<OUString> * typeArguments,
bool * entity)
91 assert(rank !=
nullptr);
92 assert(typeArguments !=
nullptr);
93 assert(entity !=
nullptr);
94 std::u16string_view nucl(type);
96 typeArguments->clear();
100 size_t i = nucl.find(
'<');
101 if (i != std::u16string_view::npos) {
102 std::u16string_view tmpl(nucl.substr(0, i));
106 for (
size_t level = 0; j != nucl.size(); ++j) {
112 }
else if (c ==
'<') {
114 }
else if (c ==
'>') {
121 if (j != nucl.size()) {
122 typeArguments->push_back(OUString(nucl.substr(i, j - i)));
125 }
while (i != nucl.size() && nucl[i] !=
'>');
126 assert(i == nucl.size() - 1 && nucl[i] ==
'>');
127 assert(!typeArguments->empty());
130 assert(!nucl.empty());
131 *entity = nucl !=
u"void" && nucl !=
u"boolean" && nucl !=
u"byte"
132 && nucl !=
u"short" && nucl !=
u"unsigned short" && nucl !=
u"long"
133 && nucl !=
u"unsigned long" && nucl !=
u"hyper"
134 && nucl !=
u"unsigned hyper" && nucl !=
u"float" && nucl !=
u"double"
135 && nucl !=
u"char" && nucl !=
u"string" && nucl !=
u"type"
137 assert(*entity || typeArguments->empty());
143 enum class Written {
NO, DECLARATION, DEFINITION };
147 entity(
std::move(theEntity)), relevant(theRelevant), sorted(Sorted::
NO),
148 written(Written::
NO), parent(theParent)
152 std::set<OUString> dependencies;
153 std::set<OUString> interfaceDependencies;
160void insertEntityDependency(
162 std::map<OUString, Entity>::iterator
const & iterator,
163 OUString
const & name,
bool weakInterfaceDependency =
false)
166 if (name == iterator->first)
170 if (weakInterfaceDependency) {
173 std::cerr <<
"Unknown entity " <<
name << std::endl;
174 std::exit(EXIT_FAILURE);
179 ? iterator->second.interfaceDependencies
180 : iterator->second.dependencies)
184void insertEntityDependencies(
186 std::map<OUString, Entity>::iterator
const & iterator,
187 std::vector<OUString>
const & names)
189 for (
auto & i: names) {
190 insertEntityDependency(manager, iterator, i);
194void insertEntityDependencies(
196 std::map<OUString, Entity>::iterator
const & iterator,
197 std::vector<unoidl::AnnotatedReference>
const & references)
199 for (
auto & i: references) {
200 insertEntityDependency(manager, iterator,
i.name);
204void insertTypeDependency(
206 std::map<OUString, Entity>::iterator
const & iterator,
207 std::u16string_view type)
210 std::vector<OUString>
args;
212 OUString nucl(decomposeType(type, &rank, &args, &entity));
214 insertEntityDependency(manager, iterator, nucl,
true);
215 for (
const auto & i: args) {
216 insertTypeDependency(manager, iterator, i);
224 std::u16string_view prefix, Entity * parent, std::map<OUString, Entity> & entities)
233 OUString
name(prefix +
id);
235 Entity *
p =
nullptr;
237 p = &entities.insert(std::make_pair(name, Entity(ent, !published, parent))).first
243 published, Concat2View(name +
"."), p, entities);
246 std::map<OUString, Entity>::iterator
i(
256 if (modules && published && pub) {
257 for (
auto j = parent; j; j = j->parent) {
261 switch (ent->getSort()) {
270 if (!ent2->getDirectBase().isEmpty()) {
271 insertEntityDependency(
272 manager, i, ent2->getDirectBase());
274 for (
auto & j: ent2->getDirectMembers()) {
275 insertTypeDependency(manager, i, j.type);
285 for (
auto & j: ent2->getMembers()) {
286 if (!j.parameterized) {
287 insertTypeDependency(manager, i, j.type);
296 if (!ent2->getDirectBase().isEmpty()) {
297 insertEntityDependency(
298 manager, i, ent2->getDirectBase());
300 for (
auto & j: ent2->getDirectMembers()) {
301 insertTypeDependency(manager, i, j.type);
310 insertEntityDependencies(
311 manager, i, ent2->getDirectMandatoryBases());
312 insertEntityDependencies(
313 manager, i, ent2->getDirectOptionalBases());
314 for (
auto & j: ent2->getDirectAttributes()) {
315 insertTypeDependency(manager, i, j.type);
317 for (
auto & j: ent2->getDirectMethods()) {
318 insertTypeDependency(manager, i, j.returnType);
319 for (
auto & k: j.parameters) {
320 insertTypeDependency(manager, i, k.type);
322 insertEntityDependencies(manager, i, j.exceptions);
330 insertTypeDependency(manager, i, ent2->getType());
339 insertEntityDependency(manager, i, ent2->getBase());
340 for (
auto & j: ent2->getConstructors()) {
341 for (
auto & k: j.parameters) {
342 insertTypeDependency(manager, i, k.type);
344 insertEntityDependencies(manager, i, j.exceptions);
353 insertEntityDependencies(
354 manager, i, ent2->getDirectMandatoryBaseServices());
355 insertEntityDependencies(
356 manager, i, ent2->getDirectOptionalBaseServices());
357 insertEntityDependencies(
358 manager, i, ent2->getDirectMandatoryBaseInterfaces());
359 insertEntityDependencies(
360 manager, i, ent2->getDirectOptionalBaseInterfaces());
361 for (
auto & j: ent2->getDirectProperties()) {
362 insertTypeDependency(manager, i, j.type);
371 insertEntityDependency(manager, i, ent2->getBase());
379 insertEntityDependency(manager, i, ent2->getBase());
383 assert(
false &&
"this cannot happen");
389void propagateRelevant(std::map<OUString, Entity> & entities, Entity & entity) {
390 if (!entity.relevant) {
391 entity.relevant =
true;
392 if (entity.sorted != Entity::Sorted::YES) {
393 for (
auto & i: entity.dependencies) {
394 std::map<OUString, Entity>::iterator j(entities.find(i));
395 if (j != entities.end()) {
396 propagateRelevant(entities, j->second);
404 std::map<OUString, Entity> & entities,
405 std::map<OUString, Entity>::iterator
const & iterator,
406 std::vector<OUString> & result)
408 switch (iterator->second.sorted) {
409 case Entity::Sorted::NO:
410 iterator->second.sorted = Entity::Sorted::ACTIVE;
411 for (
auto & i: iterator->second.dependencies) {
412 std::map<OUString, Entity>::iterator j(entities.find(i));
413 if (j != entities.end()) {
414 if (iterator->second.relevant) {
415 propagateRelevant(entities, j->second);
417 visit(entities, j, result);
420 iterator->second.sorted = Entity::Sorted::YES;
421 result.push_back(iterator->first);
423 case Entity::Sorted::ACTIVE:
425 <<
"Entity " << iterator->first <<
" recursively depends on itself"
427 std::exit(EXIT_FAILURE);
434std::vector<OUString> sort(std::map<OUString, Entity> & entities) {
435 std::vector<OUString> res;
436 for (
auto i(entities.begin()); i != entities.end(); ++i) {
437 visit(entities, i, res);
442void indent(std::vector<OUString>
const & modules,
unsigned int extra = 0) {
443 for (std::vector<OUString>::size_type i = 0;
i != modules.size(); ++
i) {
446 for (
unsigned int i = 0;
i != extra; ++
i) {
452 std::vector<OUString> & modules, std::vector<OUString>::size_type n)
454 for (std::vector<OUString>::size_type i = 0;
i !=
n; ++
i) {
455 assert(!modules.empty());
462OUString openModulesFor(std::vector<OUString> & modules, std::u16string_view name)
464 std::vector<OUString>::iterator
i(modules.begin());
465 for (sal_Int32 j = 0;;) {
470 static_cast< std::vector<OUString>::size_type
>(
475 if (i != modules.end()) {
482 static_cast< std::vector<OUString>::size_type
>(
487 std::cout <<
"module " <<
id <<
" {\n";
488 modules.push_back(
id);
493void writeName(OUString
const & name) {
494 std::cout <<
"::" <<
name.replaceAll(
".",
"::");
497void writeAnnotations(std::vector<OUString>
const & annotations) {
498 if (!annotations.empty()) {
500 for (
auto & i: annotations) {
502 std::cout <<
" @" <<
i;
510 if (entity->isPublished()) {
511 std::cout <<
"published ";
515void writeAnnotationsPublished(
519 writeAnnotations(entity->getAnnotations());
520 writePublished(entity);
523void writeType(std::u16string_view type) {
525 std::vector<OUString>
args;
527 OUString nucl(decomposeType(type, &rank, &args, &entity));
528 for (std::size_t i = 0;
i != rank; ++
i) {
529 std::cout <<
"sequence< ";
538 for (
auto i(
args.begin()); i !=
args.end(); ++i) {
539 if (i !=
args.begin()) {
546 for (std::size_t i = 0;
i != rank; ++
i) {
551void writeExceptionSpecification(std::vector<OUString>
const & exceptions) {
552 if (!exceptions.empty()) {
553 std::cout <<
" raises (";
554 for (
auto i(exceptions.begin()); i != exceptions.end(); ++i) {
555 if (i != exceptions.begin()) {
565 std::map<OUString, Entity> & entities, std::vector<OUString> & modules,
566 OUString
const & name)
568 std::map<OUString, Entity>::iterator
i(entities.find(name));
569 if (i == entities.end() || !
i->second.relevant)
572 assert(
i->second.written != Entity::Written::DEFINITION);
573 i->second.written = Entity::Written::DEFINITION;
574 for (
auto & j:
i->second.interfaceDependencies) {
575 std::map<OUString, Entity>::iterator k(entities.find(j));
576 if (k != entities.end() && k->second.written == Entity::Written::NO) {
577 k->second.written = Entity::Written::DECLARATION;
578 OUString id(openModulesFor(modules, j));
579 if (k->second.entity->getSort()
583 <<
"Entity " << j <<
" should be an interface type"
585 std::exit(EXIT_FAILURE);
589 k->second.entity.get()));
590 std::cout <<
"interface " <<
id <<
";\n";
593 OUString id(openModulesFor(modules, name));
596 switch (ent->getSort()) {
601 writeAnnotationsPublished(ent);
602 std::cout <<
"enum " <<
id <<
" {\n";
603 for (
auto j(ent2->getMembers().begin());
604 j != ent2->getMembers().end(); ++j)
607 writeAnnotations(j->annotations);
608 std::cout << j->name <<
" = " << j->value;
609 if (j + 1 != ent2->getMembers().end()) {
622 writeAnnotationsPublished(ent);
623 std::cout <<
"struct " << id;
624 if (!ent2->getDirectBase().isEmpty()) {
626 writeName(ent2->getDirectBase());
629 for (
auto & j: ent2->getDirectMembers()) {
631 writeAnnotations(j.annotations);
633 std::cout <<
' ' << j.name <<
";\n";
645 writeAnnotationsPublished(ent);
646 std::cout <<
"struct " <<
id <<
'<';
647 for (
auto j(ent2->getTypeParameters().begin());
648 j != ent2->getTypeParameters().end(); ++j)
650 if (j != ent2->getTypeParameters().begin()) {
655 std::cout <<
"> {\n";
656 for (
auto & j: ent2->getMembers()) {
658 writeAnnotations(j.annotations);
659 if (j.parameterized) {
664 std::cout <<
' ' << j.name <<
";\n";
674 writeAnnotationsPublished(ent);
675 std::cout <<
"exception " << id;
676 if (!ent2->getDirectBase().isEmpty()) {
678 writeName(ent2->getDirectBase());
681 for (
auto & j: ent2->getDirectMembers()) {
683 writeAnnotations(j.annotations);
685 std::cout <<
' ' << j.name <<
";\n";
696 writeAnnotationsPublished(ent);
697 std::cout <<
"interface " <<
id <<
" {\n";
698 for (
auto & j: ent2->getDirectMandatoryBases()) {
700 writeAnnotations(j.annotations);
701 std::cout <<
"interface ";
705 for (
auto & j: ent2->getDirectOptionalBases()) {
707 writeAnnotations(j.annotations);
708 std::cout <<
"[optional] interface ";
712 for (
auto & j: ent2->getDirectAttributes()) {
714 writeAnnotations(j.annotations);
715 std::cout <<
"[attribute";
717 std::cout <<
", bound";
720 std::cout <<
", readonly";
724 std::cout <<
' ' << j.name;
725 if (!(j.getExceptions.empty() && j.setExceptions.empty())) {
727 if (!j.getExceptions.empty()) {
730 writeExceptionSpecification(j.getExceptions);
733 if (!j.setExceptions.empty()) {
736 writeExceptionSpecification(j.setExceptions);
743 for (
auto & j: ent2->getDirectMethods()) {
745 writeAnnotations(j.annotations);
746 writeType(j.returnType);
747 std::cout <<
' ' << j.name <<
'(';
748 for (
auto k(j.parameters.begin()); k != j.parameters.end();
751 if (k != j.parameters.begin()) {
754 switch (k->direction) {
756 std::cout <<
"[in] ";
759 std::cout <<
"[out] ";
762 std::cout <<
"[inout] ";
766 std::cout <<
' ' << k->name;
769 writeExceptionSpecification(j.exceptions);
780 writeAnnotationsPublished(ent);
781 std::cout <<
"typedef ";
782 writeType(ent2->getType());
783 std::cout <<
' ' <<
id <<
";\n";
790 writeAnnotationsPublished(ent);
791 std::cout <<
"constants " <<
id <<
" {\n";
792 for (
auto & j: ent2->getMembers()) {
794 writeAnnotations(j.annotations);
795 std::cout <<
"const ";
796 switch (j.value.type) {
798 std::cout <<
"boolean";
804 std::cout <<
"short";
807 std::cout <<
"unsigned short";
813 std::cout <<
"unsigned long";
816 std::cout <<
"hyper";
819 std::cout <<
"unsigned hyper";
822 std::cout <<
"float";
825 std::cout <<
"double";
828 std::cout <<
' ' << j.name <<
" = ";
829 switch (j.value.type) {
831 std::cout << (j.value.booleanValue ?
"TRUE" :
"FALSE");
834 std::cout <<
int(j.value.byteValue);
837 std::cout << j.value.shortValue;
840 std::cout << j.value.unsignedShortValue;
843 std::cout << j.value.longValue;
846 std::cout << j.value.unsignedLongValue;
849 std::cout << j.value.hyperValue;
852 std::cout << j.value.unsignedHyperValue;
855 std::cout << j.value.floatValue;
858 std::cout << j.value.doubleValue;
872 writeAnnotationsPublished(ent);
873 std::cout <<
"service " <<
id <<
": ";
874 writeName(ent2->getBase());
875 if (ent2->getConstructors().size() != 1
876 || !ent2->getConstructors().front().defaultConstructor)
879 for (
auto & j: ent2->getConstructors()) {
881 writeAnnotations(j.annotations);
882 std::cout << j.name <<
'(';
883 for (
auto k(j.parameters.begin());
884 k != j.parameters.end(); ++k)
886 if (k != j.parameters.begin()) {
889 std::cout <<
"[in] ";
894 std::cout <<
' ' << k->name;
897 writeExceptionSpecification(j.exceptions);
911 writeAnnotationsPublished(ent);
912 std::cout <<
"service " <<
id <<
" {\n";
913 for (
auto & j: ent2->getDirectMandatoryBaseServices()) {
915 writeAnnotations(j.annotations);
916 std::cout <<
"service ";
920 for (
auto & j: ent2->getDirectOptionalBaseServices()) {
922 writeAnnotations(j.annotations);
923 std::cout <<
"[optional] service ";
927 for (
auto & j: ent2->getDirectMandatoryBaseInterfaces()) {
929 writeAnnotations(j.annotations);
930 std::cout <<
"interface ";
934 for (
auto & j: ent2->getDirectOptionalBaseInterfaces()) {
936 writeAnnotations(j.annotations);
937 std::cout <<
"[optional] interface ";
941 for (
auto & j: ent2->getDirectProperties()) {
943 writeAnnotations(j.annotations);
944 std::cout <<
"[property";
949 std::cout <<
", bound";
955 std::cout <<
", constrained";
961 std::cout <<
", maybeambiguous";
967 std::cout <<
", maybedefault";
973 std::cout <<
", maybevoid";
979 std::cout <<
", optional";
985 std::cout <<
", readonly";
991 std::cout <<
", removable";
997 std::cout <<
", transient";
1001 std::cout <<
' ' << j.name <<
";\n";
1004 std::cout <<
"};\n";
1012 writeAnnotationsPublished(ent);
1013 std::cout <<
"singleton " <<
id <<
": ";
1014 writeName(ent2->getBase());
1023 writeAnnotationsPublished(ent);
1024 std::cout <<
"singleton " <<
id <<
" { service ";
1025 writeName(ent2->getBase());
1026 std::cout <<
"; };";
1030 assert(
false &&
"this cannot happen");
1034void writeSummary(OUString
const & name, Entity
const & entity) {
1035 if (!entity.relevant) {
1038 switch (entity.entity->getSort()) {
1040 std::cout <<
"enum";
1044 std::cout <<
"struct";
1047 std::cout <<
"exception";
1050 std::cout <<
"interface";
1053 std::cout <<
"typedef";
1056 std::cout <<
"constants";
1060 std::cout <<
"service";
1064 std::cout <<
"singleton";
1067 std::cout <<
"module";
1070 std::cout <<
' ' <<
name <<
'\n';
1077 sal_uInt32
args = rtl_getAppCommandArgCount();
1079 bool published =
false;
1080 bool summary =
false;
1086 rtl_getAppCommandArg(
i, &arg.pData);
1087 if (arg ==
"--published") {
1092 }
else if (arg ==
"--summary") {
1104 OUString uri(getArgumentUri(
i));
1106 prov = mgr->addProvider(uri);
1109 <<
"Input <" << uri <<
"> does not exist" << std::endl;
1110 std::exit(EXIT_FAILURE);
1113 std::map<OUString, Entity> ents;
1114 scanMap(mgr, prov->createRootCursor(), summary, published,
u"",
nullptr, ents);
1116 for (
auto const & j: ents) {
1117 writeSummary(j.first, j.second);
1120 std::vector<OUString> sorted(sort(ents));
1121 std::vector<OUString> mods;
1122 for (
const auto & j: sorted) {
1123 writeEntity(ents, mods, j);
1125 closeModules(mods, mods.size());
1127 return EXIT_SUCCESS;
1132 std::exit(EXIT_FAILURE);
1133 }
catch (std::exception & e1) {
1134 std::cerr <<
"Failure: " << e1.what() << std::endl;
1135 std::exit(EXIT_FAILURE);
@ SORT_ACCUMULATION_BASED_SERVICE
@ SORT_SINGLE_INTERFACE_BASED_SERVICE
@ SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
@ SORT_INTERFACE_BASED_SINGLETON
@ SORT_SERVICE_BASED_SINGLETON
virtual rtl::Reference< MapCursor > createCursor() const =0
rtl::Reference< ParseManager > manager
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
SwNodeOffset abs(const SwNodeOffset &a)
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
@ ATTRIBUTE_MAYBE_DEFAULT
@ ATTRIBUTE_MAYBE_AMBIGUOUS