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