INTEGRATION: CWS sb83 (1.39.26); FILE MERGED

2008/01/29 14:35:32 sb 1.39.26.3: #i84200# link files are always in UTF-8
2008/01/07 15:28:07 sb 1.39.26.2: #i84985# new (for now internal-only) feature of INIFILEPATH (similar to INIFILENAME, but a system path and not a URL)
2007/12/18 15:36:49 sb 1.39.26.1: #i84200# Refactored expandMacros so that I could add support for a ${.link:...} hack to simulate symbolic links under Windows.
This commit is contained in:
Vladimir Glazounov
2008-03-18 12:17:51 +00:00
parent cae424b883
commit 4a415c4c5a
+234 -16
View File
@@ -4,9 +4,9 @@
*
* $RCSfile: bootstrap.cxx,v $
*
* $Revision: 1.39 $
* $Revision: 1.40 $
*
* last change: $Author: vg $ $Date: 2007-10-15 12:50:42 $
* last change: $Author: vg $ $Date: 2008-03-18 13:17:51 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -54,6 +54,7 @@
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#include <osl/profile.hxx>
#ifndef _RTL_ALLOC_H_
#include <rtl/alloc.h>
@@ -61,6 +62,7 @@
#ifndef _RTL_STRING_HXX_
#include <rtl/string.hxx>
#endif
#include <rtl/ustrbuf.hxx>
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
@@ -70,6 +72,8 @@
#ifndef INCLUDED_RTL_INSTANCE_HXX
#include <rtl/instance.hxx>
#endif
#include <rtl/malformeduriexception.hxx>
#include <rtl/uri.hxx>
#ifndef INCLUDED_RTL_ALLOCATOR_HXX
#include "rtl/allocator.hxx"
@@ -89,6 +93,8 @@ using rtl::OString;
using rtl::OUString;
using rtl::OUStringToOString;
struct Bootstrap_Impl;
namespace {
static char const URE_BOOTSTRAP[] = "URE_BOOTSTRAP";
@@ -114,6 +120,16 @@ private:
struct FundamentalIni: public rtl::Static< FundamentalIniData, FundamentalIni >
{};
struct ExpandRequestLink {
ExpandRequestLink const * next;
Bootstrap_Impl const * file;
rtl::OUString key;
};
rtl::OUString expandMacros(
Bootstrap_Impl const * file, rtl::OUString const & text,
ExpandRequestLink const * requestStack);
}
//----------------------------------------------------------------------------
@@ -237,8 +253,28 @@ static OUString & getIniFileName_Impl()
{
OUString fileName;
OUString sVarName(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME"));
if(!getFromCommandLineArgs(&fileName.pData, sVarName.pData))
if(getFromCommandLineArgs(
&fileName.pData,
OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")).pData))
{
// do nothing
}
else if(getFromCommandLineArgs(
&fileName.pData,
OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILEPATH")).pData))
{
OUString url;
if (osl::FileBase::getFileURLFromSystemPath(fileName, url) ==
osl::FileBase::E_None)
{
fileName = url;
}
else
{
fileName = OUString();
}
}
else
{
getExecutableFile_Impl (&(fileName.pData));
@@ -348,7 +384,7 @@ struct Bootstrap_Impl
static void operator delete (void * p , std::size_t) SAL_THROW(())
{ rtl_freeMemory (p); }
sal_Bool getValue( rtl_uString * pName, rtl_uString ** ppValue, rtl_uString * pDefault, bool recursive ) const;
sal_Bool getValue( rtl_uString * pName, rtl_uString ** ppValue, rtl_uString * pDefault, bool recursive, ExpandRequestLink const * requestStack ) const;
};
//----------------------------------------------------------------------------
@@ -430,13 +466,14 @@ Bootstrap_Impl::~Bootstrap_Impl()
sal_Bool Bootstrap_Impl::getValue(
rtl_uString * pName, rtl_uString ** ppValue, rtl_uString * pDefault,
bool recursive ) const
bool recursive, ExpandRequestLink const * requestStack ) const
{
// lookup this ini
sal_Bool result = sal_True;
bool further_macro_expansion = true;
OUString const & name = *reinterpret_cast< OUString const * >( &pName );
ExpandRequestLink link = { requestStack, this, name };
if (name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_CPPU_ENV") ))
{
#define MSTR_(x) # x
@@ -505,7 +542,7 @@ sal_Bool Bootstrap_Impl::getValue(
EnsureNoFinalSlash(ppValue);
further_macro_expansion = false;
}
else if (!recursive && _base_ini && (_base_ini->getValue(pName, ppValue, NULL, true)))
else if (!recursive && _base_ini && (_base_ini->getValue(pName, ppValue, NULL, true, &link)))
{
further_macro_expansion = false;
}
@@ -526,7 +563,7 @@ sal_Bool Bootstrap_Impl::getValue(
FundamentalIniData & d = FundamentalIni::get();
if (d.ini != NULL && d.ini != this) {
if (static_cast< Bootstrap_Impl * >(d.ini)->
getValue(pName, ppValue, NULL, true))
getValue(pName, ppValue, NULL, true, &link))
{
further_macro_expansion = false;
} else {
@@ -559,8 +596,7 @@ sal_Bool Bootstrap_Impl::getValue(
if (further_macro_expansion)
{
OUString val = expandMacros(
static_cast< rtlBootstrapHandle >( const_cast< Bootstrap_Impl * >( this ) ),
OUString::unacquired(ppValue) );
this, OUString::unacquired(ppValue), &link );
rtl_uString_assign( ppValue, val.pData );
}
}
@@ -749,7 +785,7 @@ sal_Bool SAL_CALL rtl_bootstrap_get_from_handle (
if (handle == 0)
handle = get_static_bootstrap_handle();
found = static_cast< Bootstrap_Impl * >( handle )->getValue(
pName, ppValue, pDefault, false );
pName, ppValue, pDefault, false, NULL );
}
return found;
@@ -841,8 +877,12 @@ void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
rtl_uString ** macro
) SAL_THROW_EXTERN_C()
{
OUString expanded( expandMacros( handle,
* reinterpret_cast< OUString const * >( macro ) ) );
if (handle == NULL) {
handle = get_static_bootstrap_handle();
}
OUString expanded( expandMacros( static_cast< Bootstrap_Impl * >( handle ),
* reinterpret_cast< OUString const * >( macro ),
NULL ) );
rtl_uString_assign( macro, expanded.pData );
}
@@ -852,9 +892,187 @@ void SAL_CALL rtl_bootstrap_expandMacros(
rtl_uString ** macro )
SAL_THROW_EXTERN_C()
{
OUString expanded( expandMacros( get_static_bootstrap_handle(),
* reinterpret_cast< OUString const * >( macro ) ) );
rtl_uString_assign( macro, expanded.pData );
rtl_bootstrap_expandMacros_from_handle(NULL, macro);
}
//----------------------------------------------------------------------------
namespace {
int hex(sal_Unicode c) {
return
c >= '0' && c <= '9' ? c - '0' :
c >= 'A' && c <= 'F' ? c - 'A' + 10 :
c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
}
sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) {
OSL_ASSERT(
pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL);
sal_Unicode c = text[(*pos)++];
if (c == '\\') {
int n1, n2, n3, n4;
if (*pos < text.getLength() - 4 && text[*pos] == 'u' &&
((n1 = hex(text[*pos + 1])) >= 0) &&
((n2 = hex(text[*pos + 2])) >= 0) &&
((n3 = hex(text[*pos + 3])) >= 0) &&
((n4 = hex(text[*pos + 4])) >= 0))
{
*pos += 5;
*escaped = true;
return static_cast< sal_Unicode >(
(n1 << 12) | (n2 << 8) | (n3 << 4) | n4);
} else if (*pos < text.getLength()) {
*escaped = true;
return text[(*pos)++];
}
}
*escaped = false;
return c;
}
rtl::OUString lookup(
Bootstrap_Impl const * file, rtl::OUString const & key,
ExpandRequestLink const * requestStack)
{
OSL_ASSERT(file != NULL);
for (; requestStack != NULL; requestStack = requestStack->next) {
if (requestStack->file == file && requestStack->key == key) {
return rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***"));
}
}
rtl::OUString v;
file->getValue(key.pData, &v.pData, NULL, false, requestStack);
return v;
}
rtl::OUString expandMacros(
Bootstrap_Impl const * file, rtl::OUString const & text,
ExpandRequestLink const * requestStack)
{
rtl::OUStringBuffer buf;
for (sal_Int32 i = 0; i < text.getLength();) {
bool escaped;
sal_Unicode c = read(text, &i, &escaped);
if (escaped || c != '$') {
buf.append(c);
} else {
if (i < text.getLength() && text[i] == '{') {
++i;
sal_Int32 p = i;
sal_Int32 nesting = 0;
rtl::OUString seg[3];
int n = 0;
while (i < text.getLength()) {
sal_Int32 j = i;
c = read(text, &i, &escaped);
if (!escaped) {
switch (c) {
case '{':
++nesting;
break;
case '}':
if (nesting == 0) {
seg[n++] = text.copy(p, j - p);
goto done;
} else {
--nesting;
}
break;
case ':':
if (nesting == 0 && n < 2) {
seg[n++] = text.copy(p, j - p);
p = i;
}
break;
}
}
}
done:
for (int j = 0; j < n; ++j) {
seg[j] = expandMacros(file, seg[j], requestStack);
}
if (n == 3 && seg[1].getLength() == 0) {
// For backward compatibility, treat ${file::key} the same
// as just ${file:key}:
seg[1] = seg[2];
n = 2;
}
if (n == 1) {
buf.append(lookup(file, seg[0], requestStack));
} else if (n == 2) {
if (seg[0].equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM(".link")))
{
osl::File f(seg[1]);
rtl::ByteSequence seq;
rtl::OUString line;
rtl::OUString url;
// Silently ignore any errors (is that good?):
if (f.open(OpenFlag_Read) == osl::FileBase::E_None &&
f.readLine(seq) == osl::FileBase::E_None &&
rtl_convertStringToUString(
&line.pData,
reinterpret_cast< char const * >(
seq.getConstArray()),
seq.getLength(), RTL_TEXTENCODING_UTF8,
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) &&
(osl::File::getFileURLFromSystemPath(line, url) ==
osl::FileBase::E_None))
{
try {
buf.append(
rtl::Uri::convertRelToAbs(seg[1], url));
} catch (rtl::MalformedUriException &) {}
}
} else {
rtl::Bootstrap b(seg[0]);
Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >(
b.getHandle());
// Silently ignore bootstrap files that cannot be opened
// (is that good?):
if (f != NULL) {
buf.append(lookup(f, seg[1], requestStack));
}
}
} else {
// Going through osl::Profile, this code erroneously does
// not recursively expand macros in the resulting
// replacement text (and if it did, it would fail to detect
// cycles that pass through here):
buf.append(
rtl::OStringToOUString(
osl::Profile(seg[0]).readString(
rtl::OUStringToOString(
seg[1], RTL_TEXTENCODING_UTF8),
rtl::OUStringToOString(
seg[2], RTL_TEXTENCODING_UTF8),
rtl::OString()),
RTL_TEXTENCODING_UTF8));
}
} else {
rtl::OUStringBuffer kbuf;
for (; i < text.getLength();) {
sal_Int32 j = i;
c = read(text, &j, &escaped);
if (!escaped &&
(c == ' ' || c == '$' || c == '-' || c == '/' ||
c == ';' || c == '\\'))
{
break;
}
kbuf.append(c);
i = j;
}
buf.append(
lookup(file, kbuf.makeStringAndClear(), requestStack));
}
}
}
return buf.makeStringAndClear();
}
}