summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2013-09-18 11:49:54 +0200
committerStephan Bergmann <sbergman@redhat.com>2013-09-18 14:44:10 +0200
commitcbea5d30b99b93b2118f5c1a081740e5880f18c1 (patch)
treee1e15213585fff6edeb814c8d42456e02696db45
parent53d7f614d59a31fdaa8a31b1181e469de3e517af (diff)
New unoidl-check tool to replace regcompare
...for checking compatibility with the reference rdbs. unoidl-check is no longer based on the legacy registry format, but can process all the various new UNOIDL registry formats. regcompare is still included in the SDK for now. (gb_UnoApi[Target]_set_reference_rdbfile now takes a non-empty sequence of rdb files, any necessary dependencies of the final rdf file preceding it just like it is required on the unoidl-check command line. Also, executing the unoidl-check now properly depends on those rdb files.) TODO: unoidl-check is too conservative for now and flags some changes as incompatible that are not. Change-Id: I92e4c69403c5e3fcb31707c98c65a2f509592dd4
-rw-r--r--Repository.mk1
-rw-r--r--offapi/UnoApi_offapi.mk2
-rw-r--r--registry/Module_registry.mk3
-rw-r--r--solenv/gbuild/LinkTarget.mk2
-rw-r--r--solenv/gbuild/UnoApiTarget.mk15
-rw-r--r--solenv/gbuild/extensions/pre_BuildTools.mk3
-rw-r--r--unoidl/Executable_unoidl-check.mk22
-rw-r--r--unoidl/Module_unoidl.mk1
-rw-r--r--unoidl/source/unoidl-check.cxx922
9 files changed, 958 insertions, 13 deletions
diff --git a/Repository.mk b/Repository.mk
index d91c021e2c32..b8b1aa003afb 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -59,6 +59,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
treex \
uiex \
ulfex \
+ unoidl-check \
unoidl-read \
unoidl-write \
xrmex \
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 6eeb694b6877..5e369eaa5f21 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -4318,6 +4318,6 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,offapi/org/freedesktop/Package
SyncDbusSessionHelper \
))
-$(eval $(call gb_UnoApi_set_reference_rdbfile,offapi,offapi/type_reference/offapi))
+$(eval $(call gb_UnoApi_set_reference_rdbfile,offapi,udkapi/type_reference/udkapi offapi/type_reference/offapi))
# vim: set noet sw=4 ts=4:
diff --git a/registry/Module_registry.mk b/registry/Module_registry.mk
index 890649c09caa..fb962c64c012 100644
--- a/registry/Module_registry.mk
+++ b/registry/Module_registry.mk
@@ -18,8 +18,7 @@ $(eval $(call gb_Module_add_targets,registry,\
) \
))
-# if not cross-compiling or we need this for ODK
-ifneq (,$(if $(CROSS_COMPILING),,T)$(filter ODK,$(BUILD_TYPE)))
+ifneq (,$(filter ODK,$(BUILD_TYPE)))
$(eval $(call gb_Module_add_targets,registry,\
Executable_regcompare \
diff --git a/solenv/gbuild/LinkTarget.mk b/solenv/gbuild/LinkTarget.mk
index b7150f0db44b..dc213bdeb7cd 100644
--- a/solenv/gbuild/LinkTarget.mk
+++ b/solenv/gbuild/LinkTarget.mk
@@ -850,10 +850,10 @@ gb_BUILD_HELPER_LIBS := basegfx \
gb_BUILD_HELPER_TOOLS := cppumaker \
idlc \
- regcompare \
regmerge \
rsc \
svidl \
+ unoidl-check \
unoidl-write \
define gb_LinkTarget__is_build_lib
diff --git a/solenv/gbuild/UnoApiTarget.mk b/solenv/gbuild/UnoApiTarget.mk
index 92b812c15dd2..b1c3e08ea033 100644
--- a/solenv/gbuild/UnoApiTarget.mk
+++ b/solenv/gbuild/UnoApiTarget.mk
@@ -78,8 +78,8 @@ endif
# UnoApiTarget
-gb_UnoApiTarget_REGCOMPAREDEPS := $(call gb_Executable_get_runtime_dependencies,regcompare)
-gb_UnoApiTarget_REGCOMPARECOMMAND := SOLARBINDIR=$(OUTDIR_FOR_BUILD)/bin $(call gb_Executable_get_command,regcompare)
+gb_UnoApiTarget_UNOIDLCHECKDEPS := $(call gb_Executable_get_runtime_dependencies,unoidl-check)
+gb_UnoApiTarget_UNOIDLCHECKCOMMAND := SOLARBINDIR=$(OUTDIR_FOR_BUILD)/bin $(call gb_Executable_get_command,unoidl-check)
gb_UnoApiTarget_REGMERGEDEPS := $(call gb_Executable_get_runtime_dependencies,regmerge) $(call gb_Executable_get_runtime_dependencies,unoidl-write)
gb_UnoApiTarget_REGMERGECOMMAND := SOLARBINDIR=$(OUTDIR_FOR_BUILD)/bin $(call gb_Executable_get_command,regmerge)
@@ -103,10 +103,8 @@ rm -f $(1) && \
$(call gb_UnoApiTarget__command_impl,$(1),$(UNOAPI_ROOT),$(UNOAPI_FILES),$(UNOAPI_DEPRDBS)) \
$(if $(UNOAPI_REFERENCE), \
$(call gb_Output_announce,$(2),$(true),DBc,3) \
- && $(gb_UnoApiTarget_REGCOMPARECOMMAND) \
- -f -t \
- -r1 $(UNOAPI_REFERENCE) \
- -r2 $(1).oldformat)
+ && $(gb_UnoApiTarget_UNOIDLCHECKCOMMAND) $(UNOAPI_REFERENCE) -- \
+ $(foreach rdb,$(4),$(call gb_UnoApiTarget_get_target,$(rdb))) $(1))
endef
define gb_UnoApiTarget__check_mode
@@ -223,8 +221,9 @@ $$(call gb_Output_error,gb_UnoApiTarget_add_reference_rdbfile: use gb_UnoApiTarg
endef
define gb_UnoApiTarget_set_reference_rdbfile
-$(call gb_UnoApiTarget_get_target,$(1)) : UNOAPI_REFERENCE := $(SRCDIR)/$(strip $(2)).rdb
-$(call gb_UnoApiTarget_get_target,$(1)) : $(gb_UnoApiTarget_REGCOMPAREDEPS)
+$(call gb_UnoApiTarget_get_target,$(1)) : UNOAPI_REFERENCE := $(foreach rdb,$(2),$(SRCDIR)/$(rdb).rdb)
+$(call gb_UnoApiTarget_get_target,$(1)) : $(foreach rdb,$(2),$(SRCDIR)/$(rdb).rdb)
+$(call gb_UnoApiTarget_get_target,$(1)) : $(gb_UnoApiTarget_UNOIDLCHECKDEPS)
endef
diff --git a/solenv/gbuild/extensions/pre_BuildTools.mk b/solenv/gbuild/extensions/pre_BuildTools.mk
index 76d94d83ff59..2e0c208d4a9b 100644
--- a/solenv/gbuild/extensions/pre_BuildTools.mk
+++ b/solenv/gbuild/extensions/pre_BuildTools.mk
@@ -24,7 +24,6 @@ gb_BUILD_TOOLS = \
javamaker \
makedepend \
propex \
- regcompare \
regmerge \
regview \
rsc \
@@ -35,6 +34,8 @@ gb_BUILD_TOOLS = \
treex \
uiex \
ulfex \
+ unoidl-check \
+ unoidl-write \
xrmex \
$(call gb_Helper_optional_for_host,DESKTOP, \
gengal \
diff --git a/unoidl/Executable_unoidl-check.mk b/unoidl/Executable_unoidl-check.mk
new file mode 100644
index 000000000000..562fba9b8828
--- /dev/null
+++ b/unoidl/Executable_unoidl-check.mk
@@ -0,0 +1,22 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,unoidl-check))
+
+$(eval $(call gb_Executable_add_exception_objects,unoidl-check, \
+ unoidl/source/unoidl-check \
+))
+
+$(eval $(call gb_Executable_use_libraries,unoidl-check, \
+ sal \
+ salhelper \
+ unoidl \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/unoidl/Module_unoidl.mk b/unoidl/Module_unoidl.mk
index 93f816493774..e377ba8162c3 100644
--- a/unoidl/Module_unoidl.mk
+++ b/unoidl/Module_unoidl.mk
@@ -16,6 +16,7 @@ $(eval $(call gb_Module_add_targets,unoidl, \
))
$(eval $(call gb_Module_add_targets_for_build,unoidl, \
+ Executable_unoidl-check \
Executable_unoidl-write \
))
diff --git a/unoidl/source/unoidl-check.cxx b/unoidl/source/unoidl-check.cxx
new file mode 100644
index 000000000000..ff84f52c655c
--- /dev/null
+++ b/unoidl/source/unoidl-check.cxx
@@ -0,0 +1,922 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "sal/config.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <vector>
+
+#include "osl/file.hxx"
+#include "osl/process.h"
+#include "rtl/process.h"
+#include "rtl/ref.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/main.h"
+#include "sal/types.h"
+#include "unoidl/unoidl.hxx"
+
+namespace unoidl {
+
+bool operator ==(ConstantValue const & lhs, ConstantValue const & rhs) {
+ if (lhs.type == rhs.type) {
+ switch (lhs.type) {
+ case ConstantValue::TYPE_BOOLEAN:
+ return lhs.booleanValue == rhs.booleanValue;
+ case ConstantValue::TYPE_BYTE:
+ return lhs.byteValue == rhs.byteValue;
+ case ConstantValue::TYPE_SHORT:
+ return lhs.shortValue == rhs.shortValue;
+ case ConstantValue::TYPE_UNSIGNED_SHORT:
+ return lhs.unsignedShortValue == rhs.unsignedShortValue;
+ case ConstantValue::TYPE_LONG:
+ return lhs.longValue == rhs.longValue;
+ case ConstantValue::TYPE_UNSIGNED_LONG:
+ return lhs.unsignedLongValue == rhs.unsignedLongValue;
+ case ConstantValue::TYPE_HYPER:
+ return lhs.hyperValue == rhs.hyperValue;
+ case ConstantValue::TYPE_UNSIGNED_HYPER:
+ return lhs.unsignedHyperValue == rhs.unsignedHyperValue;
+ case ConstantValue::TYPE_FLOAT:
+ return lhs.floatValue == rhs.floatValue;
+ case ConstantValue::TYPE_DOUBLE:
+ return lhs.doubleValue == rhs.doubleValue;
+ }
+ }
+ return false;
+}
+
+bool operator !=(ConstantValue const & lhs, ConstantValue const & rhs) {
+ return !(lhs == rhs);
+}
+
+bool operator ==(
+ SingleInterfaceBasedServiceEntity::Constructor::Parameter const & lhs,
+ SingleInterfaceBasedServiceEntity::Constructor::Parameter const & rhs)
+{
+ return lhs.name == rhs.name && lhs.type == rhs.type && lhs.rest == rhs.rest;
+}
+
+}
+
+namespace {
+
+void badUsage() {
+ std::cerr
+ << "Usage:" << std::endl << std::endl
+ << (" unoidl-check [<extra registries A>] <registry A> -- [<extra"
+ " registries B>]")
+ << std::endl << " <registry B>" << std::endl << std::endl
+ << ("where each <registry> is either a new- or legacy-format .rdb file,"
+ " a single .idl")
+ << std::endl
+ << ("file, or a root directory of an .idl file tree. Check that each"
+ " entity from")
+ << std::endl
+ << "<registry A> is also present in <registry B> in a compatible form."
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+}
+
+OUString getArgumentUri(sal_uInt32 argument, bool * delimiter) {
+ OUString arg;
+ rtl_getAppCommandArg(argument, &arg.pData);
+ if (arg == "--") {
+ if (delimiter == 0) {
+ badUsage();
+ }
+ *delimiter = true;
+ return OUString();
+ }
+ OUString url;
+ osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
+ if (e1 != osl::FileBase::E_None) {
+ std::cerr
+ << "Cannot convert \"" << arg << "\" to file URL, error code "
+ << +e1 << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ OUString cwd;
+ oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
+ if (e2 != osl_Process_E_None) {
+ std::cerr
+ << "Cannot obtain working directory, error code " << +e2
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ OUString abs;
+ e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
+ if (e1 != osl::FileBase::E_None) {
+ std::cerr
+ << "Cannot make \"" << url
+ << "\" into an absolute file URL, error code " << +e1 << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ return abs;
+}
+
+OUString showDirection(
+ unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction)
+{
+ switch (direction) {
+ case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN:
+ return OUString("[in]");
+ case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT:
+ return OUString("[out]");
+ case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT:
+ return OUString("[inout]");
+ default:
+ assert(false); for (;;) { std::abort(); } // this cannot happen
+ }
+}
+
+void checkMap(
+ rtl::Reference<unoidl::Provider> const & providerB, OUString const & prefix,
+ rtl::Reference<unoidl::MapCursor> const & cursor)
+{
+ assert(providerB.is());
+ assert(cursor.is());
+ for (;;) {
+ OUString id;
+ rtl::Reference<unoidl::Entity> entA(cursor->getNext(&id));
+ if (!entA.is()) {
+ break;
+ }
+ OUString name(prefix + id);
+ if (entA->getSort() == unoidl::Entity::SORT_MODULE) {
+ checkMap(
+ providerB, name + ".",
+ (static_cast<unoidl::ModuleEntity *>(entA.get())
+ ->createCursor()));
+ } else {
+ rtl::Reference<unoidl::Entity> entB(providerB->findEntity(name));
+ if (!entB.is()) {
+ std::cerr
+ << "A entity " << name << " is not present in B"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if (entA->getSort() != entB->getSort()) {
+ std::cerr
+ << "A entity " << name << " is of different sort in B"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if ((dynamic_cast<unoidl::PublishableEntity *>(entA.get())
+ ->isPublished())
+ && (!dynamic_cast<unoidl::PublishableEntity *>(entB.get())
+ ->isPublished()))
+ {
+ std::cerr
+ << "A published entity " << name << " is not published in B"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ switch (entA->getSort()) {
+ case unoidl::Entity::SORT_MODULE:
+ assert(false); // this cannot happen
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ {
+ rtl::Reference<unoidl::EnumTypeEntity> ent2A(
+ static_cast<unoidl::EnumTypeEntity *>(entA.get()));
+ rtl::Reference<unoidl::EnumTypeEntity> ent2B(
+ static_cast<unoidl::EnumTypeEntity *>(entB.get()));
+ if (ent2A->getMembers().size()
+ != ent2B->getMembers().size())
+ {
+ std::cerr
+ << "enum type " << name
+ << " number of members changed from "
+ << ent2A->getMembers().size() << " to "
+ << ent2B->getMembers().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::EnumTypeEntity::Member>::const_iterator
+ i(ent2A->getMembers().begin()),
+ j(ent2B->getMembers().begin());
+ i != ent2A->getMembers().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->value != j->value) {
+ std::cerr
+ << "enum type " << name << " member #"
+ << i - ent2A->getMembers().begin() + 1
+ << " changed from " << i->name << " = "
+ << i->value << " to " << j->name << " = "
+ << j->value << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ {
+ rtl::Reference<unoidl::PlainStructTypeEntity> ent2A(
+ static_cast<unoidl::PlainStructTypeEntity *>(
+ entA.get()));
+ rtl::Reference<unoidl::PlainStructTypeEntity> ent2B(
+ static_cast<unoidl::PlainStructTypeEntity *>(
+ entB.get()));
+ if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
+ std::cerr
+ << "plain struct type " << name
+ << " direct base changed from "
+ << (ent2A->getDirectBase().isEmpty()
+ ? OUString("none") : ent2A->getDirectBase())
+ << " to "
+ << (ent2B->getDirectBase().isEmpty()
+ ? OUString("none") : ent2B->getDirectBase())
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if (ent2A->getDirectMembers().size()
+ != ent2B->getDirectMembers().size())
+ {
+ std::cerr
+ << "plain struct type " << name
+ << " number of direct members changed from "
+ << ent2A->getDirectMembers().size() << " to "
+ << ent2B->getDirectMembers().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::PlainStructTypeEntity::Member>::const_iterator
+ i(ent2A->getDirectMembers().begin()),
+ j(ent2B->getDirectMembers().begin());
+ i != ent2A->getDirectMembers().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->type != j->type) {
+ std::cerr
+ << "plain struct type " << name
+ << " direct member #"
+ << i - ent2A->getDirectMembers().begin() + 1
+ << " changed from " << i->type << " " << i->name
+ << " to " << j->type << " " << j->name
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ {
+ rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
+ ent2A(
+ static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
+ entA.get()));
+ rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity>
+ ent2B(
+ static_cast<unoidl::PolymorphicStructTypeTemplateEntity *>(
+ entB.get()));
+ if (ent2A->getTypeParameters().size()
+ != ent2B->getTypeParameters().size())
+ {
+ std::cerr
+ << "polymorphic struct type template " << name
+ << " number of type parameters changed from "
+ << ent2A->getTypeParameters().size() << " to "
+ << ent2B->getTypeParameters().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<OUString>::const_iterator
+ i(ent2A->getTypeParameters().begin()),
+ j(ent2B->getTypeParameters().begin());
+ i != ent2A->getTypeParameters().end(); ++i, ++j)
+ {
+ if (*i != *j) {
+ std::cerr
+ << "polymorphic struct type template " << name
+ << " type parameter #"
+ << i - ent2A->getTypeParameters().begin() + 1
+ << " changed from " << *i << " to " << *j
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getMembers().size()
+ != ent2B->getMembers().size())
+ {
+ std::cerr
+ << "polymorphic struct type template " << name
+ << " number of members changed from "
+ << ent2A->getMembers().size() << " to "
+ << ent2B->getMembers().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::PolymorphicStructTypeTemplateEntity::Member>::const_iterator
+ i(ent2A->getMembers().begin()),
+ j(ent2B->getMembers().begin());
+ i != ent2A->getMembers().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->type != j->type
+ || i->parameterized != j->parameterized)
+ {
+ std::cerr
+ << "polymorphic struct type template " << name
+ << " member #"
+ << i - ent2A->getMembers().begin() + 1
+ << " changed from "
+ << (i->parameterized
+ ? OUString("parameterized ") : OUString())
+ << i->type << " " << i->name
+ << " to "
+ << (j->parameterized
+ ? OUString("parameterized ") : OUString())
+ << j->type << " " << j->name
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ {
+ rtl::Reference<unoidl::ExceptionTypeEntity> ent2A(
+ static_cast<unoidl::ExceptionTypeEntity *>(entA.get()));
+ rtl::Reference<unoidl::ExceptionTypeEntity> ent2B(
+ static_cast<unoidl::ExceptionTypeEntity *>(entB.get()));
+ if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
+ std::cerr
+ << "exception type " << name
+ << " direct base changed from "
+ << (ent2A->getDirectBase().isEmpty()
+ ? OUString("none") : ent2A->getDirectBase())
+ << " to "
+ << (ent2B->getDirectBase().isEmpty()
+ ? OUString("none") : ent2B->getDirectBase())
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if (ent2A->getDirectMembers().size()
+ != ent2B->getDirectMembers().size())
+ {
+ std::cerr
+ << "exception type " << name
+ << " number of direct members changed from "
+ << ent2A->getDirectMembers().size() << " to "
+ << ent2B->getDirectMembers().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::ExceptionTypeEntity::Member>::const_iterator
+ i(ent2A->getDirectMembers().begin()),
+ j(ent2B->getDirectMembers().begin());
+ i != ent2A->getDirectMembers().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->type != j->type) {
+ std::cerr
+ << "exception type " << name
+ << " direct member #"
+ << i - ent2A->getDirectMembers().begin() + 1
+ << " changed from " << i->type << " " << i->name
+ << " to " << j->type << " " << j->name
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ {
+ rtl::Reference<unoidl::InterfaceTypeEntity> ent2A(
+ static_cast<unoidl::InterfaceTypeEntity *>(entA.get()));
+ rtl::Reference<unoidl::InterfaceTypeEntity> ent2B(
+ static_cast<unoidl::InterfaceTypeEntity *>(entB.get()));
+ if (ent2A->getDirectMandatoryBases().size()
+ != ent2B->getDirectMandatoryBases().size())
+ {
+ std::cerr
+ << "interface type " << name
+ << " number of direct mandatory bases changed from "
+ << ent2A->getDirectMandatoryBases().size() << " to "
+ << ent2B->getDirectMandatoryBases().size()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AnnotatedReference>::const_iterator
+ i(ent2A->getDirectMandatoryBases().begin()),
+ j(ent2B->getDirectMandatoryBases().begin());
+ i != ent2A->getDirectMandatoryBases().end(); ++i, ++j)
+ {
+ if (i->name != j->name) {
+ std::cerr
+ << "interface type " << name
+ << " direct mandatory base #"
+ << (i - ent2A->getDirectMandatoryBases().begin()
+ + 1)
+ << " changed from " << i->name << " to "
+ << j->name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectOptionalBases().size()
+ != ent2B->getDirectOptionalBases().size())
+ {
+ std::cerr
+ << "interface type " << name
+ << " number of direct optional bases changed from "
+ << ent2A->getDirectOptionalBases().size() << " to "
+ << ent2B->getDirectOptionalBases().size()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AnnotatedReference>::const_iterator
+ i(ent2A->getDirectOptionalBases().begin()),
+ j(ent2B->getDirectOptionalBases().begin());
+ i != ent2A->getDirectOptionalBases().end(); ++i, ++j)
+ {
+ if (i->name != j->name) {
+ std::cerr
+ << "interface type " << name
+ << " direct optional base #"
+ << (i - ent2A->getDirectOptionalBases().begin()
+ + 1)
+ << " changed from " << i->name << " to "
+ << j->name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectAttributes().size()
+ != ent2B->getDirectAttributes().size())
+ {
+ std::cerr
+ << "interface type " << name
+ << " number of direct attributes changed from "
+ << ent2A->getDirectAttributes().size() << " to "
+ << ent2B->getDirectAttributes().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator
+ i(ent2A->getDirectAttributes().begin()),
+ j(ent2B->getDirectAttributes().begin());
+ i != ent2A->getDirectAttributes().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->type != j->type
+ || i->bound != j->bound
+ || i->readOnly != j->readOnly
+ || i->getExceptions != j->getExceptions
+ || i->setExceptions != j->setExceptions)
+ {
+ std::cerr
+ << "interface type " << name
+ << " direct attribute #"
+ << i - ent2A->getDirectAttributes().begin() + 1
+ << " changed from "
+ << (i->bound ? OUString("bound ") : OUString())
+ << (i->readOnly
+ ? OUString("read-only ") : OUString())
+ << i->type << " " << i->name //TODO: exceptions
+ << " to "
+ << (j->bound ? OUString("bound ") : OUString())
+ << (j->readOnly
+ ? OUString("read-only ") : OUString())
+ << j->type << " " << j->name //TODO: exceptions
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectMethods().size()
+ != ent2B->getDirectMethods().size())
+ {
+ std::cerr
+ << "interface type " << name
+ << " number of direct methods changed from "
+ << ent2A->getDirectMethods().size() << " to "
+ << ent2B->getDirectMethods().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator
+ i(ent2A->getDirectMethods().begin()),
+ j(ent2B->getDirectMethods().begin());
+ i != ent2A->getDirectMethods().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->returnType != j->returnType
+ || i->exceptions != j->exceptions)
+ {
+ std::cerr
+ << "interface type " << name
+ << " direct method #"
+ << i - ent2A->getDirectMethods().begin() + 1
+ << " changed from "
+ << i->returnType << " " << i->name //TODO: exceptions
+ << " to " << j->returnType << " " << j->name //TODO: exceptions
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if (i->parameters.size() != j->parameters.size()) {
+ std::cerr
+ << "interface type " << name
+ << " direct method " << i->name
+ << " number of parameters changed from "
+ << i->parameters.size() << " to "
+ << j->parameters.size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::const_iterator
+ k(i->parameters.begin()),
+ l(j->parameters.begin());
+ k != i->parameters.end(); ++k, ++l)
+ {
+ if (k->type != l->type || k->direction != l->direction)
+ {
+ std::cerr
+ << "interface type " << name
+ << " direct method " << i->name
+ << " parameter #"
+ << k - i->parameters.begin() + 1
+ << " changed from "
+ << showDirection(k->direction) << " "
+ << k->type << " to "
+ << showDirection(l->direction) << " "
+ << l->type << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if (k->name != l->name) {
+ std::cerr
+ << "Warning: interface type " << name
+ << " direct method " << i->name
+ << " parameter #"
+ << k - i->parameters.begin() + 1
+ << " changed name from " << k->name
+ << " to " << l->name << std::endl;
+ }
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_TYPEDEF:
+ {
+ rtl::Reference<unoidl::TypedefEntity> ent2A(
+ static_cast<unoidl::TypedefEntity *>(entA.get()));
+ rtl::Reference<unoidl::TypedefEntity> ent2B(
+ static_cast<unoidl::TypedefEntity *>(entB.get()));
+ if (ent2A->getType() != ent2B->getType()) {
+ std::cerr
+ << "typedef " << name << " type changed from "
+ << ent2A->getType() << " to " << ent2B->getType()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ {
+ rtl::Reference<unoidl::ConstantGroupEntity> ent2A(
+ static_cast<unoidl::ConstantGroupEntity *>(entA.get()));
+ rtl::Reference<unoidl::ConstantGroupEntity> ent2B(
+ static_cast<unoidl::ConstantGroupEntity *>(entB.get()));
+ for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
+ i(ent2A->getMembers().begin());
+ i != ent2A->getMembers().end(); ++i)
+ {
+ bool found = false;
+ for (std::vector<unoidl::ConstantGroupEntity::Member>::const_iterator
+ j(ent2B->getMembers().begin());
+ j != ent2B->getMembers().end(); ++j)
+ {
+ if (i->name == j->name) {
+ if (i->value != j->value) {
+ std::cerr
+ << "constant group " << name
+ << " member " << i->name
+ << " changed value" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ std::cerr
+ << "A constant group " << name << " member "
+ << i->name << " is not present in B"
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ {
+ rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
+ ent2A(
+ static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
+ entA.get()));
+ rtl::Reference<unoidl::SingleInterfaceBasedServiceEntity>
+ ent2B(
+ static_cast<unoidl::SingleInterfaceBasedServiceEntity *>(
+ entB.get()));
+ if (ent2A->getBase() != ent2B->getBase()) {
+ std::cerr
+ << "single-interface--based servcie " << name
+ << " base changed from " << ent2A->getBase()
+ << " to " << ent2B->getBase()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ if (ent2A->getConstructors().size()
+ != ent2B->getConstructors().size())
+ {
+ std::cerr
+ << "single-interface--based service " << name
+ << " number of constructors changed from "
+ << ent2A->getConstructors().size() << " to "
+ << ent2B->getConstructors().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::SingleInterfaceBasedServiceEntity::Constructor>::const_iterator
+ i(ent2A->getConstructors().begin()),
+ j(ent2B->getConstructors().begin());
+ i != ent2A->getConstructors().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->parameters != j->parameters
+ || i->exceptions != j->exceptions
+ || i->defaultConstructor != j->defaultConstructor)
+ {
+ std::cerr
+ << "single-interface--based service " << name
+ << " constructor #"
+ << i - ent2A->getConstructors().begin() + 1
+ << " changed from "
+ << (i->defaultConstructor
+ ? OUString("default ") : i->name) //TODO: parameters, exceptions
+ << " to "
+ << (j->defaultConstructor
+ ? OUString("default ") : j->name) //TODO: parameters, exceptions
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ {
+ rtl::Reference<unoidl::AccumulationBasedServiceEntity>
+ ent2A(
+ static_cast<unoidl::AccumulationBasedServiceEntity *>(
+ entA.get()));
+ rtl::Reference<unoidl::AccumulationBasedServiceEntity>
+ ent2B(
+ static_cast<unoidl::AccumulationBasedServiceEntity *>(
+ entB.get()));
+ if (ent2A->getDirectMandatoryBaseServices().size()
+ != ent2B->getDirectMandatoryBaseServices().size())
+ {
+ std::cerr
+ << "accumulation-based service " << name
+ << (" number of direct mandatory base services"
+ " changed from ")
+ << ent2A->getDirectMandatoryBaseServices().size()
+ << " to "
+ << ent2B->getDirectMandatoryBaseServices().size()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AnnotatedReference>::const_iterator
+ i(ent2A->getDirectMandatoryBaseServices().begin()),
+ j(ent2B->getDirectMandatoryBaseServices().begin());
+ i != ent2A->getDirectMandatoryBaseServices().end();
+ ++i, ++j)
+ {
+ if (i->name != j->name) {
+ std::cerr
+ << "accumulation-based service " << name
+ << " direct mandatory base service #"
+ << (i
+ - (ent2A->getDirectMandatoryBaseServices()
+ .begin())
+ + 1)
+ << " changed from " << i->name << " to "
+ << j->name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectOptionalBaseServices().size()
+ != ent2B->getDirectOptionalBaseServices().size())
+ {
+ std::cerr
+ << "accumulation-based service " << name
+ << (" number of direct optional base services"
+ " changed from ")
+ << ent2A->getDirectOptionalBaseServices().size()
+ << " to "
+ << ent2B->getDirectOptionalBaseServices().size()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AnnotatedReference>::const_iterator
+ i(ent2A->getDirectOptionalBaseServices().begin()),
+ j(ent2B->getDirectOptionalBaseServices().begin());
+ i != ent2A->getDirectOptionalBaseServices().end();
+ ++i, ++j)
+ {
+ if (i->name != j->name) {
+ std::cerr
+ << "accumulation-based service " << name
+ << " direct optional base service #"
+ << (i
+ - (ent2A->getDirectOptionalBaseServices()
+ .begin())
+ + 1)
+ << " changed from " << i->name << " to "
+ << j->name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectMandatoryBaseInterfaces().size()
+ != ent2B->getDirectMandatoryBaseInterfaces().size())
+ {
+ std::cerr
+ << "accumulation-based service " << name
+ << (" number of direct mandatory base interfaces"
+ " changed from ")
+ << ent2A->getDirectMandatoryBaseInterfaces().size()
+ << " to "
+ << ent2B->getDirectMandatoryBaseInterfaces().size()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AnnotatedReference>::const_iterator
+ i(ent2A->getDirectMandatoryBaseInterfaces()
+ .begin()),
+ j(ent2B->getDirectMandatoryBaseInterfaces()
+ .begin());
+ i != ent2A->getDirectMandatoryBaseInterfaces().end();
+ ++i, ++j)
+ {
+ if (i->name != j->name) {
+ std::cerr
+ << "accumulation-based service " << name
+ << " direct mandatory base interface #"
+ << (i
+ - (ent2A->getDirectMandatoryBaseInterfaces()
+ .begin())
+ + 1)
+ << " changed from " << i->name << " to "
+ << j->name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectOptionalBaseInterfaces().size()
+ != ent2B->getDirectOptionalBaseInterfaces().size())
+ {
+ std::cerr
+ << "accumulation-based service " << name
+ << (" number of direct optional base interfaces"
+ " changed from ")
+ << ent2A->getDirectOptionalBaseInterfaces().size()
+ << " to "
+ << ent2B->getDirectOptionalBaseInterfaces().size()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AnnotatedReference>::const_iterator
+ i(ent2A->getDirectOptionalBaseInterfaces()
+ .begin()),
+ j(ent2B->getDirectOptionalBaseInterfaces()
+ .begin());
+ i != ent2A->getDirectOptionalBaseInterfaces().end();
+ ++i, ++j)
+ {
+ if (i->name != j->name) {
+ std::cerr
+ << "accumulation-based service " << name
+ << " direct optional base interface #"
+ << (i
+ - (ent2A->getDirectOptionalBaseInterfaces()
+ .begin())
+ + 1)
+ << " changed from " << i->name << " to "
+ << j->name << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ if (ent2A->getDirectProperties().size()
+ > ent2B->getDirectProperties().size())
+ {
+ std::cerr
+ << "accumulation-based service " << name
+ << " number of direct properties changed from "
+ << ent2A->getDirectProperties().size() << " to "
+ << ent2B->getDirectProperties().size() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
+ i(ent2A->getDirectProperties().begin()),
+ j(ent2B->getDirectProperties().begin());
+ i != ent2A->getDirectProperties().end(); ++i, ++j)
+ {
+ if (i->name != j->name || i->type != j->type
+ || i->attributes != j->attributes)
+ {
+ std::cerr
+ << "accumulation-based service " << name
+ << " direct property #"
+ << i - ent2A->getDirectProperties().begin() + 1
+ << " changed from "
+ << i->type << " " << i->name //TODO: attributes
+ << " to "
+ << j->type << " " << j->name //TODO: attributes
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ for (std::vector<unoidl::AccumulationBasedServiceEntity::Property>::const_iterator
+ i(ent2B->getDirectProperties().begin()
+ + ent2A->getDirectProperties().size());
+ i != ent2B->getDirectProperties().end(); ++i)
+ {
+ if ((i->attributes & unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL) == 0)
+ {
+ std::cerr
+ << "B accumulation-based service " << name
+ << " additional direct property " << i->name
+ << " is not optional" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ {
+ rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2A(
+ static_cast<unoidl::InterfaceBasedSingletonEntity *>(
+ entA.get()));
+ rtl::Reference<unoidl::InterfaceBasedSingletonEntity> ent2B(
+ static_cast<unoidl::InterfaceBasedSingletonEntity *>(
+ entB.get()));
+ if (ent2A->getBase() != ent2B->getBase()) {
+ std::cerr
+ << "interface-based singleton " << name
+ << " base changed from " << ent2A->getBase()
+ << " to " << ent2B->getBase() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ break;
+ }
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ {
+ rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2A(
+ static_cast<unoidl::ServiceBasedSingletonEntity *>(
+ entA.get()));
+ rtl::Reference<unoidl::ServiceBasedSingletonEntity> ent2B(
+ static_cast<unoidl::ServiceBasedSingletonEntity *>(
+ entB.get()));
+ if (ent2A->getBase() != ent2B->getBase()) {
+ std::cerr
+ << "service-based singleton " << name
+ << " base changed from " << ent2A->getBase()
+ << " to " << ent2B->getBase() << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+}
+
+SAL_IMPLEMENT_MAIN() {
+ try {
+ sal_uInt32 args = rtl_getAppCommandArgCount();
+ rtl::Reference<unoidl::Manager> mgr[2];
+ mgr[0] = new unoidl::Manager;
+ mgr[1] = new unoidl::Manager;
+ rtl::Reference<unoidl::Provider> prov[2];
+ int side = 0;
+ for (sal_uInt32 i = 0; i != args; ++i) {
+ bool delimiter = false;
+ OUString uri(getArgumentUri(i, side == 0 ? &delimiter : 0));
+ if (delimiter) {
+ side = 1;
+ } else {
+ try {
+ prov[side] = unoidl::loadProvider(mgr[side], uri);
+ } catch (unoidl::NoSuchFileException &) {
+ std::cerr
+ << "Input <" << uri << "> does not exist" << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+ mgr[side]->addProvider(prov[side]);
+ }
+ }
+ if (side == 0 || !(prov[0].is() && prov[1].is())) {
+ badUsage();
+ }
+ checkMap(prov[1], "", prov[0]->createRootCursor());
+ return EXIT_SUCCESS;
+ } catch (unoidl::FileFormatException & e1) {
+ std::cerr
+ << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
+ << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */