tdf#124384 sw DOCX: fix crash during bibliography loading
[LibreOffice.git] / unoidl / source / unoidl-read.cxx
blob6414fb376a1cdbc1b24f510829855354583b638c
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 <utility>
18 #include <vector>
20 #include <osl/file.hxx>
21 #include <osl/process.h>
22 #include <rtl/process.h>
23 #include <rtl/ref.hxx>
24 #include <rtl/ustring.hxx>
25 #include <sal/main.h>
26 #include <sal/types.h>
27 #include <unoidl/unoidl.hxx>
29 namespace {
31 void badUsage() {
32 std::cerr
33 << "Usage:" << std::endl << std::endl
34 << " unoidl-read [--published] [<extra registries>] <registry>"
35 << std::endl << std::endl
36 << ("where each <registry> is either a new- or legacy-format .rdb file,"
37 " a single .idl")
38 << std::endl
39 << ("file, or a root directory of an .idl file tree. The complete"
40 " content of the")
41 << std::endl
42 << ("last <registry> is written to stdout; if --published is specified,"
43 " only the")
44 << std::endl
45 << ("published entities (plus any non-published entities referenced"
46 " from published")
47 << std::endl
48 << "via any unpublished optional bases) are written out." << std::endl;
49 std::exit(EXIT_FAILURE);
52 OUString getArgumentUri(sal_uInt32 argument) {
53 OUString arg;
54 rtl_getAppCommandArg(argument, &arg.pData);
55 OUString url;
56 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
57 if (e1 != osl::FileBase::E_None) {
58 std::cerr
59 << "Cannot convert \"" << arg << "\" to file URL, error code "
60 << +e1 << std::endl;
61 std::exit(EXIT_FAILURE);
63 OUString cwd;
64 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
65 if (e2 != osl_Process_E_None) {
66 std::cerr
67 << "Cannot obtain working directory, error code " << +e2
68 << std::endl;
69 std::exit(EXIT_FAILURE);
71 OUString abs;
72 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
73 if (e1 != osl::FileBase::E_None) {
74 std::cerr
75 << "Cannot make \"" << url
76 << "\" into an absolute file URL, error code " << +e1 << std::endl;
77 std::exit(EXIT_FAILURE);
79 return abs;
82 OUString decomposeType(
83 OUString const & type, std::size_t * rank,
84 std::vector<OUString> * typeArguments, bool * entity)
86 assert(rank != nullptr);
87 assert(typeArguments != nullptr);
88 assert(entity != nullptr);
89 OUString nucl(type);
90 *rank = 0;
91 typeArguments->clear();
92 while (nucl.startsWith("[]", &nucl)) {
93 ++*rank;
95 sal_Int32 i = nucl.indexOf('<');
96 if (i != -1) {
97 OUString tmpl(nucl.copy(0, i));
98 do {
99 ++i; // skip '<' or ','
100 sal_Int32 j = i;
101 for (sal_Int32 level = 0; j != nucl.getLength(); ++j) {
102 sal_Unicode c = nucl[j];
103 if (c == ',') {
104 if (level == 0) {
105 break;
107 } else if (c == '<') {
108 ++level;
109 } else if (c == '>') {
110 if (level == 0) {
111 break;
113 --level;
116 if (j != nucl.getLength()) {
117 typeArguments->push_back(nucl.copy(i, j - i));
119 i = j;
120 } while (i != nucl.getLength() && nucl[i] != '>');
121 assert(i == nucl.getLength() - 1 && nucl[i] == '>');
122 assert(!typeArguments->empty());
123 nucl = tmpl;
125 assert(!nucl.isEmpty());
126 *entity = nucl != "void" && nucl != "boolean" && nucl != "byte"
127 && nucl != "short" && nucl != "unsigned short" && nucl != "long"
128 && nucl != "unsigned long" && nucl != "hyper"
129 && nucl != "unsigned hyper" && nucl != "float" && nucl != "double"
130 && nucl != "char" && nucl != "string" && nucl != "type"
131 && nucl != "any";
132 assert(*entity || typeArguments->empty());
133 return nucl;
136 struct Entity {
137 enum class Sorted { NO, ACTIVE, YES };
139 explicit Entity(
140 rtl::Reference<unoidl::Entity> const & theEntity, bool theRelevant):
141 entity(theEntity), relevant(theRelevant), sorted(Sorted::NO),
142 written(false)
145 rtl::Reference<unoidl::Entity> const entity;
146 std::set<OUString> dependencies;
147 std::set<OUString> interfaceDependencies;
148 bool relevant;
149 Sorted sorted;
150 bool written;
153 void insertEntityDependency(
154 rtl::Reference<unoidl::Manager> const & manager,
155 std::map<OUString, Entity>::iterator const & iterator,
156 OUString const & name, bool weakInterfaceDependency = false)
158 assert(manager.is());
159 if (name != iterator->first) {
160 bool ifc = false;
161 if (weakInterfaceDependency) {
162 rtl::Reference<unoidl::Entity> ent(manager->findEntity(name));
163 if (!ent.is()) {
164 std::cerr << "Unknown entity " << name << std::endl;
165 std::exit(EXIT_FAILURE);
167 ifc = ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE;
169 (ifc
170 ? iterator->second.interfaceDependencies
171 : iterator->second.dependencies)
172 .insert(name);
176 void insertEntityDependencies(
177 rtl::Reference<unoidl::Manager> const & manager,
178 std::map<OUString, Entity>::iterator const & iterator,
179 std::vector<OUString> const & names)
181 for (auto & i: names) {
182 insertEntityDependency(manager, iterator, i);
186 void insertEntityDependencies(
187 rtl::Reference<unoidl::Manager> const & manager,
188 std::map<OUString, Entity>::iterator const & iterator,
189 std::vector<unoidl::AnnotatedReference> const & references)
191 for (auto & i: references) {
192 insertEntityDependency(manager, iterator, i.name);
196 void insertTypeDependency(
197 rtl::Reference<unoidl::Manager> const & manager,
198 std::map<OUString, Entity>::iterator const & iterator,
199 OUString const & type)
201 std::size_t rank;
202 std::vector<OUString> args;
203 bool entity;
204 OUString nucl(decomposeType(type, &rank, &args, &entity));
205 if (entity) {
206 insertEntityDependency(manager, iterator, nucl, true);
207 for (auto & i: args) {
208 insertTypeDependency(manager, iterator, i);
213 void scanMap(
214 rtl::Reference<unoidl::Manager> const & manager,
215 rtl::Reference<unoidl::MapCursor> const & cursor, bool published,
216 OUString const & prefix, std::map<OUString, Entity> & entities)
218 assert(cursor.is());
219 for (;;) {
220 OUString id;
221 rtl::Reference<unoidl::Entity> ent(cursor->getNext(&id));
222 if (!ent.is()) {
223 break;
225 OUString name(prefix + id);
226 if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
227 scanMap(
228 manager,
229 static_cast<unoidl::ModuleEntity *>(ent.get())->createCursor(),
230 published, name + ".", entities);
231 } else {
232 std::map<OUString, Entity>::iterator i(
233 entities.insert(
234 std::make_pair(
235 name,
236 Entity(
237 ent,
238 (!published
239 || (static_cast<unoidl::PublishableEntity *>(
240 ent.get())
241 ->isPublished())))))
242 .first);
243 switch (ent->getSort()) {
244 case unoidl::Entity::SORT_ENUM_TYPE:
245 case unoidl::Entity::SORT_CONSTANT_GROUP:
246 break;
247 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
249 rtl::Reference<unoidl::PlainStructTypeEntity> ent2(
250 static_cast<unoidl::PlainStructTypeEntity *>(
251 ent.get()));
252 if (!ent2->getDirectBase().isEmpty()) {
253 insertEntityDependency(
254 manager, i, ent2->getDirectBase());
256 for (auto & j: ent2->getDirectMembers()) {
257 insertTypeDependency(manager, i, j.type);
259 break;
261 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
263 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
264 ent2(
265 static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
266 ent.get()));
267 for (auto & j: ent2->getMembers()) {
268 if (!j.parameterized) {
269 insertTypeDependency(manager, i, j.type);
272 break;
274 case unoidl::Entity::SORT_EXCEPTION_TYPE:
276 rtl::Reference<unoidl::ExceptionTypeEntity> ent2(
277 static_cast<unoidl::ExceptionTypeEntity *>(ent.get()));
278 if (!ent2->getDirectBase().isEmpty()) {
279 insertEntityDependency(
280 manager, i, ent2->getDirectBase());
282 for (auto & j: ent2->getDirectMembers()) {
283 insertTypeDependency(manager, i, j.type);
285 break;
287 case unoidl::Entity::SORT_INTERFACE_TYPE:
289 rtl::Reference<unoidl::InterfaceTypeEntity> ent2(
290 static_cast<unoidl::InterfaceTypeEntity *>(
291 ent.get()));
292 insertEntityDependencies(
293 manager, i, ent2->getDirectMandatoryBases());
294 insertEntityDependencies(
295 manager, i, ent2->getDirectOptionalBases());
296 for (auto & j: ent2->getDirectAttributes()) {
297 insertTypeDependency(manager, i, j.type);
299 for (auto & j: ent2->getDirectMethods()) {
300 insertTypeDependency(manager, i, j.returnType);
301 for (auto & k: j.parameters) {
302 insertTypeDependency(manager, i, k.type);
304 insertEntityDependencies(manager, i, j.exceptions);
306 break;
308 case unoidl::Entity::SORT_TYPEDEF:
310 rtl::Reference<unoidl::TypedefEntity> ent2(
311 static_cast<unoidl::TypedefEntity *>(ent.get()));
312 insertTypeDependency(manager, i, ent2->getType());
313 break;
315 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
317 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
318 ent2(
319 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
320 ent.get()));
321 insertEntityDependency(manager, i, ent2->getBase());
322 for (auto & j: ent2->getConstructors()) {
323 for (auto & k: j.parameters) {
324 insertTypeDependency(manager, i, k.type);
326 insertEntityDependencies(manager, i, j.exceptions);
328 break;
330 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
332 rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2(
333 static_cast<unoidl::AccumulationBasedServiceEntity *>(
334 ent.get()));
335 insertEntityDependencies(
336 manager, i, ent2->getDirectMandatoryBaseServices());
337 insertEntityDependencies(
338 manager, i, ent2->getDirectOptionalBaseServices());
339 insertEntityDependencies(
340 manager, i, ent2->getDirectMandatoryBaseInterfaces());
341 insertEntityDependencies(
342 manager, i, ent2->getDirectOptionalBaseInterfaces());
343 for (auto & j: ent2->getDirectProperties()) {
344 insertTypeDependency(manager, i, j.type);
346 break;
348 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
350 rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2(
351 static_cast<unoidl::InterfaceBasedSingletonEntity *>(
352 ent.get()));
353 insertEntityDependency(manager, i, ent2->getBase());
354 break;
356 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
358 rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2(
359 static_cast<unoidl::ServiceBasedSingletonEntity *>(
360 ent.get()));
361 insertEntityDependency(manager, i, ent2->getBase());
362 break;
364 case unoidl::Entity::SORT_MODULE:
365 assert(false && "this cannot happen");
371 void propagateRelevant(std::map<OUString, Entity> & entities, Entity & entity) {
372 if (!entity.relevant) {
373 entity.relevant = true;
374 if (entity.sorted != Entity::Sorted::YES) {
375 for (auto & i: entity.dependencies) {
376 std::map<OUString, Entity>::iterator j(entities.find(i));
377 if (j != entities.end()) {
378 propagateRelevant(entities, j->second);
385 void visit(
386 std::map<OUString, Entity> & entities,
387 std::map<OUString, Entity>::iterator const & iterator,
388 std::vector<OUString> & result)
390 switch (iterator->second.sorted) {
391 case Entity::Sorted::NO:
392 iterator->second.sorted = Entity::Sorted::ACTIVE;
393 for (auto & i: iterator->second.dependencies) {
394 std::map<OUString, Entity>::iterator j(entities.find(i));
395 if (j != entities.end()) {
396 if (iterator->second.relevant) {
397 propagateRelevant(entities, j->second);
399 visit(entities, j, result);
402 iterator->second.sorted = Entity::Sorted::YES;
403 result.push_back(iterator->first);
404 break;
405 case Entity::Sorted::ACTIVE:
406 std::cerr
407 << "Entity " << iterator->first << " recursively depends on itself"
408 << std::endl;
409 std::exit(EXIT_FAILURE);
410 // fall-through avoids warnings
411 default:
412 break;
416 std::vector<OUString> sort(std::map<OUString, Entity> & entities) {
417 std::vector<OUString> res;
418 for (auto i(entities.begin()); i != entities.end(); ++i) {
419 visit(entities, i, res);
421 return res;
424 void indent(std::vector<OUString> const & modules, unsigned int extra = 0) {
425 for (std::vector<OUString>::size_type i = 0; i != modules.size(); ++i) {
426 std::cout << ' ';
428 for (unsigned int i = 0; i != extra; ++i) {
429 std::cout << ' ';
433 void closeModules(
434 std::vector<OUString> & modules, std::vector<OUString>::size_type n)
436 for (std::vector<OUString>::size_type i = 0; i != n; ++i) {
437 assert(!modules.empty());
438 modules.pop_back();
439 indent(modules);
440 std::cout << "};\n";
444 OUString openModulesFor(std::vector<OUString> & modules, OUString const & name)
446 std::vector<OUString>::iterator i(modules.begin());
447 for (sal_Int32 j = 0;;) {
448 OUString id(name.getToken(0, '.', j));
449 if (j == -1) {
450 closeModules(
451 modules,
452 static_cast< std::vector<OUString>::size_type >(
453 modules.end() - i));
454 indent(modules);
455 return id;
457 if (i != modules.end()) {
458 if (id == *i) {
459 ++i;
460 continue;
462 closeModules(
463 modules,
464 static_cast< std::vector<OUString>::size_type >(
465 modules.end() - i));
466 i = modules.end();
468 indent(modules);
469 std::cout << "module " << id << " {\n";
470 modules.push_back(id);
471 i = modules.end();
475 void writeName(OUString const & name) {
476 std::cout << "::" << name.replaceAll(".", "::");
479 void writeAnnotations(std::vector<OUString> const & annotations) {
480 if (!annotations.empty()) {
481 std::cout << "/**";
482 for (auto & i: annotations) {
483 //TODO: i.indexOf("*/") == -1
484 std::cout << " @" << i;
486 std::cout << " */ ";
490 void writePublished(rtl::Reference<unoidl::PublishableEntity> const & entity) {
491 assert(entity.is());
492 if (entity->isPublished()) {
493 std::cout << "published ";
497 void writeAnnotationsPublished(
498 rtl::Reference<unoidl::PublishableEntity> const & entity)
500 assert(entity.is());
501 writeAnnotations(entity->getAnnotations());
502 writePublished(entity);
505 void writeType(OUString const & type) {
506 std::size_t rank;
507 std::vector<OUString> args;
508 bool entity;
509 OUString nucl(decomposeType(type, &rank, &args, &entity));
510 for (std::size_t i = 0; i != rank; ++i) {
511 std::cout << "sequence< ";
513 if (entity) {
514 writeName(nucl);
515 } else {
516 std::cout << nucl;
518 if (!args.empty()) {
519 std::cout << "< ";
520 for (auto i(args.begin()); i != args.end(); ++i) {
521 if (i != args.begin()) {
522 std::cout << ", ";
524 writeType(*i);
526 std::cout << " >";
528 for (std::size_t i = 0; i != rank; ++i) {
529 std::cout << " >";
533 void writeExceptionSpecification(std::vector<OUString> const & exceptions) {
534 if (!exceptions.empty()) {
535 std::cout << " raises (";
536 for (auto i(exceptions.begin()); i != exceptions.end(); ++i) {
537 if (i != exceptions.begin()) {
538 std::cout << ", ";
540 writeName(*i);
542 std::cout << ')';
546 void writeEntity(
547 std::map<OUString, Entity> & entities, std::vector<OUString> & modules,
548 OUString const & name)
550 std::map<OUString, Entity>::iterator i(entities.find(name));
551 if (i != entities.end() && i->second.relevant) {
552 assert(!i->second.written);
553 i->second.written = true;
554 for (auto & j: i->second.interfaceDependencies) {
555 std::map<OUString, Entity>::iterator k(entities.find(j));
556 if (k != entities.end() && !k->second.written) {
557 OUString id(openModulesFor(modules, j));
558 if (k->second.entity->getSort()
559 != unoidl::Entity::SORT_INTERFACE_TYPE)
561 std::cerr
562 << "Entity " << j << " should be an interface type"
563 << std::endl;
564 std::exit(EXIT_FAILURE);
566 writePublished(
567 static_cast<unoidl::PublishableEntity *>(
568 k->second.entity.get()));
569 std::cout << "interface " << id << ";\n";
572 OUString id(openModulesFor(modules, name));
573 rtl::Reference<unoidl::PublishableEntity> ent(
574 static_cast<unoidl::PublishableEntity *>(i->second.entity.get()));
575 switch (ent->getSort()) {
576 case unoidl::Entity::SORT_ENUM_TYPE:
578 rtl::Reference<unoidl::EnumTypeEntity> ent2(
579 static_cast<unoidl::EnumTypeEntity *>(ent.get()));
580 writeAnnotationsPublished(ent);
581 std::cout << "enum " << id << " {\n";
582 for (auto j(ent2->getMembers().begin());
583 j != ent2->getMembers().end(); ++j)
585 indent(modules, 1);
586 writeAnnotations(j->annotations);
587 std::cout << j->name << " = " << j->value;
588 if (j + 1 != ent2->getMembers().end()) {
589 std::cout << ',';
591 std::cout << '\n';
593 indent(modules);
594 std::cout << "};\n";
595 break;
597 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
599 rtl::Reference<unoidl::PlainStructTypeEntity> ent2(
600 static_cast<unoidl::PlainStructTypeEntity *>(ent.get()));
601 writeAnnotationsPublished(ent);
602 std::cout << "struct " << id;
603 if (!ent2->getDirectBase().isEmpty()) {
604 std::cout << ": ";
605 writeName(ent2->getDirectBase());
607 std::cout << " {\n";
608 for (auto & j: ent2->getDirectMembers()) {
609 indent(modules, 1);
610 writeAnnotations(j.annotations);
611 writeType(j.type);
612 std::cout << ' ' << j.name << ";\n";
614 indent(modules);
615 std::cout << "};\n";
616 break;
618 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
620 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
621 ent2(
622 static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
623 ent.get()));
624 writeAnnotationsPublished(ent);
625 std::cout << "struct " << id << '<';
626 for (auto j(ent2->getTypeParameters().begin());
627 j != ent2->getTypeParameters().end(); ++j)
629 if (j != ent2->getTypeParameters().begin()) {
630 std::cout << ", ";
632 std::cout << *j;
634 std::cout << "> {\n";
635 for (auto & j: ent2->getMembers()) {
636 indent(modules, 1);
637 writeAnnotations(j.annotations);
638 if (j.parameterized) {
639 std::cout << j.type;
640 } else {
641 writeType(j.type);
643 std::cout << ' ' << j.name << ";\n";
645 indent(modules);
646 std::cout << "};\n";
647 break;
649 case unoidl::Entity::SORT_EXCEPTION_TYPE:
651 rtl::Reference<unoidl::ExceptionTypeEntity> ent2(
652 static_cast<unoidl::ExceptionTypeEntity *>(ent.get()));
653 writeAnnotationsPublished(ent);
654 std::cout << "exception " << id;
655 if (!ent2->getDirectBase().isEmpty()) {
656 std::cout << ": ";
657 writeName(ent2->getDirectBase());
659 std::cout << " {\n";
660 for (auto & j: ent2->getDirectMembers()) {
661 indent(modules, 1);
662 writeAnnotations(j.annotations);
663 writeType(j.type);
664 std::cout << ' ' << j.name << ";\n";
666 indent(modules);
667 std::cout << "};\n";
668 break;
670 case unoidl::Entity::SORT_INTERFACE_TYPE:
672 rtl::Reference<unoidl::InterfaceTypeEntity> ent2(
673 static_cast<unoidl::InterfaceTypeEntity *>(
674 ent.get()));
675 writeAnnotationsPublished(ent);
676 std::cout << "interface " << id << " {\n";
677 for (auto & j: ent2->getDirectMandatoryBases()) {
678 indent(modules, 1);
679 writeAnnotations(j.annotations);
680 std::cout << "interface ";
681 writeName(j.name);
682 std::cout << ";\n";
684 for (auto & j: ent2->getDirectOptionalBases()) {
685 indent(modules, 1);
686 writeAnnotations(j.annotations);
687 std::cout << "[optional] interface ";
688 writeName(j.name);
689 std::cout << ";\n";
691 for (auto & j: ent2->getDirectAttributes()) {
692 indent(modules, 1);
693 writeAnnotations(j.annotations);
694 std::cout << "[attribute";
695 if (j.bound) {
696 std::cout << ", bound";
698 if (j.readOnly) {
699 std::cout << ", readonly";
701 std::cout << "] ";
702 writeType(j.type);
703 std::cout << ' ' << j.name;
704 if (!(j.getExceptions.empty() && j.setExceptions.empty())) {
705 std::cout << " {\n";
706 if (!j.getExceptions.empty()) {
707 indent(modules, 2);
708 std::cout << "get";
709 writeExceptionSpecification(j.getExceptions);
710 std::cout << ";\n";
712 if (!j.setExceptions.empty()) {
713 indent(modules, 2);
714 std::cout << "set";
715 writeExceptionSpecification(j.setExceptions);
716 std::cout << ";\n";
718 std::cout << " }";
720 std::cout << ";\n";
722 for (auto & j: ent2->getDirectMethods()) {
723 indent(modules, 1);
724 writeAnnotations(j.annotations);
725 writeType(j.returnType);
726 std::cout << ' ' << j.name << '(';
727 for (auto k(j.parameters.begin()); k != j.parameters.end();
728 ++k)
730 if (k != j.parameters.begin()) {
731 std::cout << ", ";
733 switch (k->direction) {
734 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN:
735 std::cout << "[in] ";
736 break;
737 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT:
738 std::cout << "[out] ";
739 break;
740 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT:
741 std::cout << "[inout] ";
742 break;
744 writeType(k->type);
745 std::cout << ' ' << k->name;
747 std::cout << ')';
748 writeExceptionSpecification(j.exceptions);
749 std::cout << ";\n";
751 indent(modules);
752 std::cout << "};\n";
753 break;
755 case unoidl::Entity::SORT_TYPEDEF:
757 rtl::Reference<unoidl::TypedefEntity> ent2(
758 static_cast<unoidl::TypedefEntity *>(ent.get()));
759 writeAnnotationsPublished(ent);
760 std::cout << "typedef ";
761 writeType(ent2->getType());
762 std::cout << ' ' << id << ";\n";
763 break;
765 case unoidl::Entity::SORT_CONSTANT_GROUP:
767 rtl::Reference<unoidl::ConstantGroupEntity> ent2(
768 static_cast<unoidl::ConstantGroupEntity *>(ent.get()));
769 writeAnnotationsPublished(ent);
770 std::cout << "constants " << id << " {\n";
771 for (auto & j: ent2->getMembers()) {
772 indent(modules, 1);
773 writeAnnotations(j.annotations);
774 std::cout << "const ";
775 switch (j.value.type) {
776 case unoidl::ConstantValue::TYPE_BOOLEAN:
777 std::cout << "boolean";
778 break;
779 case unoidl::ConstantValue::TYPE_BYTE:
780 std::cout << "byte";
781 break;
782 case unoidl::ConstantValue::TYPE_SHORT:
783 std::cout << "short";
784 break;
785 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
786 std::cout << "unsigned short";
787 break;
788 case unoidl::ConstantValue::TYPE_LONG:
789 std::cout << "long";
790 break;
791 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
792 std::cout << "unsigned long";
793 break;
794 case unoidl::ConstantValue::TYPE_HYPER:
795 std::cout << "hyper";
796 break;
797 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
798 std::cout << "unsigned hyper";
799 break;
800 case unoidl::ConstantValue::TYPE_FLOAT:
801 std::cout << "float";
802 break;
803 case unoidl::ConstantValue::TYPE_DOUBLE:
804 std::cout << "double";
805 break;
807 std::cout << ' ' << j.name << " = ";
808 switch (j.value.type) {
809 case unoidl::ConstantValue::TYPE_BOOLEAN:
810 std::cout << (j.value.booleanValue ? "TRUE" : "FALSE");
811 break;
812 case unoidl::ConstantValue::TYPE_BYTE:
813 std::cout << int(j.value.byteValue);
814 break;
815 case unoidl::ConstantValue::TYPE_SHORT:
816 std::cout << j.value.shortValue;
817 break;
818 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
819 std::cout << j.value.unsignedShortValue;
820 break;
821 case unoidl::ConstantValue::TYPE_LONG:
822 std::cout << j.value.longValue;
823 break;
824 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
825 std::cout << j.value.unsignedLongValue;
826 break;
827 case unoidl::ConstantValue::TYPE_HYPER:
828 std::cout << j.value.hyperValue;
829 break;
830 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
831 std::cout << j.value.unsignedHyperValue;
832 break;
833 case unoidl::ConstantValue::TYPE_FLOAT:
834 std::cout << j.value.floatValue;
835 break;
836 case unoidl::ConstantValue::TYPE_DOUBLE:
837 std::cout << j.value.doubleValue;
838 break;
840 std::cout << ";\n";
842 indent(modules);
843 std::cout << "};\n";
844 break;
846 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
848 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity> ent2(
849 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
850 ent.get()));
851 writeAnnotationsPublished(ent);
852 std::cout << "service " << id << ": ";
853 writeName(ent2->getBase());
854 if (ent2->getConstructors().size() != 1
855 || !ent2->getConstructors().front().defaultConstructor)
857 std::cout << " {\n";
858 for (auto & j: ent2->getConstructors()) {
859 indent(modules, 1);
860 writeAnnotations(j.annotations);
861 std::cout << j.name << '(';
862 for (auto k(j.parameters.begin());
863 k != j.parameters.end(); ++k)
865 if (k != j.parameters.begin()) {
866 std::cout << ", ";
868 std::cout << "[in] ";
869 writeType(k->type);
870 if (k->rest) {
871 std::cout << "...";
873 std::cout << ' ' << k->name;
875 std::cout << ')';
876 writeExceptionSpecification(j.exceptions);
877 std::cout << ";\n";
879 indent(modules);
880 std::cout << '}';
882 std::cout << ";\n";
883 break;
885 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
887 rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2(
888 static_cast<unoidl::AccumulationBasedServiceEntity *>(
889 ent.get()));
890 writeAnnotationsPublished(ent);
891 std::cout << "service " << id << " {\n";
892 for (auto & j: ent2->getDirectMandatoryBaseServices()) {
893 indent(modules, 1);
894 writeAnnotations(j.annotations);
895 std::cout << "service ";
896 writeName(j.name);
897 std::cout << ";\n";
899 for (auto & j: ent2->getDirectOptionalBaseServices()) {
900 indent(modules, 1);
901 writeAnnotations(j.annotations);
902 std::cout << "[optional] service ";
903 writeName(j.name);
904 std::cout << ";\n";
906 for (auto & j: ent2->getDirectMandatoryBaseInterfaces()) {
907 indent(modules, 1);
908 writeAnnotations(j.annotations);
909 std::cout << "interface ";
910 writeName(j.name);
911 std::cout << ";\n";
913 for (auto & j: ent2->getDirectOptionalBaseInterfaces()) {
914 indent(modules, 1);
915 writeAnnotations(j.annotations);
916 std::cout << "[optional] interface ";
917 writeName(j.name);
918 std::cout << ";\n";
920 for (auto & j: ent2->getDirectProperties()) {
921 indent(modules, 1);
922 writeAnnotations(j.annotations);
923 std::cout << "[property";
924 if ((j.attributes
925 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_BOUND)
926 != 0)
928 std::cout << ", bound";
930 if ((j.attributes
931 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_CONSTRAINED)
932 != 0)
934 std::cout << ", constrained";
936 if ((j.attributes
937 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_AMBIGUOUS)
938 != 0)
940 std::cout << ", maybeambiguous";
942 if ((j.attributes
943 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_DEFAULT)
944 != 0)
946 std::cout << ", maybedefault";
948 if ((j.attributes
949 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_MAYBE_VOID)
950 != 0)
952 std::cout << ", maybevoid";
954 if ((j.attributes
955 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL)
956 != 0)
958 std::cout << ", optional";
960 if ((j.attributes
961 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_READ_ONLY)
962 != 0)
964 std::cout << ", readonly";
966 if ((j.attributes
967 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_REMOVABLE)
968 != 0)
970 std::cout << ", removable";
972 if ((j.attributes
973 & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_TRANSIENT)
974 != 0)
976 std::cout << ", transient";
978 std::cout << "] ";
979 writeType(j.type);
980 std::cout << ' ' << j.name << ";\n";
982 indent(modules);
983 std::cout << "};\n";
984 break;
986 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
988 rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2(
989 static_cast<unoidl::InterfaceBasedSingletonEntity *>(
990 ent.get()));
991 writeAnnotationsPublished(ent);
992 std::cout << "singleton " << id << ": ";
993 writeName(ent2->getBase());
994 std::cout << ";\n";
995 break;
997 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
999 rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2(
1000 static_cast<unoidl::ServiceBasedSingletonEntity *>(
1001 ent.get()));
1002 writeAnnotationsPublished(ent);
1003 std::cout << "singleton " << id << " { service ";
1004 writeName(ent2->getBase());
1005 std::cout << "; };";
1006 break;
1008 case unoidl::Entity::SORT_MODULE:
1009 assert(false && "this cannot happen");
1016 SAL_IMPLEMENT_MAIN() {
1017 try {
1018 sal_uInt32 args = rtl_getAppCommandArgCount();
1019 if (args == 0) {
1020 badUsage();
1022 OUString arg;
1023 rtl_getAppCommandArg(0, &arg.pData);
1024 bool published = arg == "--published";
1025 if (published && args == 1) {
1026 badUsage();
1028 rtl::Reference<unoidl::Manager> mgr(new unoidl::Manager);
1029 rtl::Reference<unoidl::Provider> prov;
1030 for (sal_uInt32 i = (published ? 1 : 0); i != args; ++i) {
1031 OUString uri(getArgumentUri(i));
1032 try {
1033 prov = mgr->addProvider(uri);
1034 } catch (unoidl::NoSuchFileException &) {
1035 std::cerr
1036 << "Input <" << uri << "> does not exist" << std::endl;
1037 std::exit(EXIT_FAILURE);
1040 std::map<OUString, Entity> ents;
1041 scanMap(mgr, prov->createRootCursor(), published, "", ents);
1042 std::vector<OUString> sorted(sort(ents));
1043 std::vector<OUString> mods;
1044 for (auto & i: sorted) {
1045 writeEntity(ents, mods, i);
1047 closeModules(mods, mods.size());
1048 return EXIT_SUCCESS;
1049 } catch (unoidl::FileFormatException & e1) {
1050 std::cerr
1051 << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1052 << std::endl;
1053 std::exit(EXIT_FAILURE);
1054 } catch (std::exception & e1) {
1055 std::cerr << "Failure: " << e1.what() << std::endl;
1056 std::exit(EXIT_FAILURE);
1060 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */