LCOV - code coverage report
Current view: top level - registry/tools - regcompare.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 911 0.0 %
Date: 2014-11-03 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10