Bump version to 24.04.3.4
[LibreOffice.git] / unoidl / source / unoidl-read.cxx
blob721fdabe9c8b17e947c82dc07ec9978d1dcaa60f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sal/config.h>
12 #include <cassert>
13 #include <cstdlib>
14 #include <iostream>
15 #include <map>
16 #include <set>
17 #include <string_view>
18 #include <utility>
19 #include <vector>
21 #include <osl/file.hxx>
22 #include <osl/process.h>
23 #include <rtl/process.h>
24 #include <rtl/ref.hxx>
25 #include <rtl/ustring.hxx>
26 #include <sal/main.h>
27 #include <sal/types.h>
28 #include <unoidl/unoidl.hxx>
29 #include <o3tl/string_view.hxx>
31 namespace {
33 void badUsage() {
34 std::cerr
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,"
39 " a single .idl")
40 << std::endl
41 << ("file, or a root directory of an .idl file tree. The complete"
42 " content of the")
43 << std::endl
44 << ("last <registry> is written to stdout; if --published is specified,"
45 " only the")
46 << std::endl
47 << ("published entities (plus any non-published entities referenced"
48 " from published")
49 << std::endl
50 << "via any unpublished optional bases) are written out. If --summary is specified,"
51 << std::endl
52 << "only a short summary is written, with the type and name of one entity per line."
53 << std::endl;
54 std::exit(EXIT_FAILURE);
57 OUString getArgumentUri(sal_uInt32 argument) {
58 OUString arg;
59 rtl_getAppCommandArg(argument, &arg.pData);
60 OUString url;
61 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
62 if (e1 != osl::FileBase::E_None) {
63 std::cerr
64 << "Cannot convert \"" << arg << "\" to file URL, error code "
65 << +e1 << std::endl;
66 std::exit(EXIT_FAILURE);
68 OUString cwd;
69 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
70 if (e2 != osl_Process_E_None) {
71 std::cerr
72 << "Cannot obtain working directory, error code " << +e2
73 << std::endl;
74 std::exit(EXIT_FAILURE);
76 OUString abs;
77 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
78 if (e1 != osl::FileBase::E_None) {
79 std::cerr
80 << "Cannot make \"" << url
81 << "\" into an absolute file URL, error code " << +e1 << std::endl;
82 std::exit(EXIT_FAILURE);
84 return abs;
87 std::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);
95 *rank = 0;
96 typeArguments->clear();
97 while (o3tl::starts_with(nucl, u"[]", &nucl)) {
98 ++*rank;
100 size_t i = nucl.find('<');
101 if (i != std::u16string_view::npos) {
102 std::u16string_view tmpl(nucl.substr(0, i));
103 do {
104 ++i; // skip '<' or ','
105 size_t j = i;
106 for (size_t level = 0; j != nucl.size(); ++j) {
107 sal_Unicode c = nucl[j];
108 if (c == ',') {
109 if (level == 0) {
110 break;
112 } else if (c == '<') {
113 ++level;
114 } else if (c == '>') {
115 if (level == 0) {
116 break;
118 --level;
121 if (j != nucl.size()) {
122 typeArguments->push_back(OUString(nucl.substr(i, j - i)));
124 i = j;
125 } while (i != nucl.size() && nucl[i] != '>');
126 assert(i == nucl.size() - 1 && nucl[i] == '>');
127 assert(!typeArguments->empty());
128 nucl = tmpl;
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"
136 && nucl != u"any";
137 assert(*entity || typeArguments->empty());
138 return nucl;
141 struct Entity {
142 enum class Sorted { NO, ACTIVE, YES };
143 enum class Written { NO, DECLARATION, DEFINITION };
145 explicit Entity(
146 rtl::Reference<unoidl::Entity> theEntity, bool theRelevant, Entity * theParent):
147 entity(std::move(theEntity)), relevant(theRelevant), sorted(Sorted::NO),
148 written(Written::NO), parent(theParent)
151 rtl::Reference<unoidl::Entity> const entity;
152 std::set<OUString> dependencies;
153 std::set<OUString> interfaceDependencies;
154 bool relevant;
155 Sorted sorted;
156 Written written;
157 Entity * parent;
160 void insertEntityDependency(
161 rtl::Reference<unoidl::Manager> const & manager,
162 std::map<OUString, Entity>::iterator const & iterator,
163 OUString const & name, bool weakInterfaceDependency = false)
165 assert(manager.is());
166 if (name == iterator->first)
167 return;
169 bool ifc = false;
170 if (weakInterfaceDependency) {
171 rtl::Reference<unoidl::Entity> ent(manager->findEntity(name));
172 if (!ent.is()) {
173 std::cerr << "Unknown entity " << name << std::endl;
174 std::exit(EXIT_FAILURE);
176 ifc = ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE;
178 (ifc
179 ? iterator->second.interfaceDependencies
180 : iterator->second.dependencies)
181 .insert(name);
184 void insertEntityDependencies(
185 rtl::Reference<unoidl::Manager> const & manager,
186 std::map<OUString, Entity>::iterator const & iterator,
187 std::vector<OUString> const & names)
189 for (auto & i: names) {
190 insertEntityDependency(manager, iterator, i);
194 void insertEntityDependencies(
195 rtl::Reference<unoidl::Manager> const & manager,
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);
204 void insertTypeDependency(
205 rtl::Reference<unoidl::Manager> const & manager,
206 std::map<OUString, Entity>::iterator const & iterator,
207 std::u16string_view type)
209 std::size_t rank;
210 std::vector<OUString> args;
211 bool entity;
212 OUString nucl(decomposeType(type, &rank, &args, &entity));
213 if (entity) {
214 insertEntityDependency(manager, iterator, nucl, true);
215 for (const auto & i: args) {
216 insertTypeDependency(manager, iterator, i);
221 void scanMap(
222 rtl::Reference<unoidl::Manager> const & manager,
223 rtl::Reference<unoidl::MapCursor> const & cursor, bool modules, bool published,
224 std::u16string_view prefix, Entity * parent, std::map<OUString, Entity> & entities)
226 assert(cursor.is());
227 for (;;) {
228 OUString id;
229 rtl::Reference<unoidl::Entity> ent(cursor->getNext(&id));
230 if (!ent.is()) {
231 break;
233 OUString name(prefix + id);
234 if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
235 Entity * p = nullptr;
236 if (modules) {
237 p = &entities.insert(std::make_pair(name, Entity(ent, !published, parent))).first
238 ->second;
240 scanMap(
241 manager,
242 static_cast<unoidl::ModuleEntity *>(ent.get())->createCursor(), modules,
243 published, Concat2View(name + "."), p, entities);
244 } else {
245 auto const pub = static_cast<unoidl::PublishableEntity *>(ent.get())->isPublished();
246 std::map<OUString, Entity>::iterator i(
247 entities.insert(
248 std::make_pair(
249 name,
250 Entity(
251 ent,
252 (!published
253 || pub),
254 parent)))
255 .first);
256 if (modules && published && pub) {
257 for (auto j = parent; j; j = j->parent) {
258 j->relevant = true;
261 switch (ent->getSort()) {
262 case unoidl::Entity::SORT_ENUM_TYPE:
263 case unoidl::Entity::SORT_CONSTANT_GROUP:
264 break;
265 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
267 rtl::Reference<unoidl::PlainStructTypeEntity> ent2(
268 static_cast<unoidl::PlainStructTypeEntity *>(
269 ent.get()));
270 if (!ent2->getDirectBase().isEmpty()) {
271 insertEntityDependency(
272 manager, i, ent2->getDirectBase());
274 for (auto & j: ent2->getDirectMembers()) {
275 insertTypeDependency(manager, i, j.type);
277 break;
279 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
281 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
282 ent2(
283 static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
284 ent.get()));
285 for (auto & j: ent2->getMembers()) {
286 if (!j.parameterized) {
287 insertTypeDependency(manager, i, j.type);
290 break;
292 case unoidl::Entity::SORT_EXCEPTION_TYPE:
294 rtl::Reference<unoidl::ExceptionTypeEntity> ent2(
295 static_cast<unoidl::ExceptionTypeEntity *>(ent.get()));
296 if (!ent2->getDirectBase().isEmpty()) {
297 insertEntityDependency(
298 manager, i, ent2->getDirectBase());
300 for (auto & j: ent2->getDirectMembers()) {
301 insertTypeDependency(manager, i, j.type);
303 break;
305 case unoidl::Entity::SORT_INTERFACE_TYPE:
307 rtl::Reference<unoidl::InterfaceTypeEntity> ent2(
308 static_cast<unoidl::InterfaceTypeEntity *>(
309 ent.get()));
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);
324 break;
326 case unoidl::Entity::SORT_TYPEDEF:
328 rtl::Reference<unoidl::TypedefEntity> ent2(
329 static_cast<unoidl::TypedefEntity *>(ent.get()));
330 insertTypeDependency(manager, i, ent2->getType());
331 break;
333 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
335 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
336 ent2(
337 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
338 ent.get()));
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);
346 break;
348 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
350 rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2(
351 static_cast<unoidl::AccumulationBasedServiceEntity *>(
352 ent.get()));
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);
364 break;
366 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
368 rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2(
369 static_cast<unoidl::InterfaceBasedSingletonEntity *>(
370 ent.get()));
371 insertEntityDependency(manager, i, ent2->getBase());
372 break;
374 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
376 rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2(
377 static_cast<unoidl::ServiceBasedSingletonEntity *>(
378 ent.get()));
379 insertEntityDependency(manager, i, ent2->getBase());
380 break;
382 case unoidl::Entity::SORT_MODULE:
383 assert(false && "this cannot happen");
389 void 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);
403 void visit(
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);
422 break;
423 case Entity::Sorted::ACTIVE:
424 std::cerr
425 << "Entity " << iterator->first << " recursively depends on itself"
426 << std::endl;
427 std::exit(EXIT_FAILURE);
428 // fall-through avoids warnings
429 default:
430 break;
434 std::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);
439 return res;
442 void indent(std::vector<OUString> const & modules, unsigned int extra = 0) {
443 for (std::vector<OUString>::size_type i = 0; i != modules.size(); ++i) {
444 std::cout << ' ';
446 for (unsigned int i = 0; i != extra; ++i) {
447 std::cout << ' ';
451 void closeModules(
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());
456 modules.pop_back();
457 indent(modules);
458 std::cout << "};\n";
462 OUString openModulesFor(std::vector<OUString> & modules, std::u16string_view name)
464 std::vector<OUString>::iterator i(modules.begin());
465 for (sal_Int32 j = 0;;) {
466 OUString id(o3tl::getToken(name, 0, '.', j));
467 if (j == -1) {
468 closeModules(
469 modules,
470 static_cast< std::vector<OUString>::size_type >(
471 modules.end() - i));
472 indent(modules);
473 return id;
475 if (i != modules.end()) {
476 if (id == *i) {
477 ++i;
478 continue;
480 closeModules(
481 modules,
482 static_cast< std::vector<OUString>::size_type >(
483 modules.end() - i));
484 i = modules.end();
486 indent(modules);
487 std::cout << "module " << id << " {\n";
488 modules.push_back(id);
489 i = modules.end();
493 void writeName(OUString const & name) {
494 std::cout << "::" << name.replaceAll(".", "::");
497 void writeAnnotations(std::vector<OUString> const & annotations) {
498 if (!annotations.empty()) {
499 std::cout << "/**";
500 for (auto & i: annotations) {
501 //TODO: i.indexOf("*/") == -1
502 std::cout << " @" << i;
504 std::cout << " */ ";
508 void writePublished(rtl::Reference<unoidl::PublishableEntity> const & entity) {
509 assert(entity.is());
510 if (entity->isPublished()) {
511 std::cout << "published ";
515 void writeAnnotationsPublished(
516 rtl::Reference<unoidl::PublishableEntity> const & entity)
518 assert(entity.is());
519 writeAnnotations(entity->getAnnotations());
520 writePublished(entity);
523 void writeType(std::u16string_view type) {
524 std::size_t rank;
525 std::vector<OUString> args;
526 bool entity;
527 OUString nucl(decomposeType(type, &rank, &args, &entity));
528 for (std::size_t i = 0; i != rank; ++i) {
529 std::cout << "sequence< ";
531 if (entity) {
532 writeName(nucl);
533 } else {
534 std::cout << nucl;
536 if (!args.empty()) {
537 std::cout << "< ";
538 for (auto i(args.begin()); i != args.end(); ++i) {
539 if (i != args.begin()) {
540 std::cout << ", ";
542 writeType(*i);
544 std::cout << " >";
546 for (std::size_t i = 0; i != rank; ++i) {
547 std::cout << " >";
551 void 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()) {
556 std::cout << ", ";
558 writeName(*i);
560 std::cout << ')';
564 void writeEntity(
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)
570 return;
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()
580 != unoidl::Entity::SORT_INTERFACE_TYPE)
582 std::cerr
583 << "Entity " << j << " should be an interface type"
584 << std::endl;
585 std::exit(EXIT_FAILURE);
587 writePublished(
588 static_cast<unoidl::PublishableEntity *>(
589 k->second.entity.get()));
590 std::cout << "interface " << id << ";\n";
593 OUString id(openModulesFor(modules, name));
594 rtl::Reference<unoidl::PublishableEntity> ent(
595 static_cast<unoidl::PublishableEntity *>(i->second.entity.get()));
596 switch (ent->getSort()) {
597 case unoidl::Entity::SORT_ENUM_TYPE:
599 rtl::Reference<unoidl::EnumTypeEntity> ent2(
600 static_cast<unoidl::EnumTypeEntity *>(ent.get()));
601 writeAnnotationsPublished(ent);
602 std::cout << "enum " << id << " {\n";
603 for (auto j(ent2->getMembers().begin());
604 j != ent2->getMembers().end(); ++j)
606 indent(modules, 1);
607 writeAnnotations(j->annotations);
608 std::cout << j->name << " = " << j->value;
609 if (j + 1 != ent2->getMembers().end()) {
610 std::cout << ',';
612 std::cout << '\n';
614 indent(modules);
615 std::cout << "};\n";
616 break;
618 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
620 rtl::Reference<unoidl::PlainStructTypeEntity> ent2(
621 static_cast<unoidl::PlainStructTypeEntity *>(ent.get()));
622 writeAnnotationsPublished(ent);
623 std::cout << "struct " << id;
624 if (!ent2->getDirectBase().isEmpty()) {
625 std::cout << ": ";
626 writeName(ent2->getDirectBase());
628 std::cout << " {\n";
629 for (auto & j: ent2->getDirectMembers()) {
630 indent(modules, 1);
631 writeAnnotations(j.annotations);
632 writeType(j.type);
633 std::cout << ' ' << j.name << ";\n";
635 indent(modules);
636 std::cout << "};\n";
637 break;
639 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
641 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
642 ent2(
643 static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
644 ent.get()));
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()) {
651 std::cout << ", ";
653 std::cout << *j;
655 std::cout << "> {\n";
656 for (auto & j: ent2->getMembers()) {
657 indent(modules, 1);
658 writeAnnotations(j.annotations);
659 if (j.parameterized) {
660 std::cout << j.type;
661 } else {
662 writeType(j.type);
664 std::cout << ' ' << j.name << ";\n";
666 indent(modules);
667 std::cout << "};\n";
668 break;
670 case unoidl::Entity::SORT_EXCEPTION_TYPE:
672 rtl::Reference<unoidl::ExceptionTypeEntity> ent2(
673 static_cast<unoidl::ExceptionTypeEntity *>(ent.get()));
674 writeAnnotationsPublished(ent);
675 std::cout << "exception " << id;
676 if (!ent2->getDirectBase().isEmpty()) {
677 std::cout << ": ";
678 writeName(ent2->getDirectBase());
680 std::cout << " {\n";
681 for (auto & j: ent2->getDirectMembers()) {
682 indent(modules, 1);
683 writeAnnotations(j.annotations);
684 writeType(j.type);
685 std::cout << ' ' << j.name << ";\n";
687 indent(modules);
688 std::cout << "};\n";
689 break;
691 case unoidl::Entity::SORT_INTERFACE_TYPE:
693 rtl::Reference<unoidl::InterfaceTypeEntity> ent2(
694 static_cast<unoidl::InterfaceTypeEntity *>(
695 ent.get()));
696 writeAnnotationsPublished(ent);
697 std::cout << "interface " << id << " {\n";
698 for (auto & j: ent2->getDirectMandatoryBases()) {
699 indent(modules, 1);
700 writeAnnotations(j.annotations);
701 std::cout << "interface ";
702 writeName(j.name);
703 std::cout << ";\n";
705 for (auto & j: ent2->getDirectOptionalBases()) {
706 indent(modules, 1);
707 writeAnnotations(j.annotations);
708 std::cout << "[optional] interface ";
709 writeName(j.name);
710 std::cout << ";\n";
712 for (auto & j: ent2->getDirectAttributes()) {
713 indent(modules, 1);
714 writeAnnotations(j.annotations);
715 std::cout << "[attribute";
716 if (j.bound) {
717 std::cout << ", bound";
719 if (j.readOnly) {
720 std::cout << ", readonly";
722 std::cout << "] ";
723 writeType(j.type);
724 std::cout << ' ' << j.name;
725 if (!(j.getExceptions.empty() && j.setExceptions.empty())) {
726 std::cout << " {\n";
727 if (!j.getExceptions.empty()) {
728 indent(modules, 2);
729 std::cout << "get";
730 writeExceptionSpecification(j.getExceptions);
731 std::cout << ";\n";
733 if (!j.setExceptions.empty()) {
734 indent(modules, 2);
735 std::cout << "set";
736 writeExceptionSpecification(j.setExceptions);
737 std::cout << ";\n";
739 std::cout << " }";
741 std::cout << ";\n";
743 for (auto & j: ent2->getDirectMethods()) {
744 indent(modules, 1);
745 writeAnnotations(j.annotations);
746 writeType(j.returnType);
747 std::cout << ' ' << j.name << '(';
748 for (auto k(j.parameters.begin()); k != j.parameters.end();
749 ++k)
751 if (k != j.parameters.begin()) {
752 std::cout << ", ";
754 switch (k->direction) {
755 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN:
756 std::cout << "[in] ";
757 break;
758 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT:
759 std::cout << "[out] ";
760 break;
761 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT:
762 std::cout << "[inout] ";
763 break;
765 writeType(k->type);
766 std::cout << ' ' << k->name;
768 std::cout << ')';
769 writeExceptionSpecification(j.exceptions);
770 std::cout << ";\n";
772 indent(modules);
773 std::cout << "};\n";
774 break;
776 case unoidl::Entity::SORT_TYPEDEF:
778 rtl::Reference<unoidl::TypedefEntity> ent2(
779 static_cast<unoidl::TypedefEntity *>(ent.get()));
780 writeAnnotationsPublished(ent);
781 std::cout << "typedef ";
782 writeType(ent2->getType());
783 std::cout << ' ' << id << ";\n";
784 break;
786 case unoidl::Entity::SORT_CONSTANT_GROUP:
788 rtl::Reference<unoidl::ConstantGroupEntity> ent2(
789 static_cast<unoidl::ConstantGroupEntity *>(ent.get()));
790 writeAnnotationsPublished(ent);
791 std::cout << "constants " << id << " {\n";
792 for (auto & j: ent2->getMembers()) {
793 indent(modules, 1);
794 writeAnnotations(j.annotations);
795 std::cout << "const ";
796 switch (j.value.type) {
797 case unoidl::ConstantValue::TYPE_BOOLEAN:
798 std::cout << "boolean";
799 break;
800 case unoidl::ConstantValue::TYPE_BYTE:
801 std::cout << "byte";
802 break;
803 case unoidl::ConstantValue::TYPE_SHORT:
804 std::cout << "short";
805 break;
806 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
807 std::cout << "unsigned short";
808 break;
809 case unoidl::ConstantValue::TYPE_LONG:
810 std::cout << "long";
811 break;
812 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
813 std::cout << "unsigned long";
814 break;
815 case unoidl::ConstantValue::TYPE_HYPER:
816 std::cout << "hyper";
817 break;
818 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
819 std::cout << "unsigned hyper";
820 break;
821 case unoidl::ConstantValue::TYPE_FLOAT:
822 std::cout << "float";
823 break;
824 case unoidl::ConstantValue::TYPE_DOUBLE:
825 std::cout << "double";
826 break;
828 std::cout << ' ' << j.name << " = ";
829 switch (j.value.type) {
830 case unoidl::ConstantValue::TYPE_BOOLEAN:
831 std::cout << (j.value.booleanValue ? "TRUE" : "FALSE");
832 break;
833 case unoidl::ConstantValue::TYPE_BYTE:
834 std::cout << int(j.value.byteValue);
835 break;
836 case unoidl::ConstantValue::TYPE_SHORT:
837 std::cout << j.value.shortValue;
838 break;
839 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
840 std::cout << j.value.unsignedShortValue;
841 break;
842 case unoidl::ConstantValue::TYPE_LONG:
843 std::cout << j.value.longValue;
844 break;
845 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
846 std::cout << j.value.unsignedLongValue;
847 break;
848 case unoidl::ConstantValue::TYPE_HYPER:
849 std::cout << j.value.hyperValue;
850 break;
851 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
852 std::cout << j.value.unsignedHyperValue;
853 break;
854 case unoidl::ConstantValue::TYPE_FLOAT:
855 std::cout << j.value.floatValue;
856 break;
857 case unoidl::ConstantValue::TYPE_DOUBLE:
858 std::cout << j.value.doubleValue;
859 break;
861 std::cout << ";\n";
863 indent(modules);
864 std::cout << "};\n";
865 break;
867 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
869 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity> ent2(
870 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
871 ent.get()));
872 writeAnnotationsPublished(ent);
873 std::cout << "service " << id << ": ";
874 writeName(ent2->getBase());
875 if (ent2->getConstructors().size() != 1
876 || !ent2->getConstructors().front().defaultConstructor)
878 std::cout << " {\n";
879 for (auto & j: ent2->getConstructors()) {
880 indent(modules, 1);
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()) {
887 std::cout << ", ";
889 std::cout << "[in] ";
890 writeType(k->type);
891 if (k->rest) {
892 std::cout << "...";
894 std::cout << ' ' << k->name;
896 std::cout << ')';
897 writeExceptionSpecification(j.exceptions);
898 std::cout << ";\n";
900 indent(modules);
901 std::cout << '}';
903 std::cout << ";\n";
904 break;
906 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
908 rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2(
909 static_cast<unoidl::AccumulationBasedServiceEntity *>(
910 ent.get()));
911 writeAnnotationsPublished(ent);
912 std::cout << "service " << id << " {\n";
913 for (auto & j: ent2->getDirectMandatoryBaseServices()) {
914 indent(modules, 1);
915 writeAnnotations(j.annotations);
916 std::cout << "service ";
917 writeName(j.name);
918 std::cout << ";\n";
920 for (auto & j: ent2->getDirectOptionalBaseServices()) {
921 indent(modules, 1);
922 writeAnnotations(j.annotations);
923 std::cout << "[optional] service ";
924 writeName(j.name);
925 std::cout << ";\n";
927 for (auto & j: ent2->getDirectMandatoryBaseInterfaces()) {
928 indent(modules, 1);
929 writeAnnotations(j.annotations);
930 std::cout << "interface ";
931 writeName(j.name);
932 std::cout << ";\n";
934 for (auto & j: ent2->getDirectOptionalBaseInterfaces()) {
935 indent(modules, 1);
936 writeAnnotations(j.annotations);
937 std::cout << "[optional] interface ";
938 writeName(j.name);
939 std::cout << ";\n";
941 for (auto & j: ent2->getDirectProperties()) {
942 indent(modules, 1);
943 writeAnnotations(j.annotations);
944 std::cout << "[property";
945 if ((j.attributes
946 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_BOUND)
947 != 0)
949 std::cout << ", bound";
951 if ((j.attributes
952 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_CONSTRAINED)
953 != 0)
955 std::cout << ", constrained";
957 if ((j.attributes
958 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_AMBIGUOUS)
959 != 0)
961 std::cout << ", maybeambiguous";
963 if ((j.attributes
964 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_DEFAULT)
965 != 0)
967 std::cout << ", maybedefault";
969 if ((j.attributes
970 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_VOID)
971 != 0)
973 std::cout << ", maybevoid";
975 if ((j.attributes
976 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL)
977 != 0)
979 std::cout << ", optional";
981 if ((j.attributes
982 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_READ_ONLY)
983 != 0)
985 std::cout << ", readonly";
987 if ((j.attributes
988 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_REMOVABLE)
989 != 0)
991 std::cout << ", removable";
993 if ((j.attributes
994 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_TRANSIENT)
995 != 0)
997 std::cout << ", transient";
999 std::cout << "] ";
1000 writeType(j.type);
1001 std::cout << ' ' << j.name << ";\n";
1003 indent(modules);
1004 std::cout << "};\n";
1005 break;
1007 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
1009 rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2(
1010 static_cast<unoidl::InterfaceBasedSingletonEntity *>(
1011 ent.get()));
1012 writeAnnotationsPublished(ent);
1013 std::cout << "singleton " << id << ": ";
1014 writeName(ent2->getBase());
1015 std::cout << ";\n";
1016 break;
1018 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
1020 rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2(
1021 static_cast<unoidl::ServiceBasedSingletonEntity *>(
1022 ent.get()));
1023 writeAnnotationsPublished(ent);
1024 std::cout << "singleton " << id << " { service ";
1025 writeName(ent2->getBase());
1026 std::cout << "; };";
1027 break;
1029 case unoidl::Entity::SORT_MODULE:
1030 assert(false && "this cannot happen");
1034 void writeSummary(OUString const & name, Entity const & entity) {
1035 if (!entity.relevant) {
1036 return;
1038 switch (entity.entity->getSort()) {
1039 case unoidl::Entity::SORT_ENUM_TYPE:
1040 std::cout << "enum";
1041 break;
1042 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
1043 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
1044 std::cout << "struct";
1045 break;
1046 case unoidl::Entity::SORT_EXCEPTION_TYPE:
1047 std::cout << "exception";
1048 break;
1049 case unoidl::Entity::SORT_INTERFACE_TYPE:
1050 std::cout << "interface";
1051 break;
1052 case unoidl::Entity::SORT_TYPEDEF:
1053 std::cout << "typedef";
1054 break;
1055 case unoidl::Entity::SORT_CONSTANT_GROUP:
1056 std::cout << "constants";
1057 break;
1058 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
1059 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
1060 std::cout << "service";
1061 break;
1062 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
1063 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
1064 std::cout << "singleton";
1065 break;
1066 case unoidl::Entity::SORT_MODULE:
1067 std::cout << "module";
1068 break;
1070 std::cout << ' ' << name << '\n';
1075 SAL_IMPLEMENT_MAIN() {
1076 try {
1077 sal_uInt32 args = rtl_getAppCommandArgCount();
1078 sal_uInt32 i = 0;
1079 bool published = false;
1080 bool summary = false;
1081 for (;; ++i) {
1082 if (i == args) {
1083 badUsage();
1085 OUString arg;
1086 rtl_getAppCommandArg(i, &arg.pData);
1087 if (arg == "--published") {
1088 if (published) {
1089 badUsage();
1091 published = true;
1092 } else if (arg == "--summary") {
1093 if (summary) {
1094 badUsage();
1096 summary = true;
1097 } else {
1098 break;
1101 rtl::Reference<unoidl::Manager> mgr(new unoidl::Manager);
1102 rtl::Reference<unoidl::Provider> prov;
1103 for (; i != args; ++i) {
1104 OUString uri(getArgumentUri(i));
1105 try {
1106 prov = mgr->addProvider(uri);
1107 } catch (unoidl::NoSuchFileException &) {
1108 std::cerr
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);
1115 if (summary) {
1116 for (auto const & j: ents) {
1117 writeSummary(j.first, j.second);
1119 } else {
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;
1128 } catch (unoidl::FileFormatException & e1) {
1129 std::cerr
1130 << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1131 << std::endl;
1132 std::exit(EXIT_FAILURE);
1133 } catch (std::exception & e1) {
1134 std::cerr << "Failure: " << e1.what() << std::endl;
1135 std::exit(EXIT_FAILURE);
1139 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */