Kaydet (Commit) 7a9fed14 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

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
üst d9a18176
......@@ -56,6 +56,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
pdf2xml \
pdfunzip \
propex \
reg2bin \
regsvrex \
renewpo \
rsc \
......
This source diff could not be displayed because it is too large. You can view the blob instead.
# -*- 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:
......@@ -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 \
......
/* -*- 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: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment