merge the formfield patch from ooo-build
[ooovba.git] / registry / tools / regcompare.cxx
blob4adf2f23d94b74601d2760dcca4f691263622940
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: regcompare.cxx,v $
10 * $Revision: 1.27 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_registry.hxx"
33 #include <stdio.h>
34 #include <string.h>
36 #include <set>
37 #include <vector>
38 #include "registry/registry.hxx"
39 #include "registry/reader.hxx"
40 #include "registry/version.h"
41 #include <rtl/ustring.hxx>
42 #include <rtl/alloc.h>
43 #include <osl/process.h>
44 #include <osl/diagnose.h>
45 #include <osl/thread.h>
46 #include <osl/file.hxx>
48 #ifdef SAL_UNX
49 #define SEPARATOR '/'
50 #else
51 #define SEPARATOR '\\'
52 #endif
54 using namespace ::rtl;
55 using namespace ::osl;
57 OUString shortName(const OUString& fullName)
59 return fullName.copy(fullName.lastIndexOf('/') + 1);
62 sal_Bool isFileUrl(const OString& fileName)
64 if (fileName.indexOf("file://") == 0 )
65 return sal_True;
66 return sal_False;
69 OUString convertToFileUrl(const OString& fileName)
71 if ( isFileUrl(fileName) )
73 return OStringToOUString(fileName, osl_getThreadTextEncoding());
76 OUString uUrlFileName;
77 OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
78 if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 )
80 OUString uWorkingDir;
81 if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
83 OSL_ASSERT(false);
85 if (FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName)
86 != FileBase::E_None)
88 OSL_ASSERT(false);
90 } else
92 if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
93 != FileBase::E_None)
95 OSL_ASSERT(false);
99 return uUrlFileName;
102 #define U2S( s ) \
103 OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr()
104 #define S2U( s ) \
105 OStringToOUString(s, RTL_TEXTENCODING_UTF8)
107 struct LessString
109 sal_Bool operator()(const OUString& str1, const OUString& str2) const
111 return (str1 < str2);
115 typedef ::std::set< OUString > StringSet;
117 class Options
119 public:
120 Options()
121 : m_bFullCheck(sal_False)
122 , m_bForceOutput(sal_False)
123 , m_bUnoTypeCheck(sal_False)
124 , m_checkUnpublished(false)
126 ~Options()
129 sal_Bool initOptions(int ac, char* av[], sal_Bool bCmdFile=sal_False);
131 OString prepareHelp();
132 OString prepareVersion();
134 const OString& getProgramName()
135 { return m_program; }
136 const OString& getRegName1()
137 { return m_regName1; }
138 const OString& getRegName2()
139 { return m_regName2; }
140 sal_Bool isStartKeyValid()
141 { return (m_startKey.getLength() > 0); };
142 const OString& getStartKey()
143 { return m_startKey; }
144 sal_Bool existsExcludeKeys()
145 { return !m_excludeKeys.empty(); };
146 StringSet& getExcludeKeys()
147 { return m_excludeKeys; }
148 sal_Bool matchedWithExcludeKey( const OUString& keyName);
149 sal_Bool fullCheck()
150 { return m_bFullCheck; }
151 sal_Bool forceOutput()
152 { return m_bForceOutput; }
153 sal_Bool unoTypeCheck()
154 { return m_bUnoTypeCheck; }
155 bool checkUnpublished() const { return m_checkUnpublished; }
156 protected:
157 OString m_program;
158 OString m_regName1;
159 OString m_regName2;
160 OString m_startKey;
161 StringSet m_excludeKeys;
162 sal_Bool m_bFullCheck;
163 sal_Bool m_bForceOutput;
164 sal_Bool m_bUnoTypeCheck;
165 bool m_checkUnpublished;
168 sal_Bool Options::initOptions(int ac, char* av[], sal_Bool bCmdFile)
170 sal_Bool bRet = sal_True;
171 sal_uInt16 i=0;
173 if (!bCmdFile)
175 bCmdFile = sal_True;
177 m_program = av[0];
179 if (ac < 2)
181 fprintf(stdout, "%s", prepareHelp().getStr());
182 bRet = sal_False;
185 i = 1;
186 } else
188 i = 0;
191 char *s=NULL;
192 for (; i < ac; i++)
194 if (av[i][0] == '-')
196 switch (av[i][1])
198 case 'r':
199 case 'R':
201 sal_Bool bFirst = sal_True;
202 if (av[i][2] == '2')
204 bFirst = sal_False;
205 } else if (av[i][2] != '1')
207 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
209 if (av[i][3] == '\0')
211 if (i < ac - 1 && av[i+1][0] != '-')
213 i++;
214 s = av[i];
215 } else
217 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
218 bRet = sal_False;
219 break;
221 } else
223 s = av[i] + 2;
226 if ( bFirst )
228 m_regName1 = OString(s);
229 } else
231 m_regName2 = OString(s);
234 break;
235 case 's':
236 case 'S':
237 if (av[i][2] == '\0')
239 if (i < ac - 1 && av[i+1][0] != '-')
241 i++;
242 s = av[i];
243 } else
245 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
246 bRet = sal_False;
247 break;
249 } else
251 s = av[i] + 2;
253 m_startKey = OString(s);
254 break;
255 case 'x':
256 case 'X':
257 if (av[i][2] == '\0')
259 if (i < ac - 1 && av[i+1][0] != '-')
261 i++;
262 s = av[i];
263 } else
265 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
266 bRet = sal_False;
267 break;
269 } else
271 s = av[i] + 2;
273 m_excludeKeys.insert(S2U(s));
274 break;
275 case 'c':
276 case 'C':
277 if (av[i][2] != '\0')
279 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
281 m_bFullCheck = sal_True;
282 break;
283 case 'f':
284 case 'F':
285 if (av[i][2] != '\0')
287 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
288 bRet = sal_False;
290 m_bForceOutput = sal_True;
291 break;
292 case 't':
293 case 'T':
294 if (av[i][2] != '\0')
296 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
298 m_bUnoTypeCheck = sal_True;
299 break;
300 case 'u':
301 case 'U':
302 if (av[i][2] != '\0')
304 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
306 m_checkUnpublished = true;
307 break;
308 case 'h':
309 case '?':
310 if (av[i][2] != '\0')
312 fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]);
313 bRet = sal_False;
314 } else
316 fprintf(stdout, "%s", prepareHelp().getStr());
317 exit(0);
319 break;
320 default:
321 fprintf(stdout, "%s: unknown option '%s'\n", m_program.getStr(), av[i]);
322 bRet = sal_False;
323 break;
325 } else
327 if (av[i][0] == '@')
329 FILE* cmdFile = fopen(av[i]+1, "r");
330 if( cmdFile == NULL )
332 fprintf(stdout, "%s", prepareHelp().getStr());
333 bRet = sal_False;
334 } else
336 int rargc=0;
337 char* rargv[512];
338 char buffer[512];
340 while ( fscanf(cmdFile, "%s", buffer) != EOF )
342 rargv[rargc]= strdup(buffer);
343 rargc++;
345 fclose(cmdFile);
347 bRet = initOptions(rargc, rargv, bCmdFile);
349 for (long j=0; j < rargc; j++)
351 free(rargv[j]);
354 } else
356 fprintf(stdout, "%s: unknown option '%s'\n", m_program.getStr(), av[i]);
357 bRet = sal_False;
362 if ( bRet )
364 if ( m_regName1.getLength() == 0 )
366 fprintf(stdout, "%s: missing option '-r1'\n", m_program.getStr());
367 bRet = sal_False;
369 if ( m_regName2.getLength() == 0 )
371 fprintf(stdout, "%s: missing option '-r2'\n", m_program.getStr());
372 bRet = sal_False;
376 return bRet;
379 OString Options::prepareHelp()
381 OString help("\nusing: ");
382 help += m_program + " -r1<filename> -r2<filename> [-options] | @<filename>\n";
383 help += " -r1<filename> = filename specifies the name of the first registry.\n";
384 help += " -r2<filename> = filename specifies the name of the second registry.\n";
385 help += " @<filename> = filename specifies a command file.\n";
386 help += "Options:\n";
387 help += " -s<name> = name specifies the name of a start key. If no start key\n";
388 help += " |S<name> is specified the comparison starts with the root key.\n";
389 help += " -x<name> = name specifies the name of a key which won't be compared. All\n";
390 help += " |X<name> subkeys won't be compared also. This option can be used more than once.\n";
391 help += " -f|F = force the detailed output of any diffenrences. Default\n";
392 help += " is that only the number of differences is returned.\n";
393 help += " -c|C = make a complete check, that means any differences will be\n";
394 help += " detected. Default is only a compatibility check that means\n";
395 help += " only UNO typelibrary entries will be checked.\n";
396 help += " -t|T = make an UNO type compatiblity check. This means that registry 2\n";
397 help += " will be checked against registry 1. If a interface in r2 contains\n";
398 help += " more methods or the methods are in a different order as in r1, r2 is\n";
399 help += " incompatible to r1. But if a service in r2 supports more properties as\n";
400 help += " in r1 and the new properties are 'optonal' it is compatible.\n";
401 help += " -u|U = additionally check types that are unpublished in registry 1.\n";
402 help += " -h|-? = print this help message and exit.\n";
403 help += prepareVersion();
405 return help;
408 OString Options::prepareVersion()
410 OString version("\nSun Microsystems (R) ");
411 version += m_program + " Version 1.0\n\n";
412 return version;
415 sal_Bool Options::matchedWithExcludeKey( const OUString& keyName)
417 if ( m_excludeKeys.empty() )
418 return sal_False;
420 StringSet::const_iterator iter = m_excludeKeys.begin();
421 StringSet::const_iterator end = m_excludeKeys.end();
423 while ( iter != end )
425 if ( keyName.indexOf(*iter) == 0)
426 return sal_True;
428 ++iter;
431 return sal_False;
434 static Options options;
436 static char const * getTypeClass(RTTypeClass typeClass)
438 switch (typeClass)
440 case RT_TYPE_INTERFACE:
441 return "INTERFACE";
442 case RT_TYPE_MODULE:
443 return "MODULE";
444 case RT_TYPE_STRUCT:
445 return "STRUCT";
446 case RT_TYPE_ENUM:
447 return "ENUM";
448 case RT_TYPE_EXCEPTION:
449 return "EXCEPTION";
450 case RT_TYPE_TYPEDEF:
451 return "TYPEDEF";
452 case RT_TYPE_SERVICE:
453 return "SERVICE";
454 case RT_TYPE_OBJECT:
455 return "OBJECT";
456 case RT_TYPE_CONSTANTS:
457 return "CONSTANTS";
458 default:
459 return "INVALID";
463 static OString getFieldAccess(RTFieldAccess fieldAccess)
465 OString ret;
466 if ( (fieldAccess & RT_ACCESS_INVALID) == RT_ACCESS_INVALID )
468 ret += OString("INVALID");
470 if ( (fieldAccess & RT_ACCESS_READONLY) == RT_ACCESS_READONLY )
472 ret += OString(ret.getLength() > 0 ? ",READONLY" : "READONLY");
474 if ( (fieldAccess & RT_ACCESS_OPTIONAL) == RT_ACCESS_OPTIONAL )
476 ret += OString(ret.getLength() > 0 ? ",OPTIONAL" : "OPTIONAL");
478 if ( (fieldAccess & RT_ACCESS_MAYBEVOID) == RT_ACCESS_MAYBEVOID )
480 ret += OString(ret.getLength() > 0 ? ",MAYBEVOID" : "MAYBEVOID");
482 if ( (fieldAccess & RT_ACCESS_BOUND) == RT_ACCESS_BOUND )
484 ret += OString(ret.getLength() > 0 ? ",BOUND" : "BOUND");
486 if ( (fieldAccess & RT_ACCESS_CONSTRAINED) == RT_ACCESS_CONSTRAINED )
488 ret += OString(ret.getLength() > 0 ? ",CONSTRAINED" : "CONSTRAINED");
490 if ( (fieldAccess & RT_ACCESS_TRANSIENT) == RT_ACCESS_TRANSIENT )
492 ret += OString(ret.getLength() > 0 ? ",TRANSIENT" : "TRANSIENT");
494 if ( (fieldAccess & RT_ACCESS_MAYBEAMBIGUOUS) == RT_ACCESS_MAYBEAMBIGUOUS )
496 ret += OString(ret.getLength() > 0 ? ",MAYBEAMBIGUOUS" : "MAYBEAMBIGUOUS");
498 if ( (fieldAccess & RT_ACCESS_MAYBEDEFAULT) == RT_ACCESS_MAYBEDEFAULT )
500 ret += OString(ret.getLength() > 0 ? ",MAYBEDEFAULT" : "MAYBEDEFAULT");
502 if ( (fieldAccess & RT_ACCESS_REMOVEABLE) == RT_ACCESS_REMOVEABLE )
504 ret += OString(ret.getLength() > 0 ? ",REMOVEABLE" : "REMOVEABLE");
506 if ( (fieldAccess & RT_ACCESS_ATTRIBUTE) == RT_ACCESS_ATTRIBUTE )
508 ret += OString(ret.getLength() > 0 ? ",ATTRIBUTE" : "ATTRIBUTE");
510 if ( (fieldAccess & RT_ACCESS_PROPERTY) == RT_ACCESS_PROPERTY )
512 ret += OString(ret.getLength() > 0 ? ",PROPERTY" : "PROPERTY");
514 if ( (fieldAccess & RT_ACCESS_CONST) == RT_ACCESS_CONST )
516 ret += OString(ret.getLength() > 0 ? ",CONST" : "CONST");
518 if ( (fieldAccess & RT_ACCESS_READWRITE) == RT_ACCESS_READWRITE )
520 ret += OString(ret.getLength() > 0 ? ",READWRITE" : "READWRITE");
522 return ret;
525 static char const * getConstValueType(RTConstValue& constValue)
527 switch (constValue.m_type)
529 case RT_TYPE_BOOL:
530 return "sal_Bool";
531 case RT_TYPE_BYTE:
532 return "sal_uInt8";
533 case RT_TYPE_INT16:
534 return "sal_Int16";
535 case RT_TYPE_UINT16:
536 return "sal_uInt16";
537 case RT_TYPE_INT32:
538 return "sal_Int32";
539 case RT_TYPE_UINT32:
540 return "sal_uInt32";
541 // case RT_TYPE_INT64:
542 // return "sal_Int64";
543 // case RT_TYPE_UINT64:
544 // return "sal_uInt64";
545 case RT_TYPE_FLOAT:
546 return "float";
547 case RT_TYPE_DOUBLE:
548 return "double";
549 case RT_TYPE_STRING:
550 return "sal_Unicode*";
551 default:
552 return "NONE";
555 static void printConstValue(RTConstValue& constValue)
557 switch (constValue.m_type)
559 case RT_TYPE_NONE:
560 fprintf(stdout, "none");
561 break;
562 case RT_TYPE_BOOL:
563 fprintf(stdout, "%s", constValue.m_value.aBool ? "TRUE" : "FALSE");
564 break;
565 case RT_TYPE_BYTE:
566 fprintf(stdout, "%d", constValue.m_value.aByte);
567 break;
568 case RT_TYPE_INT16:
569 fprintf(stdout, "%d", constValue.m_value.aShort);
570 break;
571 case RT_TYPE_UINT16:
572 fprintf(stdout, "%d", constValue.m_value.aUShort);
573 break;
574 case RT_TYPE_INT32:
575 fprintf(
576 stdout, "%ld",
577 sal::static_int_cast< long >(constValue.m_value.aLong));
578 break;
579 case RT_TYPE_UINT32:
580 fprintf(
581 stdout, "%lu",
582 sal::static_int_cast< unsigned long >(
583 constValue.m_value.aULong));
584 break;
585 // case RT_TYPE_INT64:
586 // fprintf(stdout, "%d", constValue.m_value.aHyper);
587 // case RT_TYPE_UINT64:
588 // fprintf(stdout, "%d", constValue.m_value.aUHyper);
589 case RT_TYPE_FLOAT:
590 fprintf(stdout, "%f", constValue.m_value.aFloat);
591 break;
592 case RT_TYPE_DOUBLE:
593 fprintf(stdout, "%f", constValue.m_value.aDouble);
594 break;
595 case RT_TYPE_STRING:
596 fprintf(
597 stdout, "%s",
598 (rtl::OUStringToOString(
599 constValue.m_value.aString, RTL_TEXTENCODING_UTF8).
600 getStr()));
601 break;
602 default:
603 break;
607 static sal_uInt32 checkConstValue(const OUString& keyName,
608 RTTypeClass typeClass,
609 sal_Bool& bDump,
610 RTConstValue& constValue1,
611 RTConstValue& constValue2,
612 sal_uInt16 index1)
614 switch (constValue1.m_type)
616 case RT_TYPE_INVALID:
617 break;
618 case RT_TYPE_BOOL:
619 if (constValue1.m_value.aBool != constValue2.m_value.aBool)
621 if ( options.forceOutput() && !options.unoTypeCheck() )
623 if ( bDump )
625 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
626 bDump = sal_False;
628 fprintf(stdout, " Field %d: Value1 = %s != Value2 = %s\n", index1,
629 constValue1.m_value.aBool ? "TRUE" : "FALSE",
630 constValue2.m_value.aBool ? "TRUE" : "FALSE");
632 return 1;
634 break;
635 case RT_TYPE_BYTE:
636 if (constValue1.m_value.aByte != constValue2.m_value.aByte)
638 if ( options.forceOutput() && !options.unoTypeCheck() )
640 if ( bDump )
642 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
643 bDump = sal_False;
645 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
646 constValue1.m_value.aByte, constValue2.m_value.aByte);
648 return 1;
650 break;
651 case RT_TYPE_INT16:
652 if (constValue1.m_value.aShort != constValue2.m_value.aShort)
654 if ( options.forceOutput() && !options.unoTypeCheck() )
656 if ( bDump )
658 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
659 bDump = sal_False;
661 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
662 constValue1.m_value.aShort, constValue2.m_value.aShort);
664 return 1;
666 break;
667 case RT_TYPE_UINT16:
668 if (constValue1.m_value.aUShort != constValue2.m_value.aUShort)
670 if ( options.forceOutput() && !options.unoTypeCheck() )
672 if ( bDump )
674 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
675 bDump = sal_False;
677 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1,
678 constValue1.m_value.aUShort, constValue2.m_value.aUShort);
680 return 1;
682 break;
683 case RT_TYPE_INT32:
684 if (constValue1.m_value.aLong != constValue2.m_value.aLong)
686 if ( options.forceOutput() && !options.unoTypeCheck() )
688 if ( bDump )
690 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
691 bDump = sal_False;
693 fprintf(stdout, " Field %d: Value1 = %ld != Value2 = %ld\n", index1,
694 sal::static_int_cast< long >(constValue1.m_value.aLong),
695 sal::static_int_cast< long >(constValue2.m_value.aLong));
697 return 1;
699 break;
700 case RT_TYPE_UINT32:
701 if (constValue1.m_value.aULong != constValue2.m_value.aULong)
703 if ( options.forceOutput() && !options.unoTypeCheck() )
705 if ( bDump )
707 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
708 bDump = sal_False;
710 fprintf(stdout, " Field %d: Value1 = %lu != Value2 = %lu\n", index1,
711 sal::static_int_cast< unsigned long >(constValue1.m_value.aULong),
712 sal::static_int_cast< unsigned long >(constValue2.m_value.aULong));
714 return 1;
716 break;
717 case RT_TYPE_INT64:
718 if (constValue1.m_value.aHyper != constValue2.m_value.aHyper)
720 if ( options.forceOutput() && !options.unoTypeCheck() )
722 if ( bDump )
724 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
725 bDump = sal_False;
727 fprintf(
728 stdout, " Field %d: Value1 = %s != Value2 = %s\n",
729 index1,
730 rtl::OUStringToOString(
731 rtl::OUString::valueOf(constValue1.m_value.aHyper),
732 RTL_TEXTENCODING_ASCII_US).getStr(),
733 rtl::OUStringToOString(
734 rtl::OUString::valueOf(constValue2.m_value.aHyper),
735 RTL_TEXTENCODING_ASCII_US).getStr());
737 return 1;
739 break;
740 case RT_TYPE_UINT64:
741 if (constValue1.m_value.aUHyper != constValue2.m_value.aUHyper)
743 if ( options.forceOutput() && !options.unoTypeCheck() )
745 if ( bDump )
747 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
748 bDump = sal_False;
750 fprintf(
751 stdout, " Field %d: Value1 = %s != Value2 = %s\n",
752 index1,
753 rtl::OUStringToOString(
754 rtl::OUString::valueOf(
755 static_cast< sal_Int64 >(
756 constValue1.m_value.aUHyper)),
757 RTL_TEXTENCODING_ASCII_US).getStr(),
758 rtl::OUStringToOString(
759 rtl::OUString::valueOf(
760 static_cast< sal_Int64 >(
761 constValue2.m_value.aUHyper)),
762 RTL_TEXTENCODING_ASCII_US).getStr());
763 // printing the unsigned values as signed should be
764 // acceptable...
766 return 1;
768 break;
769 case RT_TYPE_FLOAT:
770 if (constValue1.m_value.aFloat != constValue2.m_value.aFloat)
772 if ( options.forceOutput() && !options.unoTypeCheck() )
774 if ( bDump )
776 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
777 bDump = sal_False;
779 fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1,
780 constValue1.m_value.aFloat, constValue2.m_value.aFloat);
782 return 1;
784 break;
785 case RT_TYPE_DOUBLE:
786 if (constValue1.m_value.aDouble != constValue2.m_value.aDouble)
788 if ( options.forceOutput() && !options.unoTypeCheck() )
790 if ( bDump )
792 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
793 bDump = sal_False;
795 fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1,
796 constValue1.m_value.aDouble, constValue2.m_value.aDouble);
798 return 1;
800 break;
801 default:
802 OSL_ASSERT(false);
803 break;
805 return 0;
808 static sal_uInt32 checkField(const OUString& keyName,
809 RTTypeClass typeClass,
810 sal_Bool& bDump,
811 typereg::Reader& reader1,
812 typereg::Reader& reader2,
813 sal_uInt16 index1,
814 sal_uInt16 index2)
816 sal_uInt32 nError = 0;
817 if ( reader1.getFieldName(index1) !=
818 reader2.getFieldName(index2) )
820 if ( options.forceOutput() && !options.unoTypeCheck() )
822 if ( bDump )
824 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
825 bDump = sal_False;
827 fprintf(stdout, " Field %d: Name1 = %s != Name2 = %s\n", index1,
828 U2S(reader1.getFieldName(index1)), U2S(reader2.getFieldName(index2)));
830 nError++;
832 if ( reader1.getFieldTypeName(index1) !=
833 reader2.getFieldTypeName(index2) )
835 if ( options.forceOutput() && !options.unoTypeCheck() )
837 if ( bDump )
839 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
840 bDump = sal_False;
842 fprintf(stdout, " Field %d: Type1 = %s != Type2 = %s\n", index1,
843 U2S(reader1.getFieldTypeName(index1)), U2S(reader2.getFieldTypeName(index2)));
845 nError++;
846 } else
848 RTConstValue constValue1 = reader1.getFieldValue(index1);
849 RTConstValue constValue2 = reader2.getFieldValue(index2);
850 if ( constValue1.m_type != constValue2.m_type )
852 if ( options.forceOutput() && !options.unoTypeCheck() )
854 if ( bDump )
856 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
857 bDump = sal_False;
859 fprintf(stdout, " Field %d: Access1 = %s != Access2 = %s\n", index1,
860 getConstValueType(constValue1), getConstValueType(constValue2));
861 fprintf(stdout, " Field %d: Value1 = ", index1);
862 printConstValue(constValue1);
863 fprintf(stdout, " != Value2 = ");
864 printConstValue(constValue1);
865 fprintf(stdout, "\n;");
867 nError++;
868 } else
870 nError += checkConstValue(keyName, typeClass, bDump, constValue1, constValue2, index1);
874 if ( reader1.getFieldFlags(index1) != reader2.getFieldFlags(index2) )
876 if ( options.forceOutput() && !options.unoTypeCheck() )
878 if ( bDump )
880 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
881 bDump = sal_False;
883 fprintf(stdout, " Field %d: FieldAccess1 = %s != FieldAccess2 = %s\n", index1,
884 getFieldAccess(reader1.getFieldFlags(index1)).getStr(),
885 getFieldAccess(reader1.getFieldFlags(index2)).getStr());
887 nError++;
890 if ( options.fullCheck() &&
891 (reader1.getFieldDocumentation(index1) != reader2.getFieldDocumentation(index2)) )
893 if ( options.forceOutput() && !options.unoTypeCheck() )
895 if ( bDump )
897 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
898 bDump = sal_False;
900 fprintf(stdout, " Field %d: Doku1 = %s\n Doku2 = %s\n", index1,
901 U2S(reader1.getFieldDocumentation(index1)), U2S(reader2.getFieldDocumentation(index2)));
903 nError++;
905 return nError;
908 static char const * getMethodMode(RTMethodMode methodMode)
910 switch ( methodMode )
912 case RT_MODE_ONEWAY:
913 return "ONEWAY";
914 case RT_MODE_ONEWAY_CONST:
915 return "ONEWAY,CONST";
916 case RT_MODE_TWOWAY:
917 return "NONE";
918 case RT_MODE_TWOWAY_CONST:
919 return "CONST";
920 default:
921 return "INVALID";
925 static char const * getParamMode(RTParamMode paramMode)
927 switch ( paramMode )
929 case RT_PARAM_IN:
930 return "IN";
931 case RT_PARAM_OUT:
932 return "OUT";
933 case RT_PARAM_INOUT:
934 return "INOUT";
935 default:
936 return "INVALID";
940 static sal_uInt32 checkMethod(const OUString& keyName,
941 RTTypeClass typeClass,
942 sal_Bool& bDump,
943 typereg::Reader& reader1,
944 typereg::Reader& reader2,
945 sal_uInt16 index)
947 sal_uInt32 nError = 0;
948 if ( reader1.getMethodName(index) !=
949 reader2.getMethodName(index) )
951 if ( options.forceOutput() )
953 if ( bDump )
955 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
956 bDump = sal_False;
958 fprintf(stdout, " Method1 %d: Name1 = %s != Name2 = %s\n", index,
959 U2S(reader1.getMethodName(index)),
960 U2S(reader2.getMethodName(index)));
962 nError++;
965 if ( reader1.getMethodReturnTypeName(index) !=
966 reader2.getMethodReturnTypeName(index) )
968 if ( options.forceOutput() )
970 if ( bDump )
972 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
973 bDump = sal_False;
975 fprintf(stdout, " Method1 %d: ReturnType1 = %s != ReturnType2 = %s\n", index,
976 U2S(reader1.getMethodReturnTypeName(index)),
977 U2S(reader2.getMethodReturnTypeName(index)));
979 nError++;
982 sal_uInt16 nParams1 = (sal_uInt16)reader1.getMethodParameterCount(index);
983 sal_uInt16 nParams2 = (sal_uInt16)reader2.getMethodParameterCount(index);
984 if ( nParams1 != nParams2 )
986 if ( options.forceOutput() )
988 if ( bDump )
990 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
991 bDump = sal_False;
993 fprintf(stdout, " Method %d : nParameters1 = %d != nParameters2 = %d\n", index, nParams1, nParams2);
995 nError++;
997 sal_uInt16 i=0;
998 for (i=0; i < nParams1 && i < nParams2; i++)
1000 if ( reader1.getMethodParameterTypeName(index, i) != reader2.getMethodParameterTypeName(index, i) )
1002 if ( options.forceOutput() )
1004 if ( bDump )
1006 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1007 bDump = sal_False;
1009 fprintf(stdout, " Method %d, Parameter %d: Type1 = %s != Type2 = %s\n", index, i,
1010 U2S(reader1.getMethodParameterTypeName(index, i)),
1011 U2S(reader2.getMethodParameterTypeName(index, i)));
1013 nError++;
1015 if ( options.fullCheck() &&
1016 (reader1.getMethodParameterName(index, i) != reader2.getMethodParameterName(index, i)) )
1018 if ( options.forceOutput() )
1020 if ( bDump )
1022 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1023 bDump = sal_False;
1025 fprintf(stdout, " Method %d, Parameter %d: Name1 = %s != Name2 = %s\n", index, i,
1026 U2S(reader1.getMethodParameterName(index, i)),
1027 U2S(reader2.getMethodParameterName(index, i)));
1029 nError++;
1031 if ( reader1.getMethodParameterFlags(index, i) != reader2.getMethodParameterFlags(index, i) )
1033 if ( options.forceOutput() )
1035 if ( bDump )
1037 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1038 bDump = sal_False;
1040 fprintf(stdout, " Method %d, Parameter %d: Mode1 = %s != Mode2 = %s\n", index, i,
1041 getParamMode(reader1.getMethodParameterFlags(index, i)),
1042 getParamMode(reader2.getMethodParameterFlags(index, i)));
1044 nError++;
1047 if ( i < nParams1 && options.forceOutput() )
1049 if ( bDump )
1051 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1052 bDump = sal_False;
1054 fprintf(stdout, " Registry1: Method %d contains %d more parameters\n", index, nParams1 - i);
1056 if ( i < nParams2 && options.forceOutput() )
1058 if ( bDump )
1060 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1061 bDump = sal_False;
1063 fprintf(stdout, " Registry2: Method %d contains %d more parameters\n", index, nParams2 - i);
1066 sal_uInt16 nExcep1 = (sal_uInt16)reader1.getMethodExceptionCount(index);
1067 sal_uInt16 nExcep2 = (sal_uInt16)reader2.getMethodExceptionCount(index);
1068 if ( nExcep1 != nExcep2 )
1070 if ( options.forceOutput() )
1072 if ( bDump )
1074 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1075 bDump = sal_False;
1077 fprintf(stdout, " nExceptions1 = %d != nExceptions2 = %d\n", nExcep1, nExcep2);
1079 nError++;
1081 for (i=0; i < nExcep1 && i < nExcep2; i++)
1083 if ( reader1.getMethodExceptionTypeName(index, i) != reader2.getMethodExceptionTypeName(index, i) )
1085 if ( options.forceOutput() )
1087 if ( bDump )
1089 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1090 bDump = sal_False;
1092 fprintf(stdout, " Method %d, Exception %d: Name1 = %s != Name2 = %s\n", index, i,
1093 U2S(reader1.getMethodExceptionTypeName(index, i)),
1094 U2S(reader2.getMethodExceptionTypeName(index, i)));
1096 nError++;
1099 if ( i < nExcep1 && options.forceOutput() )
1101 if ( bDump )
1103 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1104 bDump = sal_False;
1106 fprintf(stdout, " Registry1: Method %d contains %d more exceptions\n", index, nExcep1 - i);
1108 if ( i < nExcep2 && options.forceOutput() )
1110 if ( bDump )
1112 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1113 bDump = sal_False;
1115 fprintf(stdout, " Registry2: Method %d contains %d more exceptions\n", index, nExcep2 - i);
1118 if ( reader1.getMethodFlags(index) != reader2.getMethodFlags(index) )
1120 if ( options.forceOutput() )
1122 if ( bDump )
1124 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1125 bDump = sal_False;
1127 fprintf(stdout, " Method %d: Mode1 = %s != Mode2 = %s\n", index,
1128 getMethodMode(reader1.getMethodFlags(index)),
1129 getMethodMode(reader2.getMethodFlags(index)));
1131 nError++;
1134 if ( options.fullCheck() &&
1135 (reader1.getMethodDocumentation(index) != reader2.getMethodDocumentation(index)) )
1137 if ( options.forceOutput() )
1139 if ( bDump )
1141 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1142 bDump = sal_False;
1144 fprintf(stdout, " Method %d: Doku1 = %s\n Doku2 = %s\n", index,
1145 U2S(reader1.getMethodDocumentation(index)),
1146 U2S(reader2.getMethodDocumentation(index)));
1148 nError++;
1150 return nError;
1153 static char const * getReferenceType(RTReferenceType refType)
1155 switch (refType)
1157 case RT_REF_SUPPORTS:
1158 return "RT_REF_SUPPORTS";
1159 case RT_REF_OBSERVES:
1160 return "RT_REF_OBSERVES";
1161 case RT_REF_EXPORTS:
1162 return "RT_REF_EXPORTS";
1163 case RT_REF_NEEDS:
1164 return "RT_REF_NEEDS";
1165 default:
1166 return "RT_REF_INVALID";
1170 static sal_uInt32 checkReference(const OUString& keyName,
1171 RTTypeClass typeClass,
1172 sal_Bool& bDump,
1173 typereg::Reader& reader1,
1174 typereg::Reader& reader2,
1175 sal_uInt16 index1,
1176 sal_uInt16 index2)
1178 sal_uInt32 nError = 0;
1179 if ( reader1.getReferenceTypeName(index1) !=
1180 reader2.getReferenceTypeName(index2) )
1182 if ( options.forceOutput() && !options.unoTypeCheck() )
1184 if ( bDump )
1186 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1187 bDump = sal_False;
1189 fprintf(stdout, " Reference %d: Name1 = %s != Name2 = %s\n", index1,
1190 U2S(reader1.getReferenceTypeName(index1)),
1191 U2S(reader2.getReferenceTypeName(index2)));
1193 nError++;
1195 if ( reader1.getReferenceTypeName(index1) !=
1196 reader2.getReferenceTypeName(index2) )
1198 if ( options.forceOutput() && !options.unoTypeCheck() )
1200 if ( bDump )
1202 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1203 bDump = sal_False;
1205 fprintf(stdout, " Reference %d: Type1 = %s != Type2 = %s\n", index1,
1206 getReferenceType(reader1.getReferenceSort(index1)),
1207 getReferenceType(reader2.getReferenceSort(index2)));
1209 nError++;
1211 if ( options.fullCheck() &&
1212 (reader1.getReferenceDocumentation(index1) != reader2.getReferenceDocumentation(index2)) )
1214 if ( options.forceOutput() && !options.unoTypeCheck() )
1216 if ( bDump )
1218 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1219 bDump = sal_False;
1221 fprintf(stdout, " Reference %d: Doku1 = %s\n Doku2 = %s\n", index1,
1222 U2S(reader1.getReferenceDocumentation(index1)),
1223 U2S(reader2.getReferenceDocumentation(index2)));
1225 nError++;
1227 if ( reader1.getReferenceFlags(index1) !=
1228 reader2.getReferenceFlags(index2) )
1230 if ( options.forceOutput() && !options.unoTypeCheck() )
1232 if ( bDump )
1234 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1235 bDump = sal_False;
1237 fprintf(stdout, " Reference %d: Access1 = %s != Access2 = %s\n", index1,
1238 getFieldAccess(reader1.getReferenceFlags(index1)).getStr(),
1239 getFieldAccess(reader1.getReferenceFlags(index2)).getStr());
1241 nError++;
1243 return nError;
1246 static sal_uInt32 checkFieldsWithoutOrder(const OUString& keyName,
1247 RTTypeClass typeClass,
1248 sal_Bool& bDump,
1249 typereg::Reader& reader1,
1250 typereg::Reader& reader2)
1252 sal_uInt32 nError = 0;
1254 sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount();
1255 sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount();
1256 sal_uInt16 i=0, j=0;
1258 if ( nFields1 > nFields2 )
1260 if ( options.forceOutput() )
1262 if ( bDump )
1264 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1265 bDump = sal_False;
1267 fprintf(stdout, " %s1 contains %d more properties as %s2\n",
1268 getTypeClass(typeClass), nFields1-nFields2, getTypeClass(typeClass));
1272 sal_Bool bFound = sal_False;
1273 ::std::set< sal_uInt16 > moreProps;
1275 for (i=0; i < nFields1; i++)
1277 for (j=0; j < nFields2; j++)
1279 if (!checkField(keyName, typeClass, bDump, reader1, reader2, i, j))
1281 bFound = sal_True;
1282 moreProps.insert(j);
1283 break;
1286 if (!bFound)
1288 if (options.forceOutput())
1290 if ( bDump )
1292 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1293 bDump = sal_False;
1295 fprintf(stdout, " incompatible change: Field %d ('%s') of r1 is not longer a property of this %s in r2\n",
1296 i, U2S(shortName(reader1.getFieldName(i))), getTypeClass(typeClass));
1298 nError++;
1299 } else
1301 bFound = sal_False;
1305 if ( typeClass == RT_TYPE_SERVICE && !moreProps.empty() )
1307 for (j=0; j < nFields2; j++)
1309 if ( moreProps.find(j) == moreProps.end() )
1311 if ( (reader2.getFieldFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL )
1313 if ( options.forceOutput() )
1315 if ( bDump )
1317 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1318 bDump = sal_False;
1320 fprintf(stdout, " incompatible change: Field %d ('%s') of r2 is a new property compared to this %s in r1 and is not 'optional'\n",
1321 j, U2S(shortName(reader2.getFieldName(j))), getTypeClass(typeClass));
1323 nError++;
1329 return nError;
1332 static sal_uInt32 checkBlob(const OUString& keyName, typereg::Reader& reader1, sal_uInt32 size1,
1333 typereg::Reader& reader2, sal_uInt32 size2)
1335 sal_uInt32 nError = 0;
1336 sal_Bool bDump = sal_True;
1338 if ( options.fullCheck() && (size1 != size2) )
1340 if ( options.forceOutput() )
1342 fprintf(
1343 stdout, " Size1 = %lu Size2 = %lu\n",
1344 sal::static_int_cast< unsigned long >(size1),
1345 sal::static_int_cast< unsigned long >(size2));
1348 if (reader1.isPublished()) {
1349 if (!reader2.isPublished()) {
1350 if (options.forceOutput()) {
1351 if (bDump) {
1352 fprintf(stdout, "?: %s\n", U2S(keyName));
1353 bDump = false;
1355 fprintf(stdout, " published in 1 but unpublished in 2\n");
1357 ++nError;
1359 } else if (!options.checkUnpublished()) {
1360 return nError;
1362 if ( reader1.getTypeClass() != reader2.getTypeClass() )
1364 if ( options.forceOutput() )
1366 if (bDump) {
1367 fprintf(stdout, "?: %s\n", U2S(keyName));
1368 bDump = sal_False;
1370 fprintf(stdout, " TypeClass1 = %s != TypeClass2 = %s\n",
1371 getTypeClass(reader1.getTypeClass()),
1372 getTypeClass(reader2.getTypeClass()));
1374 return ++nError;
1377 RTTypeClass typeClass = reader1.getTypeClass();
1379 if ( reader1.getTypeName() != reader2.getTypeName() )
1381 if ( options.forceOutput() )
1383 if ( bDump )
1385 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1386 bDump = sal_False;
1388 fprintf(stdout, " TypeName1 = %s != TypeName2 = %s\n",
1389 U2S(reader1.getTypeName()), U2S(reader2.getTypeName()));
1391 nError++;
1393 if ( (typeClass == RT_TYPE_INTERFACE ||
1394 typeClass == RT_TYPE_STRUCT ||
1395 typeClass == RT_TYPE_EXCEPTION) )
1397 if (reader1.getSuperTypeCount() != reader2.getSuperTypeCount()) {
1398 if (bDump) {
1399 fprintf(
1400 stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1401 bDump = false;
1403 fprintf(
1404 stdout, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n",
1405 static_cast< int >(reader1.getSuperTypeCount()),
1406 static_cast< int >(reader2.getSuperTypeCount()));
1407 ++nError;
1408 } else {
1409 for (sal_Int16 i = 0; i < reader1.getSuperTypeCount(); ++i) {
1410 if (reader1.getSuperTypeName(i) != reader2.getSuperTypeName(i))
1412 if ( options.forceOutput() )
1414 if ( bDump )
1416 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1417 bDump = sal_False;
1419 fprintf(stdout, " SuperTypeName1 = %s != SuperTypeName2 = %s\n",
1420 U2S(reader1.getSuperTypeName(i)), U2S(reader2.getSuperTypeName(i)));
1422 nError++;
1427 sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount();
1428 sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount();
1429 sal_Bool bCheckNormal = sal_True;
1431 if ( (typeClass == RT_TYPE_SERVICE ||
1432 typeClass == RT_TYPE_MODULE ||
1433 typeClass == RT_TYPE_CONSTANTS) && options.unoTypeCheck() )
1435 bCheckNormal = sal_False;
1438 if ( bCheckNormal )
1440 if ( nFields1 != nFields2 )
1442 if ( options.forceOutput() )
1444 if ( bDump )
1446 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1447 bDump = sal_False;
1449 fprintf(stdout, " nFields1 = %d != nFields2 = %d\n", nFields1, nFields2);
1451 nError++;
1453 sal_uInt16 i;
1454 for (i=0; i < nFields1 && i < nFields2; i++)
1456 nError += checkField(keyName, typeClass, bDump, reader1, reader2, i, i);
1458 if ( i < nFields1 && options.forceOutput() )
1460 if ( bDump )
1462 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1463 bDump = sal_False;
1465 fprintf(stdout, " Registry1 contains %d more fields\n", nFields1 - i);
1467 if ( i < nFields2 && options.forceOutput() )
1469 if ( bDump )
1471 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1472 bDump = sal_False;
1474 fprintf(stdout, " Registry2 contains %d more fields\n", nFields2 - i);
1476 } else
1478 nError += checkFieldsWithoutOrder(keyName, typeClass, bDump, reader1, reader2);
1481 if ( typeClass == RT_TYPE_INTERFACE )
1483 sal_uInt16 nMethods1 = (sal_uInt16)reader1.getMethodCount();
1484 sal_uInt16 nMethods2 = (sal_uInt16)reader2.getMethodCount();
1485 if ( nMethods1 != nMethods2 )
1487 if ( options.forceOutput() )
1489 if ( bDump )
1491 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1492 bDump = sal_False;
1494 fprintf(stdout, " nMethods1 = %d != nMethods2 = %d\n", nMethods1, nMethods2);
1496 nError++;
1498 sal_uInt16 i;
1499 for (i=0; i < nMethods1 && i < nMethods2; i++)
1501 nError += checkMethod(keyName, typeClass, bDump, reader1, reader2, i);
1503 if ( i < nMethods1 && options.forceOutput() )
1505 fprintf(stdout, " Registry1 contains %d more methods\n", nMethods1 - i);
1507 if ( i < nMethods2 && options.forceOutput() )
1509 fprintf(stdout, " Registry2 contains %d more methods\n", nMethods2 - i);
1512 if ( typeClass == RT_TYPE_SERVICE )
1514 sal_uInt16 nReference1 = (sal_uInt16)reader1.getReferenceCount();
1515 sal_uInt16 nReference2 = (sal_uInt16)reader2.getReferenceCount();
1517 if ( !bCheckNormal )
1519 sal_uInt16 i=0, j=0;
1521 if ( nReference1 > nReference2 )
1523 if ( options.forceOutput() )
1525 if ( bDump )
1527 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1528 bDump = sal_False;
1530 fprintf(stdout, " service1 contains %d more references as service2\n",
1531 nReference1-nReference2);
1535 sal_Bool bFound = sal_False;
1536 ::std::set< sal_uInt16 > moreReferences;
1538 for (i=0; i < nReference1; i++)
1540 for (j=0; j < nReference2; j++)
1542 if (!checkReference(keyName, typeClass, bDump, reader1, reader2, i, j))
1544 bFound = sal_True;
1545 moreReferences.insert(j);
1546 break;
1549 if (!bFound)
1551 if (options.forceOutput())
1553 if ( bDump )
1555 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1556 bDump = sal_False;
1558 fprintf(stdout, " incompatible change: Reference %d ('%s') in 'r1' is not longer a reference of this service in 'r2'\n",
1559 i, U2S(shortName(reader1.getReferenceTypeName(i))));
1561 nError++;
1562 } else
1564 bFound = sal_False;
1568 if ( !moreReferences.empty() )
1570 for (j=0; j < nReference2; j++)
1572 if ( moreReferences.find(j) == moreReferences.end() )
1574 if ( (reader2.getReferenceFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL )
1576 if ( options.forceOutput() )
1578 if ( bDump )
1580 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1581 bDump = sal_False;
1583 fprintf(stdout, " incompatible change: Reference %d ('%s') of r2 is a new reference compared to this service in r1 and is not 'optional'\n",
1584 j, U2S(shortName(reader2.getReferenceTypeName(j))));
1586 nError++;
1591 } else
1593 if ( nReference1 != nReference2 )
1595 if ( options.forceOutput() )
1597 if ( bDump )
1599 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1600 bDump = sal_False;
1602 fprintf(stdout, " nReferences1 = %d != nReferences2 = %d\n", nReference1, nReference2);
1604 nError++;
1606 sal_uInt16 i;
1607 for (i=0; i < nReference1 && i < nReference2; i++)
1609 nError += checkReference(keyName, typeClass, bDump, reader1, reader2, i, i);
1611 if ( i < nReference1 && options.forceOutput() )
1613 fprintf(stdout, " Registry1 contains %d more references\n", nReference1 - i);
1615 if ( i < nReference2 && options.forceOutput() )
1617 fprintf(stdout, " Registry2 contains %d more references\n", nReference2 - i);
1622 if ( options.fullCheck() && (reader1.getDocumentation() != reader2.getDocumentation()) )
1624 if ( options.forceOutput() )
1626 if ( bDump )
1628 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1629 bDump = sal_False;
1631 fprintf(stdout, " Doku1 = %s\n Doku2 = %s\n",
1632 U2S(reader1.getDocumentation()), U2S(reader2.getDocumentation()));
1634 nError++;
1637 if ( nError &&
1638 (!keyName.compareTo(OUString::createFromAscii("/UCR/drafts"), 11) ||
1639 !keyName.compareTo(OUString::createFromAscii("/drafts"), 7)) )
1641 if ( options.forceOutput() )
1643 if ( bDump )
1645 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1646 bDump = sal_False;
1648 fprintf(stdout, " Note: \"drafts\" type changed incompatible, no effect to the final API\n");
1650 return 0;
1653 return nError;
1656 static sal_uInt32 checkValueDifference(RegistryKey& key1, RegValueType valueType1, sal_uInt32 size1,
1657 RegistryKey& key2, RegValueType valueType2, sal_uInt32 size2)
1659 OUString tmpName;
1660 sal_uInt32 nError = 0;
1662 if ( valueType1 == valueType2 )
1664 sal_Bool bEqual = sal_True;
1665 switch (valueType1)
1667 case RG_VALUETYPE_LONGLIST:
1669 RegistryValueList<sal_Int32> valueList1;
1670 RegistryValueList<sal_Int32> valueList2;
1671 key1.getLongListValue(tmpName, valueList1);
1672 key2.getLongListValue(tmpName, valueList2);
1673 sal_uInt32 length1 = valueList1.getLength();
1674 sal_uInt32 length2 = valueList1.getLength();
1675 if ( length1 != length2 )
1677 bEqual = sal_False;
1678 break;
1680 for (sal_uInt32 i=0; i<length1; i++)
1682 if ( valueList1.getElement(i) != valueList2.getElement(i) )
1684 bEqual = sal_False;
1685 break;
1689 break;
1690 case RG_VALUETYPE_STRINGLIST:
1692 RegistryValueList<sal_Char*> valueList1;
1693 RegistryValueList<sal_Char*> valueList2;
1694 key1.getStringListValue(tmpName, valueList1);
1695 key2.getStringListValue(tmpName, valueList2);
1696 sal_uInt32 length1 = valueList1.getLength();
1697 sal_uInt32 length2 = valueList1.getLength();
1698 if ( length1 != length2 )
1700 bEqual = sal_False;
1701 break;
1703 for (sal_uInt32 i=0; i<length1; i++)
1705 if ( strcmp(valueList1.getElement(i), valueList2.getElement(i)) != 0 )
1707 bEqual = sal_False;
1708 break;
1712 break;
1713 case RG_VALUETYPE_UNICODELIST:
1715 RegistryValueList<sal_Unicode*> valueList1;
1716 RegistryValueList<sal_Unicode*> valueList2;
1717 key1.getUnicodeListValue(tmpName, valueList1);
1718 key2.getUnicodeListValue(tmpName, valueList2);
1719 sal_uInt32 length1 = valueList1.getLength();
1720 sal_uInt32 length2 = valueList1.getLength();
1721 if ( length1 != length2 )
1723 bEqual = sal_False;
1724 break;
1726 for (sal_uInt32 i=0; i<length1; i++)
1728 if ( rtl_ustr_compare(valueList1.getElement(i), valueList2.getElement(i)) != 0 )
1730 bEqual = sal_False;
1731 break;
1735 break;
1736 default:
1737 break;
1740 if ( bEqual)
1742 RegValue value1 = rtl_allocateMemory(size1);
1743 RegValue value2 = rtl_allocateMemory(size2);
1745 key1.getValue(tmpName, value1);
1746 key2.getValue(tmpName, value2);
1748 bEqual = (rtl_compareMemory(value1, value2, size1) == 0 );
1750 if ( !bEqual && valueType1 == RG_VALUETYPE_BINARY && valueType2 == RG_VALUETYPE_BINARY )
1752 typereg::Reader reader1(
1753 value1, size1, false, TYPEREG_VERSION_1);
1754 typereg::Reader reader2(
1755 value2, size2, false, TYPEREG_VERSION_1);
1757 if ( reader1.isValid() && reader2.isValid() )
1759 return checkBlob(key1.getName(), reader1, size1, reader2, size2);
1763 rtl_freeMemory(value1);
1764 rtl_freeMemory(value2);
1766 if ( bEqual )
1768 return 0;
1769 } else
1771 if ( options.forceOutput() )
1773 fprintf(stdout, "Difference: key values of key \"%s\" are different\n",
1774 U2S(key1.getName()));
1776 nError++;
1781 if ( options.forceOutput() )
1783 switch (valueType1)
1785 case RG_VALUETYPE_NOT_DEFINED:
1786 fprintf(stdout, " Registry 1: key has no value\n");
1787 break;
1788 case RG_VALUETYPE_LONG:
1789 case RG_VALUETYPE_STRING:
1790 case RG_VALUETYPE_UNICODE:
1792 RegValue value1 = rtl_allocateMemory(size1);
1793 key1.getValue(tmpName, value1);
1795 switch (valueType1)
1797 case RG_VALUETYPE_LONG:
1798 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONG\n");
1799 fprintf(
1800 stdout, " Size = %lu\n",
1801 sal::static_int_cast< unsigned long >(size1));
1802 fprintf(stdout, " Data = %p\n", value1);
1803 break;
1804 case RG_VALUETYPE_STRING:
1805 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRING\n");
1806 fprintf(
1807 stdout, " Size = %lu\n",
1808 sal::static_int_cast< unsigned long >(size1));
1809 fprintf(stdout, " Data = \"%s\"\n", (sal_Char*)value1);
1810 break;
1811 case RG_VALUETYPE_UNICODE:
1813 OUString uStrValue((sal_Unicode*)value1);
1814 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODE\n");
1815 fprintf(
1816 stdout, " Size = %lu\n",
1817 sal::static_int_cast< unsigned long >(size1));
1818 fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue));
1820 break;
1821 default:
1822 OSL_ASSERT(false);
1823 break;
1826 rtl_freeMemory(value1);
1828 break;
1829 case RG_VALUETYPE_BINARY:
1830 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_BINARY\n");
1831 break;
1832 case RG_VALUETYPE_LONGLIST:
1834 RegistryValueList<sal_Int32> valueList;
1835 key1.getLongListValue(tmpName, valueList);
1836 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONGLIST\n");
1837 fprintf(
1838 stdout, " Size = %lu\n",
1839 sal::static_int_cast< unsigned long >(size1));
1840 sal_uInt32 length = valueList.getLength();
1841 for (sal_uInt32 i=0; i<length; i++)
1843 fprintf(
1844 stdout, " Data[%lu] = %ld\n",
1845 sal::static_int_cast< unsigned long >(i),
1846 sal::static_int_cast< long >(valueList.getElement(i)));
1849 break;
1850 case RG_VALUETYPE_STRINGLIST:
1852 RegistryValueList<sal_Char*> valueList;
1853 key1.getStringListValue(tmpName, valueList);
1854 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRINGLIST\n");
1855 fprintf(
1856 stdout, " Size = %lu\n",
1857 sal::static_int_cast< unsigned long >(size1));
1858 sal_uInt32 length = valueList.getLength();
1859 for (sal_uInt32 i=0; i<length; i++)
1861 fprintf(
1862 stdout, " Data[%lu] = \"%s\"\n",
1863 sal::static_int_cast< unsigned long >(i),
1864 valueList.getElement(i));
1867 break;
1868 case RG_VALUETYPE_UNICODELIST:
1870 RegistryValueList<sal_Unicode*> valueList;
1871 key1.getUnicodeListValue(tmpName, valueList);
1872 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODELIST\n");
1873 fprintf(
1874 stdout, " Size = %lu\n",
1875 sal::static_int_cast< unsigned long >(size1));
1876 sal_uInt32 length = valueList.getLength();
1877 OUString uStrValue;
1878 for (sal_uInt32 i=0; i<length; i++)
1880 uStrValue = OUString(valueList.getElement(i));
1881 fprintf(
1882 stdout, " Data[%lu] = \"%s\"\n",
1883 sal::static_int_cast< unsigned long >(i), U2S(uStrValue));
1886 break;
1889 switch (valueType2)
1891 case RG_VALUETYPE_NOT_DEFINED:
1892 fprintf(stdout, " Registry 2: key has no value\n");
1893 break;
1894 case RG_VALUETYPE_LONG:
1895 case RG_VALUETYPE_STRING:
1896 case RG_VALUETYPE_UNICODE:
1898 RegValue value2 = rtl_allocateMemory(size2);
1899 key2.getValue(tmpName, value2);
1901 switch (valueType2)
1903 case RG_VALUETYPE_LONG:
1904 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONG\n");
1905 fprintf(
1906 stdout, " Size = %lu\n",
1907 sal::static_int_cast< unsigned long >(size2));
1908 fprintf(stdout, " Data = %p\n", value2);
1909 break;
1910 case RG_VALUETYPE_STRING:
1911 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRING\n");
1912 fprintf(
1913 stdout, " Size = %lu\n",
1914 sal::static_int_cast< unsigned long >(size2));
1915 fprintf(stdout, " Data = \"%s\"\n", (sal_Char*)value2);
1916 break;
1917 case RG_VALUETYPE_UNICODE:
1919 OUString uStrValue((sal_Unicode*)value2);
1920 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODE\n");
1921 fprintf(
1922 stdout, " Size = %lu\n",
1923 sal::static_int_cast< unsigned long >(size2));
1924 fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue));
1926 break;
1927 default:
1928 OSL_ASSERT(false);
1929 break;
1932 rtl_freeMemory(value2);
1934 break;
1935 case RG_VALUETYPE_BINARY:
1936 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_BINARY\n");
1937 break;
1938 case RG_VALUETYPE_LONGLIST:
1940 RegistryValueList<sal_Int32> valueList;
1941 key2.getLongListValue(tmpName, valueList);
1942 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONGLIST\n");
1943 fprintf(
1944 stdout, " Size = %lu\n",
1945 sal::static_int_cast< unsigned long >(size2));
1946 sal_uInt32 length = valueList.getLength();
1947 for (sal_uInt32 i=0; i<length; i++)
1949 fprintf(
1950 stdout, " Data[%lu] = %ld\n",
1951 sal::static_int_cast< unsigned long >(i),
1952 sal::static_int_cast< long >(valueList.getElement(i)));
1955 break;
1956 case RG_VALUETYPE_STRINGLIST:
1958 RegistryValueList<sal_Char*> valueList;
1959 key2.getStringListValue(tmpName, valueList);
1960 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRINGLIST\n");
1961 fprintf(
1962 stdout, " Size = %lu\n",
1963 sal::static_int_cast< unsigned long >(size2));
1964 sal_uInt32 length = valueList.getLength();
1965 for (sal_uInt32 i=0; i<length; i++)
1967 fprintf(
1968 stdout, " Data[%lu] = \"%s\"\n",
1969 sal::static_int_cast< unsigned long >(i),
1970 valueList.getElement(i));
1973 break;
1974 case RG_VALUETYPE_UNICODELIST:
1976 RegistryValueList<sal_Unicode*> valueList;
1977 key2.getUnicodeListValue(tmpName, valueList);
1978 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODELIST\n");
1979 fprintf(
1980 stdout, " Size = %lu\n",
1981 sal::static_int_cast< unsigned long >(size2));
1982 sal_uInt32 length = valueList.getLength();
1983 OUString uStrValue;
1984 for (sal_uInt32 i=0; i<length; i++)
1986 uStrValue = OUString(valueList.getElement(i));
1987 fprintf(
1988 stdout, " Data[%lu] = \"%s\"\n",
1989 sal::static_int_cast< unsigned long >(i), U2S(uStrValue));
1992 break;
1995 return nError;
1998 static bool hasPublishedChildren(RegistryKey & key) {
1999 RegistryKeyNames subKeyNames;
2000 key.getKeyNames(rtl::OUString(), subKeyNames);
2001 for (sal_uInt32 i = 0; i < subKeyNames.getLength(); ++i) {
2002 rtl::OUString keyName(subKeyNames.getElement(i));
2003 if (!options.matchedWithExcludeKey(keyName)) {
2004 keyName = keyName.copy(keyName.lastIndexOf('/') + 1);
2005 RegistryKey subKey;
2006 if (!key.openKey(keyName, subKey)) {
2007 if (options.forceOutput()) {
2008 fprintf(
2009 stdout,
2010 ("WARNING: could not open key \"%s\" in registry"
2011 " \"%s\"\n"),
2012 U2S(subKeyNames.getElement(i)),
2013 options.getRegName1().getStr());
2016 if (subKey.isValid()) {
2017 RegValueType type;
2018 sal_uInt32 size;
2019 if (subKey.getValueInfo(rtl::OUString(), &type, &size)
2020 != REG_NO_ERROR)
2022 if (options.forceOutput()) {
2023 fprintf(
2024 stdout,
2025 ("WARNING: could not read key \"%s\" in registry"
2026 " \"%s\"\n"),
2027 U2S(subKeyNames.getElement(i)),
2028 options.getRegName1().getStr());
2030 } else if (type == RG_VALUETYPE_BINARY) {
2031 char * value = new char[size];
2032 bool published = false;
2033 if (subKey.getValue(rtl::OUString(), value) != REG_NO_ERROR)
2035 if (options.forceOutput()) {
2036 fprintf(
2037 stdout,
2038 ("WARNING: could not read key \"%s\" in"
2039 " registry \"%s\"\n"),
2040 U2S(subKeyNames.getElement(i)),
2041 options.getRegName1().getStr());
2043 } else {
2044 published = typereg::Reader(
2045 value, size, false, TYPEREG_VERSION_1).
2046 isPublished();
2048 delete[] value;
2049 if (published) {
2050 return true;
2056 return false;
2059 static sal_uInt32 checkDifferences(
2060 RegistryKey& key, StringSet& keys, RegistryKeyNames& subKeyNames1,
2061 RegistryKeyNames& subKeyNames2)
2063 sal_uInt32 nError = 0;
2064 sal_uInt32 length1 = subKeyNames1.getLength();
2065 sal_uInt32 length2 = subKeyNames2.getLength();
2066 sal_uInt32 i,j;
2068 for (i=0; i<length1; i++)
2070 sal_Bool bFound = sal_False;
2071 for (j=0; j<length2; j++)
2073 if ( subKeyNames1.getElement(i) == subKeyNames2.getElement(j) )
2075 bFound = sal_True;
2076 keys.insert(subKeyNames1.getElement(i));
2077 break;
2080 if ( !bFound )
2082 if ( options.fullCheck() )
2084 if ( options.forceOutput() )
2086 fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
2087 U2S(subKeyNames1.getElement(i)), options.getRegName1().getStr());
2089 nError++;
2091 else
2093 rtl::OUString keyName(subKeyNames1.getElement(i));
2094 if (!options.matchedWithExcludeKey(keyName)) {
2095 keyName = keyName.copy(keyName.lastIndexOf('/') + 1);
2096 RegistryKey subKey;
2097 if (key.openKey(keyName, subKey)) {
2098 if (options.forceOutput()) {
2099 fprintf(
2100 stdout,
2101 ("ERROR: could not open key \"%s\" in registry"
2102 " \"%s\"\n"),
2103 U2S(subKeyNames1.getElement(i)),
2104 options.getRegName1().getStr());
2106 ++nError;
2108 if (subKey.isValid()) {
2109 RegValueType type;
2110 sal_uInt32 size;
2111 if (subKey.getValueInfo(rtl::OUString(), &type, &size)
2112 != REG_NO_ERROR)
2114 if (options.forceOutput()) {
2115 fprintf(
2116 stdout,
2117 ("ERROR: could not read key \"%s\" in"
2118 " registry \"%s\"\n"),
2119 U2S(subKeyNames1.getElement(i)),
2120 options.getRegName1().getStr());
2122 ++nError;
2123 } else if (type == RG_VALUETYPE_BINARY) {
2124 char * value = new char[size];
2125 if (subKey.getValue(rtl::OUString(), value)
2126 != REG_NO_ERROR)
2128 if (options.forceOutput()) {
2129 fprintf(
2130 stdout,
2131 ("ERROR: could not read key \"%s\" in"
2132 " registry \"%s\"\n"),
2133 U2S(subKeyNames1.getElement(i)),
2134 options.getRegName1().getStr());
2136 ++nError;
2137 } else {
2138 typereg::Reader reader(
2139 value, size, false, TYPEREG_VERSION_1);
2140 if (reader.getTypeClass() == RT_TYPE_MODULE) {
2141 if (options.checkUnpublished()
2142 || hasPublishedChildren(subKey))
2144 if (options.forceOutput()) {
2145 fprintf(
2146 stdout,
2147 ("EXISTENCE: module \"%s\""
2148 " %sexists only in registry"
2149 " 1\n"),
2150 U2S(subKeyNames1.getElement(
2151 i)),
2152 (options.checkUnpublished()
2153 ? ""
2154 : "with published children "));
2156 ++nError;
2158 } else if (options.checkUnpublished()
2159 || reader.isPublished())
2161 if (options.forceOutput()) {
2162 fprintf(
2163 stdout,
2164 ("EXISTENCE: %spublished key \"%s\""
2165 " exists only in registry 1\n"),
2166 reader.isPublished() ? "" : "un",
2167 U2S(subKeyNames1.getElement(i)));
2169 ++nError;
2172 delete[] value;
2180 for (i=0; i<length2; i++)
2182 sal_Bool bFound = sal_False;
2183 for (j=0; j<length1; j++)
2185 if ( subKeyNames2.getElement(i) == subKeyNames1.getElement(j) )
2187 bFound = sal_True;
2188 keys.insert(subKeyNames2.getElement(i));
2189 break;
2192 if ( !bFound && options.fullCheck() )
2194 if ( options.forceOutput() )
2196 fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
2197 U2S(subKeyNames2.getElement(i)), options.getRegName2().getStr());
2199 nError++;
2202 return nError;
2205 static sal_uInt32 compareKeys(RegistryKey& key1, RegistryKey& key2)
2207 sal_uInt32 nError = 0;
2209 RegValueType valueType1 = RG_VALUETYPE_NOT_DEFINED;
2210 RegValueType valueType2 = RG_VALUETYPE_NOT_DEFINED;
2211 sal_uInt32 size1 = 0;
2212 sal_uInt32 size2 = 0;
2213 OUString tmpName;
2214 RegError e1 = key1.getValueInfo(tmpName, &valueType1, &size1);
2215 RegError e2 = key2.getValueInfo(tmpName, &valueType2, &size2);
2217 if ( e1 == e2 && e1 != REG_VALUE_NOT_EXISTS && e1 != REG_INVALID_VALUE )
2219 nError += checkValueDifference(key1, valueType1, size1, key2, valueType2, size2);
2220 } else
2222 if ( e1 != REG_INVALID_VALUE || e2 != REG_INVALID_VALUE )
2224 if ( options.forceOutput() )
2226 fprintf(stdout, "VALUES: key values of key \"%s\" are different\n", U2S(key1.getName()));
2228 nError++;
2232 RegistryKeyNames subKeyNames1;
2233 RegistryKeyNames subKeyNames2;
2235 key1.getKeyNames(tmpName, subKeyNames1);
2236 key2.getKeyNames(tmpName, subKeyNames2);
2238 StringSet keys;
2239 nError += checkDifferences(key1, keys, subKeyNames1, subKeyNames2);
2241 StringSet::iterator iter = keys.begin();
2242 StringSet::iterator end = keys.end();
2244 RegistryKey subKey1, subKey2;
2245 OUString keyName;
2246 while ( iter != end )
2248 keyName = OUString(*iter);
2249 if ( options.matchedWithExcludeKey(keyName) )
2251 ++iter;
2252 continue;
2255 sal_Int32 nPos = keyName.lastIndexOf( '/' );
2256 keyName = keyName.copy( nPos != -1 ? nPos+1 : 0 );
2257 if ( key1.openKey(keyName, subKey1) )
2259 if ( options.forceOutput() )
2261 fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
2262 U2S(*iter), options.getRegName1().getStr());
2264 nError++;
2266 if ( key2.openKey(keyName, subKey2) )
2268 if ( options.forceOutput() )
2270 fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
2271 U2S(*iter), options.getRegName2().getStr());
2273 nError++;
2275 if ( subKey1.isValid() && subKey2.isValid() )
2277 nError += compareKeys(subKey1, subKey2);
2279 subKey1.closeKey();
2280 subKey2.closeKey();
2281 ++iter;
2284 return nError;
2287 #if (defined UNX) || (defined OS2) || defined __MINGW32__
2288 int main( int argc, char * argv[] )
2289 #else
2290 int _cdecl main( int argc, char * argv[] )
2291 #endif
2293 if ( !options.initOptions(argc, argv) )
2295 exit(1);
2298 OUString regName1( convertToFileUrl(options.getRegName1()) );
2299 OUString regName2( convertToFileUrl(options.getRegName2()) );
2301 Registry reg1;
2302 Registry reg2;
2304 if ( reg1.open(regName1, REG_READONLY) )
2306 fprintf(stdout, "%s: open registry \"%s\" failed\n",
2307 options.getProgramName().getStr(), options.getRegName1().getStr());
2308 exit(2);
2310 if ( reg2.open(regName2, REG_READONLY) )
2312 fprintf(stdout, "%s: open registry \"%s\" failed\n",
2313 options.getProgramName().getStr(), options.getRegName2().getStr());
2314 exit(3);
2317 RegistryKey key1, key2;
2318 if ( reg1.openRootKey(key1) )
2320 fprintf(stdout, "%s: open root key of registry \"%s\" failed\n",
2321 options.getProgramName().getStr(), options.getRegName1().getStr());
2322 exit(4);
2324 if ( reg2.openRootKey(key2) )
2326 fprintf(stdout, "%s: open root key of registry \"%s\" failed\n",
2327 options.getProgramName().getStr(), options.getRegName2().getStr());
2328 exit(5);
2330 if ( options.isStartKeyValid() )
2332 if ( options.matchedWithExcludeKey( S2U(options.getStartKey()) ) )
2334 fprintf(stdout, "%s: start key is equal to one of the exclude keys\n",
2335 options.getProgramName().getStr());
2336 exit(6);
2338 RegistryKey sk1, sk2;
2339 if ( key1.openKey(S2U(options.getStartKey()), sk1) )
2341 fprintf(stdout, "%s: open start key of registry \"%s\" failed\n",
2342 options.getProgramName().getStr(), options.getRegName1().getStr());
2343 exit(7);
2345 if ( key2.openKey(S2U(options.getStartKey()), sk2) )
2347 fprintf(stdout, "%s: open start key of registry \"%s\" failed\n",
2348 options.getProgramName().getStr(), options.getRegName2().getStr());
2349 exit(8);
2352 key1 = sk1;
2353 key2 = sk2;
2356 sal_uInt32 nError = compareKeys(key1, key2);
2357 if ( nError )
2359 if ( options.unoTypeCheck() )
2361 fprintf(stdout, "%s: registries are incompatible: %lu differences!\n",
2362 options.getProgramName().getStr(),
2363 sal::static_int_cast< unsigned long >(nError));
2364 } else
2366 fprintf(stdout, "%s: registries contain %lu differences!\n",
2367 options.getProgramName().getStr(),
2368 sal::static_int_cast< unsigned long >(nError));
2370 } else
2372 if ( options.unoTypeCheck() )
2374 fprintf(stdout, "%s: registries are compatible!\n",
2375 options.getProgramName().getStr());
2376 } else
2378 fprintf(stdout, "%s: registries are equal!\n",
2379 options.getProgramName().getStr());
2383 key1.closeKey();
2384 key2.closeKey();
2385 if ( reg1.close() )
2387 fprintf(stdout, "%s: closing registry \"%s\" failed\n",
2388 options.getProgramName().getStr(), options.getRegName1().getStr());
2389 exit(9);
2391 if ( reg2.close() )
2393 fprintf(stdout, "%s: closing registry \"%s\" failed\n",
2394 options.getProgramName().getStr(), options.getRegName2().getStr());
2395 exit(10);
2398 return nError > 0 ? 11 : 0;