bump product version to 5.0.4.1
[LibreOffice.git] / unoidl / source / unoidl-check.cxx
blob22dff88d5f519cdc4859ea1b9de18453c0b5feb0
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 <algorithm>
13 #include <cassert>
14 #include <cstdlib>
15 #include <iostream>
16 #include <vector>
18 #include "osl/file.hxx"
19 #include "osl/process.h"
20 #include "rtl/character.hxx"
21 #include "rtl/process.h"
22 #include "rtl/ref.hxx"
23 #include "rtl/ustring.hxx"
24 #include "sal/main.h"
25 #include "sal/types.h"
26 #include "unoidl/unoidl.hxx"
28 namespace unoidl {
30 bool operator ==(ConstantValue const & lhs, ConstantValue const & rhs) {
31 if (lhs.type == rhs.type) {
32 switch (lhs.type) {
33 case ConstantValue::TYPE_BOOLEAN:
34 return lhs.booleanValue == rhs.booleanValue;
35 case ConstantValue::TYPE_BYTE:
36 return lhs.byteValue == rhs.byteValue;
37 case ConstantValue::TYPE_SHORT:
38 return lhs.shortValue == rhs.shortValue;
39 case ConstantValue::TYPE_UNSIGNED_SHORT:
40 return lhs.unsignedShortValue == rhs.unsignedShortValue;
41 case ConstantValue::TYPE_LONG:
42 return lhs.longValue == rhs.longValue;
43 case ConstantValue::TYPE_UNSIGNED_LONG:
44 return lhs.unsignedLongValue == rhs.unsignedLongValue;
45 case ConstantValue::TYPE_HYPER:
46 return lhs.hyperValue == rhs.hyperValue;
47 case ConstantValue::TYPE_UNSIGNED_HYPER:
48 return lhs.unsignedHyperValue == rhs.unsignedHyperValue;
49 case ConstantValue::TYPE_FLOAT:
50 return lhs.floatValue == rhs.floatValue;
51 case ConstantValue::TYPE_DOUBLE:
52 return lhs.doubleValue == rhs.doubleValue;
55 return false;
58 bool operator !=(ConstantValue const & lhs, ConstantValue const & rhs) {
59 return !(lhs == rhs);
62 bool operator ==(
63 SingleInterfaceBasedServiceEntity::Constructor::Parameter const & lhs,
64 SingleInterfaceBasedServiceEntity::Constructor::Parameter const & rhs)
66 return lhs.name == rhs.name && lhs.type == rhs.type && lhs.rest == rhs.rest;
71 namespace {
73 void badUsage() {
74 std::cerr
75 << "Usage:" << std::endl << std::endl
76 << (" unoidl-check [<extra registries A>] <registry A> -- [<extra"
77 " registries B>]")
78 << std::endl << " <registry B>" << std::endl << std::endl
79 << ("where each <registry> is either a new- or legacy-format .rdb file,"
80 " a single .idl")
81 << std::endl
82 << ("file, or a root directory of an .idl file tree. Check that each"
83 " entity from")
84 << std::endl
85 << "<registry A> is also present in <registry B> in a compatible form."
86 << std::endl;
87 std::exit(EXIT_FAILURE);
90 OUString getArgumentUri(sal_uInt32 argument, bool * delimiter) {
91 OUString arg;
92 rtl_getAppCommandArg(argument, &arg.pData);
93 if (arg == "--") {
94 if (delimiter == 0) {
95 badUsage();
97 *delimiter = true;
98 return OUString();
100 OUString url;
101 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
102 if (e1 != osl::FileBase::E_None) {
103 std::cerr
104 << "Cannot convert \"" << arg << "\" to file URL, error code "
105 << +e1 << std::endl;
106 std::exit(EXIT_FAILURE);
108 OUString cwd;
109 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
110 if (e2 != osl_Process_E_None) {
111 std::cerr
112 << "Cannot obtain working directory, error code " << +e2
113 << std::endl;
114 std::exit(EXIT_FAILURE);
116 OUString abs;
117 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
118 if (e1 != osl::FileBase::E_None) {
119 std::cerr
120 << "Cannot make \"" << url
121 << "\" into an absolute file URL, error code " << +e1 << std::endl;
122 std::exit(EXIT_FAILURE);
124 return abs;
127 OUString showDirection(
128 unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction)
130 switch (direction) {
131 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN:
132 return OUString("[in]");
133 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT:
134 return OUString("[out]");
135 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT:
136 return OUString("[inout]");
137 default:
138 assert(false && "this cannot happen"); for (;;) { std::abort(); }
142 struct EqualsAnnotation {
143 EqualsAnnotation(OUString const & name): name_(name) {}
145 bool operator ()(unoidl::AnnotatedReference const & ref)
146 { return ref.name == name_; }
148 private:
149 OUString name_;
152 void checkMap(
153 rtl::Reference<unoidl::Provider> const & providerB, OUString const & prefix,
154 rtl::Reference<unoidl::MapCursor> const & cursor)
156 assert(providerB.is());
157 assert(cursor.is());
158 for (;;) {
159 OUString id;
160 rtl::Reference<unoidl::Entity> entA(cursor->getNext(&id));
161 if (!entA.is()) {
162 break;
164 OUString name(prefix + id);
165 if (entA->getSort() == unoidl::Entity::SORT_MODULE) {
166 checkMap(
167 providerB, name + ".",
168 (static_cast<unoidl::ModuleEntity *>(entA.get())
169 ->createCursor()));
170 } else {
171 rtl::Reference<unoidl::Entity> entB(providerB->findEntity(name));
172 if (!entB.is()) {
173 std::cerr
174 << "A entity " << name << " is not present in B"
175 << std::endl;
176 std::exit(EXIT_FAILURE);
178 if (entA->getSort() != entB->getSort()) {
179 std::cerr
180 << "A entity " << name << " is of different sort in B"
181 << std::endl;
182 std::exit(EXIT_FAILURE);
184 if ((dynamic_cast<unoidl::PublishableEntity &>(*entA.get())
185 .isPublished())
186 && (!dynamic_cast<unoidl::PublishableEntity &>(*entB.get())
187 .isPublished()))
189 std::cerr
190 << "A published entity " << name << " is not published in B"
191 << std::endl;
192 std::exit(EXIT_FAILURE);
194 switch (entA->getSort()) {
195 case unoidl::Entity::SORT_MODULE:
196 assert(false && "this cannot happen");
197 //deliberate fall-through anyway
198 case unoidl::Entity::SORT_ENUM_TYPE:
200 rtl::Reference<unoidl::EnumTypeEntity> ent2A(
201 static_cast<unoidl::EnumTypeEntity *>(entA.get()));
202 rtl::Reference<unoidl::EnumTypeEntity> ent2B(
203 static_cast<unoidl::EnumTypeEntity *>(entB.get()));
204 if (ent2A->getMembers().size()
205 != ent2B->getMembers().size())
207 std::cerr
208 << "enum type " << name
209 << " number of members changed from "
210 << ent2A->getMembers().size() << " to "
211 << ent2B->getMembers().size() << std::endl;
212 std::exit(EXIT_FAILURE);
214 for (std::vector<unoidl::EnumTypeEntity::Member>::const_iterator
215 i(ent2A->getMembers().begin()),
216 j(ent2B->getMembers().begin());
217 i != ent2A->getMembers().end(); ++i, ++j)
219 if (i->name != j->name || i->value != j->value) {
220 std::cerr
221 << "enum type " << name << " member #"
222 << i - ent2A->getMembers().begin() + 1
223 << " changed from " << i->name << " = "
224 << i->value << " to " << j->name << " = "
225 << j->value << std::endl;
226 std::exit(EXIT_FAILURE);
229 break;
231 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
233 rtl::Reference<unoidl::PlainStructTypeEntity> ent2A(
234 static_cast<unoidl::PlainStructTypeEntity *>(
235 entA.get()));
236 rtl::Reference<unoidl::PlainStructTypeEntity> ent2B(
237 static_cast<unoidl::PlainStructTypeEntity *>(
238 entB.get()));
239 if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
240 std::cerr
241 << "plain struct type " << name
242 << " direct base changed from "
243 << (ent2A->getDirectBase().isEmpty()
244 ? OUString("none") : ent2A->getDirectBase())
245 << " to "
246 << (ent2B->getDirectBase().isEmpty()
247 ? OUString("none") : ent2B->getDirectBase())
248 << std::endl;
249 std::exit(EXIT_FAILURE);
251 if (ent2A->getDirectMembers().size()
252 != ent2B->getDirectMembers().size())
254 std::cerr
255 << "plain struct type " << name
256 << " number of direct members changed from "
257 << ent2A->getDirectMembers().size() << " to "
258 << ent2B->getDirectMembers().size() << std::endl;
259 std::exit(EXIT_FAILURE);
261 for (std::vector<unoidl::PlainStructTypeEntity::Member>::const_iterator
262 i(ent2A->getDirectMembers().begin()),
263 j(ent2B->getDirectMembers().begin());
264 i != ent2A->getDirectMembers().end(); ++i, ++j)
266 if (i->name != j->name || i->type != j->type) {
267 std::cerr
268 << "plain struct type " << name
269 << " direct member #"
270 << i - ent2A->getDirectMembers().begin() + 1
271 << " changed from " << i->type << " " << i->name
272 << " to " << j->type << " " << j->name
273 << std::endl;
274 std::exit(EXIT_FAILURE);
277 break;
279 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
281 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
282 ent2A(
283 static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
284 entA.get()));
285 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
286 ent2B(
287 static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
288 entB.get()));
289 if (ent2A->getTypeParameters().size()
290 != ent2B->getTypeParameters().size())
292 std::cerr
293 << "polymorphic struct type template " << name
294 << " number of type parameters changed from "
295 << ent2A->getTypeParameters().size() << " to "
296 << ent2B->getTypeParameters().size() << std::endl;
297 std::exit(EXIT_FAILURE);
299 for (std::vector<OUString>::const_iterator
300 i(ent2A->getTypeParameters().begin()),
301 j(ent2B->getTypeParameters().begin());
302 i != ent2A->getTypeParameters().end(); ++i, ++j)
304 if (*i != *j) {
305 std::cerr
306 << "polymorphic struct type template " << name
307 << " type parameter #"
308 << i - ent2A->getTypeParameters().begin() + 1
309 << " changed from " << *i << " to " << *j
310 << std::endl;
311 std::exit(EXIT_FAILURE);
314 if (ent2A->getMembers().size()
315 != ent2B->getMembers().size())
317 std::cerr
318 << "polymorphic struct type template " << name
319 << " number of members changed from "
320 << ent2A->getMembers().size() << " to "
321 << ent2B->getMembers().size() << std::endl;
322 std::exit(EXIT_FAILURE);
324 for (std::vector<unoidl::PolymorphicStructTypeTemplateEntity::Member>::const_iterator
325 i(ent2A->getMembers().begin()),
326 j(ent2B->getMembers().begin());
327 i != ent2A->getMembers().end(); ++i, ++j)
329 if (i->name != j->name || i->type != j->type
330 || i->parameterized != j->parameterized)
332 std::cerr
333 << "polymorphic struct type template " << name
334 << " member #"
335 << i - ent2A->getMembers().begin() + 1
336 << " changed from "
337 << (i->parameterized
338 ? OUString("parameterized ") : OUString())
339 << i->type << " " << i->name
340 << " to "
341 << (j->parameterized
342 ? OUString("parameterized ") : OUString())
343 << j->type << " " << j->name
344 << std::endl;
345 std::exit(EXIT_FAILURE);
348 break;
350 case unoidl::Entity::SORT_EXCEPTION_TYPE:
352 rtl::Reference<unoidl::ExceptionTypeEntity> ent2A(
353 static_cast<unoidl::ExceptionTypeEntity *>(entA.get()));
354 rtl::Reference<unoidl::ExceptionTypeEntity> ent2B(
355 static_cast<unoidl::ExceptionTypeEntity *>(entB.get()));
356 if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
357 std::cerr
358 << "exception type " << name
359 << " direct base changed from "
360 << (ent2A->getDirectBase().isEmpty()
361 ? OUString("none") : ent2A->getDirectBase())
362 << " to "
363 << (ent2B->getDirectBase().isEmpty()
364 ? OUString("none") : ent2B->getDirectBase())
365 << std::endl;
366 std::exit(EXIT_FAILURE);
368 if (ent2A->getDirectMembers().size()
369 != ent2B->getDirectMembers().size())
371 std::cerr
372 << "exception type " << name
373 << " number of direct members changed from "
374 << ent2A->getDirectMembers().size() << " to "
375 << ent2B->getDirectMembers().size() << std::endl;
376 std::exit(EXIT_FAILURE);
378 for (std::vector<unoidl::ExceptionTypeEntity::Member>::const_iterator
379 i(ent2A->getDirectMembers().begin()),
380 j(ent2B->getDirectMembers().begin());
381 i != ent2A->getDirectMembers().end(); ++i, ++j)
383 if (i->name != j->name || i->type != j->type) {
384 std::cerr
385 << "exception type " << name
386 << " direct member #"
387 << i - ent2A->getDirectMembers().begin() + 1
388 << " changed from " << i->type << " " << i->name
389 << " to " << j->type << " " << j->name
390 << std::endl;
391 std::exit(EXIT_FAILURE);
394 break;
396 case unoidl::Entity::SORT_INTERFACE_TYPE:
398 rtl::Reference<unoidl::InterfaceTypeEntity> ent2A(
399 static_cast<unoidl::InterfaceTypeEntity *>(entA.get()));
400 rtl::Reference<unoidl::InterfaceTypeEntity> ent2B(
401 static_cast<unoidl::InterfaceTypeEntity *>(entB.get()));
402 if (ent2A->getDirectMandatoryBases().size()
403 != ent2B->getDirectMandatoryBases().size())
405 std::cerr
406 << "interface type " << name
407 << " number of direct mandatory bases changed from "
408 << ent2A->getDirectMandatoryBases().size() << " to "
409 << ent2B->getDirectMandatoryBases().size()
410 << std::endl;
411 std::exit(EXIT_FAILURE);
413 for (std::vector<unoidl::AnnotatedReference>::const_iterator
414 i(ent2A->getDirectMandatoryBases().begin()),
415 j(ent2B->getDirectMandatoryBases().begin());
416 i != ent2A->getDirectMandatoryBases().end(); ++i, ++j)
418 if (i->name != j->name) {
419 std::cerr
420 << "interface type " << name
421 << " direct mandatory base #"
422 << (i - ent2A->getDirectMandatoryBases().begin()
423 + 1)
424 << " changed from " << i->name << " to "
425 << j->name << std::endl;
426 std::exit(EXIT_FAILURE);
429 if (ent2A->getDirectOptionalBases().size()
430 != ent2B->getDirectOptionalBases().size())
432 std::cerr
433 << "interface type " << name
434 << " number of direct optional bases changed from "
435 << ent2A->getDirectOptionalBases().size() << " to "
436 << ent2B->getDirectOptionalBases().size()
437 << std::endl;
438 std::exit(EXIT_FAILURE);
440 for (std::vector<unoidl::AnnotatedReference>::const_iterator
441 i(ent2A->getDirectOptionalBases().begin()),
442 j(ent2B->getDirectOptionalBases().begin());
443 i != ent2A->getDirectOptionalBases().end(); ++i, ++j)
445 if (i->name != j->name) {
446 std::cerr
447 << "interface type " << name
448 << " direct optional base #"
449 << (i - ent2A->getDirectOptionalBases().begin()
450 + 1)
451 << " changed from " << i->name << " to "
452 << j->name << std::endl;
453 std::exit(EXIT_FAILURE);
456 if (ent2A->getDirectAttributes().size()
457 != ent2B->getDirectAttributes().size())
459 std::cerr
460 << "interface type " << name
461 << " number of direct attributes changed from "
462 << ent2A->getDirectAttributes().size() << " to "
463 << ent2B->getDirectAttributes().size() << std::endl;
464 std::exit(EXIT_FAILURE);
466 for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator
467 i(ent2A->getDirectAttributes().begin()),
468 j(ent2B->getDirectAttributes().begin());
469 i != ent2A->getDirectAttributes().end(); ++i, ++j)
471 if (i->name != j->name || i->type != j->type
472 || i->bound != j->bound
473 || i->readOnly != j->readOnly
474 || i->getExceptions != j->getExceptions
475 || i->setExceptions != j->setExceptions)
477 std::cerr
478 << "interface type " << name
479 << " direct attribute #"
480 << i - ent2A->getDirectAttributes().begin() + 1
481 << " changed from "
482 << (i->bound ? OUString("bound ") : OUString())
483 << (i->readOnly
484 ? OUString("read-only ") : OUString())
485 << i->type << " " << i->name //TODO: exceptions
486 << " to "
487 << (j->bound ? OUString("bound ") : OUString())
488 << (j->readOnly
489 ? OUString("read-only ") : OUString())
490 << j->type << " " << j->name //TODO: exceptions
491 << std::endl;
492 std::exit(EXIT_FAILURE);
495 if (ent2A->getDirectMethods().size()
496 != ent2B->getDirectMethods().size())
498 std::cerr
499 << "interface type " << name
500 << " number of direct methods changed from "
501 << ent2A->getDirectMethods().size() << " to "
502 << ent2B->getDirectMethods().size() << std::endl;
503 std::exit(EXIT_FAILURE);
505 for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator
506 i(ent2A->getDirectMethods().begin()),
507 j(ent2B->getDirectMethods().begin());
508 i != ent2A->getDirectMethods().end(); ++i, ++j)
510 if (i->name != j->name || i->returnType != j->returnType
511 || i->exceptions != j->exceptions)
513 std::cerr
514 << "interface type " << name
515 << " direct method #"
516 << i - ent2A->getDirectMethods().begin() + 1
517 << " changed from "
518 << i->returnType << " " << i->name //TODO: exceptions
519 << " to " << j->returnType << " " << j->name //TODO: exceptions
520 << std::endl;
521 std::exit(EXIT_FAILURE);
523 if (i->parameters.size() != j->parameters.size()) {
524 std::cerr
525 << "interface type " << name
526 << " direct method " << i->name
527 << " number of parameters changed from "
528 << i->parameters.size() << " to "
529 << j->parameters.size() << std::endl;
530 std::exit(EXIT_FAILURE);
532 for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::const_iterator
533 k(i->parameters.begin()),
534 l(j->parameters.begin());
535 k != i->parameters.end(); ++k, ++l)
537 if (k->type != l->type || k->direction != l->direction)
539 std::cerr
540 << "interface type " << name
541 << " direct method " << i->name
542 << " parameter #"
543 << k - i->parameters.begin() + 1
544 << " changed from "
545 << showDirection(k->direction) << " "
546 << k->type << " to "
547 << showDirection(l->direction) << " "
548 << l->type << std::endl;
549 std::exit(EXIT_FAILURE);
551 if (k->name != l->name) {
552 std::cerr
553 << "interface type " << name
554 << " direct method " << i->name
555 << " parameter #"
556 << k - i->parameters.begin() + 1
557 << " changed name from " << k->name
558 << " to " << l->name << std::endl;
559 std::exit(EXIT_FAILURE);
563 break;
565 case unoidl::Entity::SORT_TYPEDEF:
567 rtl::Reference<unoidl::TypedefEntity> ent2A(
568 static_cast<unoidl::TypedefEntity *>(entA.get()));
569 rtl::Reference<unoidl::TypedefEntity> ent2B(
570 static_cast<unoidl::TypedefEntity *>(entB.get()));
571 if (ent2A->getType() != ent2B->getType()) {
572 std::cerr
573 << "typedef " << name << " type changed from "
574 << ent2A->getType() << " to " << ent2B->getType()
575 << std::endl;
576 std::exit(EXIT_FAILURE);
578 break;
580 case unoidl::Entity::SORT_CONSTANT_GROUP:
582 rtl::Reference<unoidl::ConstantGroupEntity> ent2A(
583 static_cast<unoidl::ConstantGroupEntity *>(entA.get()));
584 rtl::Reference<unoidl::ConstantGroupEntity> ent2B(
585 static_cast<unoidl::ConstantGroupEntity *>(entB.get()));
586 for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
587 i(ent2A->getMembers().begin());
588 i != ent2A->getMembers().end(); ++i)
590 bool found = false;
591 for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
592 j(ent2B->getMembers().begin());
593 j != ent2B->getMembers().end(); ++j)
595 if (i->name == j->name) {
596 if (i->value != j->value) {
597 std::cerr
598 << "constant group " << name
599 << " member " << i->name
600 << " changed value" << std::endl;
601 std::exit(EXIT_FAILURE);
603 found = true;
604 break;
607 if (!found) {
608 std::cerr
609 << "A constant group " << name << " member "
610 << i->name << " is not present in B"
611 << std::endl;
612 std::exit(EXIT_FAILURE);
615 break;
617 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
619 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
620 ent2A(
621 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
622 entA.get()));
623 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
624 ent2B(
625 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
626 entB.get()));
627 if (ent2A->getBase() != ent2B->getBase()) {
628 std::cerr
629 << "single-interface--based servcie " << name
630 << " base changed from " << ent2A->getBase()
631 << " to " << ent2B->getBase()
632 << std::endl;
633 std::exit(EXIT_FAILURE);
635 if (ent2A->getConstructors().size()
636 != ent2B->getConstructors().size())
638 std::cerr
639 << "single-interface--based service " << name
640 << " number of constructors changed from "
641 << ent2A->getConstructors().size() << " to "
642 << ent2B->getConstructors().size() << std::endl;
643 std::exit(EXIT_FAILURE);
645 for (std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor>::const_iterator
646 i(ent2A->getConstructors().begin()),
647 j(ent2B->getConstructors().begin());
648 i != ent2A->getConstructors().end(); ++i, ++j)
650 if (i->name != j->name || i->parameters != j->parameters
651 || i->exceptions != j->exceptions
652 || i->defaultConstructor != j->defaultConstructor)
654 std::cerr
655 << "single-interface--based service " << name
656 << " constructor #"
657 << i - ent2A->getConstructors().begin() + 1
658 << " changed from "
659 << (i->defaultConstructor
660 ? OUString("default ") : i->name) //TODO: parameters, exceptions
661 << " to "
662 << (j->defaultConstructor
663 ? OUString("default ") : j->name) //TODO: parameters, exceptions
664 << std::endl;
665 std::exit(EXIT_FAILURE);
668 break;
670 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
672 rtl::Reference<unoidl::AccumulationBasedServiceEntity>
673 ent2A(
674 static_cast<unoidl::AccumulationBasedServiceEntity *>(
675 entA.get()));
676 rtl::Reference<unoidl::AccumulationBasedServiceEntity>
677 ent2B(
678 static_cast<unoidl::AccumulationBasedServiceEntity *>(
679 entB.get()));
680 if (ent2A->getDirectMandatoryBaseServices().size()
681 != ent2B->getDirectMandatoryBaseServices().size())
683 std::cerr
684 << "accumulation-based service " << name
685 << (" number of direct mandatory base services"
686 " changed from ")
687 << ent2A->getDirectMandatoryBaseServices().size()
688 << " to "
689 << ent2B->getDirectMandatoryBaseServices().size()
690 << std::endl;
691 std::exit(EXIT_FAILURE);
693 for (std::vector<unoidl::AnnotatedReference>::const_iterator
694 i(ent2A->getDirectMandatoryBaseServices().begin()),
695 j(ent2B->getDirectMandatoryBaseServices().begin());
696 i != ent2A->getDirectMandatoryBaseServices().end();
697 ++i, ++j)
699 if (i->name != j->name) {
700 std::cerr
701 << "accumulation-based service " << name
702 << " direct mandatory base service #"
703 << (i
704 - (ent2A->getDirectMandatoryBaseServices()
705 .begin())
706 + 1)
707 << " changed from " << i->name << " to "
708 << j->name << std::endl;
709 std::exit(EXIT_FAILURE);
712 if (ent2A->getDirectOptionalBaseServices().size()
713 > ent2B->getDirectOptionalBaseServices().size())
715 std::cerr
716 << "accumulation-based service " << name
717 << (" number of direct optional base services"
718 " shrank from ")
719 << ent2A->getDirectOptionalBaseServices().size()
720 << " to "
721 << ent2B->getDirectOptionalBaseServices().size()
722 << std::endl;
723 std::exit(EXIT_FAILURE);
725 for (std::vector<unoidl::AnnotatedReference>::const_iterator
726 i(ent2A->getDirectOptionalBaseServices().begin());
727 i != ent2A->getDirectOptionalBaseServices().end();
728 ++i)
730 if (std::find_if(
731 ent2B->getDirectOptionalBaseServices().begin(),
732 ent2B->getDirectOptionalBaseServices().end(),
733 EqualsAnnotation(i->name))
734 == ent2B->getDirectOptionalBaseServices().end())
736 std::cerr
737 << "accumulation-based service " << name
738 << " direct optional base service " << i->name
739 << " was removed" << std::endl;
740 std::exit(EXIT_FAILURE);
743 if (ent2A->getDirectMandatoryBaseInterfaces().size()
744 != ent2B->getDirectMandatoryBaseInterfaces().size())
746 std::cerr
747 << "accumulation-based service " << name
748 << (" number of direct mandatory base interfaces"
749 " changed from ")
750 << ent2A->getDirectMandatoryBaseInterfaces().size()
751 << " to "
752 << ent2B->getDirectMandatoryBaseInterfaces().size()
753 << std::endl;
754 std::exit(EXIT_FAILURE);
756 for (std::vector<unoidl::AnnotatedReference>::const_iterator
757 i(ent2A->getDirectMandatoryBaseInterfaces()
758 .begin()),
759 j(ent2B->getDirectMandatoryBaseInterfaces()
760 .begin());
761 i != ent2A->getDirectMandatoryBaseInterfaces().end();
762 ++i, ++j)
764 if (i->name != j->name) {
765 std::cerr
766 << "accumulation-based service " << name
767 << " direct mandatory base interface #"
768 << (i
769 - (ent2A->getDirectMandatoryBaseInterfaces()
770 .begin())
771 + 1)
772 << " changed from " << i->name << " to "
773 << j->name << std::endl;
774 std::exit(EXIT_FAILURE);
777 if (ent2A->getDirectOptionalBaseInterfaces().size()
778 > ent2B->getDirectOptionalBaseInterfaces().size())
780 std::cerr
781 << "accumulation-based service " << name
782 << (" number of direct optional base interfaces"
783 " shrank from ")
784 << ent2A->getDirectOptionalBaseInterfaces().size()
785 << " to "
786 << ent2B->getDirectOptionalBaseInterfaces().size()
787 << std::endl;
788 std::exit(EXIT_FAILURE);
790 for (std::vector<unoidl::AnnotatedReference>::const_iterator
791 i(ent2A->getDirectOptionalBaseInterfaces()
792 .begin());
793 i != ent2A->getDirectOptionalBaseInterfaces().end();
794 ++i)
796 if (std::find_if(
797 (ent2B->getDirectOptionalBaseInterfaces()
798 .begin()),
799 ent2B->getDirectOptionalBaseInterfaces().end(),
800 EqualsAnnotation(i->name))
801 == ent2B->getDirectOptionalBaseInterfaces().end())
803 std::cerr
804 << "accumulation-based service " << name
805 << " direct optional base interface " << i->name
806 << " was removed" << std::endl;
807 std::exit(EXIT_FAILURE);
810 if (ent2A->getDirectProperties().size()
811 > ent2B->getDirectProperties().size())
813 std::cerr
814 << "accumulation-based service " << name
815 << " number of direct properties changed from "
816 << ent2A->getDirectProperties().size() << " to "
817 << ent2B->getDirectProperties().size() << std::endl;
818 std::exit(EXIT_FAILURE);
820 for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
821 i(ent2A->getDirectProperties().begin()),
822 j(ent2B->getDirectProperties().begin());
823 i != ent2A->getDirectProperties().end(); ++i, ++j)
825 if (i->name != j->name || i->type != j->type
826 || i->attributes != j->attributes)
828 std::cerr
829 << "accumulation-based service " << name
830 << " direct property #"
831 << i - ent2A->getDirectProperties().begin() + 1
832 << " changed from "
833 << i->type << " " << i->name //TODO: attributes
834 << " to "
835 << j->type << " " << j->name //TODO: attributes
836 << std::endl;
837 std::exit(EXIT_FAILURE);
840 for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
841 i(ent2B->getDirectProperties().begin()
842 + ent2A->getDirectProperties().size());
843 i != ent2B->getDirectProperties().end(); ++i)
845 if ((i->attributes & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL) == 0)
847 std::cerr
848 << "B accumulation-based service " << name
849 << " additional direct property " << i->name
850 << " is not optional" << std::endl;
851 std::exit(EXIT_FAILURE);
854 break;
856 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
858 rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2A(
859 static_cast<unoidl::InterfaceBasedSingletonEntity *>(
860 entA.get()));
861 rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2B(
862 static_cast<unoidl::InterfaceBasedSingletonEntity *>(
863 entB.get()));
864 if (ent2A->getBase() != ent2B->getBase()) {
865 std::cerr
866 << "interface-based singleton " << name
867 << " base changed from " << ent2A->getBase()
868 << " to " << ent2B->getBase() << std::endl;
869 std::exit(EXIT_FAILURE);
871 break;
873 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
875 rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2A(
876 static_cast<unoidl::ServiceBasedSingletonEntity *>(
877 entA.get()));
878 rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2B(
879 static_cast<unoidl::ServiceBasedSingletonEntity *>(
880 entB.get()));
881 if (ent2A->getBase() != ent2B->getBase()) {
882 std::cerr
883 << "service-based singleton " << name
884 << " base changed from " << ent2A->getBase()
885 << " to " << ent2B->getBase() << std::endl;
886 std::exit(EXIT_FAILURE);
888 break;
895 bool valid(OUString const & identifier) {
896 for (sal_Int32 i = 0;; ++i) {
897 i = identifier.indexOf('_', i);
898 if (i == -1) {
899 return true;
901 if (!rtl::isAsciiUpperCase(identifier[0]) || identifier[i - 1] == '_') {
902 return false;
907 void checkIds(
908 rtl::Reference<unoidl::Provider> const & providerA, OUString const & prefix,
909 rtl::Reference<unoidl::MapCursor> const & cursor)
911 assert(cursor.is());
912 for (;;) {
913 OUString id;
914 rtl::Reference<unoidl::Entity> entB(cursor->getNext(&id));
915 if (!entB.is()) {
916 break;
918 OUString name(prefix + id);
919 rtl::Reference<unoidl::Entity> entA(providerA->findEntity(name));
920 if (!(entA.is() || valid(id))) {
921 std::cerr
922 << "entity name " << name << " uses an invalid identifier"
923 << std::endl;
924 std::exit(EXIT_FAILURE);
926 switch (entB->getSort()) {
927 case unoidl::Entity::SORT_MODULE:
928 checkIds(
929 providerA, name + ".",
930 (static_cast<unoidl::ModuleEntity *>(entB.get())
931 ->createCursor()));
932 break;
933 case unoidl::Entity::SORT_ENUM_TYPE:
934 if (!entA.is()) {
935 rtl::Reference<unoidl::EnumTypeEntity> ent2B(
936 static_cast<unoidl::EnumTypeEntity *>(entB.get()));
937 for (std::vector<unoidl::EnumTypeEntity::Member>::const_iterator
938 i(ent2B->getMembers().begin());
939 i != ent2B->getMembers().end(); ++i)
941 if (!valid(i->name)) {
942 std::cerr
943 << "enum type " << name << " member " << i->name
944 << " uses an invalid identifier" << std::endl;
945 std::exit(EXIT_FAILURE);
949 break;
950 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
951 if (!entA.is()) {
952 rtl::Reference<unoidl::PlainStructTypeEntity> ent2B(
953 static_cast<unoidl::PlainStructTypeEntity *>(
954 entB.get()));
955 for (std::vector<unoidl::PlainStructTypeEntity::Member>::const_iterator
956 i(ent2B->getDirectMembers().begin());
957 i != ent2B->getDirectMembers().end(); ++i)
959 if (!valid(i->name)) {
960 std::cerr
961 << "plain struct type " << name << " direct member "
962 << i->name << " uses an invalid identifier"
963 << std::endl;
964 std::exit(EXIT_FAILURE);
968 break;
969 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
970 if (!entA.is()) {
971 rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
972 ent2B(
973 static_cast<
974 unoidl::PolymorphicStructTypeTemplateEntity *>(
975 entB.get()));
976 for (std::vector<OUString>::const_iterator i(
977 ent2B->getTypeParameters().begin());
978 i != ent2B->getTypeParameters().end(); ++i)
980 if (!valid(*i)) {
981 std::cerr
982 << "polymorphic struct type template " << name
983 << " type parameter " << *i
984 << " uses an invalid identifier" << std::endl;
985 std::exit(EXIT_FAILURE);
988 for (std::vector<unoidl::PolymorphicStructTypeTemplateEntity::Member>::const_iterator
989 i(ent2B->getMembers().begin());
990 i != ent2B->getMembers().end(); ++i)
992 if (!valid(i->name)) {
993 std::cerr
994 << "polymorphic struct type template " << name
995 << " member " << i->name
996 << " uses an invalid identifier" << std::endl;
997 std::exit(EXIT_FAILURE);
1001 break;
1002 case unoidl::Entity::SORT_EXCEPTION_TYPE:
1003 if (!entA.is()) {
1004 rtl::Reference<unoidl::ExceptionTypeEntity> ent2B(
1005 static_cast<unoidl::ExceptionTypeEntity *>(entB.get()));
1006 for (std::vector<unoidl::ExceptionTypeEntity::Member>::const_iterator
1007 i(ent2B->getDirectMembers().begin());
1008 i != ent2B->getDirectMembers().end(); ++i)
1010 if (!valid(i->name)) {
1011 std::cerr
1012 << "exception type " << name << " direct member "
1013 << i->name << " uses an invalid identifier"
1014 << std::endl;
1015 std::exit(EXIT_FAILURE);
1019 break;
1020 case unoidl::Entity::SORT_INTERFACE_TYPE:
1021 if (!entA.is()) {
1022 rtl::Reference<unoidl::InterfaceTypeEntity> ent2B(
1023 static_cast<unoidl::InterfaceTypeEntity *>(entB.get()));
1024 for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator
1025 i(ent2B->getDirectAttributes().begin());
1026 i != ent2B->getDirectAttributes().end(); ++i)
1028 if (!valid(i->name)) {
1029 std::cerr
1030 << "interface type " << name << " direct attribute "
1031 << i->name << " uses an invalid identifier"
1032 << std::endl;
1033 std::exit(EXIT_FAILURE);
1036 for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator
1037 i(ent2B->getDirectMethods().begin());
1038 i != ent2B->getDirectMethods().end(); ++i)
1040 if (!valid(i->name)) {
1041 std::cerr
1042 << "interface type " << name << " direct method "
1043 << i->name << " uses an invalid identifier"
1044 << std::endl;
1045 std::exit(EXIT_FAILURE);
1047 for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::const_iterator
1048 j(i->parameters.begin());
1049 j != i->parameters.end(); ++j)
1051 if (!valid(j->name)) {
1052 std::cerr
1053 << "interface type " << name
1054 << " direct method " << i->name << " parameter "
1055 << j->name << " uses an invalid identifier"
1056 << std::endl;
1057 std::exit(EXIT_FAILURE);
1062 break;
1063 case unoidl::Entity::SORT_TYPEDEF:
1064 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
1065 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
1066 break;
1067 case unoidl::Entity::SORT_CONSTANT_GROUP:
1069 rtl::Reference<unoidl::ConstantGroupEntity> ent2B(
1070 static_cast<unoidl::ConstantGroupEntity *>(entB.get()));
1071 for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
1072 i(ent2B->getMembers().begin());
1073 i != ent2B->getMembers().end(); ++i)
1075 bool found = false;
1076 if (entA.is()) {
1077 rtl::Reference<unoidl::ConstantGroupEntity> ent2A(
1078 static_cast<unoidl::ConstantGroupEntity *>(
1079 entA.get()));
1080 for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
1081 j(ent2A->getMembers().begin());
1082 j != ent2A->getMembers().end(); ++j)
1084 if (i->name == j->name) {
1085 found = true;
1086 break;
1090 if (!(found || valid(i->name))) {
1091 std::cerr
1092 << "Constant group " << name << " member "
1093 << i->name << " uses an invalid identifier"
1094 << std::endl;
1095 std::exit(EXIT_FAILURE);
1098 break;
1100 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
1101 if (!entA.is()) {
1102 rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
1103 ent2B(
1104 static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
1105 entB.get()));
1106 for (std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor>::const_iterator
1107 i(ent2B->getConstructors().begin());
1108 i != ent2B->getConstructors().end(); ++i)
1110 if (!valid(i->name)) {
1111 std::cerr
1112 << "single-interface--based service " << name
1113 << " constructor " << i->name
1114 << " uses an invalid identifier" << std::endl;
1115 std::exit(EXIT_FAILURE);
1117 for (std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter>::const_iterator
1118 j(i->parameters.begin());
1119 j != i->parameters.end(); ++j)
1121 if (!valid(j->name)) {
1122 std::cerr
1123 << "single-interface--based service " << name
1124 << " constructor " << i->name << " parameter "
1125 << j->name << " uses an invalid identifier"
1126 << std::endl;
1127 std::exit(EXIT_FAILURE);
1132 break;
1133 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
1135 rtl::Reference<unoidl::AccumulationBasedServiceEntity> ent2B(
1136 static_cast<unoidl::AccumulationBasedServiceEntity *>(
1137 entB.get()));
1138 std::vector<unoidl::AccumulationBasedServiceEntity::Property>::size_type
1139 n(entA.is()
1140 ? (static_cast<unoidl::AccumulationBasedServiceEntity *>(
1141 entA.get())
1142 ->getDirectProperties().size())
1143 : 0);
1144 assert(n <= ent2B->getDirectProperties().size());
1145 for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
1146 i(ent2B->getDirectProperties().begin() + n);
1147 i != ent2B->getDirectProperties().end(); ++i)
1149 if (!valid(i->name)) {
1150 std::cerr
1151 << "accumulation-based service " << name
1152 << " direct property " << i->name
1153 << " uses an invalid identifier" << std::endl;
1154 std::exit(EXIT_FAILURE);
1157 break;
1165 SAL_IMPLEMENT_MAIN() {
1166 try {
1167 sal_uInt32 args = rtl_getAppCommandArgCount();
1168 rtl::Reference<unoidl::Manager> mgr[2];
1169 mgr[0] = new unoidl::Manager;
1170 mgr[1] = new unoidl::Manager;
1171 rtl::Reference<unoidl::Provider> prov[2];
1172 int side = 0;
1173 for (sal_uInt32 i = 0; i != args; ++i) {
1174 bool delimiter = false;
1175 OUString uri(getArgumentUri(i, side == 0 ? &delimiter : 0));
1176 if (delimiter) {
1177 side = 1;
1178 } else {
1179 try {
1180 prov[side] = mgr[side]->addProvider(uri);
1181 } catch (unoidl::NoSuchFileException &) {
1182 std::cerr
1183 << "Input <" << uri << "> does not exist" << std::endl;
1184 std::exit(EXIT_FAILURE);
1188 if (side == 0 || !(prov[0].is() && prov[1].is())) {
1189 badUsage();
1191 checkMap(prov[1], "", prov[0]->createRootCursor());
1192 checkIds(prov[0], "", prov[1]->createRootCursor());
1193 return EXIT_SUCCESS;
1194 } catch (unoidl::FileFormatException & e1) {
1195 std::cerr
1196 << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1197 << std::endl;
1198 std::exit(EXIT_FAILURE);
1202 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */