LCOV - code coverage report
Current view: top level - sal/rtl/source - bootstrap.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 271 324 83.6 %
Date: 2012-08-25 Functions: 37 41 90.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 287 500 57.4 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include "boost/noncopyable.hpp"
      31                 :            : #include "rtl/bootstrap.h"
      32                 :            : #include "rtl/bootstrap.hxx"
      33                 :            : #include <osl/diagnose.h>
      34                 :            : #include <osl/module.h>
      35                 :            : #include <osl/process.h>
      36                 :            : #include <osl/file.hxx>
      37                 :            : #include <osl/mutex.hxx>
      38                 :            : #include <osl/profile.hxx>
      39                 :            : #include <osl/security.hxx>
      40                 :            : #include <rtl/alloc.h>
      41                 :            : #include <rtl/string.hxx>
      42                 :            : #include <rtl/ustrbuf.hxx>
      43                 :            : #include <rtl/ustring.hxx>
      44                 :            : #include <rtl/byteseq.hxx>
      45                 :            : #include <rtl/instance.hxx>
      46                 :            : #include <rtl/malformeduriexception.hxx>
      47                 :            : #include <rtl/uri.hxx>
      48                 :            : #include "rtl/allocator.hxx"
      49                 :            : 
      50                 :            : #include <algorithm>
      51                 :            : #include <map>
      52                 :            : #include <memory>
      53                 :            : #include <utility>
      54                 :            : 
      55                 :            : #ifdef IOS
      56                 :            : #include <premac.h>
      57                 :            : #import <Foundation/Foundation.h>
      58                 :            : #include <postmac.h>
      59                 :            : #endif
      60                 :            : 
      61                 :            : #define MY_STRING_(x) # x
      62                 :            : #define MY_STRING(x) MY_STRING_(x)
      63                 :            : 
      64                 :            : extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl(
      65                 :            :     rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C();
      66                 :            : 
      67                 :            : using osl::DirectoryItem;
      68                 :            : using osl::FileStatus;
      69                 :            : 
      70                 :            : using rtl::OString;
      71                 :            : using rtl::OUString;
      72                 :            : using rtl::OUStringToOString;
      73                 :            : 
      74                 :            : struct Bootstrap_Impl;
      75                 :            : 
      76                 :            : namespace {
      77                 :            : 
      78                 :            : static char const VND_SUN_STAR_PATHNAME[] = "vnd.sun.star.pathname:";
      79                 :            : 
      80                 :        486 : bool isPathnameUrl(rtl::OUString const & url) {
      81                 :            :     return url.matchIgnoreAsciiCaseAsciiL(
      82                 :        486 :         RTL_CONSTASCII_STRINGPARAM(VND_SUN_STAR_PATHNAME));
      83                 :            : }
      84                 :            : 
      85                 :        166 : bool resolvePathnameUrl(rtl::OUString * url) {
      86                 :            :     OSL_ASSERT(url !=  NULL);
      87 [ +  - ][ -  + ]:        332 :     if (!isPathnameUrl(*url) ||
         [ #  # ][ +  - ]
      88                 :            :         (osl::FileBase::getFileURLFromSystemPath(
      89 [ #  # ][ -  + ]:        166 :             url->copy(RTL_CONSTASCII_LENGTH(VND_SUN_STAR_PATHNAME)), *url) ==
                 [ #  # ]
      90                 :            :          osl::FileBase::E_None))
      91                 :            :     {
      92                 :        166 :         return true;
      93                 :            :     } else {
      94                 :          0 :         *url = rtl::OUString();
      95                 :        166 :         return false;
      96                 :            :     }
      97                 :            : }
      98                 :            : 
      99                 :            : enum LookupMode {
     100                 :            :     LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP,
     101                 :            :     LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION };
     102                 :            : 
     103                 :     191588 : struct ExpandRequestLink {
     104                 :            :     ExpandRequestLink const * next;
     105                 :            :     Bootstrap_Impl const * file;
     106                 :            :     rtl::OUString key;
     107                 :            : };
     108                 :            : 
     109                 :            : rtl::OUString expandMacros(
     110                 :            :     Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
     111                 :            :     ExpandRequestLink const * requestStack);
     112                 :            : 
     113                 :     191588 : rtl::OUString recursivelyExpandMacros(
     114                 :            :     Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
     115                 :            :     Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
     116                 :            :     ExpandRequestLink const * requestStack)
     117                 :            : {
     118         [ +  + ]:     314978 :     for (; requestStack != NULL; requestStack = requestStack->next) {
     119   [ +  +  -  + ]:     141209 :         if (requestStack->file == requestFile &&
                 [ -  + ]
     120                 :      17819 :             requestStack->key == requestKey)
     121                 :            :         {
     122                 :            :             return rtl::OUString(
     123         [ #  # ]:          0 :                 RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***"));
     124                 :            :         }
     125                 :            :     }
     126                 :     191588 :     ExpandRequestLink link = { requestStack, requestFile, requestKey };
     127         [ +  - ]:     191588 :     return expandMacros(file, text, mode, &link);
     128                 :            : }
     129                 :            : 
     130                 :            : class ParameterMap: private boost::noncopyable {
     131                 :            : public:
     132                 :            :     bool get(rtl::OUString const & key, rtl::OUString * value) const;
     133                 :            : 
     134                 :            : protected:
     135         [ +  - ]:       4984 :     ParameterMap() {}
     136                 :            : 
     137                 :       4984 :     ~ParameterMap() {}
     138                 :            : 
     139                 :            :     typedef std::map< rtl::OUString, rtl::OUString > Map;
     140                 :            : 
     141                 :            :     Map map_;
     142                 :            : };
     143                 :            : 
     144                 :     860124 : bool ParameterMap::get(rtl::OUString const & key, rtl::OUString * value) const {
     145                 :            :     OSL_ASSERT(value != 0);
     146         [ +  - ]:     860124 :     Map::const_iterator i(map_.find(key));
     147         [ +  + ]:     860124 :     if (i == map_.end()) {
     148                 :     668694 :         return false;
     149                 :            :     } else {
     150                 :     191430 :         *value = i->second;
     151                 :     860124 :         return true;
     152                 :            :     }
     153                 :            : }
     154                 :            : 
     155 [ +  - ][ +  - ]:       1884 : class ExplicitParameterMap: public ParameterMap {
     156                 :            : public:
     157                 :            :     bool get(rtl::OUString const & key, rtl::OUString * value) const;
     158                 :            : 
     159                 :            :     void set(rtl::OUString const & key, rtl::OUString const & value);
     160                 :            : 
     161                 :            : private:
     162                 :            :     mutable osl::Mutex mutex_;
     163                 :            : };
     164                 :            : 
     165                 :     209827 : bool ExplicitParameterMap::get(rtl::OUString const & key, rtl::OUString * value)
     166                 :            :     const
     167                 :            : {
     168         [ +  - ]:     209827 :     osl::MutexGuard g(mutex_);
     169 [ +  - ][ +  - ]:     209827 :     return ParameterMap::get(key, value);
     170                 :            : }
     171                 :            : 
     172                 :       1530 : void ExplicitParameterMap::set(
     173                 :            :     rtl::OUString const & key, rtl::OUString const & value)
     174                 :            : {
     175         [ +  - ]:       1530 :     osl::MutexGuard g(mutex_);
     176 [ +  - ][ +  - ]:       1530 :     map_[key] = value;
     177                 :       1530 : }
     178                 :            : 
     179                 :            : struct ExplicitParameters:
     180                 :            :     public rtl::Static< ExplicitParameterMap, ExplicitParameters >
     181                 :            : {};
     182                 :            : 
     183                 :        942 : class CommandLineParameterMap: public ParameterMap {
     184                 :            : public:
     185                 :            :     CommandLineParameterMap();
     186                 :            : };
     187                 :            : 
     188                 :        942 : CommandLineParameterMap::CommandLineParameterMap() {
     189         [ +  - ]:        942 :     sal_uInt32 n = osl_getCommandArgCount();
     190         [ +  + ]:       7815 :     for (sal_uInt32 i = 0; i != n; ++i) {
     191                 :       6873 :         rtl::OUString s;
     192         [ +  - ]:       6873 :         osl_getCommandArg(i, &s.pData);
     193                 :            :         static char const PREFIX[] = "-env:";
     194         [ +  + ]:       6873 :         if (s.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX))) {
     195                 :       1839 :             sal_Int32 j = s.indexOf('=', RTL_CONSTASCII_LENGTH(PREFIX));
     196         [ -  + ]:       1839 :             if (j < 0) {
     197         [ #  # ]:          0 :                 map_.erase(s.copy(RTL_CONSTASCII_LENGTH(PREFIX)));
     198                 :            :             } else {
     199                 :            :                 map_[
     200                 :            :                     s.copy(
     201                 :            :                         RTL_CONSTASCII_LENGTH(PREFIX),
     202         [ +  - ]:       3678 :                         j - RTL_CONSTASCII_LENGTH(PREFIX))] =
     203                 :       5517 :                     s.copy(j + 1);
     204                 :            :             }
     205                 :            :         }
     206                 :       6873 :     }
     207                 :        942 : }
     208                 :            : 
     209                 :            : struct CommandLineParameters:
     210                 :            :     public rtl::Static< CommandLineParameterMap, CommandLineParameters >
     211                 :            : {};
     212                 :            : 
     213                 :            : }
     214                 :            : 
     215                 :          0 : static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL)
     216                 :            : {
     217                 :          0 :     OUString fileName;
     218                 :          0 :     osl_bootstrap_getExecutableFile_Impl (&(fileName.pData));
     219                 :            : 
     220                 :          0 :     sal_Int32 nDirEnd = fileName.lastIndexOf('/');
     221                 :            :     OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory");
     222                 :            : 
     223                 :          0 :     rtl_uString_newFromStr_WithLength(ppDirURL,fileName.getStr(),nDirEnd);
     224                 :          0 : }
     225                 :            : 
     226                 :            : static inline bool path_exists( OUString const & path )
     227                 :            : {
     228                 :            :     DirectoryItem dirItem;
     229                 :            :     return (DirectoryItem::E_None == DirectoryItem::get( path, dirItem ));
     230                 :            : }
     231                 :            : 
     232                 :            : //----------------------------------------------------------------------------
     233                 :            : // #111772#
     234                 :            : // ensure the given file url has no final slash
     235                 :            : 
     236                 :       1112 : inline void EnsureNoFinalSlash (rtl::OUString & url)
     237                 :            : {
     238                 :       1112 :     sal_Int32 i = url.getLength();
     239 [ -  + ][ -  + ]:       1112 :     if (i > 0 && url[i - 1] == '/') {
                 [ +  - ]
     240                 :          0 :         url = url.copy(0, i - 1);
     241                 :            :     }
     242                 :       1112 : }
     243                 :            : 
     244                 :       3100 : struct Bootstrap_Impl: private ParameterMap
     245                 :            : {
     246                 :            :     OUString      _iniName;
     247                 :            : 
     248                 :            :     explicit Bootstrap_Impl (OUString const & rIniName);
     249                 :            : 
     250                 :            :     bool getValue(
     251                 :            :         rtl::OUString const & key, rtl_uString ** value,
     252                 :            :         rtl_uString * defaultValue, LookupMode mode, bool override,
     253                 :            :         ExpandRequestLink const * requestStack) const;
     254                 :            :     bool getDirectValue(
     255                 :            :         rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
     256                 :            :         ExpandRequestLink const * requestStack) const;
     257                 :            :     bool getAmbienceValue(
     258                 :            :         rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
     259                 :            :         ExpandRequestLink const * requestStack) const;
     260                 :            :     void expandValue(
     261                 :            :         rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
     262                 :            :         Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
     263                 :            :         ExpandRequestLink const * requestStack) const;
     264                 :            : };
     265                 :            : 
     266                 :            : //----------------------------------------------------------------------------
     267                 :            : 
     268                 :       3100 : Bootstrap_Impl::Bootstrap_Impl( OUString const & rIniName )
     269                 :       3100 :     : _iniName (rIniName)
     270                 :            : {
     271                 :            : #if OSL_DEBUG_LEVEL > 1
     272                 :            :     OString sFile = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
     273                 :            :     OSL_TRACE("Bootstrap_Impl(): sFile=%s", sFile.getStr());
     274                 :            : #endif /* OSL_DEBUG_LEVEL > 1 */
     275                 :            : 
     276                 :            :     oslFileHandle handle;
     277 [ +  + ][ +  + ]:       6196 :     if (!_iniName.isEmpty() &&
                 [ +  + ]
     278         [ +  - ]:       3096 :         osl_File_E_None == osl_openFile(_iniName.pData, &handle, osl_File_OpenFlag_Read))
     279                 :            :     {
     280                 :       2415 :         rtl::ByteSequence seq;
     281                 :            : 
     282 [ +  - ][ +  + ]:      41471 :         while (osl_File_E_None == osl_readLine(handle , (sal_Sequence **)&seq))
     283                 :            :         {
     284                 :      39056 :             OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() );
     285                 :      39056 :             sal_Int32 nIndex = line.indexOf('=');
     286         [ +  + ]:      39056 :             if (nIndex >= 1)
     287                 :            :             {
     288                 :            :                 rtl::OUString sName = OStringToOUString(
     289         [ +  - ]:      14162 :                     line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US );
     290                 :            :                 rtl::OUString sValue = OStringToOUString(
     291         [ +  - ]:      14162 :                     line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8 );
     292                 :            : 
     293                 :            : #if OSL_DEBUG_LEVEL > 1
     294                 :            :                                 OString name_tmp = OUStringToOString(sName, RTL_TEXTENCODING_ASCII_US);
     295                 :            :                                 OString value_tmp = OUStringToOString(sValue, RTL_TEXTENCODING_UTF8);
     296                 :            :                 OSL_TRACE(
     297                 :            :                     "pushing: name=%s value=%s",
     298                 :            :                     name_tmp.getStr(), value_tmp.getStr() );
     299                 :            : #endif /* OSL_DEBUG_LEVEL > 1 */
     300                 :            : 
     301         [ +  - ]:      14162 :                                 map_[sName] = sValue;
     302                 :            :             }
     303                 :      39056 :         }
     304         [ +  - ]:       2415 :         osl_closeFile(handle);
     305                 :            :     }
     306                 :            : #if OSL_DEBUG_LEVEL > 1
     307                 :            :     else
     308                 :            :     {
     309                 :            :         OString file_tmp = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
     310                 :            :         OSL_TRACE( "couldn't open file: %s", file_tmp.getStr() );
     311                 :            :     }
     312                 :            : #endif /* OSL_DEBUG_LEVEL > 1 */
     313                 :       3100 : }
     314                 :            : 
     315                 :            : namespace {
     316                 :            : 
     317                 :            : class BootstrapMap: private boost::noncopyable {
     318                 :            : public:
     319                 :            :     BootstrapMap();
     320                 :            : 
     321                 :            :     ~BootstrapMap();
     322                 :            : 
     323                 :            :     Bootstrap_Impl * getIni(rtl::OUString const & uri, bool alwaysCreate);
     324                 :            : 
     325                 :            :     void setBaseIniUri(rtl::OUString const & uri);
     326                 :            : 
     327                 :            :     Bootstrap_Impl * getBaseIni();
     328                 :            : 
     329                 :            :     Bootstrap_Impl * getFundamentalIni();
     330                 :            : 
     331                 :            : private:
     332                 :            :     typedef std::map< rtl::OUString, Bootstrap_Impl * > Map;
     333                 :            : 
     334                 :            :     osl::Mutex mutex_;
     335                 :            :     Map map_;
     336                 :            :     rtl::OUString baseIniUri_;
     337                 :            :     Bootstrap_Impl * baseIni_;
     338                 :            :     bool hasFundamentalIni_;
     339                 :            :     Bootstrap_Impl * fundamentalIni_;
     340                 :            : };
     341                 :            : 
     342                 :        942 : BootstrapMap::BootstrapMap():
     343 [ +  - ][ +  - ]:        942 :     baseIni_(0), hasFundamentalIni_(false), fundamentalIni_(0)
     344                 :        942 : {}
     345                 :            : 
     346         [ +  - ]:        942 : BootstrapMap::~BootstrapMap() {
     347         [ +  + ]:       4042 :     for (Map::iterator i(map_.begin()); i != map_.end(); ++i) {
     348         [ +  - ]:       3100 :         delete i->second;
     349                 :            :     }
     350                 :        942 : }
     351                 :            : 
     352                 :      67639 : Bootstrap_Impl * BootstrapMap::getIni(
     353                 :            :     rtl::OUString const & uri, bool alwaysCreate)
     354                 :            : {
     355                 :      67639 :     rtl::OUString normUri; // normalize URI if possible
     356                 :      67639 :     DirectoryItem dirItem;
     357                 :      67639 :     FileStatus status(osl_FileStatus_Mask_FileURL);
     358 [ +  + ][ +  - ]:     129595 :     if (DirectoryItem::get(uri, dirItem) == DirectoryItem::E_None &&
         [ +  + ][ +  - ]
     359         [ +  - ]:      61956 :         dirItem.getFileStatus(status) == DirectoryItem::E_None)
     360                 :            :     {
     361         [ +  - ]:      61956 :         normUri = status.getFileURL();
     362         [ +  + ]:       5683 :     } else if (alwaysCreate) {
     363                 :        685 :         normUri = uri;
     364                 :            :     } else {
     365                 :       4998 :         return 0;
     366                 :            :     }
     367         [ +  - ]:      62641 :     osl::MutexGuard g(mutex_);
     368         [ +  - ]:      62641 :     Map::iterator i(map_.find(normUri));
     369         [ +  + ]:      62641 :     if (i == map_.end()) {
     370 [ +  - ][ +  - ]:       3100 :         std::auto_ptr< Bootstrap_Impl > b(new Bootstrap_Impl(normUri));
     371                 :            :         std::pair< Map::iterator, bool > ins(
     372         [ +  - ]:       3100 :             map_.insert(Map::value_type(normUri, b.get())));
     373                 :       3100 :         b.release();
     374                 :            :         OSL_ASSERT(ins.second);
     375                 :       3100 :         i = ins.first;
     376                 :            :     }
     377 [ +  - ][ +  - ]:      67639 :     return i->second;
     378                 :            : }
     379                 :            : 
     380                 :          0 : void BootstrapMap::setBaseIniUri(rtl::OUString const & uri) {
     381                 :            :     OSL_ASSERT(!uri.isEmpty());
     382         [ #  # ]:          0 :     osl::MutexGuard g(mutex_);
     383                 :            :     OSL_ASSERT(baseIniUri_.isEmpty() && baseIni_ == 0);
     384         [ #  # ]:          0 :     baseIniUri_ = uri;
     385                 :          0 : }
     386                 :            : 
     387                 :     201308 : Bootstrap_Impl * BootstrapMap::getBaseIni() {
     388         [ +  - ]:     201308 :     osl::MutexGuard g(mutex_);
     389         [ +  + ]:     201308 :     if (baseIni_ == 0) {
     390                 :        843 :         rtl::OUString uri;
     391         [ +  - ]:        843 :         if (baseIniUri_.isEmpty()) {
     392                 :            : #if defined IOS
     393                 :            :             // On iOS hardcode the inifile as "rc" in the .app
     394                 :            :             // directory. Apps are self-contained anyway, there is no
     395                 :            :             // possibility to have several "applications" in the same
     396                 :            :             // installation location with different inifiles.
     397                 :            :             const char *inifile = [[@"vnd.sun.star.pathname:" stringByAppendingString: [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"rc"]] UTF8String];
     398                 :            :             uri = rtl::OUString(inifile, strlen(inifile), RTL_TEXTENCODING_UTF8);
     399                 :            :             resolvePathnameUrl(&uri);
     400                 :            : #elif defined ANDROID
     401                 :            :             // Apps are self-contained on Android, too, can as well hardcode
     402                 :            :             // it as "rc" in the "/assets" directory, i.e.  inside the app's
     403                 :            :             // .apk (zip) archive as the /assets/rc file.
     404                 :            :             uri = rtl::OUString("vnd.sun.star.pathname:/assets/rc");
     405                 :            :             resolvePathnameUrl(&uri);
     406                 :            : #else
     407         [ +  - ]:       1686 :             if (CommandLineParameters::get().get(
           [ +  -  +  + ]
     408                 :            :                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")),
     409         [ +  - ]:       1686 :                     &uri))
     410                 :            :             {
     411         [ +  - ]:          4 :                 resolvePathnameUrl(&uri);
     412                 :            :             } else {
     413                 :        839 :                 osl_bootstrap_getExecutableFile_Impl(&uri.pData);
     414                 :            :                 // Strip potentially two such extensions, to allow for
     415                 :            :                 // renaming of soffice.bin to soffice.bin.exe so that
     416                 :            :                 // Visual Studio agrees to start it, if you want to
     417                 :            :                 // debug it from the start.
     418                 :            :                 static char const BIN_EXT[] = ".bin";
     419                 :            :                 static char const EXE_EXT[] = ".exe";
     420         [ +  + ]:       2517 :                 for (int i = 0; i < 2; i++) {
     421         [ +  + ]:       1678 :                     if (uri.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(BIN_EXT))) {
     422                 :            :                         uri = uri.copy(
     423                 :        158 :                             0, uri.getLength() - RTL_CONSTASCII_LENGTH(BIN_EXT));
     424         [ -  + ]:       1520 :                     } else if (uri.endsWithAsciiL(
     425                 :            :                                    RTL_CONSTASCII_STRINGPARAM(EXE_EXT))) {
     426                 :            :                         uri = uri.copy(
     427                 :          0 :                             0, uri.getLength() - RTL_CONSTASCII_LENGTH(EXE_EXT));
     428                 :            :                     }
     429                 :            :                 }
     430                 :            :                 uri += rtl::OUString(
     431         [ +  - ]:        839 :                     RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE("")));
     432                 :            :             }
     433                 :            : #endif
     434                 :            :         } else {
     435                 :          0 :             uri = baseIniUri_;
     436                 :            :         }
     437         [ +  - ]:        843 :         baseIni_ = getIni(uri, true);
     438                 :            :     }
     439         [ +  - ]:     201308 :     return baseIni_;
     440                 :            : }
     441                 :            : 
     442                 :     111757 : Bootstrap_Impl * BootstrapMap::getFundamentalIni() {
     443         [ +  - ]:     111757 :     osl::MutexGuard g(mutex_);
     444         [ +  + ]:     111757 :     if (!hasFundamentalIni_) {
     445                 :        843 :         rtl::OUString uri;
     446                 :            :         fundamentalIni_ =
     447                 :            :             (getBaseIni()->getValue(
     448                 :            :                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")),
     449 [ +  - ][ +  - ]:       1686 :                 &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0) &&
         [ +  - ][ #  # ]
                 [ +  - ]
     450         [ +  - ]:        162 :              resolvePathnameUrl(&uri))
     451 [ +  + ][ +  - ]:       1005 :             ? getIni(uri, false) : 0;
                 [ +  - ]
     452                 :        843 :         hasFundamentalIni_ = true;
     453                 :            :     }
     454         [ +  - ]:     111757 :     return fundamentalIni_;
     455                 :            : }
     456                 :            : 
     457                 :            : struct BootstrapMapSingleton:
     458                 :            :     public rtl::Static< BootstrapMap, BootstrapMapSingleton >
     459                 :            : {};
     460                 :            : 
     461                 :            : }
     462                 :            : 
     463                 :     315064 : bool Bootstrap_Impl::getValue(
     464                 :            :     rtl::OUString const & key, rtl_uString ** value, rtl_uString * defaultValue,
     465                 :            :     LookupMode mode, bool override, ExpandRequestLink const * requestStack)
     466                 :            :     const
     467                 :            : {
     468   [ +  +  +  + ]:     629970 :     if (mode == LOOKUP_MODE_NORMAL &&
                 [ +  + ]
     469                 :     314906 :         key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URE_BOOTSTRAP")))
     470                 :            :     {
     471                 :       1001 :         mode = LOOKUP_MODE_URE_BOOTSTRAP;
     472                 :            :     }
     473 [ +  + ][ +  - ]:     315064 :     if (override && getDirectValue(key, value, mode, requestStack)) {
                 [ +  + ]
     474                 :        196 :         return true;
     475                 :            :     }
     476         [ +  + ]:     314868 :     if ( key == "_OS" ) {
     477                 :            :         rtl_uString_assign(
     478                 :       2390 :             value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(RTL_OS)).pData);
     479                 :       2390 :         return true;
     480                 :            :     }
     481         [ +  + ]:     312478 :     if ( key == "_ARCH" ) {
     482                 :            :         rtl_uString_assign(
     483                 :       2388 :             value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(RTL_ARCH)).pData);
     484                 :       2388 :         return true;
     485                 :            :     }
     486         [ -  + ]:     310090 :     if ( key == "_CPPU_ENV" ) {
     487                 :            :         rtl_uString_assign(
     488                 :            :             value,
     489                 :            :             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_STRING(CPPU_ENV))).
     490                 :          0 :              pData));
     491                 :          0 :         return true;
     492                 :            :     }
     493         [ +  + ]:     310090 :     if ( key == "ORIGIN" ) {
     494                 :            :         rtl_uString_assign(
     495                 :            :             value,
     496                 :            :             _iniName.copy(
     497         [ +  - ]:     100263 :                 0, std::max<sal_Int32>(0, _iniName.lastIndexOf('/'))).pData);
     498                 :     100263 :         return true;
     499                 :            :     }
     500         [ +  + ]:     209827 :     if (getAmbienceValue(key, value, mode, requestStack)) {
     501                 :      30577 :         return true;
     502                 :            :     }
     503         [ -  + ]:     179250 :     if ( key == "SYSUSERCONFIG" ) {
     504                 :          0 :         rtl::OUString v;
     505 [ #  # ][ #  # ]:          0 :         bool b = osl::Security().getConfigDir(v);
                 [ #  # ]
     506                 :          0 :         EnsureNoFinalSlash(v);
     507                 :          0 :         rtl_uString_assign(value, v.pData);
     508                 :          0 :         return b;
     509                 :            :     }
     510         [ +  + ]:     179250 :     if ( key == "SYSUSERHOME" ) {
     511                 :       1112 :         rtl::OUString v;
     512 [ +  - ][ +  - ]:       1112 :         bool b = osl::Security().getHomeDir(v);
                 [ +  - ]
     513                 :       1112 :         EnsureNoFinalSlash(v);
     514                 :       1112 :         rtl_uString_assign(value, v.pData);
     515                 :       1112 :         return b;
     516                 :            :     }
     517         [ -  + ]:     178138 :     if ( key == "SYSBINDIR" ) {
     518                 :          0 :         getExecutableDirectory_Impl(value);
     519                 :          0 :         return true;
     520                 :            :     }
     521                 :     178138 :     Bootstrap_Impl * b = BootstrapMapSingleton::get().getBaseIni();
     522 [ -  + ][ -  + ]:     178138 :     if (b != this && b->getDirectValue(key, value, mode, requestStack)) {
                 [ +  + ]
     523                 :          0 :         return true;
     524                 :            :     }
     525 [ +  - ][ +  + ]:     178138 :     if (!override && getDirectValue(key, value, mode, requestStack)) {
                 [ +  + ]
     526                 :      65700 :         return true;
     527                 :            :     }
     528         [ +  + ]:     112438 :     if (mode == LOOKUP_MODE_NORMAL) {
     529                 :     111757 :         b = BootstrapMapSingleton::get().getFundamentalIni();
     530   [ +  -  +  + ]:     212114 :         if (b != 0 && b != this &&
         [ +  + ][ +  + ]
     531                 :     100357 :             b->getDirectValue(key, value, mode, requestStack))
     532                 :            :         {
     533                 :      95115 :             return true;
     534                 :            :         }
     535                 :            :     }
     536         [ +  + ]:      17323 :     if (defaultValue != NULL) {
     537                 :       1957 :         rtl_uString_assign(value, defaultValue);
     538                 :       1957 :         return true;
     539                 :            :     }
     540                 :      15366 :     rtl_uString_new(value);
     541                 :     315064 :     return false;
     542                 :            : }
     543                 :            : 
     544                 :     439845 : bool Bootstrap_Impl::getDirectValue(
     545                 :            :     rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
     546                 :            :     ExpandRequestLink const * requestStack) const
     547                 :            : {
     548                 :     439845 :     rtl::OUString v;
     549 [ +  + ][ +  - ]:     439845 :     if (get(key, &v)) {
     550         [ +  - ]:     161011 :         expandValue(value, v, mode, this, key, requestStack);
     551                 :     161011 :         return true;
     552                 :            :     } else {
     553                 :     278834 :         return false;
     554                 :     439845 :     }
     555                 :            : }
     556                 :            : 
     557                 :     209827 : bool Bootstrap_Impl::getAmbienceValue(
     558                 :            :     rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
     559                 :            :     ExpandRequestLink const * requestStack) const
     560                 :            : {
     561                 :     209827 :     rtl::OUString v;
     562 [ +  - ][ +  + ]:     598848 :     if (ExplicitParameters::get().get(key, &v) ||
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
     563 [ +  - ][ +  - ]:     209609 :         CommandLineParameters::get().get(key, &v) ||
     564         [ +  - ]:     179412 :         osl_getEnvironment(key.pData, &v.pData) == osl_Process_E_None)
     565                 :            :     {
     566         [ +  - ]:      30577 :         expandValue(value, v, mode, NULL, key, requestStack);
     567                 :      30577 :         return true;
     568                 :            :     } else {
     569                 :     179250 :         return false;
     570                 :     209827 :     }
     571                 :            : }
     572                 :            : 
     573                 :     191588 : void Bootstrap_Impl::expandValue(
     574                 :            :     rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
     575                 :            :     Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
     576                 :            :     ExpandRequestLink const * requestStack) const
     577                 :            : {
     578                 :            :     rtl_uString_assign(
     579                 :            :         value,
     580                 :        320 :         (mode == LOOKUP_MODE_URE_BOOTSTRAP && isPathnameUrl(text) ?
     581                 :            :          text :
     582                 :            :          recursivelyExpandMacros(
     583                 :            :              this, text,
     584                 :            :              (mode == LOOKUP_MODE_URE_BOOTSTRAP ?
     585                 :            :               LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION : mode),
     586   [ +  +  -  + ]:     191908 :              requestFile, requestKey, requestStack)).pData);
                 [ +  + ]
     587                 :     191588 : }
     588                 :            : 
     589                 :      66634 : rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open (
     590                 :            :     rtl_uString * pIniName
     591                 :            : ) SAL_THROW_EXTERN_C()
     592                 :            : {
     593 [ +  - ][ +  - ]:      66634 :     return BootstrapMapSingleton::get().getIni(rtl::OUString(pIniName), false);
     594                 :            : }
     595                 :            : 
     596                 :            : //----------------------------------------------------------------------------
     597                 :            : 
     598                 :      67661 : void SAL_CALL rtl_bootstrap_args_close (
     599                 :            :     SAL_UNUSED_PARAMETER rtlBootstrapHandle
     600                 :            : ) SAL_THROW_EXTERN_C()
     601                 :            : {
     602                 :            :     // do nothing; the BootstrapMap::map_ just keeps growing for now
     603                 :      67661 : }
     604                 :            : 
     605                 :            : //----------------------------------------------------------------------------
     606                 :            : 
     607                 :      14089 : sal_Bool SAL_CALL rtl_bootstrap_get_from_handle(
     608                 :            :     rtlBootstrapHandle handle,
     609                 :            :     rtl_uString      * pName,
     610                 :            :     rtl_uString     ** ppValue,
     611                 :            :     rtl_uString      * pDefault
     612                 :            : ) SAL_THROW_EXTERN_C()
     613                 :            : {
     614                 :            :     return
     615                 :            :         (handle == 0
     616         [ +  - ]:       6859 :          ? BootstrapMapSingleton::get().getBaseIni()
     617                 :            :          : static_cast< Bootstrap_Impl * >(handle))->
     618 [ +  + ][ +  - ]:      20948 :         getValue(pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, 0);
                 [ +  - ]
     619                 :            : }
     620                 :            : 
     621                 :            : //----------------------------------------------------------------------------
     622                 :            : 
     623                 :        583 : void SAL_CALL rtl_bootstrap_get_iniName_from_handle (
     624                 :            :     rtlBootstrapHandle handle,
     625                 :            :     rtl_uString     ** ppIniName
     626                 :            : ) SAL_THROW_EXTERN_C()
     627                 :            : {
     628                 :            :     rtl_uString_assign(
     629                 :            :         ppIniName,
     630                 :            :         ((handle == 0
     631                 :        267 :           ? BootstrapMapSingleton::get().getBaseIni()
     632                 :            :           : static_cast<Bootstrap_Impl*>(handle))->
     633         [ +  + ]:        850 :          _iniName.pData));
     634                 :        583 : }
     635                 :            : 
     636                 :            : //----------------------------------------------------------------------------
     637                 :            : 
     638                 :          0 : void SAL_CALL rtl_bootstrap_setIniFileName (
     639                 :            :     rtl_uString * pName
     640                 :            : ) SAL_THROW_EXTERN_C()
     641                 :            : {
     642 [ #  # ][ #  # ]:          0 :     BootstrapMapSingleton::get().setBaseIniUri(rtl::OUString(pName));
     643                 :          0 : }
     644                 :            : 
     645                 :            : //----------------------------------------------------------------------------
     646                 :            : 
     647                 :       2294 : sal_Bool SAL_CALL rtl_bootstrap_get (
     648                 :            :     rtl_uString  * pName,
     649                 :            :     rtl_uString ** ppValue,
     650                 :            :     rtl_uString  * pDefault
     651                 :            : ) SAL_THROW_EXTERN_C()
     652                 :            : {
     653                 :       2294 :     return rtl_bootstrap_get_from_handle(0, pName, ppValue, pDefault);
     654                 :            : }
     655                 :            : 
     656                 :            : //----------------------------------------------------------------------------
     657                 :            : 
     658                 :       1530 : void SAL_CALL rtl_bootstrap_set (
     659                 :            :     rtl_uString * pName,
     660                 :            :     rtl_uString * pValue
     661                 :            : ) SAL_THROW_EXTERN_C()
     662                 :            : {
     663 [ +  - ][ +  - ]:       1530 :     ExplicitParameters::get().set(rtl::OUString(pName), rtl::OUString(pValue));
     664                 :       1530 : }
     665                 :            : 
     666                 :            : //----------------------------------------------------------------------------
     667                 :            : 
     668                 :      74476 : void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
     669                 :            :     rtlBootstrapHandle handle,
     670                 :            :     rtl_uString     ** macro
     671                 :            : ) SAL_THROW_EXTERN_C()
     672                 :            : {
     673                 :            :     rtl::OUString expanded(
     674                 :            :         expandMacros(
     675                 :            :             (handle == 0
     676         [ +  - ]:      13412 :              ? BootstrapMapSingleton::get().getBaseIni()
     677                 :            :              : static_cast< Bootstrap_Impl * >(handle)),
     678                 :            :             *reinterpret_cast< OUString const * >(macro), LOOKUP_MODE_NORMAL,
     679 [ +  + ][ +  - ]:      87888 :             0));
                 [ +  - ]
     680                 :      74476 :     rtl_uString_assign(macro, expanded.pData);
     681                 :      74476 : }
     682                 :            : 
     683                 :            : //----------------------------------------------------------------------------
     684                 :            : 
     685                 :      13412 : void SAL_CALL rtl_bootstrap_expandMacros(
     686                 :            :     rtl_uString ** macro )
     687                 :            :     SAL_THROW_EXTERN_C()
     688                 :            : {
     689                 :      13412 :     rtl_bootstrap_expandMacros_from_handle(NULL, macro);
     690                 :      13412 : }
     691                 :            : 
     692                 :        158 : void rtl_bootstrap_encode( rtl_uString const * value, rtl_uString ** encoded )
     693                 :            :     SAL_THROW_EXTERN_C()
     694                 :            : {
     695                 :            :     OSL_ASSERT(value != NULL);
     696                 :        158 :     rtl::OUStringBuffer b;
     697         [ +  + ]:      14694 :     for (sal_Int32 i = 0; i < value->length; ++i) {
     698                 :      14536 :         sal_Unicode c = value->buffer[i];
     699 [ +  - ][ -  + ]:      14536 :         if (c == '$' || c == '\\') {
     700         [ #  # ]:          0 :             b.append(sal_Unicode('\\'));
     701                 :            :         }
     702         [ +  - ]:      14536 :         b.append(c);
     703                 :            :     }
     704         [ +  - ]:        158 :     rtl_uString_assign(encoded, b.makeStringAndClear().pData);
     705                 :        158 : }
     706                 :            : 
     707                 :            : namespace {
     708                 :            : 
     709                 :          0 : int hex(sal_Unicode c) {
     710                 :            :     return
     711                 :            :         c >= '0' && c <= '9' ? c - '0' :
     712                 :            :         c >= 'A' && c <= 'F' ? c - 'A' + 10 :
     713 [ #  # ][ #  # ]:          0 :         c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     714                 :            : }
     715                 :            : 
     716                 :   15850317 : sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) {
     717                 :            :     OSL_ASSERT(
     718                 :            :         pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL);
     719                 :   15850317 :     sal_Unicode c = text[(*pos)++];
     720         [ +  + ]:   15850317 :     if (c == '\\') {
     721                 :            :         int n1, n2, n3, n4;
     722 [ +  - ][ -  +  :        392 :         if (*pos < text.getLength() - 4 && text[*pos] == 'u' &&
          #  #  #  #  #  
                #  #  # ]
                 [ -  + ]
     723                 :          0 :             ((n1 = hex(text[*pos + 1])) >= 0) &&
     724                 :          0 :             ((n2 = hex(text[*pos + 2])) >= 0) &&
     725                 :          0 :             ((n3 = hex(text[*pos + 3])) >= 0) &&
     726                 :          0 :             ((n4 = hex(text[*pos + 4])) >= 0))
     727                 :            :         {
     728                 :          0 :             *pos += 5;
     729                 :          0 :             *escaped = true;
     730                 :            :             return static_cast< sal_Unicode >(
     731                 :          0 :                 (n1 << 12) | (n2 << 8) | (n3 << 4) | n4);
     732         [ +  - ]:        392 :         } else if (*pos < text.getLength()) {
     733                 :        392 :             *escaped = true;
     734                 :        392 :             return text[(*pos)++];
     735                 :            :         }
     736                 :            :     }
     737                 :   15849925 :     *escaped = false;
     738                 :   15850317 :     return c;
     739                 :            : }
     740                 :            : 
     741                 :     300132 : rtl::OUString lookup(
     742                 :            :     Bootstrap_Impl const * file, LookupMode mode, bool override,
     743                 :            :     rtl::OUString const & key, ExpandRequestLink const * requestStack)
     744                 :            : {
     745                 :     300132 :     rtl::OUString v;
     746         [ +  - ]:       1789 :     (file == 0 ? BootstrapMapSingleton::get().getBaseIni() : file)->getValue(
     747 [ +  - ][ +  - ]:     301921 :         key, &v.pData, NULL, mode, override, requestStack);
                 [ +  + ]
     748                 :     300132 :     return v;
     749                 :            : }
     750                 :            : 
     751                 :     468406 : rtl::OUString expandMacros(
     752                 :            :     Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
     753                 :            :     ExpandRequestLink const * requestStack)
     754                 :            : {
     755                 :     468406 :     rtl::OUStringBuffer buf;
     756         [ +  + ]:   10753426 :     for (sal_Int32 i = 0; i < text.getLength();) {
     757                 :            :         bool escaped;
     758                 :   10285020 :         sal_Unicode c = read(text, &i, &escaped);
     759 [ +  + ][ +  + ]:   10285020 :         if (escaped || c != '$') {
     760         [ +  - ]:    9984392 :             buf.append(c);
     761                 :            :         } else {
     762 [ +  - ][ +  + ]:     300628 :             if (i < text.getLength() && text[i] == '{') {
                 [ +  + ]
     763                 :     140324 :                 ++i;
     764                 :     140324 :                 sal_Int32 p = i;
     765                 :     140324 :                 sal_Int32 nesting = 0;
     766         [ +  + ]:     982268 :                 rtl::OUString seg[3];
     767                 :     140324 :                 int n = 0;
     768         [ +  - ]:    3293820 :                 while (i < text.getLength()) {
     769                 :    3293820 :                     sal_Int32 j = i;
     770                 :    3293820 :                     c = read(text, &i, &escaped);
     771         [ +  + ]:    3293820 :                     if (!escaped) {
     772   [ +  +  +  + ]:    3293624 :                         switch (c) {
     773                 :            :                         case '{':
     774                 :       1812 :                             ++nesting;
     775                 :       1812 :                             break;
     776                 :            :                         case '}':
     777         [ +  + ]:     142136 :                             if (nesting == 0) {
     778                 :     140324 :                                 seg[n++] = text.copy(p, j - p);
     779                 :     140324 :                                 goto done;
     780                 :            :                             } else {
     781                 :       1812 :                                 --nesting;
     782                 :            :                             }
     783                 :       1812 :                             break;
     784                 :            :                         case ':':
     785 [ +  + ][ +  - ]:      62990 :                             if (nesting == 0 && n < 2) {
     786                 :      62018 :                                 seg[n++] = text.copy(p, j - p);
     787                 :      62018 :                                 p = i;
     788                 :            :                             }
     789                 :    3153300 :                             break;
     790                 :            :                         }
     791                 :            :                     }
     792                 :            :                 }
     793                 :            :             done:
     794         [ +  + ]:     342666 :                 for (int j = 0; j < n; ++j) {
     795         [ +  - ]:     202342 :                     seg[j] = expandMacros(file, seg[j], mode, requestStack);
     796                 :            :                 }
     797         [ +  + ]:     140324 :                 if (n == 1) {
     798 [ +  - ][ +  - ]:      78998 :                     buf.append(lookup(file, mode, false, seg[0], requestStack));
     799 [ +  + ][ -  + ]:      61326 :                 } else if (n == 2 && seg[0] == ".link") {
                 [ -  + ]
     800                 :          0 :                     osl::File f(seg[1]);
     801                 :          0 :                     rtl::ByteSequence seq;
     802                 :          0 :                     rtl::OUString line;
     803                 :          0 :                     rtl::OUString url;
     804                 :            :                     // Silently ignore any errors (is that good?):
     805         [ #  # ]:          0 :                     if ((f.open(osl_File_OpenFlag_Read) ==
           [ #  #  #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     806                 :            :                          osl::FileBase::E_None) &&
     807         [ #  # ]:          0 :                         f.readLine(seq) == osl::FileBase::E_None &&
     808                 :            :                         rtl_convertStringToUString(
     809                 :            :                             &line.pData,
     810                 :            :                             reinterpret_cast< char const * >(
     811                 :          0 :                                 seq.getConstArray()),
     812                 :            :                             seq.getLength(), RTL_TEXTENCODING_UTF8,
     813                 :            :                             (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
     814                 :            :                              RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
     815                 :          0 :                              RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) &&
     816         [ #  # ]:          0 :                         (osl::File::getFileURLFromSystemPath(line, url) ==
     817                 :            :                          osl::FileBase::E_None))
     818                 :            :                     {
     819                 :            :                         try {
     820                 :            :                             buf.append(
     821 [ #  # ][ #  # ]:          0 :                                 rtl::Uri::convertRelToAbs(seg[1], url));
                 [ #  # ]
     822                 :          0 :                         } catch (const rtl::MalformedUriException &) {}
     823         [ #  # ]:          0 :                     }
     824 [ +  + ][ +  + ]:      61326 :                 } else if (n == 3 && seg[0] == ".override") {
                 [ +  + ]
     825                 :        196 :                     rtl::Bootstrap b(seg[1]);
     826                 :            :                     Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >(
     827                 :        196 :                         b.getHandle());
     828                 :            :                     buf.append(
     829 [ +  - ][ +  - ]:        196 :                         lookup(f, mode, f != NULL, seg[2], requestStack));
     830                 :            :                 } else {
     831 [ +  + ][ -  + ]:      61130 :                     if (n == 3 && seg[1].isEmpty()) {
                 [ -  + ]
     832                 :            :                         // For backward compatibility, treat ${file::key} the
     833                 :            :                         // same as just ${file:key}:
     834                 :          0 :                         seg[1] = seg[2];
     835                 :          0 :                         n = 2;
     836                 :            :                     }
     837         [ +  + ]:      61130 :                     if (n == 2) {
     838                 :            :                         buf.append(
     839                 :            :                             lookup(
     840                 :            :                                 static_cast< Bootstrap_Impl * >(
     841                 :     121268 :                                     rtl::Bootstrap(seg[0]).getHandle()),
     842 [ +  - ][ +  - ]:      60634 :                                 mode, false, seg[1], requestStack));
     843                 :            :                     } else {
     844                 :            :                         // Going through osl::Profile, this code erroneously
     845                 :            :                         // does not recursively expand macros in the resulting
     846                 :            :                         // replacement text (and if it did, it would fail to
     847                 :            :                         // detect cycles that pass through here):
     848                 :            :                         buf.append(
     849                 :            :                             rtl::OStringToOUString(
     850                 :            :                                 osl::Profile(seg[0]).readString(
     851                 :            :                                     rtl::OUStringToOString(
     852                 :            :                                         seg[1], RTL_TEXTENCODING_UTF8),
     853                 :            :                                     rtl::OUStringToOString(
     854                 :            :                                         seg[2], RTL_TEXTENCODING_UTF8),
     855                 :            :                                     rtl::OString()),
     856 [ +  - ][ +  - ]:        496 :                                 RTL_TEXTENCODING_UTF8));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     857                 :            :                     }
     858 [ +  + ][ #  # ]:     561296 :                 }
     859                 :            :             } else {
     860                 :     160304 :                 rtl::OUStringBuffer kbuf;
     861         [ +  + ]:    2277690 :                 for (; i < text.getLength();) {
     862                 :    2271477 :                     sal_Int32 j = i;
     863                 :    2271477 :                     c = read(text, &j, &escaped);
     864 [ +  - ][ +  - ]:    2271477 :                     if (!escaped &&
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
     865                 :            :                         (c == ' ' || c == '$' || c == '-' || c == '/' ||
     866                 :            :                          c == ';' || c == '\\'))
     867                 :            :                     {
     868                 :            :                         break;
     869                 :            :                     }
     870         [ +  - ]:    2117386 :                     kbuf.append(c);
     871                 :    2271477 :                     i = j;
     872                 :            :                 }
     873                 :            :                 buf.append(
     874                 :            :                     lookup(
     875                 :            :                         file, mode, false, kbuf.makeStringAndClear(),
     876 [ +  - ][ +  - ]:   10285020 :                         requestStack));
                 [ +  - ]
     877                 :            :             }
     878                 :            :         }
     879                 :            :     }
     880         [ +  - ]:     468406 :     return buf.makeStringAndClear();
     881                 :            : }
     882                 :            : 
     883                 :            : }
     884                 :            : 
     885                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10