diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2013-01-31 19:06:09 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2013-01-31 19:09:24 +0100 |
commit | 7a9fed14d45ba99d5639d4cc80286ee146b8d40a (patch) | |
tree | 8e25391af962166faac3dd90e187b1fd5535c6db /registry | |
parent | d9a18176d6b56119aa91699cd3aa102e36a7805c (diff) |
WIP: Experimental new binary type.rdb format
cppuhelper/source/typedescriptionprovider.cxx would read it if it finds .rdb
files in that format.
Throwaway new reg2bin tool for now can translate existing .rdb files into the
new format.
Change-Id: Iacf219c30cfc358c3d31fb0d73966cf2296a4fe5
Diffstat (limited to 'registry')
-rw-r--r-- | registry/Executable_reg2bin.mk | 21 | ||||
-rw-r--r-- | registry/Module_registry.mk | 1 | ||||
-rw-r--r-- | registry/tools/reg2bin.cxx | 1418 |
3 files changed, 1440 insertions, 0 deletions
diff --git a/registry/Executable_reg2bin.mk b/registry/Executable_reg2bin.mk new file mode 100644 index 000000000000..c28770be96ba --- /dev/null +++ b/registry/Executable_reg2bin.mk @@ -0,0 +1,21 @@ +# -*- 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,reg2bin)) + +$(eval $(call gb_Executable_add_exception_objects,reg2bin, \ + registry/tools/reg2bin \ +)) + +$(eval $(call gb_Executable_use_libraries,reg2bin, \ + reg \ + sal \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/registry/Module_registry.mk b/registry/Module_registry.mk index c79100f580cb..0ad522678c7c 100644 --- a/registry/Module_registry.mk +++ b/registry/Module_registry.mk @@ -35,6 +35,7 @@ ifneq (,$(filter DESKTOP,$(BUILD_TYPE))) $(eval $(call gb_Module_add_targets,registry,\ StaticLibrary_registry_helper \ + Executable_reg2bin \ Executable_regmerge \ Executable_regview \ Executable_regcompare \ diff --git a/registry/tools/reg2bin.cxx b/registry/tools/reg2bin.cxx new file mode 100644 index 000000000000..94012cbd675c --- /dev/null +++ b/registry/tools/reg2bin.cxx @@ -0,0 +1,1418 @@ +/* -*- 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 <cstring> +#include <iostream> +#include <map> +#include <utility> +#include <vector> + +#include "osl/file.h" +#include "osl/file.hxx" +#include "osl/process.h" +#include "registry/reader.hxx" +#include "registry/refltype.hxx" +#include "registry/registry.hxx" +#include "registry/regtype.h" +#include "registry/types.h" +#include "registry/version.h" +#include "rtl/process.h" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/textcvt.h" +#include "rtl/ustring.hxx" +#include "sal/main.h" + +namespace { + +rtl::OUString getArgumentUrl(sal_uInt32 argument) { + rtl::OUString arg; + rtl_getAppCommandArg(argument, &arg.pData); + rtl::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 << "\n"; + std::exit(EXIT_FAILURE); + } + rtl::OUString cwd; + oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData); + if (e2 != osl_Process_E_None) { + std::cerr + << "Cannot obtain working directory, error code " << +e2 << "\n"; + std::exit(EXIT_FAILURE); + } + rtl::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 << "\n"; + std::exit(EXIT_FAILURE); + } + return abs; +} + +enum Type { + TYPE_MODULE, + TYPE_ENUM, + TYPE_STRUCT, + TYPE_POLYSTRUCT, + TYPE_EXCEPTION, + TYPE_INTERFACE, + TYPE_TYPEDEF, + TYPE_CONSTANTS, + TYPE_NEWSERVICE, + TYPE_OLDSERVICE, + TYPE_NEWSINGLETON, + TYPE_OLDSINGLETON +}; + +struct Field { + Field(rtl::OUString const & theName, sal_Int32 theValue): + name(theName), value(theValue) {} + + Field(rtl::OUString const & theName, rtl::OUString const & theType): + name(theName), type(theType) {} + + Field( + rtl::OUString const & theName, rtl::OUString const & theType, + bool parameterized): + name(theName), type(theType), bound(parameterized) {} + + Field( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theBound, bool theReadOnly, + std::vector< rtl::OUString > theGetExceptions, + std::vector< rtl::OUString > theSetExceptions): + name(theName), type(theType), bound(theBound), readOnly(theReadOnly), + getExceptions(theGetExceptions), setExceptions(theSetExceptions) {} + + Field( + rtl::OUString const & theName, rtl::OUString const & theType, + sal_Int32 flags): + name(theName), type(theType), value(flags) {} + + rtl::OUString name; + rtl::OUString type; + sal_Int32 value; + bool bound; // aka polymorphic struct type template of parameterized type + bool readOnly; + std::vector< rtl::OUString > getExceptions; + std::vector< rtl::OUString > setExceptions; +}; + +struct Parameter { + Parameter( + rtl::OUString const & theName, rtl::OUString const & theType, + RTParamMode theMode): + name(theName), type(theType), mode(theMode) {} + + rtl::OUString name; + rtl::OUString type; + RTParamMode mode; +}; + +struct Method { + Method( + rtl::OUString const & theName, rtl::OUString const & theReturnType, + std::vector< Parameter > const & theParameters, + std::vector< rtl::OUString > const & theExceptions): + name(theName), returnType(theReturnType), parameters(theParameters), + exceptions(theExceptions) {} + + Method( + rtl::OUString const & theName, + std::vector< Parameter > const & theParameters, + std::vector< rtl::OUString > const & theExceptions): + name(theName), parameters(theParameters), exceptions(theExceptions) {} + + rtl::OUString name; + rtl::OUString returnType; + std::vector< Parameter > parameters; + std::vector< rtl::OUString > exceptions; +}; + +enum ConstantType { + CONSTANT_TYPE_BOOLEAN, + CONSTANT_TYPE_BYTE, + CONSTANT_TYPE_SHORT, + CONSTANT_TYPE_UNSIGNED_SHORT, + CONSTANT_TYPE_LONG, + CONSTANT_TYPE_UNSIGNED_LONG, + CONSTANT_TYPE_HYPER, + CONSTANT_TYPE_UNSIGNED_HYPER, + CONSTANT_TYPE_FLOAT, + CONSTANT_TYPE_DOUBLE +}; + +struct Item { + Type type; + std::map< rtl::OUString, Item > elements; + bool published; + bool deprecated; + std::vector< rtl::OUString > supertypes; + std::vector< rtl::OUString > optionalSupertypes; + std::vector< Field > fields; + std::vector< Method > methods; + std::vector< rtl::OUString > references; + std::vector< rtl::OUString > optionalReferences; + ConstantType constantType; + union { + bool bo; + sal_Int8 by; + sal_Int16 s; + sal_uInt16 us; + sal_Int32 l; + sal_uInt32 ul; + sal_Int64 h; + sal_uInt64 uh; + float f; + double d; + } constantValue; + bool defaultConstructor; + sal_uInt64 nameOffset; + sal_uInt64 dataOffset; +}; + +void insert( + rtl::OUString const & name, Item const & item, + std::map< rtl::OUString, Item > * map) +{ + assert(map != 0); + bool b = map->insert(std::make_pair(name, item)).second; + assert(b); +} + +typereg::Reader getReader(RegistryKey & key, std::vector< char > * buffer) { + assert(buffer != 0); + RegValueType type; + sal_uInt32 size; + RegError e = key.getValueInfo("", &type, &size); + if (e != REG_NO_ERROR) { + std::cerr + << "Cannot get value info about key \"" << key.getName() + << "\" in registry \"" << key.getRegistryName() << "\", error code " + << +e << "\n"; + std::exit(EXIT_FAILURE); + } + if (type != RG_VALUETYPE_BINARY) { + std::cerr + << "Unexpected value type " << +type << " of key \"" + << key.getName() << "\" in registry \"" << key.getRegistryName() + << "\"\n"; + std::exit(EXIT_FAILURE); + } + if (size == 0 + || size > std::numeric_limits< std::vector< char >::size_type >::max()) + { + std::cerr + << "Bad binary value size " << size << " of key \"" << key.getName() + << "\" in registry \"" << key.getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + buffer->resize(static_cast< std::vector< char >::size_type >(size)); + e = key.getValue("", &(*buffer)[0]); + if (e != REG_NO_ERROR) { + std::cerr + << "Cannot get binary value of key \"" << key.getName() + << "\" in registry \"" << key.getRegistryName() << "\", error code " + << +e << "\n"; + std::exit(EXIT_FAILURE); + } + typereg::Reader reader(&(*buffer)[0], size, false, TYPEREG_VERSION_1); + if (!reader.isValid()) { + std::cerr + << "Malformed binary value of key \"" << key.getName() + << "\" in registry \"" << key.getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + return reader; +} + +void setDeprecated(rtl::OUString const & documentation, Item * item) { + assert(item != 0); + item->deprecated = documentation.indexOf("@deprecated") != -1; + //TODO: this check is somewhat crude +} + +void setFlags(typereg::Reader const & reader, Item * item) { + assert(item != 0); + item->published = reader.isPublished(); + setDeprecated(reader.getDocumentation(), item); +} + +void readModule( + std::vector< RegistryKey > & roots, RegistryKey & key, + std::map< rtl::OUString, Item > * map) +{ + RegistryKeyNames names; + RegError e = key.getKeyNames("", names); + if (e != REG_NO_ERROR) { + std::cerr + << "Cannot get sub-key names of \"" << key.getName() + << "\" in registry \"" << roots[0].getRegistryName() + << "\", error code " << +e << "\n"; + std::exit(EXIT_FAILURE); + } + for (sal_uInt32 i = 0; i != names.getLength(); ++i) { + RegistryKey sub; + e = roots[0].openKey(names.getElement(i), sub); + if (e != REG_NO_ERROR) { + std::cerr + << "Cannot get key \"" << names.getElement(i) + << "\" in registry \"" << roots[0].getRegistryName() + << "\", error code " << +e << "\n"; + std::exit(EXIT_FAILURE); + } + std::vector< char > buf; + typereg::Reader reader(getReader(sub, &buf)); + assert(sub.getName().match(key.getName() + "/")); + rtl::OUString name( + sub.getName().copy(key.getName().getLength() + std::strlen("/"))); + switch (reader.getTypeClass()) { + case RT_TYPE_INTERFACE: + { + Item item; + item.type = TYPE_INTERFACE; + setFlags(reader, &item); + sal_uInt16 n = reader.getSuperTypeCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + item.supertypes.push_back( + reader.getSuperTypeName(j).replace('/', '.')); + } + n = reader.getReferenceCount(); // optional base types + for (sal_uInt16 j = 0; j != n; ++j) { + item.optionalSupertypes.push_back( + reader.getReferenceTypeName(j).replace('/', '.')); + } + sal_uInt16 methodCount = reader.getMethodCount(); + n = reader.getFieldCount(); // attributes + for (sal_uInt16 j = 0; j != n; ++j) { + rtl::OUString attrName(reader.getFieldName(j)); + std::vector< rtl::OUString > getExcs; + std::vector< rtl::OUString > setExcs; + for (sal_uInt16 k = 0; k != methodCount; ++k) { + if (reader.getMethodName(k) == attrName) { + switch (reader.getMethodFlags(k)) { + case RT_MODE_ATTRIBUTE_GET: + { + sal_uInt16 m + = reader.getMethodExceptionCount(k); + for (sal_uInt16 l = 0; l != m; ++l) { + getExcs.push_back( + reader. + getMethodExceptionTypeName(k, l). + replace('/', '.')); + } + break; + } + case RT_MODE_ATTRIBUTE_SET: + { + sal_uInt16 m + = reader.getMethodExceptionCount(k); + for (sal_uInt16 l = 0; l != m; ++l) { + setExcs.push_back( + reader. + getMethodExceptionTypeName(k, l). + replace('/', '.')); + } + break; + } + default: + std::cerr + << "Method and attribute with same name \"" + << attrName + << "\" in interface type with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + } + } + RTFieldAccess flags = reader.getFieldFlags(j); + item.fields.push_back( + Field( + attrName, + reader.getFieldTypeName(j).replace('/', '.'), + (flags & RT_ACCESS_BOUND) != 0, + (flags & RT_ACCESS_READONLY) != 0, getExcs, + setExcs)); + } + for (sal_uInt16 j = 0; j != methodCount; ++j) { + RTMethodMode flags = reader.getMethodFlags(j); + if (flags != RT_MODE_ATTRIBUTE_GET + && flags != RT_MODE_ATTRIBUTE_SET) + { + std::vector< Parameter > params; + sal_uInt16 m = reader.getMethodParameterCount(j); + for (sal_uInt16 k = 0; k != m; ++k) { + RTParamMode mode = reader.getMethodParameterFlags( + j, k); + switch (mode) { + case RT_PARAM_IN: + case RT_PARAM_OUT: + case RT_PARAM_INOUT: + break; + default: + std::cerr + << "Unexpected mode " << +mode + << " of parameter \"" + << reader.getMethodParameterName(j, k) + << "\" of method \"" + << reader.getMethodName(j) + << "\" in interface type with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + params.push_back( + Parameter( + reader.getMethodParameterName(j, k), + (reader.getMethodParameterTypeName(j, k). + replace('/', '.')), + mode)); + } + std::vector< rtl::OUString > excs; + m = reader.getMethodExceptionCount(j); + for (sal_uInt16 k = 0; k != m; ++k) { + excs.push_back( + reader.getMethodExceptionTypeName(j, k).replace( + '/', '.')); + } + item.methods.push_back( + Method( + reader.getMethodName(j), + reader.getMethodReturnTypeName(j).replace( + '/', '.'), + params, excs)); + } + } + insert(name, item, map); + break; + } + case RT_TYPE_MODULE: + { + Item item; + item.type = TYPE_MODULE; + readModule(roots, sub, &item.elements); + insert(name, item, map); + break; + } + case RT_TYPE_STRUCT: + { + Item item; + sal_uInt32 n = reader.getReferenceCount(); + if (n == 0) { + item.type = TYPE_STRUCT; + setFlags(reader, &item); + switch (reader.getSuperTypeCount()) { + case 0: + break; + case 1: + item.supertypes.push_back( + reader.getSuperTypeName(0).replace('/', '.')); + break; + default: + std::cerr + << "Unexpected number " + << reader.getSuperTypeCount() + << (" of super-types of plain struct type with key" + " \"") + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + item.fields.push_back( + Field( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'))); + } + } else { + item.type = TYPE_POLYSTRUCT; + setFlags(reader, &item); + if (reader.getSuperTypeCount() != 0) { + std::cerr + << "Unexpected number " + << reader.getSuperTypeCount() + << (" of super-types of polymorphic struct type" + " template with key \"") + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + for (sal_uInt16 j = 0; j != n; ++j) { + item.references.push_back( + reader.getReferenceTypeName(j).replace('/', '.')); + } + n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + item.fields.push_back( + Field( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'), + ((reader.getFieldFlags(j) + & RT_ACCESS_PARAMETERIZED_TYPE) + != 0))); + } + } + insert(name, item, map); + break; + } + case RT_TYPE_ENUM: + { + Item item; + item.type = TYPE_ENUM; + setFlags(reader, &item); + sal_uInt16 n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + RTConstValue v(reader.getFieldValue(j)); + if (v.m_type != RT_TYPE_INT32) { + std::cerr + << "Unexpected type " +v.m_type + << " of value of field \"" << reader.getFieldName(j) + << "\" of enum type with key \"" << sub.getName() + << "\" in registry \"" << roots[0].getRegistryName() + << "\"\n"; + std::exit(EXIT_FAILURE); + } + item.fields.push_back( + Field(reader.getFieldName(j), v.m_value.aLong)); + } + insert(name, item, map); + break; + } + case RT_TYPE_EXCEPTION: + { + Item item; + item.type = TYPE_EXCEPTION; + setFlags(reader, &item); + switch (reader.getSuperTypeCount()) { + case 0: + break; + case 1: + item.supertypes.push_back( + reader.getSuperTypeName(0).replace('/', '.')); + break; + default: + std::cerr + << "Unexpected number " << reader.getSuperTypeCount() + << " of super-types of exception type with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + sal_uInt16 n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + item.fields.push_back( + Field( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace('/', '.'))); + } + insert(name, item, map); + break; + } + case RT_TYPE_TYPEDEF: + { + Item item; + item.type = TYPE_TYPEDEF; + setFlags(reader, &item); + if (reader.getSuperTypeCount() != 1) { + std::cerr + << "Unexpected number " << reader.getSuperTypeCount() + << " of super-types of typedef with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + item.supertypes.push_back( + reader.getSuperTypeName(0).replace('/', '.')); + insert(name, item, map); + break; + } + case RT_TYPE_SERVICE: + { + Item item; + switch (reader.getSuperTypeCount()) { + case 0: + { + item.type = TYPE_OLDSERVICE; + setFlags(reader, &item); + sal_uInt16 n = reader.getReferenceCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + rtl::OUString refName( + reader.getReferenceTypeName(j).replace( + '/', '.')); + switch (reader.getReferenceSort(j)) { + case RT_REF_SUPPORTS: + if ((reader.getReferenceFlags(j) + & RT_ACCESS_OPTIONAL) + != 0) + { + item.optionalSupertypes.push_back(refName); + } else { + item.supertypes.push_back(refName); + } + break; + case RT_REF_EXPORTS: + if ((reader.getReferenceFlags(j) + & RT_ACCESS_OPTIONAL) + != 0) + { + item.optionalReferences.push_back(refName); + } else { + item.references.push_back(refName); + } + break; + default: + std::cerr + << "Unexpected mode " + << +reader.getReferenceSort(j) + << " of reference \"" + << reader.getReferenceTypeName(j) + << "\" in service with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + } + n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + RTFieldAccess acc = reader.getFieldFlags(j); + sal_Int32 v = 0; + if ((acc & RT_ACCESS_READONLY) != 0) { + v |= 0x0010; + } + if ((acc & RT_ACCESS_OPTIONAL) != 0) { + v |= 0x0100; + } + if ((acc & RT_ACCESS_MAYBEVOID) != 0) { + v |= 0x0001; + } + if ((acc & RT_ACCESS_BOUND) != 0) { + v |= 0x0002; + } + if ((acc & RT_ACCESS_CONSTRAINED) != 0) { + v |= 0x0004; + } + if ((acc & RT_ACCESS_TRANSIENT) != 0) { + v |= 0x0008; + } + if ((acc & RT_ACCESS_MAYBEAMBIGUOUS) != 0) { + v |= 0x0020; + } + if ((acc & RT_ACCESS_MAYBEDEFAULT) != 0) { + v |= 0x0040; + } + if ((acc & RT_ACCESS_REMOVEABLE) != 0) { + v |= 0x0080; + } + item.fields.push_back( + Field( + reader.getFieldName(j), + reader.getFieldTypeName(j).replace( + '/', '.'), + acc)); + } + break; + } + case 1: + { + item.type = TYPE_NEWSERVICE; + setFlags(reader, &item); + item.supertypes.push_back( + reader.getSuperTypeName(0).replace('/', '.')); + sal_uInt16 n = reader.getMethodCount(); + if (n == 1 && reader.getMethodFlags(0) == 0 + && reader.getMethodName(0).isEmpty() + && reader.getMethodReturnTypeName(0) == "void" + && reader.getMethodParameterCount(0) == 0 + && reader.getMethodExceptionCount(0) == 0) + { + item.defaultConstructor = true; + } else { + item.defaultConstructor = false; + for (sal_uInt16 j = 0; j != n; ++j) { + if (reader.getMethodFlags(j) != RT_MODE_TWOWAY) + { + std::cerr + << "Unexpected mode " + << +reader.getMethodFlags(j) + << " of constructor \"" + << reader.getMethodName(j) + << "\" in service with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + std::vector< Parameter > params; + sal_uInt16 m = reader.getMethodParameterCount( + j); + for (sal_uInt16 k = 0; k != m; ++k) { + RTParamMode mode + = reader.getMethodParameterFlags(j, k); + if ((mode & ~RT_PARAM_REST) != RT_PARAM_IN) + { + std::cerr + << "Unexpected mode " << +mode + << " of parameter \"" + << reader.getMethodParameterName( + j, k) + << "\" of constructor \"" + << reader.getMethodName(j) + << "\" in service with key \"" + << sub.getName() + << "\" in registry \"" + << roots[0].getRegistryName() + << "\"\n"; + std::exit(EXIT_FAILURE); + } + if ((mode & RT_PARAM_REST) != 0 + && !(m == 1 + && ((reader. + getMethodParameterTypeName( + j, 1)) + == "any"))) + { + std::cerr + << "Bad rest parameter \"" + << reader.getMethodParameterName( + j, k) + << "\" of constructor \"" + << reader.getMethodName(j) + << "\" in service with key \"" + << sub.getName() + << "\" in registry \"" + << roots[0].getRegistryName() + << "\"\n"; + std::exit(EXIT_FAILURE); + } + params.push_back( + Parameter( + reader.getMethodParameterName(j, k), + (reader. + getMethodParameterTypeName(j, k). + replace('/', '.')), + mode)); + } + std::vector< rtl::OUString > excs; + m = reader.getMethodExceptionCount(j); + for (sal_uInt16 k = 0; k != m; ++k) { + excs.push_back( + reader.getMethodExceptionTypeName(j, k). + replace('/', '.')); + } + item.methods.push_back( + Method( + reader.getMethodName(j), params, excs)); + } + } + break; + } + default: + std::cerr + << "Unexpected number " << reader.getSuperTypeCount() + << " of super-types of service with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + insert(name, item, map); + break; + } + case RT_TYPE_SINGLETON: + { + Item item; + if (reader.getSuperTypeCount() != 1) { + std::cerr + << "Unexpected number " << reader.getSuperTypeCount() + << " of super-types of singleton with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + rtl::OUString path("/UCR/" + reader.getSuperTypeName(0)); + RegistryKey key2; + for (std::vector< RegistryKey >::iterator j(roots.begin()); + j != roots.end(); ++j) + { + e = j->openKey(path, key2); + switch (e) { + case REG_NO_ERROR: + { + std::vector< char > buf2; + typereg::Reader reader2(getReader(key2, &buf2)); + switch (reader2.getTypeClass()) { + case RT_TYPE_INTERFACE: + item.type = TYPE_NEWSINGLETON; + goto done; + case RT_TYPE_SERVICE: + item.type = TYPE_OLDSINGLETON; + goto done; + default: + std::cerr + << "Unexpected type class " + << +reader2.getTypeClass() + << " of super-type with key \"" + << key2.getName() << "\" in registry \"" + << j->getRegistryName() + << "\" of singleton with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + break; + } + case REG_KEY_NOT_EXISTS: + break; + default: + std::cerr + << "Cannot get key \"" << path + << "\" in registry \"" << j->getRegistryName() + << "\", error code " << +e << "\n"; + std::exit(EXIT_FAILURE); + } + } + std::cerr + << "Unknown super-type with key \"" << path + << "\" of singleton with key \"" << sub.getName() + << "\" in registry \"" << roots[0].getRegistryName() + << "\"\n"; + std::exit(EXIT_FAILURE); + done: + setFlags(reader, &item); + item.supertypes.push_back( + reader.getSuperTypeName(0).replace('/', '.')); + insert(name, item, map); + break; + } + case RT_TYPE_CONSTANTS: + { + Item item; + item.type = TYPE_CONSTANTS; + setFlags(reader, &item); + sal_uInt16 n = reader.getFieldCount(); + for (sal_uInt16 j = 0; j != n; ++j) { + Item item2; + setDeprecated(reader.getFieldDocumentation(j), &item2); + RTConstValue v(reader.getFieldValue(j)); + switch (v.m_type) { + case RT_TYPE_BOOL: + item2.constantType = CONSTANT_TYPE_BOOLEAN; + item2.constantValue.bo = v.m_value.aBool; + break; + case RT_TYPE_BYTE: + item2.constantType = CONSTANT_TYPE_BYTE; + item2.constantValue.by = v.m_value.aByte; + break; + case RT_TYPE_INT16: + item2.constantType = CONSTANT_TYPE_SHORT; + item2.constantValue.s = v.m_value.aShort; + break; + case RT_TYPE_UINT16: + item2.constantType = CONSTANT_TYPE_UNSIGNED_SHORT; + item2.constantValue.us = v.m_value.aUShort; + break; + case RT_TYPE_INT32: + item2.constantType = CONSTANT_TYPE_LONG; + item2.constantValue.l = v.m_value.aLong; + break; + case RT_TYPE_UINT32: + item2.constantType = CONSTANT_TYPE_UNSIGNED_LONG; + item2.constantValue.ul = v.m_value.aULong; + break; + case RT_TYPE_INT64: + item2.constantType = CONSTANT_TYPE_HYPER; + item2.constantValue.h = v.m_value.aHyper; + break; + case RT_TYPE_UINT64: + item2.constantType = CONSTANT_TYPE_UNSIGNED_HYPER; + item2.constantValue.uh = v.m_value.aUHyper; + break; + case RT_TYPE_FLOAT: + item2.constantType = CONSTANT_TYPE_FLOAT; + item2.constantValue.f = v.m_value.aFloat; + break; + case RT_TYPE_DOUBLE: + item2.constantType = CONSTANT_TYPE_DOUBLE; + item2.constantValue.d = v.m_value.aDouble; + break; + default: + std::cerr + << "Unexpected type " +v.m_type + << " of value of field \"" << reader.getFieldName(j) + << "\" of constant group with key \"" + << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + insert(reader.getFieldName(j), item2, &item.elements); + } + insert(name, item, map); + break; + } + default: + std::cerr + << "Unexpected type class " << +reader.getTypeClass() + << " of key \"" << sub.getName() << "\" in registry \"" + << roots[0].getRegistryName() << "\"\n"; + std::exit(EXIT_FAILURE); + } + } +} + +sal_uInt64 getOffset(osl::File & file) { + sal_uInt64 off; + osl::FileBase::RC e = file.getPos(off); + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot determine current position in \"" << file.getURL() + << "\", error code " << +e << "\n"; + std::exit(EXIT_FAILURE); + } + return off; +} + +void write(osl::File & file, void const * buffer, sal_uInt64 size) { + sal_uInt64 n; + osl::FileBase::RC e = file.write(buffer, size, n); + if (e != osl::FileBase::E_None) { + std::cerr + << "Cannot write to \"" << file.getURL() << "\", error code " << +e + << "\n"; + std::exit(EXIT_FAILURE); + } + if (n != size) { + std::cerr + << "Bad write of " << n << " instead of " << size << " bytes to \"" + << file.getURL() << "\"\n"; + std::exit(EXIT_FAILURE); + } +} + +void write8(osl::File & file, sal_uInt64 value) { + if (value > 0xFF) { + std::cerr << "Cannot write value >= 2^8; input is too large\n"; + std::exit(EXIT_FAILURE); + } + unsigned char buf = value & 0xFF; + write(file, &buf, 1); +} + +void write16(osl::File & file, sal_uInt64 value) { + if (value > 0xFFFF) { + std::cerr << "Cannot write value >= 2^16; input is too large\n"; + std::exit(EXIT_FAILURE); + } + unsigned char buf[2]; + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + write(file, buf, 2); +} + +void write32(osl::File & file, sal_uInt64 value) { + if (value > 0xFFFFFFFF) { + std::cerr << "Cannot write value >= 2^32; input is too large\n"; + std::exit(EXIT_FAILURE); + } + unsigned char buf[4]; + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + buf[2] = (value >> 16) & 0xFF; + buf[3] = (value >> 24) & 0xFF; + write(file, buf, 4); +} + +void write64(osl::File & file, sal_uInt64 value) { + unsigned char buf[8]; + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + buf[2] = (value >> 16) & 0xFF; + buf[3] = (value >> 24) & 0xFF; + buf[3] = (value >> 32) & 0xFF; + buf[3] = (value >> 40) & 0xFF; + buf[3] = (value >> 48) & 0xFF; + buf[3] = (value >> 56) & 0xFF; + write(file, buf, 8); +} + +rtl::OString toAscii(rtl::OUString const & name) { + rtl::OString ascii; + if (!name.convertToString( + &ascii, RTL_TEXTENCODING_ASCII_US, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::cerr << "Cannot convert \"" << name << "\" to US ASCII\n"; + std::exit(EXIT_FAILURE); + } + return ascii; +} + +sal_uInt64 writeNameNul(osl::File & file, rtl::OUString const & name) { + rtl::OString ascii(toAscii(name)); + if (ascii.indexOf('\0') != -1) { + std::cerr << "Name \"" << ascii << "\" contains NUL characters\n"; + std::exit(EXIT_FAILURE); + } + sal_uInt64 off = getOffset(file); + write(file, ascii.getStr(), ascii.getLength() + 1); + return off; +} + +void writeNameLen(osl::File & file, rtl::OUString const & name) { + rtl::OString ascii(toAscii(name)); + write32(file, name.getLength()); + write(file, ascii.getStr(), ascii.getLength()); +} + +void writeType(osl::File & file, Item const & item, bool flag = false) { + assert(item.type != TYPE_MODULE); + sal_uInt64 v = item.type; + if (item.published) { + v |= 0x80; + } + if (item.deprecated) { + v |= 0x40; + } + if (flag) { + v |= 0x20; + } + write8(file, v); +} + +sal_uInt64 writeMap( + osl::File & file, std::map< rtl::OUString, Item > & map, bool root) +{ + for (std::map< rtl::OUString, Item >::iterator i(map.begin()); + i != map.end(); ++i) + { + switch (i->second.type) { + case TYPE_MODULE: + i->second.dataOffset = writeMap(file, i->second.elements, false); + break; + case TYPE_ENUM: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + write32(file, i->second.fields.size()); + for (std::vector< Field >::const_iterator j( + i->second.fields.begin()); + j != i->second.fields.end(); ++j) + { + writeNameLen(file, j->name); + write32(file, static_cast< sal_uInt32 >(j->value)); + } + break; + case TYPE_STRUCT: + case TYPE_EXCEPTION: + i->second.dataOffset = getOffset(file); + writeType(file, i->second, !i->second.supertypes.empty()); + if (!i->second.supertypes.empty()) { + writeNameLen(file, i->second.supertypes[0]); + } + write32(file, i->second.fields.size()); + for (std::vector< Field >::const_iterator j( + i->second.fields.begin()); + j != i->second.fields.end(); ++j) + { + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + case TYPE_POLYSTRUCT: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + write32(file, i->second.references.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.references.begin()); + j != i->second.references.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.fields.size()); + for (std::vector< Field >::const_iterator j( + i->second.fields.begin()); + j != i->second.fields.end(); ++j) + { + sal_uInt64 f = 0; + if (j->bound) { + f |= 0x01; + } + write8(file, f); + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + case TYPE_INTERFACE: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + write32(file, i->second.supertypes.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.supertypes.begin()); + j != i->second.supertypes.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.optionalSupertypes.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.optionalSupertypes.begin()); + j != i->second.optionalSupertypes.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.fields.size()); + for (std::vector< Field >::const_iterator j( + i->second.fields.begin()); + j != i->second.fields.end(); ++j) + { + sal_uInt64 f = 0; + if (j->bound) { + f |= 0x01; + } + if (!j->readOnly) { + f |= 0x02; + } + write8(file, f); + writeNameLen(file, j->name); + writeNameLen(file, j->type); + write32(file, j->getExceptions.size()); + for (std::vector< rtl::OUString >::const_iterator k( + j->getExceptions.begin()); + k != j->getExceptions.end(); ++k) + { + writeNameLen(file, *k); + } + if (!j->readOnly) { + write32(file, j->setExceptions.size()); + for (std::vector< rtl::OUString >::const_iterator k( + j->setExceptions.begin()); + k != j->setExceptions.end(); ++k) + { + writeNameLen(file, *k); + } + } + } + write32(file, i->second.methods.size()); + for (std::vector< Method >::const_iterator j( + i->second.methods.begin()); + j != i->second.methods.end(); ++j) + { + writeNameLen(file, j->name); + writeNameLen(file, j->returnType); + write32(file, j->parameters.size()); + for (std::vector< Parameter >::const_iterator k( + j->parameters.begin()); + k != j->parameters.end(); ++k) + { + sal_uInt64 f; + switch (k->mode) { + case RT_PARAM_IN: + f = 0; + break; + case RT_PARAM_OUT: + f = 1; + break; + case RT_PARAM_INOUT: + f = 2; + break; + default: + std::abort(); // this cannot happen + } + write8(file, f); + writeNameLen(file, k->name); + writeNameLen(file, k->type); + } + write32(file, j->exceptions.size()); + for (std::vector< rtl::OUString >::const_iterator k( + j->exceptions.begin()); + k != j->exceptions.end(); ++k) + { + writeNameLen(file, *k); + } + } + break; + case TYPE_TYPEDEF: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + assert(i->second.supertypes.size() == 1); + writeNameLen(file, i->second.supertypes[0]); + break; + case TYPE_CONSTANTS: + for (std::map< rtl::OUString, Item >::iterator j( + i->second.elements.begin()); + j != i->second.elements.end(); ++j) + { + j->second.dataOffset = getOffset(file); + sal_uInt64 v = j->second.constantType; + if (j->second.deprecated) { + v |= 0x80; + } + write8(file, v); + switch (j->second.constantType) { + case CONSTANT_TYPE_BOOLEAN: + write8(file, j->second.constantValue.bo ? 1 : 0); + break; + case CONSTANT_TYPE_BYTE: + write8( + file, + static_cast< sal_uInt8 >(j->second.constantValue.by)); + break; + case CONSTANT_TYPE_SHORT: + write16( + file, + static_cast< sal_uInt16 >(j->second.constantValue.s)); + break; + case CONSTANT_TYPE_UNSIGNED_SHORT: + write16(file, j->second.constantValue.us); + break; + case CONSTANT_TYPE_LONG: + write32( + file, + static_cast< sal_uInt32 >(j->second.constantValue.l)); + break; + case CONSTANT_TYPE_UNSIGNED_LONG: + write32(file, j->second.constantValue.ul); + break; + case CONSTANT_TYPE_HYPER: + write64( + file, + static_cast< sal_uInt64 >(j->second.constantValue.h)); + break; + case CONSTANT_TYPE_UNSIGNED_HYPER: + write64(file, j->second.constantValue.uh); + break; + case CONSTANT_TYPE_FLOAT: + write32( + file, + *reinterpret_cast< sal_uInt32 const * >( + &j->second.constantValue.f)); + break; + case CONSTANT_TYPE_DOUBLE: + write64( + file, + *reinterpret_cast< sal_uInt64 const * >( + &j->second.constantValue.d)); + break; + default: + std::abort(); // this cannot happen + } + } + for (std::map< rtl::OUString, Item >::iterator j( + i->second.elements.begin()); + j != i->second.elements.end(); ++j) + { + j->second.nameOffset = writeNameNul(file, j->first); + } + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + write32(file, i->second.elements.size()); + // overflow from std::map::size_type -> sal_uInt64 is + // unrealistic + for (std::map< rtl::OUString, Item >::iterator j( + i->second.elements.begin()); + j != i->second.elements.end(); ++j) + { + write32(file, j->second.nameOffset); + write32(file, j->second.dataOffset); + } + break; + case TYPE_NEWSERVICE: + i->second.dataOffset = getOffset(file); + writeType(file, i->second, i->second.defaultConstructor); + assert(i->second.supertypes.size() == 1); + writeNameLen(file, i->second.supertypes[0]); + if (!i->second.defaultConstructor) { + write32(file, i->second.methods.size()); + for (std::vector< Method >::const_iterator j( + i->second.methods.begin()); + j != i->second.methods.end(); ++j) + { + writeNameLen(file, j->name); + write32(file, j->parameters.size()); + for (std::vector< Parameter >::const_iterator k( + j->parameters.begin()); + k != j->parameters.end(); ++k) + { + sal_uInt64 f = 0; + if ((k->mode & RT_PARAM_REST) != 0) { + f |= 0x04; + } + write8(file, f); + writeNameLen(file, k->name); + writeNameLen(file, k->type); + } + write32(file, j->exceptions.size()); + for (std::vector< rtl::OUString >::const_iterator k( + j->exceptions.begin()); + k != j->exceptions.end(); ++k) + { + writeNameLen(file, *k); + } + } + } + break; + case TYPE_OLDSERVICE: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + write32(file, i->second.references.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.references.begin()); + j != i->second.references.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.optionalReferences.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.optionalReferences.begin()); + j != i->second.optionalReferences.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.supertypes.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.supertypes.begin()); + j != i->second.supertypes.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.optionalSupertypes.size()); + for (std::vector< rtl::OUString >::const_iterator j( + i->second.optionalSupertypes.begin()); + j != i->second.optionalSupertypes.end(); ++j) + { + writeNameLen(file, *j); + } + write32(file, i->second.fields.size()); + for (std::vector< Field >::const_iterator j( + i->second.fields.begin()); + j != i->second.fields.end(); ++j) + { + write16(file, static_cast< sal_uInt16 >(j->value)); + writeNameLen(file, j->name); + writeNameLen(file, j->type); + } + break; + case TYPE_NEWSINGLETON: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + assert(i->second.supertypes.size() == 1); + writeNameLen(file, i->second.supertypes[0]); + break; + case TYPE_OLDSINGLETON: + i->second.dataOffset = getOffset(file); + writeType(file, i->second); + assert(i->second.supertypes.size() == 1); + writeNameLen(file, i->second.supertypes[0]); + break; + } + } + for (std::map< rtl::OUString, Item >::iterator i(map.begin()); + i != map.end(); ++i) + { + i->second.nameOffset = writeNameNul(file, i->first); + } + sal_uInt64 off = getOffset(file); + if (!root) { + write8(file, 0); // TYPE_MODULE + write32(file, map.size()); + // overflow from std::map::size_type -> sal_uInt64 is unrealistic + } + for (std::map< rtl::OUString, Item >::iterator i(map.begin()); + i != map.end(); ++i) + { + write32(file, i->second.nameOffset); + write32(file, i->second.dataOffset); + } + return off; +} + +} + +SAL_IMPLEMENT_MAIN() { + sal_uInt32 args = rtl_getAppCommandArgCount(); + if (args < 2) { + std::cerr + << ("Usage: reg2bin <.bin file> <.rdb file> <additional .rdb files>" + "\n"); + std::exit(EXIT_FAILURE); + } + std::vector< RegistryKey > roots; + for (sal_uInt32 i = 1; i != args; ++i) { + rtl::OUString url(getArgumentUrl(i)); + Registry reg; + RegError e = reg.open(url, REG_READONLY); + if (e != REG_NO_ERROR) { + std::cerr + << "Cannot open registry \"" << url << "\", error code " << +e + << "\n"; + std::exit(EXIT_FAILURE); + } + RegistryKey root; + e = reg.openRootKey(root); + if (e != REG_NO_ERROR) { + std::cerr + << "Cannot get root key of registry \"" << url + << "\", error code " << +e << "\n"; + std::exit(EXIT_FAILURE); + } + roots.push_back(root); + } + RegistryKey ucr; + RegError e1 = roots[0].openKey("UCR", ucr); + if (e1 != REG_NO_ERROR) { + std::cerr + << "Cannot get /UCR key of registry \"" + << roots[0].getRegistryName() << "\", error code " << +e1 << "\n"; + std::exit(EXIT_FAILURE); + } + std::map< rtl::OUString, Item > map; + readModule(roots, ucr, &map); + osl::File f(getArgumentUrl(0)); + osl::FileBase::RC e2 = f.open(osl_File_OpenFlag_Write); + if (e2 == osl::FileBase::E_NOENT) { + e2 = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create); + } + if (e2 != osl::FileBase::E_None) { + std::cerr + << "Cannot open \"" << f.getURL() << "\" for writing, error code " + << +e2 << "\n"; + std::exit(EXIT_FAILURE); + } + write(f, "UNOIDL\0\xFF", 8); + write32(f, 0); // root map offset + write32(f, 0); // root map size + sal_uInt64 off = writeMap(f, map, true); + e2 = f.setPos(osl_Pos_Absolut, 8); + if (e2 != osl::FileBase::E_None) { + std::cerr + << "Cannot rewind current position in \"" << f.getURL() + << "\", error code " << +e2 << "\n"; + std::exit(EXIT_FAILURE); + } + write32(f, off); + write32(f, map.size()); + // overflow from std::map::size_type -> sal_uInt64 is unrealistic + e2 = f.close(); + if (e2 != osl::FileBase::E_None) { + std::cerr + << "Cannot close \"" << f.getURL() + << "\" after writing, error code " << +e2 << "\n"; + std::exit(EXIT_FAILURE); + } + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |