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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "registry/registry.hxx"
22 : #include "registry/reader.hxx"
23 : #include "registry/version.h"
24 : #include "fileurl.hxx"
25 : #include "options.hxx"
26 :
27 : #include <rtl/ustring.hxx>
28 : #include <osl/diagnose.h>
29 :
30 : #include <stdio.h>
31 : #include <string.h>
32 :
33 : #include <set>
34 : #include <vector>
35 : #include <string>
36 :
37 : using namespace registry::tools;
38 :
39 : typedef std::set< OUString > StringSet;
40 :
41 0 : class Options_Impl : public Options
42 : {
43 : public:
44 0 : explicit Options_Impl(char const * program)
45 : : Options(program),
46 : m_bFullCheck(false),
47 : m_bForceOutput(false),
48 : m_bUnoTypeCheck(false),
49 0 : m_checkUnpublished(false)
50 0 : {}
51 :
52 0 : std::string const & getRegName1() const { return m_regName1; }
53 0 : std::string const & getRegName2() const { return m_regName2; }
54 :
55 0 : bool isStartKeyValid() const { return (!m_startKey.isEmpty()); }
56 0 : OUString const & getStartKey() const { return m_startKey; }
57 : bool matchedWithExcludeKey( const OUString& keyName) const;
58 :
59 0 : bool fullCheck() const { return m_bFullCheck; }
60 0 : bool forceOutput() const { return m_bForceOutput; }
61 0 : bool unoTypeCheck() const { return m_bUnoTypeCheck; }
62 0 : bool checkUnpublished() const { return m_checkUnpublished; }
63 :
64 : protected:
65 : bool setRegName_Impl(char c, std::string const & param);
66 :
67 : virtual void printUsage_Impl() const SAL_OVERRIDE;
68 : virtual bool initOptions_Impl (std::vector< std::string > & rArgs) SAL_OVERRIDE;
69 :
70 : std::string m_regName1;
71 : std::string m_regName2;
72 : OUString m_startKey;
73 : StringSet m_excludeKeys;
74 : bool m_bFullCheck;
75 : bool m_bForceOutput;
76 : bool m_bUnoTypeCheck;
77 : bool m_checkUnpublished;
78 : };
79 :
80 : #define U2S( s ) OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr()
81 :
82 0 : inline OUString makeOUString (std::string const & s)
83 : {
84 0 : return OUString(s.c_str(), s.size(), RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
85 : }
86 :
87 0 : inline OUString shortName(OUString const & fullName)
88 : {
89 0 : return fullName.copy(fullName.lastIndexOf('/') + 1);
90 : }
91 :
92 0 : bool Options_Impl::setRegName_Impl(char c, std::string const & param)
93 : {
94 0 : bool one = (c == '1'), two = (c == '2');
95 0 : if (one)
96 0 : m_regName1 = param;
97 0 : if (two)
98 0 : m_regName2 = param;
99 0 : return (one || two);
100 : }
101 :
102 : //virtual
103 0 : void Options_Impl::printUsage_Impl() const
104 : {
105 0 : std::string const & rProgName = getProgramName();
106 : fprintf(stderr,
107 : "Usage: %s -r1<filename> -r2<filename> [-options] | @<filename>\n", rProgName.c_str()
108 0 : );
109 : fprintf(stderr,
110 : " -r1<filename> = filename specifies the name of the first registry.\n"
111 : " -r2<filename> = filename specifies the name of the second registry.\n"
112 : " @<filename> = filename specifies a command file.\n"
113 : "Options:\n"
114 : " -s<name> = name specifies the name of a start key. If no start key\n"
115 : " |S<name> is specified the comparison starts with the root key.\n"
116 : " -x<name> = name specifies the name of a key which won't be compared. All\n"
117 : " |X<name> subkeys won't be compared also. This option can be used more than once.\n"
118 : " -f|F = force the detailed output of any diffenrences. Default\n"
119 : " is that only the number of differences is returned.\n"
120 : " -c|C = make a complete check, that means any differences will be\n"
121 : " detected. Default is only a compatibility check that means\n"
122 : " only UNO typelibrary entries will be checked.\n"
123 : " -t|T = make an UNO type compatibility check. This means that registry 2\n"
124 : " will be checked against registry 1. If a interface in r2 contains\n"
125 : " more methods or the methods are in a different order as in r1, r2 is\n"
126 : " incompatible to r1. But if a service in r2 supports more properties as\n"
127 : " in r1 and the new properties are 'optional' it is compatible.\n"
128 : " -u|U = additionally check types that are unpublished in registry 1.\n"
129 : " -h|-? = print this help message and exit.\n"
130 0 : );
131 : fprintf(stderr,
132 : "\n%s Version 1.0\n\n", rProgName.c_str()
133 0 : );
134 0 : }
135 :
136 : // virtual
137 0 : bool Options_Impl::initOptions_Impl (std::vector< std::string > & rArgs)
138 : {
139 0 : std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end();
140 0 : for (; first != last; ++first)
141 : {
142 0 : if ((*first)[0] != '-')
143 : {
144 0 : return badOption("invalid", (*first).c_str());
145 : }
146 0 : switch ((*first)[1])
147 : {
148 : case 'r':
149 : case 'R':
150 : {
151 0 : if (!((++first != last) && ((*first)[0] != '-')))
152 : {
153 0 : return badOption("invalid", (*first).c_str());
154 : }
155 :
156 0 : std::string option(*first), param;
157 0 : if (option.size() == 1)
158 : {
159 : // "-r<n><space><param>"
160 0 : if (!((++first != last) && ((*first)[0] != '-')))
161 : {
162 0 : return badOption("invalid", (*first).c_str());
163 : }
164 0 : param = (*first);
165 : }
166 : else
167 : {
168 : // "-r<n><param>"
169 0 : param = std::string(&(option[1]), option.size() - 1);
170 : }
171 0 : if (!setRegName_Impl(option[0], param))
172 : {
173 0 : return badOption("invalid", option.c_str());
174 : }
175 0 : break;
176 : }
177 : case 's':
178 : case 'S':
179 : {
180 0 : if (!((++first != last) && ((*first)[0] != '-')))
181 : {
182 0 : return badOption("invalid", (*first).c_str());
183 : }
184 0 : m_startKey = makeOUString(*first);
185 0 : break;
186 : }
187 : case 'x':
188 : case 'X':
189 : {
190 0 : if (!((++first != last) && ((*first)[0] != '-')))
191 : {
192 0 : return badOption("invalid", (*first).c_str());
193 : }
194 0 : m_excludeKeys.insert(makeOUString(*first));
195 0 : break;
196 : }
197 : case 'f':
198 : case 'F':
199 : {
200 0 : if ((*first).size() > 2)
201 : {
202 0 : return badOption("invalid", (*first).c_str());
203 : }
204 0 : m_bForceOutput = true;
205 0 : break;
206 : }
207 : case 'c':
208 : case 'C':
209 : {
210 0 : if ((*first).size() > 2)
211 : {
212 0 : return badOption("invalid", (*first).c_str());
213 : }
214 0 : m_bFullCheck = true;
215 0 : break;
216 : }
217 : case 't':
218 : case 'T':
219 : {
220 0 : if ((*first).size() > 2)
221 : {
222 0 : return badOption("invalid", (*first).c_str());
223 : }
224 0 : m_bUnoTypeCheck = true;
225 0 : break;
226 : }
227 : case 'u':
228 : case 'U':
229 : {
230 0 : if ((*first).size() > 2)
231 : {
232 0 : return badOption("invalid", (*first).c_str());
233 : }
234 0 : m_checkUnpublished = true;
235 0 : break;
236 : }
237 : case 'h':
238 : case '?':
239 : {
240 0 : if ((*first).size() > 2)
241 : {
242 0 : return badOption("invalid", (*first).c_str());
243 : }
244 0 : return printUsage();
245 : // break; // Unreachable
246 : }
247 : default:
248 : {
249 0 : return badOption("unknown", (*first).c_str());
250 : // break; // Unreachable
251 : }
252 : }
253 : }
254 :
255 0 : if ( m_regName1.empty() )
256 : {
257 0 : return badOption("missing", "-r1");
258 : }
259 0 : if ( m_regName2.empty() )
260 : {
261 0 : return badOption("missing", "-r2");
262 : }
263 0 : return true;
264 : }
265 :
266 0 : bool Options_Impl::matchedWithExcludeKey( const OUString& keyName) const
267 : {
268 0 : if (!m_excludeKeys.empty())
269 : {
270 0 : StringSet::const_iterator first = m_excludeKeys.begin(), last = m_excludeKeys.end();
271 0 : for (; first != last; ++first)
272 : {
273 0 : if (keyName.startsWith(*first))
274 0 : return true;
275 : }
276 : }
277 0 : return false;
278 : }
279 :
280 0 : static char const * getTypeClass(RTTypeClass typeClass)
281 : {
282 0 : switch (typeClass)
283 : {
284 : case RT_TYPE_INTERFACE:
285 0 : return "INTERFACE";
286 : case RT_TYPE_MODULE:
287 0 : return "MODULE";
288 : case RT_TYPE_STRUCT:
289 0 : return "STRUCT";
290 : case RT_TYPE_ENUM:
291 0 : return "ENUM";
292 : case RT_TYPE_EXCEPTION:
293 0 : return "EXCEPTION";
294 : case RT_TYPE_TYPEDEF:
295 0 : return "TYPEDEF";
296 : case RT_TYPE_SERVICE:
297 0 : return "SERVICE";
298 : case RT_TYPE_OBJECT:
299 0 : return "OBJECT";
300 : case RT_TYPE_CONSTANTS:
301 0 : return "CONSTANTS";
302 : default:
303 0 : return "INVALID";
304 : }
305 : }
306 :
307 0 : static OString getFieldAccess(RTFieldAccess fieldAccess)
308 : {
309 0 : OString ret;
310 : if ( (fieldAccess & RT_ACCESS_INVALID) == RT_ACCESS_INVALID )
311 : {
312 0 : ret += OString("INVALID");
313 : }
314 0 : if ( (fieldAccess & RT_ACCESS_READONLY) == RT_ACCESS_READONLY )
315 : {
316 0 : ret += OString(ret.isEmpty() ? "READONLY" : ",READONLY");
317 : }
318 0 : if ( (fieldAccess & RT_ACCESS_OPTIONAL) == RT_ACCESS_OPTIONAL )
319 : {
320 0 : ret += OString(ret.isEmpty() ? "OPTIONAL" : ",OPTIONAL");
321 : }
322 0 : if ( (fieldAccess & RT_ACCESS_MAYBEVOID) == RT_ACCESS_MAYBEVOID )
323 : {
324 0 : ret += OString(ret.isEmpty() ? "MAYBEVOID" : ",MAYBEVOID");
325 : }
326 0 : if ( (fieldAccess & RT_ACCESS_BOUND) == RT_ACCESS_BOUND )
327 : {
328 0 : ret += OString(ret.isEmpty() ? "BOUND" : ",BOUND");
329 : }
330 0 : if ( (fieldAccess & RT_ACCESS_CONSTRAINED) == RT_ACCESS_CONSTRAINED )
331 : {
332 0 : ret += OString(ret.isEmpty() ? "CONSTRAINED" : ",CONSTRAINED");
333 : }
334 0 : if ( (fieldAccess & RT_ACCESS_TRANSIENT) == RT_ACCESS_TRANSIENT )
335 : {
336 0 : ret += OString(ret.isEmpty() ? "TRANSIENT" : ",TRANSIENT");
337 : }
338 0 : if ( (fieldAccess & RT_ACCESS_MAYBEAMBIGUOUS) == RT_ACCESS_MAYBEAMBIGUOUS )
339 : {
340 0 : ret += OString(ret.isEmpty() ? "MAYBEAMBIGUOUS" : ",MAYBEAMBIGUOUS");
341 : }
342 0 : if ( (fieldAccess & RT_ACCESS_MAYBEDEFAULT) == RT_ACCESS_MAYBEDEFAULT )
343 : {
344 0 : ret += OString(ret.isEmpty() ? "MAYBEDEFAULT" : ",MAYBEDEFAULT");
345 : }
346 0 : if ( (fieldAccess & RT_ACCESS_REMOVABLE) == RT_ACCESS_REMOVABLE )
347 : {
348 0 : ret += OString(ret.isEmpty() ? "REMOVABLE" : ",REMOVABLE");
349 : }
350 0 : if ( (fieldAccess & RT_ACCESS_ATTRIBUTE) == RT_ACCESS_ATTRIBUTE )
351 : {
352 0 : ret += OString(ret.isEmpty() ? "ATTRIBUTE" : ",ATTRIBUTE");
353 : }
354 0 : if ( (fieldAccess & RT_ACCESS_PROPERTY) == RT_ACCESS_PROPERTY )
355 : {
356 0 : ret += OString(ret.isEmpty() ? "PROPERTY" : ",PROPERTY");
357 : }
358 0 : if ( (fieldAccess & RT_ACCESS_CONST) == RT_ACCESS_CONST )
359 : {
360 0 : ret += OString(ret.isEmpty() ? "CONST" : ",CONST");
361 : }
362 0 : if ( (fieldAccess & RT_ACCESS_READWRITE) == RT_ACCESS_READWRITE )
363 : {
364 0 : ret += OString(ret.isEmpty() ? "READWRITE" : ",READWRITE");
365 : }
366 0 : return ret;
367 : }
368 :
369 0 : static char const * getConstValueType(RTConstValue& constValue)
370 : {
371 0 : switch (constValue.m_type)
372 : {
373 : case RT_TYPE_BOOL:
374 0 : return "sal_Bool";
375 : case RT_TYPE_BYTE:
376 0 : return "sal_uInt8";
377 : case RT_TYPE_INT16:
378 0 : return "sal_Int16";
379 : case RT_TYPE_UINT16:
380 0 : return "sal_uInt16";
381 : case RT_TYPE_INT32:
382 0 : return "sal_Int32";
383 : case RT_TYPE_UINT32:
384 0 : return "sal_uInt32";
385 : // case RT_TYPE_INT64:
386 : // return "sal_Int64";
387 : // case RT_TYPE_UINT64:
388 : // return "sal_uInt64";
389 : case RT_TYPE_FLOAT:
390 0 : return "float";
391 : case RT_TYPE_DOUBLE:
392 0 : return "double";
393 : case RT_TYPE_STRING:
394 0 : return "sal_Unicode*";
395 : default:
396 0 : return "NONE";
397 : }
398 : }
399 :
400 0 : static void printConstValue(RTConstValue& constValue)
401 : {
402 0 : switch (constValue.m_type)
403 : {
404 : case RT_TYPE_NONE:
405 0 : fprintf(stdout, "none");
406 0 : break;
407 : case RT_TYPE_BOOL:
408 0 : fprintf(stdout, "%s", constValue.m_value.aBool ? "TRUE" : "FALSE");
409 0 : break;
410 : case RT_TYPE_BYTE:
411 0 : fprintf(stdout, "%d", constValue.m_value.aByte);
412 0 : break;
413 : case RT_TYPE_INT16:
414 0 : fprintf(stdout, "%d", constValue.m_value.aShort);
415 0 : break;
416 : case RT_TYPE_UINT16:
417 0 : fprintf(stdout, "%d", constValue.m_value.aUShort);
418 0 : break;
419 : case RT_TYPE_INT32:
420 : fprintf(
421 : stdout, "%ld",
422 0 : sal::static_int_cast< long >(constValue.m_value.aLong));
423 0 : break;
424 : case RT_TYPE_UINT32:
425 : fprintf(
426 : stdout, "%lu",
427 : sal::static_int_cast< unsigned long >(
428 0 : constValue.m_value.aULong));
429 0 : break;
430 : // case RT_TYPE_INT64:
431 : // fprintf(stdout, "%d", constValue.m_value.aHyper);
432 : // case RT_TYPE_UINT64:
433 : // fprintf(stdout, "%d", constValue.m_value.aUHyper);
434 : case RT_TYPE_FLOAT:
435 0 : fprintf(stdout, "%f", constValue.m_value.aFloat);
436 0 : break;
437 : case RT_TYPE_DOUBLE:
438 0 : fprintf(stdout, "%f", constValue.m_value.aDouble);
439 0 : break;
440 : case RT_TYPE_STRING:
441 : fprintf(
442 : stdout, "%s",
443 : (OUStringToOString(
444 : constValue.m_value.aString, RTL_TEXTENCODING_UTF8).
445 0 : getStr()));
446 0 : break;
447 : default:
448 0 : break;
449 : }
450 0 : }
451 :
452 0 : static void dumpTypeClass(bool & rbDump, RTTypeClass typeClass, OUString const & keyName)
453 : {
454 0 : if (rbDump)
455 0 : fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
456 0 : rbDump = false;
457 0 : }
458 :
459 0 : static sal_uInt32 checkConstValue(Options_Impl const & options,
460 : const OUString& keyName,
461 : RTTypeClass typeClass,
462 : bool & bDump,
463 : RTConstValue& constValue1,
464 : RTConstValue& constValue2,
465 : sal_uInt16 index1)
466 : {
467 0 : switch (constValue1.m_type)
468 : {
469 : case RT_TYPE_NONE:
470 0 : break;
471 : case RT_TYPE_BOOL:
472 0 : if (constValue1.m_value.aBool != constValue2.m_value.aBool)
473 : {
474 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
475 : {
476 0 : dumpTypeClass(bDump, typeClass, keyName);
477 : fprintf(stdout, " Field %d: Value1 = %s != Value2 = %s\n", index1,
478 : constValue1.m_value.aBool ? "TRUE" : "FALSE",
479 0 : constValue2.m_value.aBool ? "TRUE" : "FALSE");
480 : }
481 0 : return 1;
482 : }
483 0 : break;
484 : case RT_TYPE_BYTE:
485 0 : if (constValue1.m_value.aByte != constValue2.m_value.aByte)
486 : {
487 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
488 : {
489 0 : dumpTypeClass(bDump, typeClass, keyName);
490 : fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
491 0 : constValue1.m_value.aByte, constValue2.m_value.aByte);
492 : }
493 0 : return 1;
494 : }
495 0 : break;
496 : case RT_TYPE_INT16:
497 0 : if (constValue1.m_value.aShort != constValue2.m_value.aShort)
498 : {
499 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
500 : {
501 0 : dumpTypeClass(bDump, typeClass, keyName);
502 : fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
503 0 : constValue1.m_value.aShort, constValue2.m_value.aShort);
504 : }
505 0 : return 1;
506 : }
507 0 : break;
508 : case RT_TYPE_UINT16:
509 0 : if (constValue1.m_value.aUShort != constValue2.m_value.aUShort)
510 : {
511 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
512 : {
513 0 : dumpTypeClass(bDump, typeClass, keyName);
514 : fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
515 0 : constValue1.m_value.aUShort, constValue2.m_value.aUShort);
516 : }
517 0 : return 1;
518 : }
519 0 : break;
520 : case RT_TYPE_INT32:
521 0 : if (constValue1.m_value.aLong != constValue2.m_value.aLong)
522 : {
523 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
524 : {
525 0 : dumpTypeClass(bDump, typeClass, keyName);
526 : fprintf(stdout, " Field %d: Value1 = %ld != Value2 = %ld\n", index1,
527 : sal::static_int_cast< long >(constValue1.m_value.aLong),
528 0 : sal::static_int_cast< long >(constValue2.m_value.aLong));
529 : }
530 0 : return 1;
531 : }
532 0 : break;
533 : case RT_TYPE_UINT32:
534 0 : if (constValue1.m_value.aULong != constValue2.m_value.aULong)
535 : {
536 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
537 : {
538 0 : dumpTypeClass(bDump, typeClass, keyName);
539 : fprintf(stdout, " Field %d: Value1 = %lu != Value2 = %lu\n", index1,
540 : sal::static_int_cast< unsigned long >(constValue1.m_value.aULong),
541 0 : sal::static_int_cast< unsigned long >(constValue2.m_value.aULong));
542 : }
543 0 : return 1;
544 : }
545 0 : break;
546 : case RT_TYPE_INT64:
547 0 : if (constValue1.m_value.aHyper != constValue2.m_value.aHyper)
548 : {
549 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
550 : {
551 0 : dumpTypeClass(bDump, typeClass, keyName);
552 : fprintf(
553 : stdout, " Field %d: Value1 = %s != Value2 = %s\n",
554 : index1,
555 : OUStringToOString(
556 : OUString::number(constValue1.m_value.aHyper),
557 : RTL_TEXTENCODING_ASCII_US).getStr(),
558 : OUStringToOString(
559 : OUString::number(constValue2.m_value.aHyper),
560 0 : RTL_TEXTENCODING_ASCII_US).getStr());
561 : }
562 0 : return 1;
563 : }
564 0 : break;
565 : case RT_TYPE_UINT64:
566 0 : if (constValue1.m_value.aUHyper != constValue2.m_value.aUHyper)
567 : {
568 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
569 : {
570 0 : dumpTypeClass(bDump, typeClass, keyName);
571 : fprintf(
572 : stdout, " Field %d: Value1 = %s != Value2 = %s\n",
573 : index1,
574 : OUStringToOString(
575 : OUString::number(
576 : constValue1.m_value.aUHyper),
577 : RTL_TEXTENCODING_ASCII_US).getStr(),
578 : OUStringToOString(
579 : OUString::number(
580 : constValue2.m_value.aUHyper),
581 0 : RTL_TEXTENCODING_ASCII_US).getStr());
582 : // printing the unsigned values as signed should be
583 : // acceptable...
584 : }
585 0 : return 1;
586 : }
587 0 : break;
588 : case RT_TYPE_FLOAT:
589 0 : if (constValue1.m_value.aFloat != constValue2.m_value.aFloat)
590 : {
591 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
592 : {
593 0 : dumpTypeClass(bDump, typeClass, keyName);
594 : fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1,
595 0 : constValue1.m_value.aFloat, constValue2.m_value.aFloat);
596 : }
597 0 : return 1;
598 : }
599 0 : break;
600 : case RT_TYPE_DOUBLE:
601 0 : if (constValue1.m_value.aDouble != constValue2.m_value.aDouble)
602 : {
603 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
604 : {
605 0 : dumpTypeClass(bDump, typeClass, keyName);
606 : fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1,
607 0 : constValue1.m_value.aDouble, constValue2.m_value.aDouble);
608 : }
609 0 : return 1;
610 : }
611 0 : break;
612 : default:
613 : OSL_ASSERT(false);
614 0 : break;
615 : }
616 0 : return 0;
617 : }
618 :
619 : enum verbosity_t {SILENT, REPORT};
620 0 : static sal_uInt32 checkField(Options_Impl const & options,
621 : const OUString& keyName,
622 : RTTypeClass typeClass,
623 : bool & bDump,
624 : typereg::Reader& reader1,
625 : typereg::Reader& reader2,
626 : sal_uInt16 index1,
627 : sal_uInt16 index2,
628 : verbosity_t const eVerbosity)
629 : {
630 0 : sal_uInt32 nError = 0;
631 0 : if ( reader1.getFieldName(index1) != reader2.getFieldName(index2) )
632 : {
633 0 : if (options.forceOutput() && (REPORT == eVerbosity))
634 : {
635 0 : dumpTypeClass (bDump, typeClass, keyName);
636 : fprintf(stdout, " Field %d: Name1 = %s != Name2 = %s\n", index1,
637 0 : U2S(reader1.getFieldName(index1)), U2S(reader2.getFieldName(index2)));
638 : }
639 0 : nError++;
640 : }
641 0 : if ( reader1.getFieldTypeName(index1) != reader2.getFieldTypeName(index2) )
642 : {
643 0 : if (options.forceOutput() && (REPORT == eVerbosity))
644 : {
645 0 : dumpTypeClass (bDump, typeClass, keyName);
646 : fprintf(stdout, " Field %d: Type1 = %s != Type2 = %s\n", index1,
647 0 : U2S(reader1.getFieldTypeName(index1)), U2S(reader2.getFieldTypeName(index2)));
648 : }
649 0 : nError++;
650 : }
651 : else
652 : {
653 0 : RTConstValue constValue1 = reader1.getFieldValue(index1);
654 0 : RTConstValue constValue2 = reader2.getFieldValue(index2);
655 0 : if ( constValue1.m_type != constValue2.m_type )
656 : {
657 0 : if (options.forceOutput() && (REPORT == eVerbosity))
658 : {
659 0 : dumpTypeClass (bDump, typeClass, keyName);
660 : fprintf(stdout, " Field %d: Access1 = %s != Access2 = %s\n", index1,
661 0 : getConstValueType(constValue1), getConstValueType(constValue2));
662 0 : fprintf(stdout, " Field %d: Value1 = ", index1);
663 0 : printConstValue(constValue1);
664 0 : fprintf(stdout, " != Value2 = ");
665 0 : printConstValue(constValue1);
666 0 : fprintf(stdout, "\n;");
667 : }
668 0 : nError++;
669 : }
670 : else
671 : {
672 0 : nError += checkConstValue(options, keyName, typeClass, bDump, constValue1, constValue2, index1);
673 0 : }
674 : }
675 :
676 0 : if ( reader1.getFieldFlags(index1) != reader2.getFieldFlags(index2) )
677 : {
678 0 : if (options.forceOutput() && (REPORT == eVerbosity))
679 : {
680 0 : dumpTypeClass (bDump, typeClass, keyName);
681 : fprintf(stdout, " Field %d: FieldAccess1 = %s != FieldAccess2 = %s\n", index1,
682 0 : getFieldAccess(reader1.getFieldFlags(index1)).getStr(),
683 0 : getFieldAccess(reader1.getFieldFlags(index2)).getStr());
684 : }
685 0 : nError++;
686 : }
687 :
688 0 : if ( options.fullCheck() && (reader1.getFieldDocumentation(index1) != reader2.getFieldDocumentation(index2)) )
689 : {
690 0 : if (options.forceOutput() && (REPORT == eVerbosity))
691 : {
692 0 : dumpTypeClass (bDump, typeClass, keyName);
693 : fprintf(stdout, " Field %d: Doku1 = %s\n Doku2 = %s\n", index1,
694 0 : U2S(reader1.getFieldDocumentation(index1)), U2S(reader2.getFieldDocumentation(index2)));
695 : }
696 0 : nError++;
697 : }
698 0 : return nError;
699 : }
700 :
701 0 : static char const * getMethodMode(RTMethodMode methodMode)
702 : {
703 0 : switch ( methodMode )
704 : {
705 : case RT_MODE_ONEWAY:
706 0 : return "ONEWAY";
707 : case RT_MODE_ONEWAY_CONST:
708 0 : return "ONEWAY,CONST";
709 : case RT_MODE_TWOWAY:
710 0 : return "NONE";
711 : case RT_MODE_TWOWAY_CONST:
712 0 : return "CONST";
713 : default:
714 0 : return "INVALID";
715 : }
716 : }
717 :
718 0 : static char const * getParamMode(RTParamMode paramMode)
719 : {
720 0 : switch ( paramMode )
721 : {
722 : case RT_PARAM_IN:
723 0 : return "IN";
724 : case RT_PARAM_OUT:
725 0 : return "OUT";
726 : case RT_PARAM_INOUT:
727 0 : return "INOUT";
728 : default:
729 0 : return "INVALID";
730 : }
731 : }
732 :
733 0 : static sal_uInt32 checkMethod(Options_Impl const & options,
734 : const OUString& keyName,
735 : RTTypeClass typeClass,
736 : bool & bDump,
737 : typereg::Reader& reader1,
738 : typereg::Reader& reader2,
739 : sal_uInt16 index)
740 : {
741 0 : sal_uInt32 nError = 0;
742 0 : if ( reader1.getMethodName(index) != reader2.getMethodName(index) )
743 : {
744 0 : if ( options.forceOutput() )
745 : {
746 0 : dumpTypeClass (bDump, typeClass, keyName);
747 : fprintf(stdout, " Method1 %d: Name1 = %s != Name2 = %s\n", index,
748 : U2S(reader1.getMethodName(index)),
749 0 : U2S(reader2.getMethodName(index)));
750 : }
751 0 : nError++;
752 : }
753 :
754 0 : if ( reader1.getMethodReturnTypeName(index) != reader2.getMethodReturnTypeName(index) )
755 : {
756 0 : if ( options.forceOutput() )
757 : {
758 0 : dumpTypeClass (bDump, typeClass, keyName);
759 : fprintf(stdout, " Method1 %d: ReturnType1 = %s != ReturnType2 = %s\n", index,
760 : U2S(reader1.getMethodReturnTypeName(index)),
761 0 : U2S(reader2.getMethodReturnTypeName(index)));
762 : }
763 0 : nError++;
764 : }
765 :
766 0 : sal_uInt16 nParams1 = (sal_uInt16)reader1.getMethodParameterCount(index);
767 0 : sal_uInt16 nParams2 = (sal_uInt16)reader2.getMethodParameterCount(index);
768 0 : if ( nParams1 != nParams2 )
769 : {
770 0 : if ( options.forceOutput() )
771 : {
772 0 : dumpTypeClass (bDump, typeClass, keyName);
773 0 : fprintf(stdout, " Method %d : nParameters1 = %d != nParameters2 = %d\n", index, nParams1, nParams2);
774 : }
775 0 : nError++;
776 : }
777 0 : sal_uInt16 i=0;
778 0 : for (i=0; i < nParams1 && i < nParams2; i++)
779 : {
780 0 : if ( reader1.getMethodParameterTypeName(index, i) != reader2.getMethodParameterTypeName(index, i) )
781 : {
782 0 : if ( options.forceOutput() )
783 : {
784 0 : dumpTypeClass (bDump, typeClass, keyName);
785 : fprintf(stdout, " Method %d, Parameter %d: Type1 = %s != Type2 = %s\n", index, i,
786 : U2S(reader1.getMethodParameterTypeName(index, i)),
787 0 : U2S(reader2.getMethodParameterTypeName(index, i)));
788 : }
789 0 : nError++;
790 : }
791 0 : if ( options.fullCheck() && (reader1.getMethodParameterName(index, i) != reader2.getMethodParameterName(index, i)) )
792 : {
793 0 : if ( options.forceOutput() )
794 : {
795 0 : dumpTypeClass (bDump, typeClass, keyName);
796 : fprintf(stdout, " Method %d, Parameter %d: Name1 = %s != Name2 = %s\n", index, i,
797 : U2S(reader1.getMethodParameterName(index, i)),
798 0 : U2S(reader2.getMethodParameterName(index, i)));
799 : }
800 0 : nError++;
801 : }
802 0 : if ( reader1.getMethodParameterFlags(index, i) != reader2.getMethodParameterFlags(index, i) )
803 : {
804 0 : if ( options.forceOutput() )
805 : {
806 0 : dumpTypeClass (bDump, typeClass, keyName);
807 : fprintf(stdout, " Method %d, Parameter %d: Mode1 = %s != Mode2 = %s\n", index, i,
808 : getParamMode(reader1.getMethodParameterFlags(index, i)),
809 0 : getParamMode(reader2.getMethodParameterFlags(index, i)));
810 : }
811 0 : nError++;
812 : }
813 : }
814 0 : if ( i < nParams1 && options.forceOutput() )
815 : {
816 0 : dumpTypeClass (bDump, typeClass, keyName);
817 0 : fprintf(stdout, " Registry1: Method %d contains %d more parameters\n", index, nParams1 - i);
818 : }
819 0 : if ( i < nParams2 && options.forceOutput() )
820 : {
821 0 : dumpTypeClass (bDump, typeClass, keyName);
822 0 : fprintf(stdout, " Registry2: Method %d contains %d more parameters\n", index, nParams2 - i);
823 : }
824 :
825 0 : sal_uInt16 nExcep1 = (sal_uInt16)reader1.getMethodExceptionCount(index);
826 0 : sal_uInt16 nExcep2 = (sal_uInt16)reader2.getMethodExceptionCount(index);
827 0 : if ( nExcep1 != nExcep2 )
828 : {
829 0 : if ( options.forceOutput() )
830 : {
831 0 : dumpTypeClass (bDump, typeClass, keyName);
832 0 : fprintf(stdout, " nExceptions1 = %d != nExceptions2 = %d\n", nExcep1, nExcep2);
833 : }
834 0 : nError++;
835 : }
836 0 : for (i=0; i < nExcep1 && i < nExcep2; i++)
837 : {
838 0 : if ( reader1.getMethodExceptionTypeName(index, i) != reader2.getMethodExceptionTypeName(index, i) )
839 : {
840 0 : if ( options.forceOutput() )
841 : {
842 0 : dumpTypeClass (bDump, typeClass, keyName);
843 : fprintf(stdout, " Method %d, Exception %d: Name1 = %s != Name2 = %s\n", index, i,
844 : U2S(reader1.getMethodExceptionTypeName(index, i)),
845 0 : U2S(reader2.getMethodExceptionTypeName(index, i)));
846 : }
847 0 : nError++;
848 : }
849 : }
850 0 : if ( i < nExcep1 && options.forceOutput() )
851 : {
852 0 : dumpTypeClass (bDump, typeClass, keyName);
853 0 : fprintf(stdout, " Registry1: Method %d contains %d more exceptions\n", index, nExcep1 - i);
854 : }
855 0 : if ( i < nExcep2 && options.forceOutput() )
856 : {
857 0 : dumpTypeClass (bDump, typeClass, keyName);
858 0 : fprintf(stdout, " Registry2: Method %d contains %d more exceptions\n", index, nExcep2 - i);
859 : }
860 :
861 0 : if ( reader1.getMethodFlags(index) != reader2.getMethodFlags(index) )
862 : {
863 0 : if ( options.forceOutput() )
864 : {
865 0 : dumpTypeClass (bDump, typeClass, keyName);
866 : fprintf(stdout, " Method %d: Mode1 = %s != Mode2 = %s\n", index,
867 : getMethodMode(reader1.getMethodFlags(index)),
868 0 : getMethodMode(reader2.getMethodFlags(index)));
869 : }
870 0 : nError++;
871 : }
872 :
873 0 : if ( options.fullCheck() && (reader1.getMethodDocumentation(index) != reader2.getMethodDocumentation(index)) )
874 : {
875 0 : if ( options.forceOutput() )
876 : {
877 0 : dumpTypeClass (bDump, typeClass, keyName);
878 : fprintf(stdout, " Method %d: Doku1 = %s\n Doku2 = %s\n", index,
879 : U2S(reader1.getMethodDocumentation(index)),
880 0 : U2S(reader2.getMethodDocumentation(index)));
881 : }
882 0 : nError++;
883 : }
884 0 : return nError;
885 : }
886 :
887 0 : static char const * getReferenceType(RTReferenceType refType)
888 : {
889 0 : switch (refType)
890 : {
891 : case RT_REF_SUPPORTS:
892 0 : return "RT_REF_SUPPORTS";
893 : case RT_REF_OBSERVES:
894 0 : return "RT_REF_OBSERVES";
895 : case RT_REF_EXPORTS:
896 0 : return "RT_REF_EXPORTS";
897 : case RT_REF_NEEDS:
898 0 : return "RT_REF_NEEDS";
899 : default:
900 0 : return "RT_REF_INVALID";
901 : }
902 : }
903 :
904 0 : static sal_uInt32 checkReference(Options_Impl const & options,
905 : const OUString& keyName,
906 : RTTypeClass typeClass,
907 : bool & bDump,
908 : typereg::Reader& reader1,
909 : typereg::Reader& reader2,
910 : sal_uInt16 index1,
911 : sal_uInt16 index2)
912 : {
913 0 : sal_uInt32 nError = 0;
914 0 : if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) )
915 : {
916 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
917 : {
918 0 : dumpTypeClass (bDump, typeClass, keyName);
919 : fprintf(stdout, " Reference %d: Name1 = %s != Name2 = %s\n", index1,
920 : U2S(reader1.getReferenceTypeName(index1)),
921 0 : U2S(reader2.getReferenceTypeName(index2)));
922 : }
923 0 : nError++;
924 : }
925 0 : if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) )
926 : {
927 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
928 : {
929 0 : dumpTypeClass (bDump, typeClass, keyName);
930 : fprintf(stdout, " Reference %d: Type1 = %s != Type2 = %s\n", index1,
931 : getReferenceType(reader1.getReferenceSort(index1)),
932 0 : getReferenceType(reader2.getReferenceSort(index2)));
933 : }
934 0 : nError++;
935 : }
936 0 : if ( options.fullCheck() && (reader1.getReferenceDocumentation(index1) != reader2.getReferenceDocumentation(index2)) )
937 : {
938 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
939 : {
940 0 : dumpTypeClass (bDump, typeClass, keyName);
941 : fprintf(stdout, " Reference %d: Doku1 = %s\n Doku2 = %s\n", index1,
942 : U2S(reader1.getReferenceDocumentation(index1)),
943 0 : U2S(reader2.getReferenceDocumentation(index2)));
944 : }
945 0 : nError++;
946 : }
947 0 : if ( reader1.getReferenceFlags(index1) != reader2.getReferenceFlags(index2) )
948 : {
949 0 : if ( options.forceOutput() && !options.unoTypeCheck() )
950 : {
951 0 : dumpTypeClass (bDump, typeClass, keyName);
952 : fprintf(stdout, " Reference %d: Access1 = %s != Access2 = %s\n", index1,
953 0 : getFieldAccess(reader1.getReferenceFlags(index1)).getStr(),
954 0 : getFieldAccess(reader1.getReferenceFlags(index2)).getStr());
955 : }
956 0 : nError++;
957 : }
958 0 : return nError;
959 : }
960 :
961 0 : static sal_uInt32 checkFieldsWithoutOrder(Options_Impl const & options,
962 : const OUString& keyName,
963 : RTTypeClass typeClass,
964 : bool & bDump,
965 : typereg::Reader& reader1,
966 : typereg::Reader& reader2)
967 : {
968 0 : sal_uInt32 nError = 0;
969 :
970 0 : sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount();
971 0 : sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount();
972 0 : sal_uInt16 i=0, j=0;
973 :
974 0 : if ( nFields1 > nFields2 )
975 : {
976 0 : if ( options.forceOutput() )
977 : {
978 0 : dumpTypeClass (bDump, typeClass, keyName);
979 : fprintf(stdout, " %s1 contains %d more properties as %s2\n",
980 0 : getTypeClass(typeClass), nFields1-nFields2, getTypeClass(typeClass));
981 : }
982 : }
983 :
984 0 : bool bFound = false;
985 0 : ::std::set< sal_uInt16 > moreProps;
986 :
987 0 : for (i=0; i < nFields1; i++)
988 : {
989 0 : for (j=0; j < nFields2; j++)
990 : {
991 0 : if (!checkField(options, keyName, typeClass, bDump, reader1, reader2, i, j, SILENT))
992 : {
993 0 : bFound = true;
994 0 : moreProps.insert(j);
995 0 : break;
996 : }
997 : }
998 0 : if (!bFound)
999 : {
1000 0 : if (options.forceOutput())
1001 : {
1002 0 : dumpTypeClass (bDump, typeClass, keyName);
1003 : fprintf(stdout, " incompatible change: Field %d ('%s') of r1 is not longer a property of this %s in r2\n",
1004 0 : i, U2S(shortName(reader1.getFieldName(i))), getTypeClass(typeClass));
1005 : }
1006 0 : nError++;
1007 : }
1008 : else
1009 : {
1010 0 : bFound = false;
1011 : }
1012 : }
1013 :
1014 0 : if ( typeClass == RT_TYPE_SERVICE && !moreProps.empty() )
1015 : {
1016 0 : for (j=0; j < nFields2; j++)
1017 : {
1018 0 : if ( moreProps.find(j) == moreProps.end() )
1019 : {
1020 0 : if ( (reader2.getFieldFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL )
1021 : {
1022 0 : if ( options.forceOutput() )
1023 : {
1024 0 : dumpTypeClass (bDump, typeClass, keyName);
1025 : fprintf(stdout,
1026 : " incompatible change: Field %d ('%s') of r2 is a new property"
1027 : " compared to this %s in r1 and is not 'optional'\n",
1028 0 : j, U2S(shortName(reader2.getFieldName(j))), getTypeClass(typeClass));
1029 : }
1030 0 : nError++;
1031 : }
1032 : }
1033 : }
1034 : }
1035 :
1036 0 : return nError;
1037 : }
1038 :
1039 0 : static sal_uInt32 checkBlob(
1040 : Options_Impl const & options,
1041 : const OUString& keyName,
1042 : typereg::Reader& reader1, sal_uInt32 size1,
1043 : typereg::Reader& reader2, sal_uInt32 size2)
1044 : {
1045 0 : sal_uInt32 nError = 0;
1046 0 : bool bDump = true;
1047 :
1048 0 : if ( options.fullCheck() && (size1 != size2) )
1049 : {
1050 0 : if ( options.forceOutput() )
1051 : {
1052 : fprintf(
1053 : stdout, " Size1 = %lu Size2 = %lu\n",
1054 : sal::static_int_cast< unsigned long >(size1),
1055 0 : sal::static_int_cast< unsigned long >(size2));
1056 : }
1057 : }
1058 0 : if (reader1.isPublished())
1059 : {
1060 0 : if (!reader2.isPublished())
1061 : {
1062 0 : if (options.forceOutput())
1063 : {
1064 0 : dumpTypeClass(bDump, /*"?"*/ reader1.getTypeClass(), keyName);
1065 0 : fprintf(stdout, " published in 1 but unpublished in 2\n");
1066 : }
1067 0 : ++nError;
1068 : }
1069 : }
1070 0 : else if (!options.checkUnpublished())
1071 : {
1072 0 : return nError;
1073 : }
1074 0 : if ( reader1.getTypeClass() != reader2.getTypeClass() )
1075 : {
1076 0 : if ( options.forceOutput() )
1077 : {
1078 0 : dumpTypeClass(bDump, /*"?"*/ reader1.getTypeClass(), keyName);
1079 : fprintf(stdout, " TypeClass1 = %s != TypeClass2 = %s\n",
1080 : getTypeClass(reader1.getTypeClass()),
1081 0 : getTypeClass(reader2.getTypeClass()));
1082 : }
1083 0 : return ++nError;
1084 : }
1085 :
1086 0 : RTTypeClass typeClass = reader1.getTypeClass();
1087 0 : if ( reader1.getTypeName() != reader2.getTypeName() )
1088 : {
1089 0 : if ( options.forceOutput() )
1090 : {
1091 0 : dumpTypeClass(bDump, typeClass, keyName);
1092 : fprintf(stdout, " TypeName1 = %s != TypeName2 = %s\n",
1093 0 : U2S(reader1.getTypeName()), U2S(reader2.getTypeName()));
1094 : }
1095 0 : nError++;
1096 : }
1097 0 : if ( (typeClass == RT_TYPE_INTERFACE ||
1098 0 : typeClass == RT_TYPE_STRUCT ||
1099 : typeClass == RT_TYPE_EXCEPTION) )
1100 : {
1101 0 : if (reader1.getSuperTypeCount() != reader2.getSuperTypeCount())
1102 : {
1103 0 : dumpTypeClass(bDump, typeClass, keyName);
1104 : fprintf(
1105 : stdout, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n",
1106 0 : static_cast< int >(reader1.getSuperTypeCount()),
1107 0 : static_cast< int >(reader2.getSuperTypeCount()));
1108 0 : ++nError;
1109 : } else
1110 : {
1111 0 : for (sal_Int16 i = 0; i < reader1.getSuperTypeCount(); ++i)
1112 : {
1113 0 : if (reader1.getSuperTypeName(i) != reader2.getSuperTypeName(i))
1114 : {
1115 0 : if ( options.forceOutput() )
1116 : {
1117 0 : dumpTypeClass(bDump, typeClass, keyName);
1118 : fprintf(stdout, " SuperTypeName1 = %s != SuperTypeName2 = %s\n",
1119 0 : U2S(reader1.getSuperTypeName(i)), U2S(reader2.getSuperTypeName(i)));
1120 : }
1121 0 : nError++;
1122 : }
1123 : }
1124 : }
1125 : }
1126 :
1127 0 : sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount();
1128 0 : sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount();
1129 0 : bool bCheckNormal = true;
1130 :
1131 0 : if ( (typeClass == RT_TYPE_SERVICE ||
1132 0 : typeClass == RT_TYPE_MODULE ||
1133 0 : typeClass == RT_TYPE_CONSTANTS) && options.unoTypeCheck() )
1134 : {
1135 0 : bCheckNormal = false;
1136 : }
1137 :
1138 0 : if ( bCheckNormal )
1139 : {
1140 0 : if ( nFields1 != nFields2 )
1141 : {
1142 0 : if ( options.forceOutput() )
1143 : {
1144 0 : dumpTypeClass(bDump, typeClass, keyName);
1145 0 : fprintf(stdout, " nFields1 = %d != nFields2 = %d\n", nFields1, nFields2);
1146 : }
1147 0 : nError++;
1148 : }
1149 :
1150 : sal_uInt16 i;
1151 0 : for (i=0; i < nFields1 && i < nFields2; i++)
1152 : {
1153 0 : nError += checkField(options, keyName, typeClass, bDump, reader1, reader2, i, i, REPORT);
1154 : }
1155 0 : if ( i < nFields1 && options.forceOutput() )
1156 : {
1157 0 : dumpTypeClass(bDump, typeClass, keyName);
1158 0 : fprintf(stdout, " Registry1 contains %d more fields\n", nFields1 - i);
1159 : }
1160 0 : if ( i < nFields2 && options.forceOutput() )
1161 : {
1162 0 : dumpTypeClass(bDump, typeClass, keyName);
1163 0 : fprintf(stdout, " Registry2 contains %d more fields\n", nFields2 - i);
1164 : }
1165 : }
1166 : else
1167 : {
1168 0 : nError += checkFieldsWithoutOrder(options, keyName, typeClass, bDump, reader1, reader2);
1169 : }
1170 :
1171 0 : if ( typeClass == RT_TYPE_INTERFACE )
1172 : {
1173 0 : sal_uInt16 nMethods1 = (sal_uInt16)reader1.getMethodCount();
1174 0 : sal_uInt16 nMethods2 = (sal_uInt16)reader2.getMethodCount();
1175 0 : if ( nMethods1 != nMethods2 )
1176 : {
1177 0 : if ( options.forceOutput() )
1178 : {
1179 0 : dumpTypeClass(bDump, typeClass, keyName);
1180 0 : fprintf(stdout, " nMethods1 = %d != nMethods2 = %d\n", nMethods1, nMethods2);
1181 : }
1182 0 : nError++;
1183 : }
1184 :
1185 : sal_uInt16 i;
1186 0 : for (i=0; i < nMethods1 && i < nMethods2; i++)
1187 : {
1188 0 : nError += checkMethod(options, keyName, typeClass, bDump, reader1, reader2, i);
1189 : }
1190 0 : if ( i < nMethods1 && options.forceOutput() )
1191 : {
1192 0 : fprintf(stdout, " Registry1 contains %d more methods\n", nMethods1 - i);
1193 : }
1194 0 : if ( i < nMethods2 && options.forceOutput() )
1195 : {
1196 0 : fprintf(stdout, " Registry2 contains %d more methods\n", nMethods2 - i);
1197 : }
1198 : }
1199 0 : if ( typeClass == RT_TYPE_SERVICE )
1200 : {
1201 0 : sal_uInt16 nReference1 = (sal_uInt16)reader1.getReferenceCount();
1202 0 : sal_uInt16 nReference2 = (sal_uInt16)reader2.getReferenceCount();
1203 :
1204 0 : if ( !bCheckNormal )
1205 : {
1206 0 : sal_uInt16 i=0, j=0;
1207 :
1208 0 : if ( nReference1 > nReference2 )
1209 : {
1210 0 : if ( options.forceOutput() )
1211 : {
1212 0 : dumpTypeClass(bDump, typeClass, keyName);
1213 : fprintf(stdout, " service1 contains %d more references as service2\n",
1214 0 : nReference1-nReference2);
1215 : }
1216 : }
1217 :
1218 0 : bool bFound = false;
1219 0 : ::std::set< sal_uInt16 > moreReferences;
1220 :
1221 0 : for (i=0; i < nReference1; i++)
1222 : {
1223 0 : for (j=0; j < nReference2; j++)
1224 : {
1225 0 : if (!checkReference(options, keyName, typeClass, bDump, reader1, reader2, i, j))
1226 : {
1227 0 : bFound = true;
1228 0 : moreReferences.insert(j);
1229 0 : break;
1230 : }
1231 : }
1232 0 : if (!bFound)
1233 : {
1234 0 : if (options.forceOutput())
1235 : {
1236 0 : dumpTypeClass(bDump, typeClass, keyName);
1237 : fprintf(stdout,
1238 : " incompatible change: Reference %d ('%s') in 'r1' is not longer a reference"
1239 : " of this service in 'r2'\n",
1240 0 : i, U2S(shortName(reader1.getReferenceTypeName(i))));
1241 : }
1242 0 : nError++;
1243 : }
1244 : else
1245 : {
1246 0 : bFound = false;
1247 : }
1248 : }
1249 :
1250 0 : if ( !moreReferences.empty() )
1251 : {
1252 0 : for (j=0; j < nReference2; j++)
1253 : {
1254 0 : if ( moreReferences.find(j) == moreReferences.end() )
1255 : {
1256 0 : if ( (reader2.getReferenceFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL )
1257 : {
1258 0 : if ( options.forceOutput() )
1259 : {
1260 0 : dumpTypeClass(bDump, typeClass, keyName);
1261 : fprintf(stdout,
1262 : " incompatible change: Reference %d ('%s') of r2 is a new reference"
1263 : " compared to this service in r1 and is not 'optional'\n",
1264 0 : j, U2S(shortName(reader2.getReferenceTypeName(j))));
1265 : }
1266 0 : nError++;
1267 : }
1268 : }
1269 : }
1270 0 : }
1271 : }
1272 : else
1273 : {
1274 0 : if ( nReference1 != nReference2 )
1275 : {
1276 0 : if ( options.forceOutput() )
1277 : {
1278 0 : dumpTypeClass(bDump, typeClass, keyName);
1279 0 : fprintf(stdout, " nReferences1 = %d != nReferences2 = %d\n", nReference1, nReference2);
1280 : }
1281 0 : nError++;
1282 : }
1283 :
1284 : sal_uInt16 i;
1285 0 : for (i=0; i < nReference1 && i < nReference2; i++)
1286 : {
1287 0 : nError += checkReference(options, keyName, typeClass, bDump, reader1, reader2, i, i);
1288 : }
1289 0 : if ( i < nReference1 && options.forceOutput() )
1290 : {
1291 0 : fprintf(stdout, " Registry1 contains %d more references\n", nReference1 - i);
1292 : }
1293 0 : if ( i < nReference2 && options.forceOutput() )
1294 : {
1295 0 : fprintf(stdout, " Registry2 contains %d more references\n", nReference2 - i);
1296 : }
1297 : }
1298 : }
1299 :
1300 0 : if ( options.fullCheck() && (reader1.getDocumentation() != reader2.getDocumentation()) )
1301 : {
1302 0 : if ( options.forceOutput() )
1303 : {
1304 0 : dumpTypeClass(bDump, typeClass, keyName);
1305 : fprintf(stdout, " Doku1 = %s\n Doku2 = %s\n",
1306 0 : U2S(reader1.getDocumentation()), U2S(reader2.getDocumentation()));
1307 : }
1308 0 : nError++;
1309 : }
1310 0 : return nError;
1311 : }
1312 :
1313 0 : static sal_uInt32 checkValueDifference(
1314 : Options_Impl const & options,
1315 : RegistryKey& key1, RegValueType valueType1, sal_uInt32 size1,
1316 : RegistryKey& key2, RegValueType valueType2, sal_uInt32 size2)
1317 : {
1318 0 : OUString tmpName;
1319 0 : sal_uInt32 nError = 0;
1320 :
1321 0 : if ( valueType1 == valueType2 )
1322 : {
1323 0 : bool bEqual = true;
1324 0 : switch (valueType1)
1325 : {
1326 : case RG_VALUETYPE_LONGLIST:
1327 : {
1328 0 : RegistryValueList<sal_Int32> valueList1;
1329 0 : RegistryValueList<sal_Int32> valueList2;
1330 0 : key1.getLongListValue(tmpName, valueList1);
1331 0 : key2.getLongListValue(tmpName, valueList2);
1332 0 : sal_uInt32 length1 = valueList1.getLength();
1333 0 : sal_uInt32 length2 = valueList1.getLength();
1334 0 : if ( length1 != length2 )
1335 : {
1336 0 : bEqual = false;
1337 0 : break;
1338 : }
1339 0 : for (sal_uInt32 i=0; i<length1; i++)
1340 : {
1341 0 : if ( valueList1.getElement(i) != valueList2.getElement(i) )
1342 : {
1343 0 : bEqual = false;
1344 0 : break;
1345 : }
1346 0 : }
1347 : }
1348 0 : break;
1349 : case RG_VALUETYPE_STRINGLIST:
1350 : {
1351 0 : RegistryValueList<sal_Char*> valueList1;
1352 0 : RegistryValueList<sal_Char*> valueList2;
1353 0 : key1.getStringListValue(tmpName, valueList1);
1354 0 : key2.getStringListValue(tmpName, valueList2);
1355 0 : sal_uInt32 length1 = valueList1.getLength();
1356 0 : sal_uInt32 length2 = valueList1.getLength();
1357 0 : if ( length1 != length2 )
1358 : {
1359 0 : bEqual = false;
1360 0 : break;
1361 : }
1362 0 : for (sal_uInt32 i=0; i<length1; i++)
1363 : {
1364 0 : if ( strcmp(valueList1.getElement(i), valueList2.getElement(i)) != 0 )
1365 : {
1366 0 : bEqual = false;
1367 0 : break;
1368 : }
1369 0 : }
1370 : }
1371 0 : break;
1372 : case RG_VALUETYPE_UNICODELIST:
1373 : {
1374 0 : RegistryValueList<sal_Unicode*> valueList1;
1375 0 : RegistryValueList<sal_Unicode*> valueList2;
1376 0 : key1.getUnicodeListValue(tmpName, valueList1);
1377 0 : key2.getUnicodeListValue(tmpName, valueList2);
1378 0 : sal_uInt32 length1 = valueList1.getLength();
1379 0 : sal_uInt32 length2 = valueList1.getLength();
1380 0 : if ( length1 != length2 )
1381 : {
1382 0 : bEqual = false;
1383 0 : break;
1384 : }
1385 0 : for (sal_uInt32 i=0; i<length1; i++)
1386 : {
1387 0 : if ( rtl_ustr_compare(valueList1.getElement(i), valueList2.getElement(i)) != 0 )
1388 : {
1389 0 : bEqual = false;
1390 0 : break;
1391 : }
1392 0 : }
1393 : }
1394 0 : break;
1395 : default:
1396 0 : break;
1397 : }
1398 :
1399 0 : if ( bEqual)
1400 : {
1401 0 : std::vector< sal_uInt8 > value1(size1);
1402 0 : key1.getValue(tmpName, &value1[0]);
1403 :
1404 0 : std::vector< sal_uInt8 > value2(size2);
1405 0 : key2.getValue(tmpName, &value2[0]);
1406 :
1407 0 : bEqual = (memcmp(&value1[0], &value2[0], value1.size()) == 0 );
1408 0 : if ( !bEqual && valueType1 == RG_VALUETYPE_BINARY && valueType2 == RG_VALUETYPE_BINARY )
1409 : {
1410 0 : typereg::Reader reader1(&value1[0], value1.size(), false, TYPEREG_VERSION_1);
1411 0 : typereg::Reader reader2(&value2[0], value2.size(), false, TYPEREG_VERSION_1);
1412 0 : if ( reader1.isValid() && reader2.isValid() )
1413 : {
1414 0 : return checkBlob(options, key1.getName(), reader1, size1, reader2, size2);
1415 0 : }
1416 : }
1417 0 : if ( bEqual )
1418 : {
1419 0 : return 0;
1420 : }
1421 : else
1422 : {
1423 0 : if ( options.forceOutput() )
1424 : {
1425 0 : fprintf(stdout, "Difference: key values of key \"%s\" are different\n", U2S(key1.getName()));
1426 : }
1427 0 : nError++;
1428 0 : }
1429 : }
1430 : }
1431 :
1432 0 : if ( options.forceOutput() )
1433 : {
1434 0 : switch (valueType1)
1435 : {
1436 : case RG_VALUETYPE_NOT_DEFINED:
1437 0 : fprintf(stdout, " Registry 1: key has no value\n");
1438 0 : break;
1439 : case RG_VALUETYPE_LONG:
1440 : {
1441 0 : std::vector< sal_uInt8 > value1(size1);
1442 0 : key1.getValue(tmpName, &value1[0]);
1443 :
1444 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONG\n");
1445 : fprintf(
1446 : stdout, " Size = %lu\n",
1447 0 : sal::static_int_cast< unsigned long >(size1));
1448 0 : fprintf(stdout, " Data = %p\n", &value1[0]);
1449 : }
1450 0 : break;
1451 : case RG_VALUETYPE_STRING:
1452 : {
1453 0 : std::vector< sal_uInt8 > value1(size1);
1454 0 : key1.getValue(tmpName, &value1[0]);
1455 :
1456 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRING\n");
1457 : fprintf(
1458 : stdout, " Size = %lu\n",
1459 0 : sal::static_int_cast< unsigned long >(size1));
1460 0 : fprintf(stdout, " Data = \"%s\"\n", reinterpret_cast<char const*>(&value1[0]));
1461 : }
1462 0 : break;
1463 : case RG_VALUETYPE_UNICODE:
1464 : {
1465 0 : std::vector< sal_uInt8 > value1(size1);
1466 0 : key1.getValue(tmpName, &value1[0]);
1467 :
1468 0 : OUString uStrValue(reinterpret_cast<sal_Unicode const*>(&value1[0]));
1469 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODE\n");
1470 : fprintf(
1471 : stdout, " Size = %lu\n",
1472 0 : sal::static_int_cast< unsigned long >(size1));
1473 0 : fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue));
1474 : }
1475 0 : break;
1476 : case RG_VALUETYPE_BINARY:
1477 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_BINARY\n");
1478 0 : break;
1479 : case RG_VALUETYPE_LONGLIST:
1480 : {
1481 0 : RegistryValueList<sal_Int32> valueList;
1482 0 : key1.getLongListValue(tmpName, valueList);
1483 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONGLIST\n");
1484 : fprintf(
1485 : stdout, " Size = %lu\n",
1486 0 : sal::static_int_cast< unsigned long >(size1));
1487 0 : sal_uInt32 length = valueList.getLength();
1488 0 : for (sal_uInt32 i=0; i<length; i++)
1489 : {
1490 : fprintf(
1491 : stdout, " Data[%lu] = %ld\n",
1492 : sal::static_int_cast< unsigned long >(i),
1493 0 : sal::static_int_cast< long >(valueList.getElement(i)));
1494 0 : }
1495 : }
1496 0 : break;
1497 : case RG_VALUETYPE_STRINGLIST:
1498 : {
1499 0 : RegistryValueList<sal_Char*> valueList;
1500 0 : key1.getStringListValue(tmpName, valueList);
1501 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRINGLIST\n");
1502 : fprintf(
1503 : stdout, " Size = %lu\n",
1504 0 : sal::static_int_cast< unsigned long >(size1));
1505 0 : sal_uInt32 length = valueList.getLength();
1506 0 : for (sal_uInt32 i=0; i<length; i++)
1507 : {
1508 : fprintf(
1509 : stdout, " Data[%lu] = \"%s\"\n",
1510 : sal::static_int_cast< unsigned long >(i),
1511 0 : valueList.getElement(i));
1512 0 : }
1513 : }
1514 0 : break;
1515 : case RG_VALUETYPE_UNICODELIST:
1516 : {
1517 0 : RegistryValueList<sal_Unicode*> valueList;
1518 0 : key1.getUnicodeListValue(tmpName, valueList);
1519 0 : fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODELIST\n");
1520 : fprintf(
1521 : stdout, " Size = %lu\n",
1522 0 : sal::static_int_cast< unsigned long >(size1));
1523 0 : sal_uInt32 length = valueList.getLength();
1524 0 : OUString uStrValue;
1525 0 : for (sal_uInt32 i=0; i<length; i++)
1526 : {
1527 0 : uStrValue = OUString(valueList.getElement(i));
1528 : fprintf(
1529 : stdout, " Data[%lu] = \"%s\"\n",
1530 0 : sal::static_int_cast< unsigned long >(i), U2S(uStrValue));
1531 0 : }
1532 : }
1533 0 : break;
1534 : }
1535 :
1536 0 : switch (valueType2)
1537 : {
1538 : case RG_VALUETYPE_NOT_DEFINED:
1539 0 : fprintf(stdout, " Registry 2: key has no value\n");
1540 0 : break;
1541 : case RG_VALUETYPE_LONG:
1542 : {
1543 0 : std::vector< sal_uInt8 > value2(size2);
1544 0 : key2.getValue(tmpName, &value2[0]);
1545 :
1546 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONG\n");
1547 : fprintf(
1548 : stdout, " Size = %lu\n",
1549 0 : sal::static_int_cast< unsigned long >(size2));
1550 0 : fprintf(stdout, " Data = %p\n", &value2[0]);
1551 : }
1552 0 : break;
1553 : case RG_VALUETYPE_STRING:
1554 : {
1555 0 : std::vector< sal_uInt8 > value2(size2);
1556 0 : key2.getValue(tmpName, &value2[0]);
1557 :
1558 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRING\n");
1559 : fprintf(
1560 : stdout, " Size = %lu\n",
1561 0 : sal::static_int_cast< unsigned long >(size2));
1562 0 : fprintf(stdout, " Data = \"%s\"\n", reinterpret_cast<char const*>(&value2[0]));
1563 : }
1564 0 : break;
1565 : case RG_VALUETYPE_UNICODE:
1566 : {
1567 0 : std::vector< sal_uInt8 > value2(size2);
1568 0 : key2.getValue(tmpName, &value2[0]);
1569 :
1570 0 : OUString uStrValue(reinterpret_cast<sal_Unicode const*>(&value2[0]));
1571 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODE\n");
1572 : fprintf(
1573 : stdout, " Size = %lu\n",
1574 0 : sal::static_int_cast< unsigned long >(size2));
1575 0 : fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue));
1576 : }
1577 0 : break;
1578 : case RG_VALUETYPE_BINARY:
1579 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_BINARY\n");
1580 0 : break;
1581 : case RG_VALUETYPE_LONGLIST:
1582 : {
1583 0 : RegistryValueList<sal_Int32> valueList;
1584 0 : key2.getLongListValue(tmpName, valueList);
1585 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONGLIST\n");
1586 : fprintf(
1587 : stdout, " Size = %lu\n",
1588 0 : sal::static_int_cast< unsigned long >(size2));
1589 0 : sal_uInt32 length = valueList.getLength();
1590 0 : for (sal_uInt32 i=0; i<length; i++)
1591 : {
1592 : fprintf(
1593 : stdout, " Data[%lu] = %ld\n",
1594 : sal::static_int_cast< unsigned long >(i),
1595 0 : sal::static_int_cast< long >(valueList.getElement(i)));
1596 0 : }
1597 : }
1598 0 : break;
1599 : case RG_VALUETYPE_STRINGLIST:
1600 : {
1601 0 : RegistryValueList<sal_Char*> valueList;
1602 0 : key2.getStringListValue(tmpName, valueList);
1603 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRINGLIST\n");
1604 : fprintf(
1605 : stdout, " Size = %lu\n",
1606 0 : sal::static_int_cast< unsigned long >(size2));
1607 0 : sal_uInt32 length = valueList.getLength();
1608 0 : for (sal_uInt32 i=0; i<length; i++)
1609 : {
1610 : fprintf(
1611 : stdout, " Data[%lu] = \"%s\"\n",
1612 : sal::static_int_cast< unsigned long >(i),
1613 0 : valueList.getElement(i));
1614 0 : }
1615 : }
1616 0 : break;
1617 : case RG_VALUETYPE_UNICODELIST:
1618 : {
1619 0 : RegistryValueList<sal_Unicode*> valueList;
1620 0 : key2.getUnicodeListValue(tmpName, valueList);
1621 0 : fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODELIST\n");
1622 : fprintf(
1623 : stdout, " Size = %lu\n",
1624 0 : sal::static_int_cast< unsigned long >(size2));
1625 0 : sal_uInt32 length = valueList.getLength();
1626 0 : OUString uStrValue;
1627 0 : for (sal_uInt32 i=0; i<length; i++)
1628 : {
1629 0 : uStrValue = OUString(valueList.getElement(i));
1630 : fprintf(
1631 : stdout, " Data[%lu] = \"%s\"\n",
1632 0 : sal::static_int_cast< unsigned long >(i), U2S(uStrValue));
1633 0 : }
1634 : }
1635 0 : break;
1636 : }
1637 : }
1638 0 : return nError;
1639 : }
1640 :
1641 0 : static bool hasPublishedChildren(Options_Impl const & options, RegistryKey & key)
1642 : {
1643 0 : RegistryKeyNames subKeyNames;
1644 0 : key.getKeyNames(OUString(), subKeyNames);
1645 0 : for (sal_uInt32 i = 0; i < subKeyNames.getLength(); ++i)
1646 : {
1647 0 : OUString keyName(subKeyNames.getElement(i));
1648 0 : if (!options.matchedWithExcludeKey(keyName))
1649 : {
1650 0 : keyName = keyName.copy(keyName.lastIndexOf('/') + 1);
1651 0 : RegistryKey subKey;
1652 0 : if (!key.openKey(keyName, subKey))
1653 : {
1654 0 : if (options.forceOutput())
1655 : {
1656 : fprintf(
1657 : stdout,
1658 : ("WARNING: could not open key \"%s\" in registry"
1659 : " \"%s\"\n"),
1660 : U2S(subKeyNames.getElement(i)),
1661 0 : options.getRegName1().c_str());
1662 : }
1663 : }
1664 0 : if (subKey.isValid())
1665 : {
1666 : RegValueType type;
1667 : sal_uInt32 size;
1668 0 : if (subKey.getValueInfo(OUString(), &type, &size) != REG_NO_ERROR)
1669 : {
1670 0 : if (options.forceOutput())
1671 : {
1672 : fprintf(
1673 : stdout,
1674 : ("WARNING: could not read key \"%s\" in registry"
1675 : " \"%s\"\n"),
1676 : U2S(subKeyNames.getElement(i)),
1677 0 : options.getRegName1().c_str());
1678 : }
1679 : }
1680 0 : else if (type == RG_VALUETYPE_BINARY)
1681 : {
1682 0 : bool published = false;
1683 0 : std::vector< sal_uInt8 > value(size);
1684 0 : if (subKey.getValue(OUString(), &value[0]) != REG_NO_ERROR)
1685 : {
1686 0 : if (options.forceOutput())
1687 : {
1688 : fprintf(
1689 : stdout,
1690 : ("WARNING: could not read key \"%s\" in"
1691 : " registry \"%s\"\n"),
1692 : U2S(subKeyNames.getElement(i)),
1693 0 : options.getRegName1().c_str());
1694 : }
1695 : }
1696 : else
1697 : {
1698 0 : published = typereg::Reader(&value[0], value.size(), false, TYPEREG_VERSION_1).isPublished();
1699 : }
1700 0 : if (published)
1701 : {
1702 0 : return true;
1703 0 : }
1704 : }
1705 0 : }
1706 : }
1707 0 : }
1708 0 : return false;
1709 : }
1710 :
1711 0 : static sal_uInt32 checkDifferences(
1712 : Options_Impl const & options,
1713 : RegistryKey& key, StringSet& keys,
1714 : RegistryKeyNames& subKeyNames1,
1715 : RegistryKeyNames& subKeyNames2)
1716 : {
1717 0 : sal_uInt32 nError = 0;
1718 0 : sal_uInt32 length1 = subKeyNames1.getLength();
1719 0 : sal_uInt32 length2 = subKeyNames2.getLength();
1720 : sal_uInt32 i,j;
1721 :
1722 0 : for (i=0; i<length1; i++)
1723 : {
1724 0 : bool bFound = false;
1725 0 : for (j=0; j<length2; j++)
1726 : {
1727 0 : if ( subKeyNames1.getElement(i) == subKeyNames2.getElement(j) )
1728 : {
1729 0 : bFound = true;
1730 0 : keys.insert(subKeyNames1.getElement(i));
1731 0 : break;
1732 : }
1733 : }
1734 0 : if ( !bFound )
1735 : {
1736 0 : if ( options.fullCheck() )
1737 : {
1738 0 : if ( options.forceOutput() )
1739 : {
1740 : fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
1741 0 : U2S(subKeyNames1.getElement(i)), options.getRegName1().c_str());
1742 : }
1743 0 : nError++;
1744 : }
1745 : else
1746 : {
1747 0 : OUString keyName(subKeyNames1.getElement(i));
1748 0 : if (!options.matchedWithExcludeKey(keyName))
1749 : {
1750 0 : keyName = keyName.copy(keyName.lastIndexOf('/') + 1);
1751 0 : RegistryKey subKey;
1752 0 : if (key.openKey(keyName, subKey))
1753 : {
1754 0 : if (options.forceOutput())
1755 : {
1756 : fprintf(
1757 : stdout,
1758 : ("ERROR: could not open key \"%s\" in registry"
1759 : " \"%s\"\n"),
1760 : U2S(subKeyNames1.getElement(i)),
1761 0 : options.getRegName1().c_str());
1762 : }
1763 0 : ++nError;
1764 : }
1765 0 : if (subKey.isValid())
1766 : {
1767 : RegValueType type;
1768 : sal_uInt32 size;
1769 0 : if (subKey.getValueInfo(OUString(), &type, &size) != REG_NO_ERROR)
1770 : {
1771 0 : if (options.forceOutput())
1772 : {
1773 : fprintf(
1774 : stdout,
1775 : ("ERROR: could not read key \"%s\" in"
1776 : " registry \"%s\"\n"),
1777 : U2S(subKeyNames1.getElement(i)),
1778 0 : options.getRegName1().c_str());
1779 : }
1780 0 : ++nError;
1781 : }
1782 0 : else if (type == RG_VALUETYPE_BINARY)
1783 : {
1784 0 : std::vector< sal_uInt8 > value(size);
1785 0 : if (subKey.getValue(OUString(), &value[0]) != REG_NO_ERROR)
1786 : {
1787 0 : if (options.forceOutput())
1788 : {
1789 : fprintf(
1790 : stdout,
1791 : ("ERROR: could not read key \"%s\" in"
1792 : " registry \"%s\"\n"),
1793 : U2S(subKeyNames1.getElement(i)),
1794 0 : options.getRegName1().c_str());
1795 : }
1796 0 : ++nError;
1797 : }
1798 : else
1799 : {
1800 0 : typereg::Reader reader(&value[0], value.size(), false, TYPEREG_VERSION_1);
1801 0 : if (reader.getTypeClass() == RT_TYPE_MODULE)
1802 : {
1803 0 : if (options.checkUnpublished() || hasPublishedChildren(options, subKey))
1804 : {
1805 0 : if (options.forceOutput())
1806 : {
1807 : fprintf(
1808 : stdout,
1809 : ("EXISTENCE: module \"%s\""
1810 : " %sexists only in registry"
1811 : " 1\n"),
1812 : U2S(subKeyNames1.getElement(i)),
1813 0 : (options.checkUnpublished()
1814 : ? ""
1815 0 : : "with published children "));
1816 : }
1817 0 : ++nError;
1818 : }
1819 : }
1820 0 : else if (options.checkUnpublished() || reader.isPublished())
1821 : {
1822 0 : if (options.forceOutput())
1823 : {
1824 : fprintf(
1825 : stdout,
1826 : ("EXISTENCE: %spublished key \"%s\""
1827 : " exists only in registry 1\n"),
1828 0 : reader.isPublished() ? "" : "un",
1829 0 : U2S(subKeyNames1.getElement(i)));
1830 : }
1831 0 : ++nError;
1832 0 : }
1833 0 : }
1834 : }
1835 0 : }
1836 0 : }
1837 : }
1838 : }
1839 : }
1840 :
1841 0 : for (i=0; i<length2; i++)
1842 : {
1843 0 : bool bFound = false;
1844 0 : for (j=0; j<length1; j++)
1845 : {
1846 0 : if ( subKeyNames2.getElement(i) == subKeyNames1.getElement(j) )
1847 : {
1848 0 : bFound = true;
1849 0 : keys.insert(subKeyNames2.getElement(i));
1850 0 : break;
1851 : }
1852 : }
1853 0 : if ( !bFound && options.fullCheck() )
1854 : {
1855 0 : if ( options.forceOutput() )
1856 : {
1857 : fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
1858 0 : U2S(subKeyNames2.getElement(i)), options.getRegName2().c_str());
1859 : }
1860 0 : nError++;
1861 : }
1862 : }
1863 0 : return nError;
1864 : }
1865 :
1866 0 : static sal_uInt32 compareKeys(
1867 : Options_Impl const & options,
1868 : RegistryKey& key1,
1869 : RegistryKey& key2)
1870 : {
1871 0 : sal_uInt32 nError = 0;
1872 :
1873 0 : RegValueType valueType1 = RG_VALUETYPE_NOT_DEFINED;
1874 0 : RegValueType valueType2 = RG_VALUETYPE_NOT_DEFINED;
1875 0 : sal_uInt32 size1 = 0;
1876 0 : sal_uInt32 size2 = 0;
1877 :
1878 0 : OUString tmpName;
1879 0 : RegError e1 = key1.getValueInfo(tmpName, &valueType1, &size1);
1880 0 : RegError e2 = key2.getValueInfo(tmpName, &valueType2, &size2);
1881 0 : if ( (e1 == e2) && (e1 != REG_VALUE_NOT_EXISTS) && (e1 != REG_INVALID_VALUE) )
1882 : {
1883 0 : nError += checkValueDifference(options, key1, valueType1, size1, key2, valueType2, size2);
1884 : }
1885 : else
1886 : {
1887 0 : if ( (e1 != REG_INVALID_VALUE) || (e2 != REG_INVALID_VALUE) )
1888 : {
1889 0 : if ( options.forceOutput() )
1890 : {
1891 0 : fprintf(stdout, "VALUES: key values of key \"%s\" are different\n", U2S(key1.getName()));
1892 : }
1893 0 : nError++;
1894 : }
1895 : }
1896 :
1897 0 : RegistryKeyNames subKeyNames1;
1898 0 : RegistryKeyNames subKeyNames2;
1899 :
1900 0 : key1.getKeyNames(tmpName, subKeyNames1);
1901 0 : key2.getKeyNames(tmpName, subKeyNames2);
1902 :
1903 0 : StringSet keys;
1904 0 : nError += checkDifferences(options, key1, keys, subKeyNames1, subKeyNames2);
1905 :
1906 0 : StringSet::iterator iter = keys.begin();
1907 0 : StringSet::iterator end = keys.end();
1908 :
1909 0 : while ( iter != end )
1910 : {
1911 0 : OUString keyName(*iter);
1912 0 : if ( options.matchedWithExcludeKey(keyName) )
1913 : {
1914 0 : ++iter;
1915 0 : continue;
1916 : }
1917 :
1918 0 : sal_Int32 nPos = keyName.lastIndexOf( '/' );
1919 0 : keyName = keyName.copy( nPos != -1 ? nPos+1 : 0 );
1920 :
1921 0 : RegistryKey subKey1;
1922 0 : if ( key1.openKey(keyName, subKey1) )
1923 : {
1924 0 : if ( options.forceOutput() )
1925 : {
1926 : fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
1927 0 : U2S(*iter), options.getRegName1().c_str());
1928 : }
1929 0 : nError++;
1930 : }
1931 :
1932 0 : RegistryKey subKey2;
1933 0 : if ( key2.openKey(keyName, subKey2) )
1934 : {
1935 0 : if ( options.forceOutput() )
1936 : {
1937 : fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
1938 0 : U2S(*iter), options.getRegName2().c_str());
1939 : }
1940 0 : nError++;
1941 : }
1942 :
1943 0 : if ( subKey1.isValid() && subKey2.isValid() )
1944 : {
1945 0 : nError += compareKeys(options, subKey1, subKey2);
1946 : }
1947 0 : ++iter;
1948 0 : }
1949 :
1950 0 : return nError;
1951 : }
1952 :
1953 : #if (defined UNX) || defined __MINGW32__
1954 0 : int main( int argc, char * argv[] )
1955 : #else
1956 : int _cdecl main( int argc, char * argv[] )
1957 : #endif
1958 : {
1959 0 : std::vector< std::string > args;
1960 :
1961 0 : Options_Impl options(argv[0]);
1962 0 : for (int i = 1; i < argc; i++)
1963 : {
1964 0 : if (!Options::checkArgument(args, argv[i], strlen(argv[i])))
1965 : {
1966 : // failure.
1967 0 : options.printUsage();
1968 0 : return (1);
1969 : }
1970 : }
1971 0 : if (!options.initOptions(args))
1972 : {
1973 0 : return (1);
1974 : }
1975 :
1976 0 : OUString regName1( convertToFileUrl(options.getRegName1().c_str(), options.getRegName1().size()) );
1977 0 : OUString regName2( convertToFileUrl(options.getRegName2().c_str(), options.getRegName2().size()) );
1978 :
1979 0 : Registry reg1, reg2;
1980 0 : if ( reg1.open(regName1, REG_READONLY) )
1981 : {
1982 : fprintf(stdout, "%s: open registry \"%s\" failed\n",
1983 0 : options.getProgramName().c_str(), options.getRegName1().c_str());
1984 0 : return (2);
1985 : }
1986 0 : if ( reg2.open(regName2, REG_READONLY) )
1987 : {
1988 : fprintf(stdout, "%s: open registry \"%s\" failed\n",
1989 0 : options.getProgramName().c_str(), options.getRegName2().c_str());
1990 0 : return (3);
1991 : }
1992 :
1993 0 : RegistryKey key1, key2;
1994 0 : if ( reg1.openRootKey(key1) )
1995 : {
1996 : fprintf(stdout, "%s: open root key of registry \"%s\" failed\n",
1997 0 : options.getProgramName().c_str(), options.getRegName1().c_str());
1998 0 : return (4);
1999 : }
2000 0 : if ( reg2.openRootKey(key2) )
2001 : {
2002 : fprintf(stdout, "%s: open root key of registry \"%s\" failed\n",
2003 0 : options.getProgramName().c_str(), options.getRegName2().c_str());
2004 0 : return (5);
2005 : }
2006 :
2007 0 : if ( options.isStartKeyValid() )
2008 : {
2009 0 : if ( options.matchedWithExcludeKey( options.getStartKey() ) )
2010 : {
2011 : fprintf(stdout, "%s: start key is equal to one of the exclude keys\n",
2012 0 : options.getProgramName().c_str());
2013 0 : return (6);
2014 : }
2015 0 : RegistryKey sk1, sk2;
2016 0 : if ( key1.openKey(options.getStartKey(), sk1) )
2017 : {
2018 : fprintf(stdout, "%s: open start key of registry \"%s\" failed\n",
2019 0 : options.getProgramName().c_str(), options.getRegName1().c_str());
2020 0 : return (7);
2021 : }
2022 0 : if ( key2.openKey(options.getStartKey(), sk2) )
2023 : {
2024 : fprintf(stdout, "%s: open start key of registry \"%s\" failed\n",
2025 0 : options.getProgramName().c_str(), options.getRegName2().c_str());
2026 0 : return (8);
2027 : }
2028 :
2029 0 : key1 = sk1;
2030 0 : key2 = sk2;
2031 : }
2032 :
2033 0 : sal_uInt32 nError = compareKeys(options, key1, key2);
2034 0 : if ( nError )
2035 : {
2036 0 : if ( options.unoTypeCheck() )
2037 : {
2038 : fprintf(stdout, "%s: registries are incompatible: %lu differences!\n",
2039 0 : options.getProgramName().c_str(),
2040 0 : sal::static_int_cast< unsigned long >(nError));
2041 : }
2042 : else
2043 : {
2044 : fprintf(stdout, "%s: registries contain %lu differences!\n",
2045 0 : options.getProgramName().c_str(),
2046 0 : sal::static_int_cast< unsigned long >(nError));
2047 : }
2048 : }
2049 :
2050 0 : key1.releaseKey();
2051 0 : key2.releaseKey();
2052 0 : if ( reg1.close() )
2053 : {
2054 : fprintf(stdout, "%s: closing registry \"%s\" failed\n",
2055 0 : options.getProgramName().c_str(), options.getRegName1().c_str());
2056 0 : return (9);
2057 : }
2058 0 : if ( reg2.close() )
2059 : {
2060 : fprintf(stdout, "%s: closing registry \"%s\" failed\n",
2061 0 : options.getProgramName().c_str(), options.getRegName2().c_str());
2062 0 : return (10);
2063 : }
2064 :
2065 0 : return ((nError > 0) ? 11 : 0);
2066 : }
2067 :
2068 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|