Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : */
9 :
10 : #include "sal/config.h"
11 :
12 : #include <algorithm>
13 : #include <cassert>
14 : #include <cstdlib>
15 : #include <iostream>
16 : #include <vector>
17 :
18 : #include "osl/file.hxx"
19 : #include "osl/process.h"
20 : #include "rtl/process.h"
21 : #include "rtl/ref.hxx"
22 : #include "rtl/ustring.hxx"
23 : #include "sal/main.h"
24 : #include "sal/types.h"
25 : #include "unoidl/unoidl.hxx"
26 :
27 : namespace unoidl {
28 :
29 1882 : bool operator ==(ConstantValue const & lhs, ConstantValue const & rhs) {
30 1882 : if (lhs.type == rhs.type) {
31 1882 : switch (lhs.type) {
32 : case ConstantValue::TYPE_BOOLEAN:
33 0 : return lhs.booleanValue == rhs.booleanValue;
34 : case ConstantValue::TYPE_BYTE:
35 12 : return lhs.byteValue == rhs.byteValue;
36 : case ConstantValue::TYPE_SHORT:
37 1168 : return lhs.shortValue == rhs.shortValue;
38 : case ConstantValue::TYPE_UNSIGNED_SHORT:
39 0 : return lhs.unsignedShortValue == rhs.unsignedShortValue;
40 : case ConstantValue::TYPE_LONG:
41 653 : return lhs.longValue == rhs.longValue;
42 : case ConstantValue::TYPE_UNSIGNED_LONG:
43 0 : return lhs.unsignedLongValue == rhs.unsignedLongValue;
44 : case ConstantValue::TYPE_HYPER:
45 29 : return lhs.hyperValue == rhs.hyperValue;
46 : case ConstantValue::TYPE_UNSIGNED_HYPER:
47 0 : return lhs.unsignedHyperValue == rhs.unsignedHyperValue;
48 : case ConstantValue::TYPE_FLOAT:
49 20 : return lhs.floatValue == rhs.floatValue;
50 : case ConstantValue::TYPE_DOUBLE:
51 0 : return lhs.doubleValue == rhs.doubleValue;
52 : }
53 : }
54 0 : return false;
55 : }
56 :
57 1882 : bool operator !=(ConstantValue const & lhs, ConstantValue const & rhs) {
58 1882 : return !(lhs == rhs);
59 : }
60 :
61 31 : bool operator ==(
62 : SingleInterfaceBasedServiceEntity::Constructor::Parameter const & lhs,
63 : SingleInterfaceBasedServiceEntity::Constructor::Parameter const & rhs)
64 : {
65 31 : return lhs.name == rhs.name && lhs.type == rhs.type && lhs.rest == rhs.rest;
66 : }
67 :
68 : }
69 :
70 : namespace {
71 :
72 0 : void badUsage() {
73 : std::cerr
74 0 : << "Usage:" << std::endl << std::endl
75 : << (" unoidl-check [<extra registries A>] <registry A> -- [<extra"
76 0 : " registries B>]")
77 0 : << std::endl << " <registry B>" << std::endl << std::endl
78 : << ("where each <registry> is either a new- or legacy-format .rdb file,"
79 0 : " a single .idl")
80 0 : << std::endl
81 : << ("file, or a root directory of an .idl file tree. Check that each"
82 0 : " entity from")
83 0 : << std::endl
84 0 : << "<registry A> is also present in <registry B> in a compatible form."
85 0 : << std::endl;
86 0 : std::exit(EXIT_FAILURE);
87 : }
88 :
89 8 : OUString getArgumentUri(sal_uInt32 argument, bool * delimiter) {
90 8 : OUString arg;
91 8 : rtl_getAppCommandArg(argument, &arg.pData);
92 8 : if (arg == "--") {
93 2 : if (delimiter == 0) {
94 0 : badUsage();
95 : }
96 2 : *delimiter = true;
97 2 : return OUString();
98 : }
99 12 : OUString url;
100 6 : osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
101 6 : if (e1 != osl::FileBase::E_None) {
102 : std::cerr
103 0 : << "Cannot convert \"" << arg << "\" to file URL, error code "
104 0 : << +e1 << std::endl;
105 0 : std::exit(EXIT_FAILURE);
106 : }
107 12 : OUString cwd;
108 6 : oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
109 6 : if (e2 != osl_Process_E_None) {
110 : std::cerr
111 0 : << "Cannot obtain working directory, error code " << +e2
112 0 : << std::endl;
113 0 : std::exit(EXIT_FAILURE);
114 : }
115 12 : OUString abs;
116 6 : e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
117 6 : if (e1 != osl::FileBase::E_None) {
118 : std::cerr
119 0 : << "Cannot make \"" << url
120 0 : << "\" into an absolute file URL, error code " << +e1 << std::endl;
121 0 : std::exit(EXIT_FAILURE);
122 : }
123 14 : return abs;
124 : }
125 :
126 0 : OUString showDirection(
127 : unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction)
128 : {
129 0 : switch (direction) {
130 : case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN:
131 0 : return OUString("[in]");
132 : case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT:
133 0 : return OUString("[out]");
134 : case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT:
135 0 : return OUString("[inout]");
136 : default:
137 0 : assert(false); for (;;) { std::abort(); } // this cannot happen
138 : }
139 : }
140 :
141 912 : struct EqualsAnnotation {
142 304 : EqualsAnnotation(OUString const & name): name_(name) {}
143 :
144 674 : bool operator ()(unoidl::AnnotatedReference const & ref)
145 674 : { return ref.name == name_; }
146 :
147 : private:
148 : OUString name_;
149 : };
150 :
151 2856 : void checkMap(
152 : rtl::Reference<unoidl::Provider> const & providerB, OUString const & prefix,
153 : rtl::Reference<unoidl::MapCursor> const & cursor)
154 : {
155 : assert(providerB.is());
156 : assert(cursor.is());
157 : for (;;) {
158 2856 : OUString id;
159 5633 : rtl::Reference<unoidl::Entity> entA(cursor->getNext(&id));
160 2856 : if (!entA.is()) {
161 79 : break;
162 : }
163 5554 : OUString name(prefix + id);
164 2777 : if (entA->getSort() == unoidl::Entity::SORT_MODULE) {
165 : checkMap(
166 154 : providerB, name + ".",
167 77 : (static_cast<unoidl::ModuleEntity *>(entA.get())
168 231 : ->createCursor()));
169 : } else {
170 2700 : rtl::Reference<unoidl::Entity> entB(providerB->findEntity(name));
171 2700 : if (!entB.is()) {
172 : std::cerr
173 0 : << "A entity " << name << " is not present in B"
174 0 : << std::endl;
175 0 : std::exit(EXIT_FAILURE);
176 : }
177 2700 : if (entA->getSort() != entB->getSort()) {
178 : std::cerr
179 0 : << "A entity " << name << " is of different sort in B"
180 0 : << std::endl;
181 0 : std::exit(EXIT_FAILURE);
182 : }
183 5400 : if ((dynamic_cast<unoidl::PublishableEntity *>(entA.get())
184 2700 : ->isPublished())
185 5387 : && (!dynamic_cast<unoidl::PublishableEntity *>(entB.get())
186 2687 : ->isPublished()))
187 : {
188 : std::cerr
189 0 : << "A published entity " << name << " is not published in B"
190 0 : << std::endl;
191 0 : std::exit(EXIT_FAILURE);
192 : }
193 2700 : switch (entA->getSort()) {
194 : case unoidl::Entity::SORT_MODULE:
195 : assert(false); // this cannot happen
196 : case unoidl::Entity::SORT_ENUM_TYPE:
197 : {
198 : rtl::Reference<unoidl::EnumTypeEntity> ent2A(
199 157 : static_cast<unoidl::EnumTypeEntity *>(entA.get()));
200 : rtl::Reference<unoidl::EnumTypeEntity> ent2B(
201 314 : static_cast<unoidl::EnumTypeEntity *>(entB.get()));
202 314 : if (ent2A->getMembers().size()
203 157 : != ent2B->getMembers().size())
204 : {
205 : std::cerr
206 0 : << "enum type " << name
207 0 : << " number of members changed from "
208 0 : << ent2A->getMembers().size() << " to "
209 0 : << ent2B->getMembers().size() << std::endl;
210 0 : std::exit(EXIT_FAILURE);
211 : }
212 3747 : for (std::vector<unoidl::EnumTypeEntity::Member>::const_iterator
213 157 : i(ent2A->getMembers().begin()),
214 157 : j(ent2B->getMembers().begin());
215 2498 : i != ent2A->getMembers().end(); ++i, ++j)
216 : {
217 1092 : if (i->name != j->name || i->value != j->value) {
218 : std::cerr
219 0 : << "enum type " << name << " member #"
220 0 : << i - ent2A->getMembers().begin() + 1
221 0 : << " changed from " << i->name << " = "
222 0 : << i->value << " to " << j->name << " = "
223 0 : << j->value << std::endl;
224 0 : std::exit(EXIT_FAILURE);
225 : }
226 : }
227 314 : break;
228 : }
229 : case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
230 : {
231 : rtl::Reference<unoidl::PlainStructTypeEntity> ent2A(
232 : static_cast<unoidl::PlainStructTypeEntity *>(
233 236 : entA.get()));
234 : rtl::Reference<unoidl::PlainStructTypeEntity> ent2B(
235 : static_cast<unoidl::PlainStructTypeEntity *>(
236 472 : entB.get()));
237 236 : if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
238 : std::cerr
239 0 : << "plain struct type " << name
240 0 : << " direct base changed from "
241 0 : << (ent2A->getDirectBase().isEmpty()
242 0 : ? OUString("none") : ent2A->getDirectBase())
243 0 : << " to "
244 0 : << (ent2B->getDirectBase().isEmpty()
245 0 : ? OUString("none") : ent2B->getDirectBase())
246 0 : << std::endl;
247 0 : std::exit(EXIT_FAILURE);
248 : }
249 472 : if (ent2A->getDirectMembers().size()
250 236 : != ent2B->getDirectMembers().size())
251 : {
252 : std::cerr
253 0 : << "plain struct type " << name
254 0 : << " number of direct members changed from "
255 0 : << ent2A->getDirectMembers().size() << " to "
256 0 : << ent2B->getDirectMembers().size() << std::endl;
257 0 : std::exit(EXIT_FAILURE);
258 : }
259 3216 : for (std::vector<unoidl::PlainStructTypeEntity::Member>::const_iterator
260 236 : i(ent2A->getDirectMembers().begin()),
261 236 : j(ent2B->getDirectMembers().begin());
262 2144 : i != ent2A->getDirectMembers().end(); ++i, ++j)
263 : {
264 836 : if (i->name != j->name || i->type != j->type) {
265 : std::cerr
266 0 : << "plain struct type " << name
267 0 : << " direct member #"
268 0 : << i - ent2A->getDirectMembers().begin() + 1
269 0 : << " changed from " << i->type << " " << i->name
270 0 : << " to " << j->type << " " << j->name
271 0 : << std::endl;
272 0 : std::exit(EXIT_FAILURE);
273 : }
274 : }
275 472 : break;
276 : }
277 : case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
278 : {
279 : rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
280 : ent2A(
281 : static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
282 0 : entA.get()));
283 : rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
284 : ent2B(
285 : static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
286 0 : entB.get()));
287 0 : if (ent2A->getTypeParameters().size()
288 0 : != ent2B->getTypeParameters().size())
289 : {
290 : std::cerr
291 0 : << "polymorphic struct type template " << name
292 0 : << " number of type parameters changed from "
293 0 : << ent2A->getTypeParameters().size() << " to "
294 0 : << ent2B->getTypeParameters().size() << std::endl;
295 0 : std::exit(EXIT_FAILURE);
296 : }
297 0 : for (std::vector<OUString>::const_iterator
298 0 : i(ent2A->getTypeParameters().begin()),
299 0 : j(ent2B->getTypeParameters().begin());
300 0 : i != ent2A->getTypeParameters().end(); ++i, ++j)
301 : {
302 0 : if (*i != *j) {
303 : std::cerr
304 0 : << "polymorphic struct type template " << name
305 0 : << " type parameter #"
306 0 : << i - ent2A->getTypeParameters().begin() + 1
307 0 : << " changed from " << *i << " to " << *j
308 0 : << std::endl;
309 0 : std::exit(EXIT_FAILURE);
310 : }
311 : }
312 0 : if (ent2A->getMembers().size()
313 0 : != ent2B->getMembers().size())
314 : {
315 : std::cerr
316 0 : << "polymorphic struct type template " << name
317 0 : << " number of members changed from "
318 0 : << ent2A->getMembers().size() << " to "
319 0 : << ent2B->getMembers().size() << std::endl;
320 0 : std::exit(EXIT_FAILURE);
321 : }
322 0 : for (std::vector<unoidl::PolymorphicStructTypeTemplateEntity::Member>::const_iterator
323 0 : i(ent2A->getMembers().begin()),
324 0 : j(ent2B->getMembers().begin());
325 0 : i != ent2A->getMembers().end(); ++i, ++j)
326 : {
327 0 : if (i->name != j->name || i->type != j->type
328 0 : || i->parameterized != j->parameterized)
329 : {
330 : std::cerr
331 0 : << "polymorphic struct type template " << name
332 0 : << " member #"
333 0 : << i - ent2A->getMembers().begin() + 1
334 0 : << " changed from "
335 0 : << (i->parameterized
336 0 : ? OUString("parameterized ") : OUString())
337 0 : << i->type << " " << i->name
338 0 : << " to "
339 0 : << (j->parameterized
340 0 : ? OUString("parameterized ") : OUString())
341 0 : << j->type << " " << j->name
342 0 : << std::endl;
343 0 : std::exit(EXIT_FAILURE);
344 : }
345 : }
346 0 : break;
347 : }
348 : case unoidl::Entity::SORT_EXCEPTION_TYPE:
349 : {
350 : rtl::Reference<unoidl::ExceptionTypeEntity> ent2A(
351 172 : static_cast<unoidl::ExceptionTypeEntity *>(entA.get()));
352 : rtl::Reference<unoidl::ExceptionTypeEntity> ent2B(
353 344 : static_cast<unoidl::ExceptionTypeEntity *>(entB.get()));
354 172 : if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
355 : std::cerr
356 0 : << "exception type " << name
357 0 : << " direct base changed from "
358 0 : << (ent2A->getDirectBase().isEmpty()
359 0 : ? OUString("none") : ent2A->getDirectBase())
360 0 : << " to "
361 0 : << (ent2B->getDirectBase().isEmpty()
362 0 : ? OUString("none") : ent2B->getDirectBase())
363 0 : << std::endl;
364 0 : std::exit(EXIT_FAILURE);
365 : }
366 344 : if (ent2A->getDirectMembers().size()
367 172 : != ent2B->getDirectMembers().size())
368 : {
369 : std::cerr
370 0 : << "exception type " << name
371 0 : << " number of direct members changed from "
372 0 : << ent2A->getDirectMembers().size() << " to "
373 0 : << ent2B->getDirectMembers().size() << std::endl;
374 0 : std::exit(EXIT_FAILURE);
375 : }
376 822 : for (std::vector<unoidl::ExceptionTypeEntity::Member>::const_iterator
377 172 : i(ent2A->getDirectMembers().begin()),
378 172 : j(ent2B->getDirectMembers().begin());
379 548 : i != ent2A->getDirectMembers().end(); ++i, ++j)
380 : {
381 102 : if (i->name != j->name || i->type != j->type) {
382 : std::cerr
383 0 : << "exception type " << name
384 0 : << " direct member #"
385 0 : << i - ent2A->getDirectMembers().begin() + 1
386 0 : << " changed from " << i->type << " " << i->name
387 0 : << " to " << j->type << " " << j->name
388 0 : << std::endl;
389 0 : std::exit(EXIT_FAILURE);
390 : }
391 : }
392 344 : break;
393 : }
394 : case unoidl::Entity::SORT_INTERFACE_TYPE:
395 : {
396 : rtl::Reference<unoidl::InterfaceTypeEntity> ent2A(
397 1047 : static_cast<unoidl::InterfaceTypeEntity *>(entA.get()));
398 : rtl::Reference<unoidl::InterfaceTypeEntity> ent2B(
399 2094 : static_cast<unoidl::InterfaceTypeEntity *>(entB.get()));
400 2094 : if (ent2A->getDirectMandatoryBases().size()
401 1047 : != ent2B->getDirectMandatoryBases().size())
402 : {
403 : std::cerr
404 0 : << "interface type " << name
405 0 : << " number of direct mandatory bases changed from "
406 0 : << ent2A->getDirectMandatoryBases().size() << " to "
407 0 : << ent2B->getDirectMandatoryBases().size()
408 0 : << std::endl;
409 0 : std::exit(EXIT_FAILURE);
410 : }
411 6552 : for (std::vector<unoidl::AnnotatedReference>::const_iterator
412 1047 : i(ent2A->getDirectMandatoryBases().begin()),
413 1047 : j(ent2B->getDirectMandatoryBases().begin());
414 4368 : i != ent2A->getDirectMandatoryBases().end(); ++i, ++j)
415 : {
416 1137 : if (i->name != j->name) {
417 : std::cerr
418 0 : << "interface type " << name
419 0 : << " direct mandatory base #"
420 0 : << (i - ent2A->getDirectMandatoryBases().begin()
421 0 : + 1)
422 0 : << " changed from " << i->name << " to "
423 0 : << j->name << std::endl;
424 0 : std::exit(EXIT_FAILURE);
425 : }
426 : }
427 2094 : if (ent2A->getDirectOptionalBases().size()
428 1047 : != ent2B->getDirectOptionalBases().size())
429 : {
430 : std::cerr
431 0 : << "interface type " << name
432 0 : << " number of direct optional bases changed from "
433 0 : << ent2A->getDirectOptionalBases().size() << " to "
434 0 : << ent2B->getDirectOptionalBases().size()
435 0 : << std::endl;
436 0 : std::exit(EXIT_FAILURE);
437 : }
438 3162 : for (std::vector<unoidl::AnnotatedReference>::const_iterator
439 1047 : i(ent2A->getDirectOptionalBases().begin()),
440 1047 : j(ent2B->getDirectOptionalBases().begin());
441 2108 : i != ent2A->getDirectOptionalBases().end(); ++i, ++j)
442 : {
443 7 : if (i->name != j->name) {
444 : std::cerr
445 0 : << "interface type " << name
446 0 : << " direct optional base #"
447 0 : << (i - ent2A->getDirectOptionalBases().begin()
448 0 : + 1)
449 0 : << " changed from " << i->name << " to "
450 0 : << j->name << std::endl;
451 0 : std::exit(EXIT_FAILURE);
452 : }
453 : }
454 2094 : if (ent2A->getDirectAttributes().size()
455 1047 : != ent2B->getDirectAttributes().size())
456 : {
457 : std::cerr
458 0 : << "interface type " << name
459 0 : << " number of direct attributes changed from "
460 0 : << ent2A->getDirectAttributes().size() << " to "
461 0 : << ent2B->getDirectAttributes().size() << std::endl;
462 0 : std::exit(EXIT_FAILURE);
463 : }
464 3483 : for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator
465 1047 : i(ent2A->getDirectAttributes().begin()),
466 1047 : j(ent2B->getDirectAttributes().begin());
467 2322 : i != ent2A->getDirectAttributes().end(); ++i, ++j)
468 : {
469 342 : if (i->name != j->name || i->type != j->type
470 114 : || i->bound != j->bound
471 114 : || i->readOnly != j->readOnly
472 114 : || i->getExceptions != j->getExceptions
473 228 : || i->setExceptions != j->setExceptions)
474 : {
475 : std::cerr
476 0 : << "interface type " << name
477 0 : << " direct attribute #"
478 0 : << i - ent2A->getDirectAttributes().begin() + 1
479 0 : << " changed from "
480 0 : << (i->bound ? OUString("bound ") : OUString())
481 0 : << (i->readOnly
482 0 : ? OUString("read-only ") : OUString())
483 0 : << i->type << " " << i->name //TODO: exceptions
484 0 : << " to "
485 0 : << (j->bound ? OUString("bound ") : OUString())
486 0 : << (j->readOnly
487 0 : ? OUString("read-only ") : OUString())
488 0 : << j->type << " " << j->name //TODO: exceptions
489 0 : << std::endl;
490 0 : std::exit(EXIT_FAILURE);
491 : }
492 : }
493 2094 : if (ent2A->getDirectMethods().size()
494 1047 : != ent2B->getDirectMethods().size())
495 : {
496 : std::cerr
497 0 : << "interface type " << name
498 0 : << " number of direct methods changed from "
499 0 : << ent2A->getDirectMethods().size() << " to "
500 0 : << ent2B->getDirectMethods().size() << std::endl;
501 0 : std::exit(EXIT_FAILURE);
502 : }
503 13428 : for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator
504 1047 : i(ent2A->getDirectMethods().begin()),
505 1047 : j(ent2B->getDirectMethods().begin());
506 8952 : i != ent2A->getDirectMethods().end(); ++i, ++j)
507 : {
508 10287 : if (i->name != j->name || i->returnType != j->returnType
509 6858 : || i->exceptions != j->exceptions)
510 : {
511 : std::cerr
512 0 : << "interface type " << name
513 0 : << " direct method #"
514 0 : << i - ent2A->getDirectMethods().begin() + 1
515 0 : << " changed from "
516 0 : << i->returnType << " " << i->name //TODO: exceptions
517 0 : << " to " << j->returnType << " " << j->name //TODO: exceptions
518 0 : << std::endl;
519 0 : std::exit(EXIT_FAILURE);
520 : }
521 3429 : if (i->parameters.size() != j->parameters.size()) {
522 : std::cerr
523 0 : << "interface type " << name
524 0 : << " direct method " << i->name
525 0 : << " number of parameters changed from "
526 0 : << i->parameters.size() << " to "
527 0 : << j->parameters.size() << std::endl;
528 0 : std::exit(EXIT_FAILURE);
529 : }
530 20544 : for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::const_iterator
531 3429 : k(i->parameters.begin()),
532 3429 : l(j->parameters.begin());
533 13696 : k != i->parameters.end(); ++k, ++l)
534 : {
535 3419 : if (k->type != l->type || k->direction != l->direction)
536 : {
537 : std::cerr
538 0 : << "interface type " << name
539 0 : << " direct method " << i->name
540 0 : << " parameter #"
541 0 : << k - i->parameters.begin() + 1
542 0 : << " changed from "
543 0 : << showDirection(k->direction) << " "
544 0 : << k->type << " to "
545 0 : << showDirection(l->direction) << " "
546 0 : << l->type << std::endl;
547 0 : std::exit(EXIT_FAILURE);
548 : }
549 3419 : if (k->name != l->name) {
550 : std::cerr
551 0 : << "interface type " << name
552 0 : << " direct method " << i->name
553 0 : << " parameter #"
554 0 : << k - i->parameters.begin() + 1
555 0 : << " changed name from " << k->name
556 0 : << " to " << l->name << std::endl;
557 0 : std::exit(EXIT_FAILURE);
558 : }
559 : }
560 : }
561 2094 : break;
562 : }
563 : case unoidl::Entity::SORT_TYPEDEF:
564 : {
565 : rtl::Reference<unoidl::TypedefEntity> ent2A(
566 14 : static_cast<unoidl::TypedefEntity *>(entA.get()));
567 : rtl::Reference<unoidl::TypedefEntity> ent2B(
568 28 : static_cast<unoidl::TypedefEntity *>(entB.get()));
569 14 : if (ent2A->getType() != ent2B->getType()) {
570 : std::cerr
571 0 : << "typedef " << name << " type changed from "
572 0 : << ent2A->getType() << " to " << ent2B->getType()
573 0 : << std::endl;
574 0 : std::exit(EXIT_FAILURE);
575 : }
576 28 : break;
577 : }
578 : case unoidl::Entity::SORT_CONSTANT_GROUP:
579 : {
580 : rtl::Reference<unoidl::ConstantGroupEntity> ent2A(
581 206 : static_cast<unoidl::ConstantGroupEntity *>(entA.get()));
582 : rtl::Reference<unoidl::ConstantGroupEntity> ent2B(
583 412 : static_cast<unoidl::ConstantGroupEntity *>(entB.get()));
584 6264 : for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
585 206 : i(ent2A->getMembers().begin());
586 4176 : i != ent2A->getMembers().end(); ++i)
587 : {
588 1882 : bool found = false;
589 95538 : for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
590 1882 : j(ent2B->getMembers().begin());
591 63692 : j != ent2B->getMembers().end(); ++j)
592 : {
593 31846 : if (i->name == j->name) {
594 1882 : if (i->value != j->value) {
595 : std::cerr
596 0 : << "constant group " << name
597 0 : << " member " << i->name
598 0 : << " changed value" << std::endl;
599 0 : std::exit(EXIT_FAILURE);
600 : }
601 1882 : found = true;
602 1882 : break;
603 : }
604 : }
605 1882 : if (!found) {
606 : std::cerr
607 0 : << "A constant group " << name << " member "
608 0 : << i->name << " is not present in B"
609 0 : << std::endl;
610 0 : std::exit(EXIT_FAILURE);
611 : }
612 : }
613 412 : break;
614 : }
615 : case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
616 : {
617 : rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
618 : ent2A(
619 : static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
620 127 : entA.get()));
621 : rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
622 : ent2B(
623 : static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
624 254 : entB.get()));
625 127 : if (ent2A->getBase() != ent2B->getBase()) {
626 : std::cerr
627 0 : << "single-interface--based servcie " << name
628 0 : << " base changed from " << ent2A->getBase()
629 0 : << " to " << ent2B->getBase()
630 0 : << std::endl;
631 0 : std::exit(EXIT_FAILURE);
632 : }
633 254 : if (ent2A->getConstructors().size()
634 127 : != ent2B->getConstructors().size())
635 : {
636 : std::cerr
637 0 : << "single-interface--based service " << name
638 0 : << " number of constructors changed from "
639 0 : << ent2A->getConstructors().size() << " to "
640 0 : << ent2B->getConstructors().size() << std::endl;
641 0 : std::exit(EXIT_FAILURE);
642 : }
643 771 : for (std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor>::const_iterator
644 127 : i(ent2A->getConstructors().begin()),
645 127 : j(ent2B->getConstructors().begin());
646 514 : i != ent2A->getConstructors().end(); ++i, ++j)
647 : {
648 390 : if (i->name != j->name || i->parameters != j->parameters
649 130 : || i->exceptions != j->exceptions
650 260 : || i->defaultConstructor != j->defaultConstructor)
651 : {
652 : std::cerr
653 0 : << "single-interface--based service " << name
654 0 : << " constructor #"
655 0 : << i - ent2A->getConstructors().begin() + 1
656 0 : << " changed from "
657 0 : << (i->defaultConstructor
658 0 : ? OUString("default ") : i->name) //TODO: parameters, exceptions
659 0 : << " to "
660 0 : << (j->defaultConstructor
661 0 : ? OUString("default ") : j->name) //TODO: parameters, exceptions
662 0 : << std::endl;
663 0 : std::exit(EXIT_FAILURE);
664 : }
665 : }
666 254 : break;
667 : }
668 : case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
669 : {
670 : rtl::Reference<unoidl::AccumulationBasedServiceEntity>
671 : ent2A(
672 : static_cast<unoidl::AccumulationBasedServiceEntity *>(
673 738 : entA.get()));
674 : rtl::Reference<unoidl::AccumulationBasedServiceEntity>
675 : ent2B(
676 : static_cast<unoidl::AccumulationBasedServiceEntity *>(
677 1476 : entB.get()));
678 1476 : if (ent2A->getDirectMandatoryBaseServices().size()
679 738 : != ent2B->getDirectMandatoryBaseServices().size())
680 : {
681 : std::cerr
682 0 : << "accumulation-based service " << name
683 : << (" number of direct mandatory base services"
684 0 : " changed from ")
685 0 : << ent2A->getDirectMandatoryBaseServices().size()
686 0 : << " to "
687 0 : << ent2B->getDirectMandatoryBaseServices().size()
688 0 : << std::endl;
689 0 : std::exit(EXIT_FAILURE);
690 : }
691 3933 : for (std::vector<unoidl::AnnotatedReference>::const_iterator
692 738 : i(ent2A->getDirectMandatoryBaseServices().begin()),
693 738 : j(ent2B->getDirectMandatoryBaseServices().begin());
694 2622 : i != ent2A->getDirectMandatoryBaseServices().end();
695 : ++i, ++j)
696 : {
697 573 : if (i->name != j->name) {
698 : std::cerr
699 0 : << "accumulation-based service " << name
700 0 : << " direct mandatory base service #"
701 : << (i
702 0 : - (ent2A->getDirectMandatoryBaseServices()
703 : .begin())
704 0 : + 1)
705 0 : << " changed from " << i->name << " to "
706 0 : << j->name << std::endl;
707 0 : std::exit(EXIT_FAILURE);
708 : }
709 : }
710 1476 : if (ent2A->getDirectOptionalBaseServices().size()
711 738 : > ent2B->getDirectOptionalBaseServices().size())
712 : {
713 : std::cerr
714 0 : << "accumulation-based service " << name
715 : << (" number of direct optional base services"
716 0 : " shrank from ")
717 0 : << ent2A->getDirectOptionalBaseServices().size()
718 0 : << " to "
719 0 : << ent2B->getDirectOptionalBaseServices().size()
720 0 : << std::endl;
721 0 : std::exit(EXIT_FAILURE);
722 : }
723 2388 : for (std::vector<unoidl::AnnotatedReference>::const_iterator
724 738 : i(ent2A->getDirectOptionalBaseServices().begin());
725 1592 : i != ent2A->getDirectOptionalBaseServices().end();
726 : ++i)
727 : {
728 116 : if (std::find_if(
729 58 : ent2B->getDirectOptionalBaseServices().begin(),
730 58 : ent2B->getDirectOptionalBaseServices().end(),
731 232 : EqualsAnnotation(i->name))
732 232 : == ent2B->getDirectOptionalBaseServices().end())
733 : {
734 : std::cerr
735 0 : << "accumulation-based service " << name
736 0 : << " direct optional base service " << i->name
737 0 : << " was removed" << std::endl;
738 0 : std::exit(EXIT_FAILURE);
739 : }
740 : }
741 1476 : if (ent2A->getDirectMandatoryBaseInterfaces().size()
742 738 : != ent2B->getDirectMandatoryBaseInterfaces().size())
743 : {
744 : std::cerr
745 0 : << "accumulation-based service " << name
746 : << (" number of direct mandatory base interfaces"
747 0 : " changed from ")
748 0 : << ent2A->getDirectMandatoryBaseInterfaces().size()
749 0 : << " to "
750 0 : << ent2B->getDirectMandatoryBaseInterfaces().size()
751 0 : << std::endl;
752 0 : std::exit(EXIT_FAILURE);
753 : }
754 5175 : for (std::vector<unoidl::AnnotatedReference>::const_iterator
755 738 : i(ent2A->getDirectMandatoryBaseInterfaces()
756 738 : .begin()),
757 738 : j(ent2B->getDirectMandatoryBaseInterfaces()
758 738 : .begin());
759 3450 : i != ent2A->getDirectMandatoryBaseInterfaces().end();
760 : ++i, ++j)
761 : {
762 987 : if (i->name != j->name) {
763 : std::cerr
764 0 : << "accumulation-based service " << name
765 0 : << " direct mandatory base interface #"
766 : << (i
767 0 : - (ent2A->getDirectMandatoryBaseInterfaces()
768 : .begin())
769 0 : + 1)
770 0 : << " changed from " << i->name << " to "
771 0 : << j->name << std::endl;
772 0 : std::exit(EXIT_FAILURE);
773 : }
774 : }
775 1476 : if (ent2A->getDirectOptionalBaseInterfaces().size()
776 738 : > ent2B->getDirectOptionalBaseInterfaces().size())
777 : {
778 : std::cerr
779 0 : << "accumulation-based service " << name
780 : << (" number of direct optional base interfaces"
781 0 : " shrank from ")
782 0 : << ent2A->getDirectOptionalBaseInterfaces().size()
783 0 : << " to "
784 0 : << ent2B->getDirectOptionalBaseInterfaces().size()
785 0 : << std::endl;
786 0 : std::exit(EXIT_FAILURE);
787 : }
788 2952 : for (std::vector<unoidl::AnnotatedReference>::const_iterator
789 738 : i(ent2A->getDirectOptionalBaseInterfaces()
790 738 : .begin());
791 1968 : i != ent2A->getDirectOptionalBaseInterfaces().end();
792 : ++i)
793 : {
794 492 : if (std::find_if(
795 246 : (ent2B->getDirectOptionalBaseInterfaces()
796 : .begin()),
797 246 : ent2B->getDirectOptionalBaseInterfaces().end(),
798 984 : EqualsAnnotation(i->name))
799 984 : == ent2B->getDirectOptionalBaseInterfaces().end())
800 : {
801 : std::cerr
802 0 : << "accumulation-based service " << name
803 0 : << " direct optional base interface " << i->name
804 0 : << " was removed" << std::endl;
805 0 : std::exit(EXIT_FAILURE);
806 : }
807 : }
808 1476 : if (ent2A->getDirectProperties().size()
809 738 : > ent2B->getDirectProperties().size())
810 : {
811 : std::cerr
812 0 : << "accumulation-based service " << name
813 0 : << " number of direct properties changed from "
814 0 : << ent2A->getDirectProperties().size() << " to "
815 0 : << ent2B->getDirectProperties().size() << std::endl;
816 0 : std::exit(EXIT_FAILURE);
817 : }
818 10197 : for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
819 738 : i(ent2A->getDirectProperties().begin()),
820 738 : j(ent2B->getDirectProperties().begin());
821 6798 : i != ent2A->getDirectProperties().end(); ++i, ++j)
822 : {
823 7983 : if (i->name != j->name || i->type != j->type
824 5322 : || i->attributes != j->attributes)
825 : {
826 : std::cerr
827 0 : << "accumulation-based service " << name
828 0 : << " direct property #"
829 0 : << i - ent2A->getDirectProperties().begin() + 1
830 0 : << " changed from "
831 0 : << i->type << " " << i->name //TODO: attributes
832 0 : << " to "
833 0 : << j->type << " " << j->name //TODO: attributes
834 0 : << std::endl;
835 0 : std::exit(EXIT_FAILURE);
836 : }
837 : }
838 2262 : for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
839 738 : i(ent2B->getDirectProperties().begin()
840 1476 : + ent2A->getDirectProperties().size());
841 1508 : i != ent2B->getDirectProperties().end(); ++i)
842 : {
843 16 : if ((i->attributes & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL) == 0)
844 : {
845 : std::cerr
846 0 : << "B accumulation-based service " << name
847 0 : << " additional direct property " << i->name
848 0 : << " is not optional" << std::endl;
849 0 : std::exit(EXIT_FAILURE);
850 : }
851 : }
852 1476 : break;
853 : }
854 : case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
855 : {
856 : rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2A(
857 : static_cast<unoidl::InterfaceBasedSingletonEntity *>(
858 3 : entA.get()));
859 : rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2B(
860 : static_cast<unoidl::InterfaceBasedSingletonEntity *>(
861 6 : entB.get()));
862 3 : if (ent2A->getBase() != ent2B->getBase()) {
863 : std::cerr
864 0 : << "interface-based singleton " << name
865 0 : << " base changed from " << ent2A->getBase()
866 0 : << " to " << ent2B->getBase() << std::endl;
867 0 : std::exit(EXIT_FAILURE);
868 : }
869 6 : break;
870 : }
871 : case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
872 : {
873 : rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2A(
874 : static_cast<unoidl::ServiceBasedSingletonEntity *>(
875 0 : entA.get()));
876 : rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2B(
877 : static_cast<unoidl::ServiceBasedSingletonEntity *>(
878 0 : entB.get()));
879 0 : if (ent2A->getBase() != ent2B->getBase()) {
880 : std::cerr
881 0 : << "service-based singleton " << name
882 0 : << " base changed from " << ent2A->getBase()
883 0 : << " to " << ent2B->getBase() << std::endl;
884 0 : std::exit(EXIT_FAILURE);
885 : }
886 0 : break;
887 : }
888 2700 : }
889 : }
890 2777 : }
891 79 : }
892 :
893 : }
894 :
895 4 : SAL_IMPLEMENT_MAIN() {
896 : try {
897 2 : sal_uInt32 args = rtl_getAppCommandArgCount();
898 6 : rtl::Reference<unoidl::Manager> mgr[2];
899 2 : mgr[0] = new unoidl::Manager;
900 2 : mgr[1] = new unoidl::Manager;
901 4 : rtl::Reference<unoidl::Provider> prov[2];
902 2 : int side = 0;
903 10 : for (sal_uInt32 i = 0; i != args; ++i) {
904 8 : bool delimiter = false;
905 8 : OUString uri(getArgumentUri(i, side == 0 ? &delimiter : 0));
906 8 : if (delimiter) {
907 2 : side = 1;
908 : } else {
909 : try {
910 6 : prov[side] = unoidl::loadProvider(mgr[side], uri);
911 0 : } catch (unoidl::NoSuchFileException &) {
912 : std::cerr
913 0 : << "Input <" << uri << "> does not exist" << std::endl;
914 0 : std::exit(EXIT_FAILURE);
915 : }
916 6 : mgr[side]->addProvider(prov[side]);
917 : }
918 8 : }
919 2 : if (side == 0 || !(prov[0].is() && prov[1].is())) {
920 0 : badUsage();
921 : }
922 2 : checkMap(prov[1], "", prov[0]->createRootCursor());
923 8 : return EXIT_SUCCESS;
924 0 : } catch (unoidl::FileFormatException & e1) {
925 : std::cerr
926 0 : << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
927 0 : << std::endl;
928 0 : std::exit(EXIT_FAILURE);
929 : }
930 6 : }
931 :
932 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|