LCOV - code coverage report
Current view: top level - sc/source/filter/oox - formulaparser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 131 1423 9.2 %
Date: 2012-08-25 Functions: 23 210 11.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 127 2124 6.0 %

           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                 :            : #include "formulaparser.hxx"
      30                 :            : 
      31                 :            : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      32                 :            : #include <com/sun/star/sheet/ComplexReference.hpp>
      33                 :            : #include <com/sun/star/sheet/ExternalReference.hpp>
      34                 :            : #include <com/sun/star/sheet/FormulaToken.hpp>
      35                 :            : #include <com/sun/star/sheet/NameToken.hpp>
      36                 :            : #include <com/sun/star/sheet/ReferenceFlags.hpp>
      37                 :            : #include <com/sun/star/sheet/SingleReference.hpp>
      38                 :            : #include "oox/core/filterbase.hxx"
      39                 :            : #include "oox/token/properties.hxx"
      40                 :            : #include "addressconverter.hxx"
      41                 :            : #include "biffinputstream.hxx"
      42                 :            : #include "defnamesbuffer.hxx"
      43                 :            : #include "externallinkbuffer.hxx"
      44                 :            : #include "tablebuffer.hxx"
      45                 :            : #include "worksheethelper.hxx"
      46                 :            : 
      47                 :            : namespace oox {
      48                 :            : namespace xls {
      49                 :            : 
      50                 :            : // ============================================================================
      51                 :            : 
      52                 :            : using namespace ::com::sun::star::sheet;
      53                 :            : using namespace ::com::sun::star::sheet::ReferenceFlags;
      54                 :            : using namespace ::com::sun::star::table;
      55                 :            : using namespace ::com::sun::star::uno;
      56                 :            : 
      57                 :            : using ::rtl::OUString;
      58                 :            : 
      59                 :            : // ============================================================================
      60                 :            : 
      61                 :            : namespace {
      62                 :            : 
      63                 :          0 : sal_uInt16 lclReadFmlaSize( BiffInputStream& rStrm, BiffType eBiff, const sal_uInt16* pnFmlaSize )
      64                 :            : {
      65 [ #  # ][ #  # ]:          0 :     return pnFmlaSize ? *pnFmlaSize : ((eBiff == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16());
      66                 :            : }
      67                 :            : 
      68                 :            : } // namespace
      69                 :            : 
      70                 :            : // formula finalizer ==========================================================
      71                 :            : 
      72                 :         24 : FormulaFinalizer::FormulaFinalizer( const OpCodeProvider& rOpCodeProv ) :
      73                 :            :     OpCodeProvider( rOpCodeProv ),
      74 [ +  - ][ +  - ]:         24 :     ApiOpCodes( getOpCodes() )
      75                 :            : {
      76         [ +  - ]:         24 :     maTokens.reserve( 0x2000 );
      77                 :         24 : }
      78                 :            : 
      79                 :        117 : ApiTokenSequence FormulaFinalizer::finalizeTokenArray( const ApiTokenSequence& rTokens )
      80                 :            : {
      81                 :        117 :     maTokens.clear();
      82         [ +  - ]:        117 :     if( rTokens.hasElements() )
      83                 :            :     {
      84                 :        117 :         const ApiToken* pToken = rTokens.getConstArray();
      85                 :        117 :         processTokens( pToken, pToken + rTokens.getLength() );
      86                 :            :     }
      87                 :        117 :     return ContainerHelper::vectorToSequence( maTokens );
      88                 :            : }
      89                 :            : 
      90                 :          0 : const FunctionInfo* FormulaFinalizer::resolveBadFuncName( const OUString& ) const
      91                 :            : {
      92                 :          0 :     return 0;
      93                 :            : }
      94                 :            : 
      95                 :          0 : OUString FormulaFinalizer::resolveDefinedName( sal_Int32 ) const
      96                 :            : {
      97                 :          0 :     return OUString();
      98                 :            : }
      99                 :            : 
     100                 :        207 : const FunctionInfo* FormulaFinalizer::getFunctionInfo( ApiToken& orFuncToken )
     101                 :            : {
     102                 :            :     // first, try to find a regular function info from token op-code
     103         [ +  + ]:        207 :     if( const FunctionInfo* pRegFuncInfo = getFuncInfoFromApiToken( orFuncToken ) )
     104                 :         21 :         return pRegFuncInfo;
     105                 :            : 
     106                 :            :     // try to recognize a function from an external library
     107 [ +  + ][ +  - ]:        186 :     if( (orFuncToken.OpCode == OPCODE_BAD) && orFuncToken.Data.has< OUString >() )
                 [ +  + ]
     108                 :            :     {
     109                 :            :         // virtual call to resolveBadFuncName()
     110 [ +  - ][ -  + ]:         12 :         if( const FunctionInfo* pLibFuncInfo = resolveBadFuncName( orFuncToken.Data.get< OUString >() ) )
     111                 :            :         {
     112                 :            :             // write function op-code to the OPCODE_BAD token
     113                 :          0 :             orFuncToken.OpCode = pLibFuncInfo->mnApiOpCode;
     114                 :            :             // if it is an external function, insert programmatic function name
     115 [ #  # ][ #  # ]:          0 :             if( (orFuncToken.OpCode == OPCODE_EXTERNAL) && (!pLibFuncInfo->maExtProgName.isEmpty()) )
                 [ #  # ]
     116                 :          0 :                 orFuncToken.Data <<= pLibFuncInfo->maExtProgName;
     117                 :            :             else
     118                 :          0 :                 orFuncToken.Data.clear();   // clear string from OPCODE_BAD
     119                 :          0 :             return pLibFuncInfo;
     120                 :            :         }
     121                 :            :     }
     122                 :            : 
     123                 :            :     // no success - return null
     124                 :        207 :     return 0;
     125                 :            : }
     126                 :            : 
     127                 :          0 : const FunctionInfo* FormulaFinalizer::getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken )
     128                 :            : {
     129                 :            :     // try to resolve the passed token to a supported sheet function
     130         [ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( rECToken ) )
     131                 :            :     {
     132                 :          0 :         orFuncToken.OpCode = pFuncInfo->mnApiOpCode;
     133                 :            :         // programmatic add-in function name
     134 [ #  # ][ #  # ]:          0 :         if( (pFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && !pFuncInfo->maExtProgName.isEmpty() )
                 [ #  # ]
     135                 :          0 :             orFuncToken.Data <<= pFuncInfo->maExtProgName;
     136                 :            :         // name of unsupported function, convert to OPCODE_BAD to preserve the name
     137 [ #  # ][ #  # ]:          0 :         else if( (pFuncInfo->mnApiOpCode == OPCODE_BAD) && !pFuncInfo->maOoxFuncName.isEmpty() )
                 [ #  # ]
     138                 :          0 :             orFuncToken.Data <<= pFuncInfo->maOoxFuncName;
     139                 :          0 :         return pFuncInfo;
     140                 :            :     }
     141                 :            : 
     142                 :            :     // macro call or unknown function name, move data to function token
     143 [ #  # ][ #  # ]:          0 :     if( (rECToken.OpCode == OPCODE_MACRO) || (rECToken.OpCode == OPCODE_BAD) )
     144                 :          0 :         orFuncToken = rECToken;
     145                 :            : 
     146                 :            :     // defined name used as function call, convert to OPCODE_BAD to preserve the name
     147 [ #  # ][ #  # ]:          0 :     if( (rECToken.OpCode == OPCODE_NAME) && rECToken.Data.has< sal_Int32 >() )
                 [ #  # ]
     148                 :            :     {
     149 [ #  # ][ #  # ]:          0 :         OUString aDefName = resolveDefinedName( rECToken.Data.get< sal_Int32 >() );
     150         [ #  # ]:          0 :         if( !aDefName.isEmpty() )
     151                 :            :         {
     152                 :          0 :             orFuncToken.OpCode = OPCODE_BAD;
     153         [ #  # ]:          0 :             orFuncToken.Data <<= aDefName;
     154                 :          0 :         }
     155                 :            :     }
     156                 :            : 
     157                 :          0 :     return 0;
     158                 :            : }
     159                 :            : 
     160                 :        162 : void FormulaFinalizer::processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd )
     161                 :            : {
     162         [ +  + ]:        369 :     while( pToken < pTokenEnd )
     163                 :            :     {
     164                 :            :         // push the current token into the vector
     165                 :        207 :         bool bValid = appendFinalToken( *pToken );
     166                 :            :         // try to process a function
     167 [ +  + ][ +  - ]:        207 :         if( const FunctionInfo* pFuncInfo = bValid ? getFunctionInfo( maTokens.back() ) : 0 )
     168                 :         21 :             pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd );
     169                 :            :         // otherwise, go to next token
     170                 :            :         else
     171                 :        186 :             ++pToken;
     172                 :            :     }
     173                 :        162 : }
     174                 :            : 
     175                 :         21 : const ApiToken* FormulaFinalizer::processParameters(
     176                 :            :         const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd )
     177                 :            : {
     178                 :            :     // remember position of the token containing the function op-code
     179                 :         21 :     size_t nFuncNameIdx = maTokens.size() - 1;
     180                 :            : 
     181                 :            :     // process a function, if an OPCODE_OPEN token is following
     182                 :            :     OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::processParameters - OPCODE_OPEN expected" );
     183 [ +  - ][ +  - ]:         21 :     if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN) )
     184                 :            :     {
     185                 :            :         // append the OPCODE_OPEN token to the vector
     186         [ +  - ]:         21 :         maTokens.append( OPCODE_OPEN );
     187                 :            : 
     188                 :            :         // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE
     189         [ +  - ]:         21 :         ParameterPosVector aParams;
     190         [ +  - ]:         21 :         pToken = findParameters( aParams, pToken, pTokenEnd );
     191                 :            :         OSL_ENSURE( aParams.size() >= 2, "FormulaFinalizer::processParameters - missing tokens" );
     192                 :         21 :         size_t nParamCount = aParams.size() - 1;
     193                 :            : 
     194 [ +  + ][ +  + ]:         21 :         if( (nParamCount == 1) && isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) )
                 [ +  + ]
     195                 :            :         {
     196                 :            :             /*  Empty pair of parentheses -> function call without parameters,
     197                 :            :                 process parameter, there might be spaces between parentheses. */
     198         [ +  - ]:          6 :             processTokens( aParams[ 0 ] + 1, aParams[ 1 ] );
     199                 :            :         }
     200                 :            :         else
     201                 :            :         {
     202                 :         15 :             const FunctionInfo* pRealFuncInfo = &rFuncInfo;
     203         [ +  - ]:         15 :             ParameterPosVector::const_iterator aPosIt = aParams.begin();
     204                 :            : 
     205                 :            :             /*  Preprocess EXTERN.CALL functions. The actual function name is
     206                 :            :                 contained as reference to a defined name in the first (hidden)
     207                 :            :                 parameter. */
     208         [ -  + ]:         15 :             if( rFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL )
     209                 :            :             {
     210                 :          0 :                 ApiToken& rFuncToken = maTokens[ nFuncNameIdx ];
     211                 :          0 :                 rFuncToken.OpCode = OPCODE_NONAME;
     212                 :            : 
     213                 :            :                 // try to initialize function token from first parameter
     214 [ #  # ][ #  # ]:          0 :                 if( const ApiToken* pECToken = getSingleToken( *aPosIt + 1, *(aPosIt + 1) ) )
     215 [ #  # ][ #  # ]:          0 :                     if( const FunctionInfo* pECFuncInfo = getExternCallInfo( rFuncToken, *pECToken ) )
     216                 :          0 :                         pRealFuncInfo = pECFuncInfo;
     217                 :            : 
     218                 :            :                 /*  On success (something has been inserted into rFuncToken),
     219                 :            :                     skip the first parameter. */
     220         [ #  # ]:          0 :                 if( rFuncToken.OpCode != OPCODE_NONAME )
     221                 :            :                 {
     222                 :          0 :                     --nParamCount;
     223                 :          0 :                     ++aPosIt;
     224                 :            :                 }
     225                 :            :             }
     226                 :            : 
     227                 :            :             // process all parameters
     228         [ +  - ]:         15 :             FunctionParamInfoIterator aParamInfoIt( *pRealFuncInfo );
     229                 :         15 :             size_t nLastValidSize = maTokens.size();
     230                 :         15 :             size_t nLastValidCount = 0;
     231 [ +  - ][ +  + ]:         54 :             for( size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aParamInfoIt )
     232                 :            :             {
     233                 :            :                 // add embedded Calc-only parameters
     234 [ +  - ][ -  + ]:         39 :                 if( aParamInfoIt.isCalcOnlyParam() )
     235                 :            :                 {
     236         [ #  # ]:          0 :                     appendCalcOnlyParameter( *pRealFuncInfo, nParam );
     237 [ #  # ][ #  # ]:          0 :                     while( aParamInfoIt.isCalcOnlyParam() ) ++aParamInfoIt;
                 [ #  # ]
     238                 :            :                 }
     239                 :            : 
     240                 :         39 :                 const ApiToken* pParamBegin = *aPosIt + 1;
     241         [ +  - ]:         39 :                 const ApiToken* pParamEnd = *(aPosIt + 1);
     242                 :         39 :                 bool bIsEmpty = isEmptyParameter( pParamBegin, pParamEnd );
     243                 :            : 
     244 [ +  - ][ +  - ]:         39 :                 if( !aParamInfoIt.isExcelOnlyParam() )
     245                 :            :                 {
     246                 :            :                     // handle empty parameters
     247         [ -  + ]:         39 :                     if( bIsEmpty )
     248                 :            :                     {
     249                 :            :                         // append leading space tokens from original token array
     250 [ #  # ][ #  # ]:          0 :                         while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) )
                 [ #  # ]
     251         [ #  # ]:          0 :                             maTokens.push_back( *pParamBegin++ );
     252                 :            :                         // add default values for some empty parameters, or the OPCODE_MISSING token
     253         [ #  # ]:          0 :                         appendEmptyParameter( *pRealFuncInfo, nParam );
     254                 :            :                         // reset bIsEmpty flag, if something has been appended in appendEmptyParameter()
     255         [ #  # ]:          0 :                         bIsEmpty = maTokens.back().OpCode == OPCODE_MISSING;
     256                 :            :                         // skip OPCODE_MISSING token in the original token array
     257                 :            :                         OSL_ENSURE( (pParamBegin == pParamEnd) || (pParamBegin->OpCode == OPCODE_MISSING), "FormulaFinalizer::processParameters - OPCODE_MISSING expected" );
     258         [ #  # ]:          0 :                         if( pParamBegin < pParamEnd ) ++pParamBegin;
     259                 :            :                         // append trailing space tokens from original token array
     260 [ #  # ][ #  # ]:          0 :                         while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) )
                 [ #  # ]
     261         [ #  # ]:          0 :                             maTokens.push_back( *pParamBegin++ );
     262                 :            :                     }
     263                 :            :                     else
     264                 :            :                     {
     265                 :            :                         // if parameter is not empty, process all tokens of the parameter
     266         [ +  - ]:         39 :                         processTokens( pParamBegin, pParamEnd );
     267                 :            :                     }
     268                 :            : 
     269                 :            :                     // append parameter separator token
     270         [ +  - ]:         39 :                     maTokens.append( OPCODE_SEP );
     271                 :            :                 }
     272                 :            : 
     273                 :            :                 /*  #84453# Update size of new token sequence with valid parameters
     274                 :            :                     to be able to remove trailing optional empty parameters. */
     275 [ -  + ][ #  # ]:         39 :                 if( !bIsEmpty || (nParam < pRealFuncInfo->mnMinParamCount) )
     276                 :            :                 {
     277                 :         39 :                     nLastValidSize = maTokens.size();
     278                 :         39 :                     nLastValidCount = nParam + 1;
     279                 :            :                 }
     280                 :            :             }
     281                 :            : 
     282                 :            :             // #84453# remove trailing optional empty parameters
     283         [ +  - ]:         15 :             maTokens.resize( nLastValidSize );
     284                 :            : 
     285                 :            :             // add trailing Calc-only parameters
     286 [ +  - ][ -  + ]:         15 :             if( aParamInfoIt.isCalcOnlyParam() )
     287         [ #  # ]:          0 :                 appendCalcOnlyParameter( *pRealFuncInfo, nLastValidCount );
     288                 :            : 
     289                 :            :             // add optional parameters that are required in Calc
     290         [ +  - ]:         15 :             appendRequiredParameters( *pRealFuncInfo, nLastValidCount );
     291                 :            : 
     292                 :            :             // remove last parameter separator token
     293 [ +  - ][ +  - ]:         15 :             if( maTokens.back().OpCode == OPCODE_SEP )
     294         [ +  - ]:         15 :                 maTokens.pop_back();
     295                 :            :         }
     296                 :            : 
     297                 :            :         /*  Append the OPCODE_CLOSE token to the vector, but only if there is
     298                 :            :             no OPCODE_BAD token at the end, this token already contains the
     299                 :            :             trailing closing parentheses. */
     300         [ +  - ]:         21 :         if( (pTokenEnd - 1)->OpCode != OPCODE_BAD )
     301         [ +  - ]:         21 :             maTokens.append( OPCODE_CLOSE );
     302                 :            :     }
     303                 :            : 
     304                 :            :     /*  Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell,
     305                 :            :         if no matching add-in function was found. */
     306                 :         21 :     ApiToken& rFuncNameToken = maTokens[ nFuncNameIdx ];
     307 [ #  # ][ -  + ]:         21 :     if( (rFuncNameToken.OpCode == OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() )
                 [ -  + ]
     308                 :          0 :         rFuncNameToken.OpCode = OPCODE_NONAME;
     309                 :            : 
     310                 :         21 :     return pToken;
     311                 :            : }
     312                 :            : 
     313                 :         48 : bool FormulaFinalizer::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
     314                 :            : {
     315 [ +  + ][ +  + ]:         54 :     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
                 [ +  + ]
     316 [ +  + ][ -  + ]:         48 :     if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_MISSING) ) ++pToken;
     317 [ +  + ][ -  + ]:         48 :     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
                 [ -  + ]
     318                 :         48 :     return pToken == pTokenEnd;
     319                 :            : }
     320                 :            : 
     321                 :          0 : const ApiToken* FormulaFinalizer::getSingleToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
     322                 :            : {
     323                 :          0 :     const ApiToken* pSingleToken = 0;
     324                 :            :     // skip leading whitespace tokens
     325 [ #  # ][ #  # ]:          0 :     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
                 [ #  # ]
     326                 :            :     // remember first non-whitespace token
     327         [ #  # ]:          0 :     if( pToken < pTokenEnd ) pSingleToken = pToken++;
     328                 :            :     // skip trailing whitespace tokens
     329 [ #  # ][ #  # ]:          0 :     while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
                 [ #  # ]
     330                 :            :     // return null, if other non-whitespace tokens follow
     331         [ #  # ]:          0 :     return (pToken == pTokenEnd) ? pSingleToken : 0;
     332                 :            : }
     333                 :            : 
     334                 :          0 : const ApiToken* FormulaFinalizer::skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
     335                 :            : {
     336                 :            :     // skip tokens between OPCODE_OPEN and OPCODE_CLOSE
     337                 :            :     OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "skipParentheses - OPCODE_OPEN expected" );
     338                 :          0 :     ++pToken;
     339 [ #  # ][ #  # ]:          0 :     while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) )
                 [ #  # ]
     340                 :            :     {
     341         [ #  # ]:          0 :         if( pToken->OpCode == OPCODE_OPEN )
     342                 :          0 :             pToken = skipParentheses( pToken, pTokenEnd );
     343                 :            :         else
     344                 :          0 :             ++pToken;
     345                 :            :     }
     346                 :            :     // skip the OPCODE_CLOSE token
     347                 :            :     OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "skipParentheses - OPCODE_CLOSE expected" );
     348         [ #  # ]:          0 :     return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
     349                 :            : }
     350                 :            : 
     351                 :         21 : const ApiToken* FormulaFinalizer::findParameters( ParameterPosVector& rParams,
     352                 :            :         const ApiToken* pToken, const ApiToken* pTokenEnd ) const
     353                 :            : {
     354                 :            :     // push position of OPCODE_OPEN
     355                 :            :     OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::findParameters - OPCODE_OPEN expected" );
     356         [ +  - ]:         21 :     rParams.push_back( pToken++ );
     357                 :            : 
     358                 :            :     // find positions of parameter separators
     359 [ +  - ][ +  + ]:         90 :     while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) )
                 [ +  + ]
     360                 :            :     {
     361         [ -  + ]:         69 :         if( pToken->OpCode == OPCODE_OPEN )
     362                 :          0 :             pToken = skipParentheses( pToken, pTokenEnd );
     363         [ +  + ]:         69 :         else if( pToken->OpCode == OPCODE_SEP )
     364         [ +  - ]:         24 :             rParams.push_back( pToken++ );
     365                 :            :         else
     366                 :         45 :             ++pToken;
     367                 :            :     }
     368                 :            : 
     369                 :            :     // push position of OPCODE_CLOSE
     370                 :            :     OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "FormulaFinalizer::findParameters - OPCODE_CLOSE expected" );
     371                 :         21 :     rParams.push_back( pToken );
     372         [ +  - ]:         21 :     return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
     373                 :            : }
     374                 :            : 
     375                 :          0 : void FormulaFinalizer::appendEmptyParameter( const FunctionInfo& rFuncInfo, size_t nParam )
     376                 :            : {
     377                 :            :     // remember old size of the token array
     378                 :          0 :     size_t nTokenArraySize = maTokens.size();
     379                 :            : 
     380         [ #  # ]:          0 :     switch( rFuncInfo.mnBiff12FuncId )
     381                 :            :     {
     382                 :            :         case BIFF_FUNC_IF:
     383 [ #  # ][ #  # ]:          0 :             if( (nParam == 1) || (nParam == 2) )
     384         [ #  # ]:          0 :                 maTokens.append< double >( OPCODE_PUSH, 0.0 );
     385                 :          0 :         break;
     386                 :            :         default:;
     387                 :            :     }
     388                 :            : 
     389                 :            :     // if no token has been added, append a OPCODE_MISSING token
     390         [ #  # ]:          0 :     if( nTokenArraySize == maTokens.size() )
     391                 :          0 :         maTokens.append( OPCODE_MISSING );
     392                 :          0 : }
     393                 :            : 
     394                 :          0 : void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam )
     395                 :            : {
     396                 :            :     (void)nParam;   // prevent 'unused' warning
     397         [ #  # ]:          0 :     switch( rFuncInfo.mnBiff12FuncId )
     398                 :            :     {
     399                 :            :         case BIFF_FUNC_FLOOR:
     400                 :            :         case BIFF_FUNC_CEILING:
     401                 :            :             OSL_ENSURE( nParam == 2, "FormulaFinalizer::appendCalcOnlyParameter - unexpected parameter index" );
     402         [ #  # ]:          0 :             maTokens.append< double >( OPCODE_PUSH, 1.0 );
     403                 :          0 :             maTokens.append( OPCODE_SEP );
     404                 :          0 :         break;
     405                 :            :     }
     406                 :          0 : }
     407                 :            : 
     408                 :         15 : void FormulaFinalizer::appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount )
     409                 :            : {
     410         [ -  + ]:         15 :     switch( rFuncInfo.mnBiff12FuncId )
     411                 :            :     {
     412                 :            :         case BIFF_FUNC_WEEKNUM:
     413         [ #  # ]:          0 :             if( nParamCount == 1 )
     414                 :            :             {
     415         [ #  # ]:          0 :                 maTokens.append< double >( OPCODE_PUSH, 1.0 );
     416                 :          0 :                 maTokens.append( OPCODE_SEP );
     417                 :            :             }
     418                 :          0 :         break;
     419                 :            :     }
     420                 :         15 : }
     421                 :            : 
     422                 :        207 : bool FormulaFinalizer::appendFinalToken( const ApiToken& rToken )
     423                 :            : {
     424                 :            :     // replace OPCODE_MACRO without macro name with #NAME? error code
     425 [ -  + ][ #  # ]:        207 :     bool bValid = (rToken.OpCode != OPCODE_MACRO) || rToken.Data.hasValue();
     426         [ +  - ]:        207 :     if( bValid )
     427                 :            :     {
     428                 :        207 :         maTokens.push_back( rToken );
     429                 :            :     }
     430                 :            :     else
     431                 :            :     {
     432                 :          0 :         maTokens.append( OPCODE_ARRAY_OPEN );
     433         [ #  # ]:          0 :         maTokens.append( OPCODE_PUSH, BiffHelper::calcDoubleFromError( BIFF_ERR_NAME ) );
     434                 :          0 :         maTokens.append( OPCODE_ARRAY_CLOSE );
     435                 :            :     }
     436                 :        207 :     return bValid;
     437                 :            : }
     438                 :            : 
     439                 :            : // parser implementation base =================================================
     440                 :            : 
     441 [ +  - ][ -  + ]:         24 : class FormulaParserImpl : public FormulaFinalizer, public WorkbookHelper
     442                 :            : {
     443                 :            : public:
     444                 :            :     explicit            FormulaParserImpl( const FormulaParser& rParent );
     445                 :            : 
     446                 :            :     /** Converts an OOXML formula string. */
     447                 :            :     virtual ApiTokenSequence importOoxFormula(
     448                 :            :                             const CellAddress& rBaseAddress,
     449                 :            :                             const OUString& rFormulaString );
     450                 :            : 
     451                 :            :     /** Imports and converts a BIFF12 token array from the passed stream. */
     452                 :            :     virtual ApiTokenSequence importBiff12Formula(
     453                 :            :                             const CellAddress& rBaseAddress,
     454                 :            :                             FormulaType eType,
     455                 :            :                             SequenceInputStream& rStrm );
     456                 :            : 
     457                 :            :     /** Imports and converts a BIFF2-BIFF8 token array from the passed stream. */
     458                 :            :     virtual ApiTokenSequence importBiffFormula(
     459                 :            :                             const CellAddress& rBaseAddress,
     460                 :            :                             FormulaType eType,
     461                 :            :                             BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize );
     462                 :            : 
     463                 :            :     /** Tries to resolve the passed ref-id to an OLE target URL. */
     464                 :            :     OUString            resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const;
     465                 :            : 
     466                 :            : protected:
     467                 :            :     typedef ::std::pair< sal_Int32, bool >  WhiteSpace;
     468                 :            :     typedef ::std::vector< WhiteSpace >     WhiteSpaceVec;
     469                 :            : 
     470                 :            :     /** Initializes the formula parser before importing a formula. */
     471                 :            :     void                initializeImport( const CellAddress& rBaseAddress, FormulaType eType );
     472                 :            :     /** Finalizes the internal token storage after import. */
     473                 :            :     ApiTokenSequence    finalizeImport();
     474                 :            : 
     475                 :            :     // token array ------------------------------------------------------------
     476                 :            : 
     477                 :            :     bool                resetSpaces();
     478                 :            :     static void         appendSpaces( WhiteSpaceVec& orSpaces, sal_Int32 nCount, bool bLineFeed );
     479                 :            :     void                appendLeadingSpaces( sal_Int32 nCount, bool bLineFeed );
     480                 :            :     void                appendOpeningSpaces( sal_Int32 nCount, bool bLineFeed );
     481                 :            :     void                appendClosingSpaces( sal_Int32 nCount, bool bLineFeed );
     482                 :            : 
     483                 :            :     size_t              getFormulaSize() const;
     484                 :            :     Any&                appendRawToken( sal_Int32 nOpCode );
     485                 :            :     Any&                insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd );
     486                 :            :     size_t              appendWhiteSpaceTokens( const WhiteSpaceVec* pSpaces );
     487                 :            :     size_t              insertWhiteSpaceTokens( const WhiteSpaceVec* pSpaces, size_t nIndexFromEnd );
     488                 :            : 
     489                 :            :     size_t              getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const;
     490                 :            :     void                pushOperandSize( size_t nSize );
     491                 :            :     size_t              popOperandSize();
     492                 :            : 
     493                 :            :     ApiToken&           getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex );
     494                 :            :     void                removeOperand( size_t nOpCountFromEnd, size_t nOpIndex );
     495                 :            : 
     496                 :            :     bool                pushOperandToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
     497                 :            :     bool                pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
     498                 :            :     template< typename Type >
     499                 :            :     bool                pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
     500                 :            :     template< typename Type >
     501                 :          0 :     inline bool         pushValueOperandToken( const Type& rValue, const WhiteSpaceVec* pSpaces = 0 )
     502                 :          0 :                             { return pushValueOperandToken( rValue, OPCODE_PUSH, pSpaces ); }
     503                 :            :     bool                pushParenthesesOperandToken( const WhiteSpaceVec* pOpeningSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
     504                 :            :     bool                pushUnaryPreOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
     505                 :            :     bool                pushUnaryPostOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
     506                 :            :     bool                pushBinaryOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 );
     507                 :            :     bool                pushParenthesesOperatorToken( const WhiteSpaceVec* pOpeningSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
     508                 :            :     bool                pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
     509                 :            :     bool                pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 );
     510                 :            : 
     511                 :            :     bool                pushOperand( sal_Int32 nOpCode );
     512                 :            :     bool                pushAnyOperand( const Any& rAny, sal_Int32 nOpCode );
     513                 :            :     template< typename Type >
     514                 :            :     bool                pushValueOperand( const Type& rValue, sal_Int32 nOpCode );
     515                 :            :     template< typename Type >
     516                 :          0 :     inline bool         pushValueOperand( const Type& rValue )
     517                 :          0 :                             { return pushValueOperand( rValue, OPCODE_PUSH ); }
     518                 :            :     bool                pushBoolOperand( bool bValue );
     519                 :            :     bool                pushErrorOperand( double fEncodedError );
     520                 :            :     bool                pushBiffBoolOperand( sal_uInt8 nValue );
     521                 :            :     bool                pushBiffErrorOperand( sal_uInt8 nErrorCode );
     522                 :            :     bool                pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
     523                 :            :     bool                pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
     524                 :            :     template< typename Type >
     525                 :            :     bool                pushReferenceOperand( const LinkSheetRange& rSheetRange, const Type& rApiRef );
     526                 :            :     bool                pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
     527                 :            :     bool                pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
     528                 :            :     bool                pushNlrOperand( const BinSingleRef2d& rRef );
     529                 :            :     bool                pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken );
     530                 :            :     bool                pushDefinedNameOperand( const DefinedNameRef& rxDefName );
     531                 :            :     bool                pushExternalFuncOperand( const FunctionInfo& rFuncInfo );
     532                 :            :     bool                pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem );
     533                 :            :     bool                pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink );
     534                 :            :     bool                pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable );
     535                 :            : 
     536                 :            :     bool                pushUnaryPreOperator( sal_Int32 nOpCode );
     537                 :            :     bool                pushUnaryPostOperator( sal_Int32 nOpCode );
     538                 :            :     bool                pushBinaryOperator( sal_Int32 nOpCode );
     539                 :            :     bool                pushParenthesesOperator();
     540                 :            :     bool                pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount );
     541                 :            :     bool                pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount );
     542                 :            : 
     543                 :            : private:
     544                 :            :     // reference conversion ---------------------------------------------------
     545                 :            : 
     546                 :            :     void                initReference2d( SingleReference& orApiRef ) const;
     547                 :            :     void                initReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet ) const;
     548                 :            :     void                convertColRow( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bRelativeAsOffset ) const;
     549                 :            :     void                convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const;
     550                 :            :     void                convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const;
     551                 :            :     void                convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const;
     552                 :            :     void                convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const;
     553                 :            :     void                convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const;
     554                 :            :     void                convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const;
     555                 :            : 
     556                 :            : private:
     557                 :            :     // finalize token sequence ------------------------------------------------
     558                 :            : 
     559                 :            :     virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const;
     560                 :            :     virtual ::rtl::OUString resolveDefinedName( sal_Int32 nTokenIndex ) const;
     561                 :            : 
     562                 :            : protected:
     563                 :            :     const sal_Int32     mnMaxApiCol;                /// Maximum column index in own document.
     564                 :            :     const sal_Int32     mnMaxApiRow;                /// Maximum row index in own document.
     565                 :            :     const sal_Int32     mnMaxXlsCol;                /// Maximum column index in imported document.
     566                 :            :     const sal_Int32     mnMaxXlsRow;                /// Maximum row index in imported document.
     567                 :            : 
     568                 :            :     CellAddress         maBaseAddr;                 /// Base address for relative references.
     569                 :            :     bool                mbRelativeAsOffset;         /// True = relative row/column index is (signed) offset, false = explicit index.
     570                 :            :     bool                mb2dRefsAs3dRefs;           /// True = convert all 2D references to 3D references in sheet specified by base address.
     571                 :            :     bool                mbSpecialTokens;            /// True = special handling for tExp and tTbl tokens, false = exit with error.
     572                 :            :     bool                mbAllowNulChars;            /// True = keep NUL characters in string tokens.
     573                 :            : 
     574                 :            : private:
     575                 :            :     typedef ::std::vector< size_t > SizeTypeVector;
     576                 :            : 
     577                 :            :     ApiTokenVector      maTokenStorage;             /// Raw unordered token storage.
     578                 :            :     SizeTypeVector      maTokenIndexes;             /// Indexes into maTokenStorage.
     579                 :            :     SizeTypeVector      maOperandSizeStack;         /// Stack with token sizes per operand.
     580                 :            :     WhiteSpaceVec       maLeadingSpaces;            /// List of whitespaces before next token.
     581                 :            :     WhiteSpaceVec       maOpeningSpaces;            /// List of whitespaces before opening parenthesis.
     582                 :            :     WhiteSpaceVec       maClosingSpaces;            /// List of whitespaces before closing parenthesis.
     583                 :            : };
     584                 :            : 
     585                 :            : // ----------------------------------------------------------------------------
     586                 :            : 
     587                 :         24 : FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) :
     588                 :            :     FormulaFinalizer( rParent ),
     589                 :            :     WorkbookHelper( rParent ),
     590         [ +  - ]:         24 :     mnMaxApiCol( rParent.getAddressConverter().getMaxApiAddress().Column ),
     591         [ +  - ]:         24 :     mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().Row ),
     592         [ +  - ]:         24 :     mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().Column ),
     593         [ +  - ]:         24 :     mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().Row ),
     594                 :            :     mbRelativeAsOffset( false ),
     595                 :            :     mb2dRefsAs3dRefs( false ),
     596                 :            :     mbSpecialTokens( false ),
     597 [ +  - ][ +  - ]:         48 :     mbAllowNulChars( false )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     598                 :            : {
     599                 :            :     // reserve enough space to make resize(), push_back() etc. cheap
     600         [ +  - ]:         24 :     maTokenStorage.reserve( 0x2000 );
     601         [ +  - ]:         24 :     maTokenIndexes.reserve( 0x2000 );
     602         [ +  - ]:         24 :     maOperandSizeStack.reserve( 256 );
     603         [ +  - ]:         24 :     maLeadingSpaces.reserve( 256 );
     604         [ +  - ]:         24 :     maOpeningSpaces.reserve( 256 );
     605         [ +  - ]:         24 :     maClosingSpaces.reserve( 256 );
     606                 :         24 : }
     607                 :            : 
     608                 :          0 : ApiTokenSequence FormulaParserImpl::importOoxFormula( const CellAddress&, const OUString& )
     609                 :            : {
     610                 :            :     OSL_FAIL( "FormulaParserImpl::importOoxFormula - not implemented" );
     611                 :          0 :     return ApiTokenSequence();
     612                 :            : }
     613                 :            : 
     614                 :          0 : ApiTokenSequence FormulaParserImpl::importBiff12Formula( const CellAddress&, FormulaType, SequenceInputStream& )
     615                 :            : {
     616                 :            :     OSL_FAIL( "FormulaParserImpl::importBiff12Formula - not implemented" );
     617                 :          0 :     return ApiTokenSequence();
     618                 :            : }
     619                 :            : 
     620                 :          0 : ApiTokenSequence FormulaParserImpl::importBiffFormula( const CellAddress&, FormulaType, BiffInputStream&, const sal_uInt16* )
     621                 :            : {
     622                 :            :     OSL_FAIL( "FormulaParserImpl::importBiffFormula - not implemented" );
     623                 :          0 :     return ApiTokenSequence();
     624                 :            : }
     625                 :            : 
     626                 :          0 : OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const
     627                 :            : {
     628                 :          0 :     const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId, bUseRefSheets ).get();
     629                 :            :     OSL_ENSURE( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE), "FormulaParserImpl::resolveOleTarget - missing or wrong link" );
     630 [ #  # ][ #  # ]:          0 :     if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE) )
                 [ #  # ]
     631                 :          0 :          return getBaseFilter().getAbsoluteUrl( pExtLink->getTargetUrl() );
     632                 :          0 :     return OUString();
     633                 :            : }
     634                 :            : 
     635                 :          0 : void FormulaParserImpl::initializeImport( const CellAddress& rBaseAddr, FormulaType eType )
     636                 :            : {
     637                 :          0 :     maBaseAddr = rBaseAddr;
     638                 :          0 :     mbRelativeAsOffset = mb2dRefsAs3dRefs = mbSpecialTokens = mbAllowNulChars = false;
     639   [ #  #  #  #  :          0 :     switch( eType )
                #  #  # ]
     640                 :            :     {
     641                 :            :         case FORMULATYPE_CELL:
     642                 :          0 :             mbSpecialTokens = true;
     643                 :          0 :         break;
     644                 :            :         case FORMULATYPE_ARRAY:
     645                 :          0 :         break;
     646                 :            :         case FORMULATYPE_SHAREDFORMULA:
     647                 :          0 :             mbRelativeAsOffset = true;
     648                 :          0 :         break;
     649                 :            :         case FORMULATYPE_CONDFORMAT:
     650                 :          0 :             mbRelativeAsOffset = true;
     651                 :          0 :         break;
     652                 :            :         case FORMULATYPE_VALIDATION:
     653                 :          0 :             mbRelativeAsOffset = true;
     654                 :            :             // enable NUL characters in BIFF import, string list is single tStr token with NUL separators
     655                 :          0 :             mbAllowNulChars = getFilterType() == FILTER_BIFF;
     656                 :          0 :         break;
     657                 :            :         case FORMULATYPE_DEFINEDNAME:
     658                 :          0 :             mbRelativeAsOffset = true;
     659                 :            :             // BIFF2-BIFF4: convert 2D referebces to absolute 3D references
     660 [ #  # ][ #  # ]:          0 :             mb2dRefsAs3dRefs = (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4);
     661                 :          0 :         break;
     662                 :            :     }
     663                 :            : 
     664                 :          0 :     maTokenStorage.clear();
     665                 :          0 :     maTokenIndexes.clear();
     666                 :          0 :     maOperandSizeStack.clear();
     667                 :          0 : }
     668                 :            : 
     669                 :          0 : ApiTokenSequence FormulaParserImpl::finalizeImport()
     670                 :            : {
     671         [ #  # ]:          0 :     ApiTokenSequence aTokens( static_cast< sal_Int32 >( maTokenIndexes.size() ) );
     672         [ #  # ]:          0 :     if( aTokens.hasElements() )
     673                 :            :     {
     674         [ #  # ]:          0 :         ApiToken* pToken = aTokens.getArray();
     675 [ #  # ][ #  # ]:          0 :         for( SizeTypeVector::const_iterator aIt = maTokenIndexes.begin(), aEnd = maTokenIndexes.end(); aIt != aEnd; ++aIt, ++pToken )
         [ #  # ][ #  # ]
                 [ #  # ]
     676         [ #  # ]:          0 :             *pToken = maTokenStorage[ *aIt ];
     677                 :            :     }
     678 [ #  # ][ #  # ]:          0 :     return finalizeTokenArray( aTokens );
     679                 :            : }
     680                 :            : 
     681                 :            : // token array ----------------------------------------------------------------
     682                 :            : 
     683                 :          0 : bool FormulaParserImpl::resetSpaces()
     684                 :            : {
     685                 :          0 :     maLeadingSpaces.clear();
     686                 :          0 :     maOpeningSpaces.clear();
     687                 :          0 :     maClosingSpaces.clear();
     688                 :          0 :     return true;
     689                 :            : }
     690                 :            : 
     691                 :          0 : void FormulaParserImpl::appendSpaces( WhiteSpaceVec& orSpaces, sal_Int32 nCount, bool bLineFeed )
     692                 :            : {
     693                 :            :     OSL_ENSURE( nCount >= 0, "FormulaParserImpl::appendSpaces - negative count" );
     694         [ #  # ]:          0 :     if( nCount > 0 )
     695         [ #  # ]:          0 :         orSpaces.push_back( WhiteSpace( nCount, bLineFeed ) );
     696                 :          0 : }
     697                 :            : 
     698                 :          0 : void FormulaParserImpl::appendLeadingSpaces( sal_Int32 nCount, bool bLineFeed )
     699                 :            : {
     700                 :          0 :     appendSpaces( maLeadingSpaces, nCount, bLineFeed );
     701                 :          0 : }
     702                 :            : 
     703                 :          0 : void FormulaParserImpl::appendOpeningSpaces( sal_Int32 nCount, bool bLineFeed )
     704                 :            : {
     705                 :          0 :     appendSpaces( maOpeningSpaces, nCount, bLineFeed );
     706                 :          0 : }
     707                 :            : 
     708                 :          0 : void FormulaParserImpl::appendClosingSpaces( sal_Int32 nCount, bool bLineFeed )
     709                 :            : {
     710                 :          0 :     appendSpaces( maClosingSpaces, nCount, bLineFeed );
     711                 :          0 : }
     712                 :            : 
     713                 :          0 : size_t FormulaParserImpl::getFormulaSize() const
     714                 :            : {
     715                 :          0 :     return maTokenIndexes.size();
     716                 :            : }
     717                 :            : 
     718                 :          0 : Any& FormulaParserImpl::appendRawToken( sal_Int32 nOpCode )
     719                 :            : {
     720         [ #  # ]:          0 :     maTokenIndexes.push_back( maTokenStorage.size() );
     721                 :          0 :     return maTokenStorage.append( nOpCode );
     722                 :            : }
     723                 :            : 
     724                 :          0 : Any& FormulaParserImpl::insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd )
     725                 :            : {
     726 [ #  # ][ #  # ]:          0 :     maTokenIndexes.insert( maTokenIndexes.end() - nIndexFromEnd, maTokenStorage.size() );
     727                 :          0 :     return maTokenStorage.append( nOpCode );
     728                 :            : }
     729                 :            : 
     730                 :          0 : size_t FormulaParserImpl::appendWhiteSpaceTokens( const WhiteSpaceVec* pSpaces )
     731                 :            : {
     732 [ #  # ][ #  # ]:          0 :     if( pSpaces && !pSpaces->empty() )
                 [ #  # ]
     733 [ #  # ][ #  # ]:          0 :         for( WhiteSpaceVec::const_iterator aIt = pSpaces->begin(), aEnd = pSpaces->end(); aIt != aEnd; ++aIt )
                 [ #  # ]
     734 [ #  # ][ #  # ]:          0 :             appendRawToken( OPCODE_SPACES ) <<= aIt->first;
                 [ #  # ]
     735         [ #  # ]:          0 :     return pSpaces ? pSpaces->size() : 0;
     736                 :            : }
     737                 :            : 
     738                 :          0 : size_t FormulaParserImpl::insertWhiteSpaceTokens( const WhiteSpaceVec* pSpaces, size_t nIndexFromEnd )
     739                 :            : {
     740 [ #  # ][ #  # ]:          0 :     if( pSpaces && !pSpaces->empty() )
                 [ #  # ]
     741 [ #  # ][ #  # ]:          0 :         for( WhiteSpaceVec::const_iterator aIt = pSpaces->begin(), aEnd = pSpaces->end(); aIt != aEnd; ++aIt )
                 [ #  # ]
     742 [ #  # ][ #  # ]:          0 :             insertRawToken( OPCODE_SPACES, nIndexFromEnd ) <<= aIt->first;
                 [ #  # ]
     743         [ #  # ]:          0 :     return pSpaces ? pSpaces->size() : 0;
     744                 :            : }
     745                 :            : 
     746                 :          0 : size_t FormulaParserImpl::getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const
     747                 :            : {
     748                 :            :     OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()),
     749                 :            :         "FormulaParserImpl::getOperandSize - invalid parameters" );
     750                 :          0 :     return maOperandSizeStack[ maOperandSizeStack.size() - nOpCountFromEnd + nOpIndex ];
     751                 :            : }
     752                 :            : 
     753                 :          0 : void FormulaParserImpl::pushOperandSize( size_t nSize )
     754                 :            : {
     755                 :          0 :     maOperandSizeStack.push_back( nSize );
     756                 :          0 : }
     757                 :            : 
     758                 :          0 : size_t FormulaParserImpl::popOperandSize()
     759                 :            : {
     760                 :            :     OSL_ENSURE( !maOperandSizeStack.empty(), "FormulaParserImpl::popOperandSize - invalid call" );
     761                 :          0 :     size_t nOpSize = maOperandSizeStack.back();
     762                 :          0 :     maOperandSizeStack.pop_back();
     763                 :          0 :     return nOpSize;
     764                 :            : }
     765                 :            : 
     766                 :          0 : ApiToken& FormulaParserImpl::getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex )
     767                 :            : {
     768                 :            :     OSL_ENSURE( getOperandSize( nOpCountFromEnd, nOpIndex ) > nTokenIndex,
     769                 :            :         "FormulaParserImpl::getOperandToken - invalid parameters" );
     770         [ #  # ]:          0 :     SizeTypeVector::const_iterator aIndexIt = maTokenIndexes.end();
     771 [ #  # ][ #  # ]:          0 :     for( SizeTypeVector::const_iterator aEnd = maOperandSizeStack.end(), aIt = aEnd - nOpCountFromEnd + nOpIndex; aIt != aEnd; ++aIt )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     772 [ #  # ][ #  # ]:          0 :         aIndexIt -= *aIt;
     773 [ #  # ][ #  # ]:          0 :     return maTokenStorage[ *(aIndexIt + nTokenIndex) ];
     774                 :            : }
     775                 :            : 
     776                 :          0 : bool FormulaParserImpl::pushOperandToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
     777                 :            : {
     778                 :          0 :     size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
     779                 :          0 :     appendRawToken( nOpCode );
     780                 :          0 :     pushOperandSize( nSpacesSize + 1 );
     781                 :          0 :     return true;
     782                 :            : }
     783                 :            : 
     784                 :          0 : bool FormulaParserImpl::pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
     785                 :            : {
     786                 :          0 :     size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
     787                 :          0 :     appendRawToken( nOpCode ) = rAny;
     788                 :          0 :     pushOperandSize( nSpacesSize + 1 );
     789                 :          0 :     return true;
     790                 :            : }
     791                 :            : 
     792                 :            : template< typename Type >
     793                 :          0 : bool FormulaParserImpl::pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
     794                 :            : {
     795                 :          0 :     size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
     796                 :          0 :     appendRawToken( nOpCode ) <<= rValue;
     797                 :          0 :     pushOperandSize( nSpacesSize + 1 );
     798                 :          0 :     return true;
     799                 :            : }
     800                 :            : 
     801                 :          0 : bool FormulaParserImpl::pushParenthesesOperandToken( const WhiteSpaceVec* pOpeningSpaces, const WhiteSpaceVec* pClosingSpaces )
     802                 :            : {
     803                 :          0 :     size_t nSpacesSize = appendWhiteSpaceTokens( pOpeningSpaces );
     804                 :          0 :     appendRawToken( OPCODE_OPEN );
     805                 :          0 :     nSpacesSize += appendWhiteSpaceTokens( pClosingSpaces );
     806                 :          0 :     appendRawToken( OPCODE_CLOSE );
     807                 :          0 :     pushOperandSize( nSpacesSize + 2 );
     808                 :          0 :     return true;
     809                 :            : }
     810                 :            : 
     811                 :          0 : bool FormulaParserImpl::pushUnaryPreOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
     812                 :            : {
     813                 :          0 :     bool bOk = maOperandSizeStack.size() >= 1;
     814         [ #  # ]:          0 :     if( bOk )
     815                 :            :     {
     816                 :          0 :         size_t nOpSize = popOperandSize();
     817                 :          0 :         size_t nSpacesSize = insertWhiteSpaceTokens( pSpaces, nOpSize );
     818                 :          0 :         insertRawToken( nOpCode, nOpSize );
     819                 :          0 :         pushOperandSize( nOpSize + nSpacesSize + 1 );
     820                 :            :     }
     821                 :          0 :     return bOk;
     822                 :            : }
     823                 :            : 
     824                 :          0 : bool FormulaParserImpl::pushUnaryPostOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
     825                 :            : {
     826                 :          0 :     bool bOk = maOperandSizeStack.size() >= 1;
     827         [ #  # ]:          0 :     if( bOk )
     828                 :            :     {
     829                 :          0 :         size_t nOpSize = popOperandSize();
     830                 :          0 :         size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces );
     831                 :          0 :         appendRawToken( nOpCode );
     832                 :          0 :         pushOperandSize( nOpSize + nSpacesSize + 1 );
     833                 :            :     }
     834                 :          0 :     return bOk;
     835                 :            : }
     836                 :            : 
     837                 :          0 : bool FormulaParserImpl::pushBinaryOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces )
     838                 :            : {
     839                 :          0 :     bool bOk = maOperandSizeStack.size() >= 2;
     840         [ #  # ]:          0 :     if( bOk )
     841                 :            :     {
     842                 :          0 :         size_t nOp2Size = popOperandSize();
     843                 :          0 :         size_t nOp1Size = popOperandSize();
     844                 :          0 :         size_t nSpacesSize = insertWhiteSpaceTokens( pSpaces, nOp2Size );
     845                 :          0 :         insertRawToken( nOpCode, nOp2Size );
     846                 :          0 :         pushOperandSize( nOp1Size + nSpacesSize + 1 + nOp2Size );
     847                 :            :     }
     848                 :          0 :     return bOk;
     849                 :            : }
     850                 :            : 
     851                 :          0 : bool FormulaParserImpl::pushParenthesesOperatorToken( const WhiteSpaceVec* pOpeningSpaces, const WhiteSpaceVec* pClosingSpaces )
     852                 :            : {
     853                 :          0 :     bool bOk = maOperandSizeStack.size() >= 1;
     854         [ #  # ]:          0 :     if( bOk )
     855                 :            :     {
     856                 :          0 :         size_t nOpSize = popOperandSize();
     857                 :          0 :         size_t nSpacesSize = insertWhiteSpaceTokens( pOpeningSpaces, nOpSize );
     858                 :          0 :         insertRawToken( OPCODE_OPEN, nOpSize );
     859                 :          0 :         nSpacesSize += appendWhiteSpaceTokens( pClosingSpaces );
     860                 :          0 :         appendRawToken( OPCODE_CLOSE );
     861                 :          0 :         pushOperandSize( nOpSize + nSpacesSize + 2 );
     862                 :            :     }
     863                 :          0 :     return bOk;
     864                 :            : }
     865                 :            : 
     866                 :          0 : bool FormulaParserImpl::pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces, const WhiteSpaceVec* pClosingSpaces )
     867                 :            : {
     868                 :            :     /*  #i70925# if there are not enough tokens available on token stack, do
     869                 :            :         not exit with error, but reduce parameter count. */
     870         [ #  # ]:          0 :     nParamCount = ::std::min( maOperandSizeStack.size(), nParamCount );
     871                 :            : 
     872                 :            :     // convert all parameters on stack to a single operand separated with OPCODE_SEP
     873                 :          0 :     bool bOk = true;
     874 [ #  # ][ #  # ]:          0 :     for( size_t nParam = 1; bOk && (nParam < nParamCount); ++nParam )
                 [ #  # ]
     875                 :          0 :         bOk = pushBinaryOperatorToken( OPCODE_SEP );
     876                 :            : 
     877                 :            :     // add function parentheses and function name
     878                 :            :     return bOk &&
     879                 :          0 :         ((nParamCount > 0) ? pushParenthesesOperatorToken( 0, pClosingSpaces ) : pushParenthesesOperandToken( 0, pClosingSpaces )) &&
     880 [ #  # ][ #  #  :          0 :         pushUnaryPreOperatorToken( nOpCode, pLeadingSpaces );
             #  #  #  # ]
                 [ #  # ]
     881                 :            : }
     882                 :            : 
     883                 :          0 : bool FormulaParserImpl::pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces, const WhiteSpaceVec* pClosingSpaces )
     884                 :            : {
     885                 :          0 :     bool bOk = pushFunctionOperatorToken( rFuncInfo.mnApiOpCode, nParamCount, pLeadingSpaces, pClosingSpaces );
     886         [ #  # ]:          0 :     if( bOk )
     887                 :            :     {
     888                 :            :        // create an external add-in call for the passed built-in function
     889 [ #  # ][ #  # ]:          0 :         if( (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) && !rFuncInfo.maExtProgName.isEmpty() )
                 [ #  # ]
     890                 :          0 :             getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maExtProgName;
     891                 :            :         // create a bad token with unsupported function name
     892 [ #  # ][ #  # ]:          0 :         else if( (rFuncInfo.mnApiOpCode == OPCODE_BAD) && !rFuncInfo.maOoxFuncName.isEmpty() )
                 [ #  # ]
     893                 :          0 :             getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maOoxFuncName;
     894                 :            :     }
     895                 :          0 :     return bOk;
     896                 :            : }
     897                 :            : 
     898                 :          0 : bool FormulaParserImpl::pushOperand( sal_Int32 nOpCode )
     899                 :            : {
     900 [ #  # ][ #  # ]:          0 :     return pushOperandToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
     901                 :            : }
     902                 :            : 
     903                 :          0 : bool FormulaParserImpl::pushAnyOperand( const Any& rAny, sal_Int32 nOpCode )
     904                 :            : {
     905 [ #  # ][ #  # ]:          0 :     return pushAnyOperandToken( rAny, nOpCode, &maLeadingSpaces ) && resetSpaces();
     906                 :            : }
     907                 :            : 
     908                 :            : template< typename Type >
     909                 :          0 : bool FormulaParserImpl::pushValueOperand( const Type& rValue, sal_Int32 nOpCode )
     910                 :            : {
     911 [ #  # ][ #  # ]:          0 :     return pushValueOperandToken( rValue, nOpCode, &maLeadingSpaces ) && resetSpaces();
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     912                 :            : }
     913                 :            : 
     914                 :          0 : bool FormulaParserImpl::pushBoolOperand( bool bValue )
     915                 :            : {
     916 [ #  # ][ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) )
     917                 :          0 :         return pushFunctionOperator( pFuncInfo->mnApiOpCode, 0 );
     918 [ #  # ][ #  # ]:          0 :     return pushValueOperand< double >( bValue ? 1.0 : 0.0 );
     919                 :            : }
     920                 :            : 
     921                 :          0 : bool FormulaParserImpl::pushErrorOperand( double fEncodedError )
     922                 :            : {
     923                 :            :     // HACK: enclose all error codes into an 1x1 matrix
     924                 :            :     // start token array with opening brace and leading spaces
     925                 :          0 :     pushOperand( OPCODE_ARRAY_OPEN );
     926                 :          0 :     size_t nOpSize = popOperandSize();
     927                 :          0 :     size_t nOldArraySize = maTokenIndexes.size();
     928                 :            :     // push a double containing the Calc error code
     929                 :          0 :     appendRawToken( OPCODE_PUSH ) <<= fEncodedError;
     930                 :            :     // close token array and set resulting operand size
     931                 :          0 :     appendRawToken( OPCODE_ARRAY_CLOSE );
     932                 :          0 :     pushOperandSize( nOpSize + maTokenIndexes.size() - nOldArraySize );
     933                 :          0 :     return true;
     934                 :            : }
     935                 :            : 
     936                 :          0 : bool FormulaParserImpl::pushBiffBoolOperand( sal_uInt8 nValue )
     937                 :            : {
     938                 :          0 :     return pushBoolOperand( nValue != BIFF_TOK_BOOL_FALSE );
     939                 :            : }
     940                 :            : 
     941                 :          0 : bool FormulaParserImpl::pushBiffErrorOperand( sal_uInt8 nErrorCode )
     942                 :            : {
     943                 :          0 :     return pushErrorOperand( BiffHelper::calcDoubleFromError( nErrorCode ) );
     944                 :            : }
     945                 :            : 
     946                 :          0 : bool FormulaParserImpl::pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
     947                 :            : {
     948                 :          0 :     SingleReference aApiRef;
     949         [ #  # ]:          0 :     convertReference2d( aApiRef, rRef, bDeleted, bRelativeAsOffset );
     950         [ #  # ]:          0 :     return pushValueOperand( aApiRef );
     951                 :            : }
     952                 :            : 
     953                 :          0 : bool FormulaParserImpl::pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
     954                 :            : {
     955                 :          0 :     ComplexReference aApiRef;
     956         [ #  # ]:          0 :     convertReference2d( aApiRef, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset );
     957         [ #  # ]:          0 :     return pushValueOperand( aApiRef );
     958                 :            : }
     959                 :            : 
     960                 :            : template< typename Type >
     961                 :          0 : bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const Type& rApiRef )
     962                 :            : {
     963 [ #  # ][ #  # ]:          0 :     if( rSheetRange.isExternal() )
     964                 :            :     {
     965                 :          0 :         ExternalReference aApiExtRef;
     966                 :          0 :         aApiExtRef.Index = rSheetRange.getDocLinkIndex();
     967   [ #  #  #  # ]:          0 :         aApiExtRef.Reference <<= rApiRef;
     968 [ #  # ][ #  # ]:          0 :         return pushValueOperand( aApiExtRef );
     969                 :            :     }
     970                 :          0 :     return pushValueOperand( rApiRef );
     971                 :            : }
     972                 :            : 
     973                 :          0 : bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
     974                 :            : {
     975         [ #  # ]:          0 :     if( rSheetRange.is3dRange() )
     976                 :            :     {
     977                 :            :         // single-cell-range over several sheets, needs to create a ComplexReference
     978                 :          0 :         ComplexReference aApiRef;
     979         [ #  # ]:          0 :         convertReference3d( aApiRef, rSheetRange, rRef, rRef, bDeleted, bRelativeAsOffset );
     980         [ #  # ]:          0 :         return pushReferenceOperand( rSheetRange, aApiRef );
     981                 :            :     }
     982                 :          0 :     SingleReference aApiRef;
     983         [ #  # ]:          0 :     convertReference3d( aApiRef, rSheetRange.getFirstSheet(), rSheetRange.isSameSheet(), rRef, bDeleted, bRelativeAsOffset );
     984         [ #  # ]:          0 :     return pushReferenceOperand( rSheetRange, aApiRef );
     985                 :            : }
     986                 :            : 
     987                 :          0 : bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
     988                 :            : {
     989                 :          0 :     ComplexReference aApiRef;
     990         [ #  # ]:          0 :     convertReference3d( aApiRef, rSheetRange, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset );
     991         [ #  # ]:          0 :     return pushReferenceOperand( rSheetRange, aApiRef );
     992                 :            : }
     993                 :            : 
     994                 :          0 : bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d& rRef )
     995                 :            : {
     996                 :          0 :     SingleReference aApiRef;
     997         [ #  # ]:          0 :     convertReference2d( aApiRef, rRef, false, false );
     998         [ #  # ]:          0 :     return pushValueOperand( aApiRef, OPCODE_NLR );
     999                 :            : }
    1000                 :            : 
    1001                 :          0 : bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken )
    1002                 :            : {
    1003         [ #  # ]:          0 :     Any aRefAny = rName.getReference( maBaseAddr );
    1004         [ #  # ]:          0 :     if( aRefAny.hasValue() )
    1005         [ #  # ]:          0 :         return pushAnyOperand( aRefAny, OPCODE_PUSH );
    1006 [ #  # ][ #  # ]:          0 :     if( bPushBadToken && !rName.getModelName().isEmpty() && (rName.getModelName()[ 0 ] >= ' ') )
         [ #  # ][ #  # ]
    1007         [ #  # ]:          0 :         return pushValueOperand( rName.getModelName(), OPCODE_BAD );
    1008         [ #  # ]:          0 :     return pushBiffErrorOperand( BIFF_ERR_NAME );
    1009                 :            : }
    1010                 :            : 
    1011                 :          0 : bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef& rxDefName )
    1012                 :            : {
    1013 [ #  # ][ #  # ]:          0 :     if( !rxDefName || rxDefName->getModelName().isEmpty() )
                 [ #  # ]
    1014                 :          0 :         return pushBiffErrorOperand( BIFF_ERR_NAME );
    1015         [ #  # ]:          0 :     if( rxDefName->isMacroFunction() )
    1016                 :          0 :         return pushValueOperand( rxDefName->getModelName(), OPCODE_MACRO );
    1017         [ #  # ]:          0 :     if( rxDefName->getTokenIndex() >= 0 )
    1018         [ #  # ]:          0 :         return pushValueOperand( rxDefName->getTokenIndex(), OPCODE_NAME );
    1019                 :          0 :     return pushEmbeddedRefOperand( *rxDefName, true );
    1020                 :            : }
    1021                 :            : 
    1022                 :          0 : bool FormulaParserImpl::pushExternalFuncOperand( const FunctionInfo& rFuncInfo )
    1023                 :            : {
    1024                 :            :     return (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) ?
    1025                 :          0 :         pushValueOperand( rFuncInfo.maExtProgName, OPCODE_EXTERNAL ) :
    1026         [ #  # ]:          0 :         pushOperand( rFuncInfo.mnApiOpCode );
    1027                 :            : }
    1028                 :            : 
    1029                 :          0 : bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem )
    1030                 :            : {
    1031                 :            :     // create the function call DDE("server";"topic";"item")
    1032                 :            :     return
    1033                 :          0 :         pushValueOperandToken( rDdeServer ) &&
    1034                 :          0 :         pushValueOperandToken( rDdeTopic ) &&
    1035                 :          0 :         pushValueOperandToken( rDdeItem ) &&
    1036 [ #  # ][ #  #  :          0 :         pushFunctionOperator( OPCODE_DDE, 3 );
             #  #  #  # ]
    1037                 :            : }
    1038                 :            : 
    1039                 :          0 : bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink )
    1040                 :            : {
    1041 [ #  # ][ #  #  :          0 :     if( rxExtName.get() ) switch( rExtLink.getLinkType() )
                #  #  # ]
    1042                 :            :     {
    1043                 :            :         case LINKTYPE_INTERNAL:
    1044                 :            :         case LINKTYPE_EXTERNAL:
    1045                 :          0 :             return pushEmbeddedRefOperand( *rxExtName, false );
    1046                 :            : 
    1047                 :            :         case LINKTYPE_ANALYSIS:
    1048                 :            :             // TODO: need support for localized addin function names
    1049         [ #  # ]:          0 :             if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseModelName() ) )
    1050                 :          0 :                 return pushExternalFuncOperand( *pFuncInfo );
    1051                 :          0 :         break;
    1052                 :            : 
    1053                 :            :         case LINKTYPE_LIBRARY:
    1054         [ #  # ]:          0 :             if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseModelName() ) )
    1055 [ #  # ][ #  # ]:          0 :                 if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == rExtLink.getFuncLibraryType()) )
                 [ #  # ]
    1056                 :          0 :                     return pushExternalFuncOperand( *pFuncInfo );
    1057                 :          0 :         break;
    1058                 :            : 
    1059                 :            :         case LINKTYPE_DDE:
    1060                 :            :         {
    1061                 :          0 :             OUString aDdeServer, aDdeTopic, aDdeItem;
    1062 [ #  # ][ #  # ]:          0 :             if( rxExtName->getDdeLinkData( aDdeServer, aDdeTopic, aDdeItem ) )
    1063 [ #  # ][ #  # ]:          0 :                 return pushDdeLinkOperand( aDdeServer, aDdeTopic, aDdeItem );
         [ #  # ][ #  # ]
    1064                 :            :         }
    1065                 :          0 :         break;
    1066                 :            : 
    1067                 :            :         default:
    1068                 :            :             OSL_ENSURE( rExtLink.getLinkType() != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" );
    1069                 :            :     }
    1070                 :          0 :     return pushBiffErrorOperand( BIFF_ERR_NAME );
    1071                 :            : }
    1072                 :            : 
    1073                 :          0 : bool FormulaParserImpl::pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable )
    1074                 :            : {
    1075                 :          0 :     CellAddress aBaseAddr( maBaseAddr.Sheet, rBaseAddr.mnCol, rBaseAddr.mnRow );
    1076                 :          0 :     ApiSpecialTokenInfo aTokenInfo( aBaseAddr, bTable );
    1077 [ #  # ][ #  # ]:          0 :     return mbSpecialTokens && (getFormulaSize() == 0) && pushValueOperand( aTokenInfo, OPCODE_BAD );
         [ #  # ][ #  # ]
    1078                 :            : }
    1079                 :            : 
    1080                 :          0 : bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode )
    1081                 :            : {
    1082 [ #  # ][ #  # ]:          0 :     return pushUnaryPreOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
    1083                 :            : }
    1084                 :            : 
    1085                 :          0 : bool FormulaParserImpl::pushUnaryPostOperator( sal_Int32 nOpCode )
    1086                 :            : {
    1087 [ #  # ][ #  # ]:          0 :     return pushUnaryPostOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
    1088                 :            : }
    1089                 :            : 
    1090                 :          0 : bool FormulaParserImpl::pushBinaryOperator( sal_Int32 nOpCode )
    1091                 :            : {
    1092 [ #  # ][ #  # ]:          0 :     return pushBinaryOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces();
    1093                 :            : }
    1094                 :            : 
    1095                 :          0 : bool FormulaParserImpl::pushParenthesesOperator()
    1096                 :            : {
    1097 [ #  # ][ #  # ]:          0 :     return pushParenthesesOperatorToken( &maOpeningSpaces, &maClosingSpaces ) && resetSpaces();
    1098                 :            : }
    1099                 :            : 
    1100                 :          0 : bool FormulaParserImpl::pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount )
    1101                 :            : {
    1102 [ #  # ][ #  # ]:          0 :     return pushFunctionOperatorToken( nOpCode, nParamCount, &maLeadingSpaces, &maClosingSpaces ) && resetSpaces();
    1103                 :            : }
    1104                 :            : 
    1105                 :          0 : bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount )
    1106                 :            : {
    1107 [ #  # ][ #  # ]:          0 :     return pushFunctionOperatorToken( rFuncInfo, nParamCount, &maLeadingSpaces, &maClosingSpaces ) && resetSpaces();
    1108                 :            : }
    1109                 :            : 
    1110                 :            : // reference conversion -------------------------------------------------------
    1111                 :            : 
    1112                 :          0 : void FormulaParserImpl::initReference2d( SingleReference& orApiRef ) const
    1113                 :            : {
    1114         [ #  # ]:          0 :     if( mb2dRefsAs3dRefs )
    1115                 :            :     {
    1116                 :          0 :         initReference3d( orApiRef, maBaseAddr.Sheet, false );
    1117                 :            :     }
    1118                 :            :     else
    1119                 :            :     {
    1120                 :          0 :         orApiRef.Flags = SHEET_RELATIVE;
    1121                 :            :         // #i10184# absolute sheet index needed for relative references in shared formulas
    1122                 :          0 :         orApiRef.Sheet = maBaseAddr.Sheet;
    1123                 :          0 :         orApiRef.RelativeSheet = 0;
    1124                 :            :     }
    1125                 :          0 : }
    1126                 :            : 
    1127                 :          0 : void FormulaParserImpl::initReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet ) const
    1128                 :            : {
    1129                 :          0 :     orApiRef.Flags = SHEET_3D;
    1130         [ #  # ]:          0 :     if( nSheet < 0 )
    1131                 :            :     {
    1132                 :          0 :         orApiRef.Sheet = 0;
    1133                 :          0 :         orApiRef.Flags |= SHEET_DELETED;
    1134                 :            :     }
    1135         [ #  # ]:          0 :     else if( bSameSheet )
    1136                 :            :     {
    1137                 :            :         OSL_ENSURE( nSheet == 0, "FormulaParserImpl::initReference3d - invalid sheet index" );
    1138                 :          0 :         orApiRef.Flags |= SHEET_RELATIVE;
    1139                 :          0 :         orApiRef.RelativeSheet = 0;
    1140                 :            :     }
    1141                 :            :     else
    1142                 :            :     {
    1143                 :          0 :         orApiRef.Sheet = nSheet;
    1144                 :            :     }
    1145                 :          0 : }
    1146                 :            : 
    1147                 :          0 : void FormulaParserImpl::convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const
    1148                 :            : {
    1149         [ #  # ]:          0 :     if( bDeleted )
    1150                 :            :     {
    1151                 :          0 :         orApiRef.Column = 0;
    1152                 :          0 :         orApiRef.Row = 0;
    1153                 :            :         // no explicit information about whether row or column is deleted
    1154                 :          0 :         orApiRef.Flags |= COLUMN_DELETED | ROW_DELETED;
    1155                 :            :     }
    1156                 :            :     else
    1157                 :            :     {
    1158                 :            :         // column/row indexes and flags
    1159                 :          0 :         setFlag( orApiRef.Flags, COLUMN_RELATIVE, rRef.mbColRel );
    1160                 :          0 :         setFlag( orApiRef.Flags, ROW_RELATIVE, rRef.mbRowRel );
    1161         [ #  # ]:          0 :         (rRef.mbColRel ? orApiRef.RelativeColumn : orApiRef.Column) = rRef.mnCol;
    1162         [ #  # ]:          0 :         (rRef.mbRowRel ? orApiRef.RelativeRow : orApiRef.Row) = rRef.mnRow;
    1163                 :            :         // convert absolute indexes to relative offsets used in API
    1164         [ #  # ]:          0 :         if( !bRelativeAsOffset )
    1165                 :            :         {
    1166         [ #  # ]:          0 :             if( rRef.mbColRel )
    1167                 :          0 :                 orApiRef.RelativeColumn -= maBaseAddr.Column;
    1168         [ #  # ]:          0 :             if( rRef.mbRowRel )
    1169                 :          0 :                 orApiRef.RelativeRow -= maBaseAddr.Row;
    1170                 :            :         }
    1171                 :            :     }
    1172                 :          0 : }
    1173                 :            : 
    1174                 :          0 : void FormulaParserImpl::convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const
    1175                 :            : {
    1176                 :          0 :     convertReference( orApiRef.Reference1, rRef1, bDeleted, bRelativeAsOffset );
    1177                 :          0 :     convertReference( orApiRef.Reference2, rRef2, bDeleted, bRelativeAsOffset );
    1178                 :            :     /*  Handle references to complete rows or columns (e.g. $1:$2 or C:D),
    1179                 :            :         need to expand or shrink to limits of own document. */
    1180 [ #  # ][ #  # ]:          0 :     if( !bDeleted && !rRef1.mbColRel && !rRef2.mbColRel && (orApiRef.Reference1.Column == 0) && (orApiRef.Reference2.Column == mnMaxXlsCol) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1181                 :          0 :         orApiRef.Reference2.Column = mnMaxApiCol;
    1182 [ #  # ][ #  # ]:          0 :     if( !bDeleted && !rRef1.mbRowRel && !rRef2.mbRowRel && (orApiRef.Reference1.Row == 0) && (orApiRef.Reference2.Row == mnMaxXlsRow) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1183                 :          0 :         orApiRef.Reference2.Row = mnMaxApiRow;
    1184                 :          0 : }
    1185                 :            : 
    1186                 :          0 : void FormulaParserImpl::convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const
    1187                 :            : {
    1188                 :          0 :     initReference2d( orApiRef );
    1189                 :          0 :     convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset );
    1190                 :          0 : }
    1191                 :            : 
    1192                 :          0 : void FormulaParserImpl::convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const
    1193                 :            : {
    1194                 :          0 :     initReference2d( orApiRef.Reference1 );
    1195                 :          0 :     initReference2d( orApiRef.Reference2 );
    1196                 :          0 :     convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset );
    1197                 :            :     // remove sheet name from second part of reference
    1198                 :          0 :     setFlag( orApiRef.Reference2.Flags, SHEET_3D, false );
    1199                 :          0 : }
    1200                 :            : 
    1201                 :          0 : void FormulaParserImpl::convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const
    1202                 :            : {
    1203                 :          0 :     initReference3d( orApiRef, nSheet, bSameSheet );
    1204                 :          0 :     convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset );
    1205                 :          0 : }
    1206                 :            : 
    1207                 :          0 : void FormulaParserImpl::convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const
    1208                 :            : {
    1209                 :          0 :     bool bSameSheet = rSheetRange.isSameSheet();
    1210                 :          0 :     initReference3d( orApiRef.Reference1, rSheetRange.getFirstSheet(), bSameSheet );
    1211                 :          0 :     initReference3d( orApiRef.Reference2, rSheetRange.getLastSheet(), bSameSheet );
    1212                 :          0 :     convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset );
    1213                 :            :     // remove sheet name from second part of reference
    1214                 :          0 :     setFlag( orApiRef.Reference2.Flags, SHEET_3D, rSheetRange.is3dRange() );
    1215                 :          0 : }
    1216                 :            : 
    1217                 :            : // finalize token sequence ----------------------------------------------------
    1218                 :            : 
    1219                 :         12 : const FunctionInfo* FormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const
    1220                 :            : {
    1221                 :            :     /*  Try to parse calls to library functions. The format of such a function
    1222                 :            :         call is "[n]!funcname", n>0 being the link identifier of the function
    1223                 :            :         library spreadsheet file. */
    1224                 :         12 :     sal_Int32 nBracketOpen = rTokenData.indexOf( '[' );
    1225                 :         12 :     sal_Int32 nBracketClose = rTokenData.indexOf( ']' );
    1226                 :         12 :     sal_Int32 nExclamation = rTokenData.indexOf( '!' );
    1227 [ #  # ][ #  # ]:         12 :     if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < rTokenData.getLength()) )
         [ #  # ][ -  + ]
                 [ -  + ]
    1228                 :            :     {
    1229                 :          0 :         sal_Int32 nRefId = rTokenData.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32();
    1230                 :          0 :         const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get();
    1231 [ #  # ][ #  # ]:          0 :         if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) )
                 [ #  # ]
    1232                 :            :         {
    1233                 :          0 :             OUString aFuncName = rTokenData.copy( nExclamation + 1 ).toAsciiUpperCase();
    1234 [ #  # ][ #  # ]:          0 :             if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ) )
    1235 [ #  # ][ #  # ]:          0 :                 if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) )
         [ #  # ][ #  # ]
    1236         [ #  # ]:          0 :                     return pFuncInfo;
    1237                 :            :         }
    1238                 :            :     }
    1239                 :         12 :     return 0;
    1240                 :            : }
    1241                 :            : 
    1242                 :          0 : OUString FormulaParserImpl::resolveDefinedName( sal_Int32 nTokenIndex ) const
    1243                 :            : {
    1244         [ #  # ]:          0 :     if( const DefinedName* pDefName = getDefinedNames().getByTokenIndex( nTokenIndex ).get() )
    1245                 :          0 :         return pDefName->getCalcName();
    1246                 :          0 :     return OUString();
    1247                 :            : }
    1248                 :            : 
    1249                 :            : // OOXML/BIFF12 parser implementation =========================================
    1250                 :            : 
    1251 [ +  - ][ -  + ]:         48 : class OoxFormulaParserImpl : public FormulaParserImpl
    1252                 :            : {
    1253                 :            : public:
    1254                 :            :     explicit            OoxFormulaParserImpl( const FormulaParser& rParent );
    1255                 :            : 
    1256                 :            :     virtual ApiTokenSequence importOoxFormula(
    1257                 :            :                             const CellAddress& rBaseAddr,
    1258                 :            :                             const OUString& rFormulaString );
    1259                 :            : 
    1260                 :            :     virtual ApiTokenSequence importBiff12Formula(
    1261                 :            :                             const CellAddress& rBaseAddr,
    1262                 :            :                             FormulaType eType,
    1263                 :            :                             SequenceInputStream& rStrm );
    1264                 :            : 
    1265                 :            : private:
    1266                 :            :     // import token contents and create API formula token ---------------------
    1267                 :            : 
    1268                 :            :     bool                importAttrToken( SequenceInputStream& rStrm );
    1269                 :            :     bool                importSpaceToken( SequenceInputStream& rStrm );
    1270                 :            :     bool                importTableToken( SequenceInputStream& rStrm );
    1271                 :            :     bool                importArrayToken( SequenceInputStream& rStrm );
    1272                 :            :     bool                importRefToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1273                 :            :     bool                importAreaToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1274                 :            :     bool                importRef3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1275                 :            :     bool                importArea3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1276                 :            :     bool                importMemAreaToken( SequenceInputStream& rStrm, bool bAddData );
    1277                 :            :     bool                importMemFuncToken( SequenceInputStream& rStrm );
    1278                 :            :     bool                importNameToken( SequenceInputStream& rStrm );
    1279                 :            :     bool                importNameXToken( SequenceInputStream& rStrm );
    1280                 :            :     bool                importFuncToken( SequenceInputStream& rStrm );
    1281                 :            :     bool                importFuncVarToken( SequenceInputStream& rStrm );
    1282                 :            :     bool                importExpToken( SequenceInputStream& rStrm );
    1283                 :            : 
    1284                 :            :     LinkSheetRange      readSheetRange( SequenceInputStream& rStrm );
    1285                 :            : 
    1286                 :            :     void                swapStreamPosition( SequenceInputStream& rStrm );
    1287                 :            :     void                skipMemAreaAddData( SequenceInputStream& rStrm );
    1288                 :            : 
    1289                 :            :     // convert BIN token and push API operand or operator ---------------------
    1290                 :            : 
    1291                 :            :     bool                pushBiff12Name( sal_Int32 nNameId );
    1292                 :            :     bool                pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId );
    1293                 :            :     bool                pushBiff12Function( sal_uInt16 nFuncId );
    1294                 :            :     bool                pushBiff12Function( sal_uInt16 nFuncId, sal_uInt8 nParamCount );
    1295                 :            : 
    1296                 :            : private:
    1297                 :            :     ApiParserWrapper    maApiParser;        /// Wrapper for the API formula parser object.
    1298                 :            :     sal_Int64           mnAddDataPos;       /// Current stream position for additional data (tExp, tArray, tMemArea).
    1299                 :            :     bool                mbNeedExtRefs;      /// True = parser needs initialization of external reference info.
    1300                 :            : };
    1301                 :            : 
    1302                 :            : // ----------------------------------------------------------------------------
    1303                 :            : 
    1304                 :         24 : OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser& rParent ) :
    1305                 :            :     FormulaParserImpl( rParent ),
    1306 [ +  - ][ +  - ]:         24 :     maApiParser( rParent.getBaseFilter().getModelFactory(), rParent ),
    1307                 :            :     mnAddDataPos( 0 ),
    1308         [ +  - ]:         48 :     mbNeedExtRefs( true )
    1309                 :            : {
    1310                 :         24 : }
    1311                 :            : 
    1312                 :        117 : ApiTokenSequence OoxFormulaParserImpl::importOoxFormula( const CellAddress& rBaseAddr, const OUString& rFormulaString )
    1313                 :            : {
    1314         [ +  + ]:        117 :     if( mbNeedExtRefs )
    1315                 :            :     {
    1316         [ +  - ]:         18 :         maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() );
    1317                 :         18 :         mbNeedExtRefs = false;
    1318                 :            :     }
    1319         [ +  - ]:        117 :     return finalizeTokenArray( maApiParser.parseFormula( rFormulaString, rBaseAddr ) );
    1320                 :            : }
    1321                 :            : 
    1322                 :          0 : ApiTokenSequence OoxFormulaParserImpl::importBiff12Formula( const CellAddress& rBaseAddr, FormulaType eType, SequenceInputStream& rStrm )
    1323                 :            : {
    1324                 :          0 :     initializeImport( rBaseAddr, eType );
    1325                 :            : 
    1326                 :          0 :     sal_Int32 nFmlaSize = rStrm.readInt32();
    1327                 :          0 :     sal_Int64 nFmlaPos = rStrm.tell();
    1328                 :          0 :     sal_Int64 nFmlaEndPos = nFmlaPos + nFmlaSize;
    1329                 :            : 
    1330                 :          0 :     rStrm.seek( nFmlaEndPos );
    1331                 :          0 :     sal_Int32 nAddDataSize = rStrm.readInt32();
    1332                 :          0 :     mnAddDataPos = rStrm.tell();
    1333                 :          0 :     sal_Int64 nAddDataEndPos = mnAddDataPos + nAddDataSize;
    1334                 :          0 :     rStrm.seek( nFmlaPos );
    1335                 :            : 
    1336 [ #  # ][ #  # ]:          0 :     bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0);
    1337                 :          0 :     bool bRelativeAsOffset = mbRelativeAsOffset;
    1338                 :            : 
    1339 [ #  # ][ #  # ]:          0 :     while( bOk && !rStrm.isEof() && (rStrm.tell() < nFmlaEndPos) )
         [ #  # ][ #  # ]
    1340                 :            :     {
    1341                 :            :         sal_uInt8 nTokenId;
    1342         [ #  # ]:          0 :         rStrm >> nTokenId;
    1343                 :          0 :         sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK;
    1344                 :          0 :         sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK;
    1345                 :            : 
    1346         [ #  # ]:          0 :         if( nTokenClass == BIFF_TOKCLASS_NONE )
    1347                 :            :         {
    1348                 :            :             // base tokens
    1349   [ #  #  #  #  :          0 :             switch( nBaseId )
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1350                 :            :             {
    1351         [ #  # ]:          0 :                 case BIFF_TOKID_EXP:        bOk = importExpToken( rStrm );                                      break;
    1352         [ #  # ]:          0 :                 case BIFF_TOKID_ADD:        bOk = pushBinaryOperator( OPCODE_ADD );                             break;
    1353         [ #  # ]:          0 :                 case BIFF_TOKID_SUB:        bOk = pushBinaryOperator( OPCODE_SUB );                             break;
    1354         [ #  # ]:          0 :                 case BIFF_TOKID_MUL:        bOk = pushBinaryOperator( OPCODE_MULT );                            break;
    1355         [ #  # ]:          0 :                 case BIFF_TOKID_DIV:        bOk = pushBinaryOperator( OPCODE_DIV );                             break;
    1356         [ #  # ]:          0 :                 case BIFF_TOKID_POWER:      bOk = pushBinaryOperator( OPCODE_POWER );                           break;
    1357         [ #  # ]:          0 :                 case BIFF_TOKID_CONCAT:     bOk = pushBinaryOperator( OPCODE_CONCAT );                          break;
    1358         [ #  # ]:          0 :                 case BIFF_TOKID_LT:         bOk = pushBinaryOperator( OPCODE_LESS );                            break;
    1359         [ #  # ]:          0 :                 case BIFF_TOKID_LE:         bOk = pushBinaryOperator( OPCODE_LESS_EQUAL );                      break;
    1360         [ #  # ]:          0 :                 case BIFF_TOKID_EQ:         bOk = pushBinaryOperator( OPCODE_EQUAL );                           break;
    1361         [ #  # ]:          0 :                 case BIFF_TOKID_GE:         bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL );                   break;
    1362         [ #  # ]:          0 :                 case BIFF_TOKID_GT:         bOk = pushBinaryOperator( OPCODE_GREATER );                         break;
    1363         [ #  # ]:          0 :                 case BIFF_TOKID_NE:         bOk = pushBinaryOperator( OPCODE_NOT_EQUAL );                       break;
    1364         [ #  # ]:          0 :                 case BIFF_TOKID_ISECT:      bOk = pushBinaryOperator( OPCODE_INTERSECT );                       break;
    1365         [ #  # ]:          0 :                 case BIFF_TOKID_LIST:       bOk = pushBinaryOperator( OPCODE_LIST );                            break;
    1366         [ #  # ]:          0 :                 case BIFF_TOKID_RANGE:      bOk = pushBinaryOperator( OPCODE_RANGE );                           break;
    1367         [ #  # ]:          0 :                 case BIFF_TOKID_UPLUS:      bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN );                     break;
    1368         [ #  # ]:          0 :                 case BIFF_TOKID_UMINUS:     bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN );                    break;
    1369         [ #  # ]:          0 :                 case BIFF_TOKID_PERCENT:    bOk = pushUnaryPostOperator( OPCODE_PERCENT );                      break;
    1370         [ #  # ]:          0 :                 case BIFF_TOKID_PAREN:      bOk = pushParenthesesOperator();                                    break;
    1371         [ #  # ]:          0 :                 case BIFF_TOKID_MISSARG:    bOk = pushOperand( OPCODE_MISSING );                                break;
    1372 [ #  # ][ #  # ]:          0 :                 case BIFF_TOKID_STR:        bOk = pushValueOperand( BiffHelper::readString( rStrm, false ) );   break;
    1373         [ #  # ]:          0 :                 case BIFF_TOKID_NLR:        bOk = importTableToken( rStrm );                                    break;
    1374         [ #  # ]:          0 :                 case BIFF_TOKID_ATTR:       bOk = importAttrToken( rStrm );                                     break;
    1375 [ #  # ][ #  # ]:          0 :                 case BIFF_TOKID_ERR:        bOk = pushBiffErrorOperand( rStrm.readuInt8() );                    break;
    1376 [ #  # ][ #  # ]:          0 :                 case BIFF_TOKID_BOOL:       bOk = pushBiffBoolOperand( rStrm.readuInt8() );                     break;
    1377 [ #  # ][ #  # ]:          0 :                 case BIFF_TOKID_INT:        bOk = pushValueOperand< double >( rStrm.readuInt16() );             break;
    1378 [ #  # ][ #  # ]:          0 :                 case BIFF_TOKID_NUM:        bOk = pushValueOperand( rStrm.readDouble() );                       break;
    1379                 :          0 :                 default:                    bOk = false;
    1380                 :            :             }
    1381                 :            :         }
    1382                 :            :         else
    1383                 :            :         {
    1384                 :            :             // classified tokens
    1385   [ #  #  #  #  :          0 :             switch( nBaseId )
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1386                 :            :             {
    1387         [ #  # ]:          0 :                 case BIFF_TOKID_ARRAY:      bOk = importArrayToken( rStrm );                            break;
    1388         [ #  # ]:          0 :                 case BIFF_TOKID_FUNC:       bOk = importFuncToken( rStrm );                             break;
    1389         [ #  # ]:          0 :                 case BIFF_TOKID_FUNCVAR:    bOk = importFuncVarToken( rStrm );                          break;
    1390         [ #  # ]:          0 :                 case BIFF_TOKID_NAME:       bOk = importNameToken( rStrm );                             break;
    1391         [ #  # ]:          0 :                 case BIFF_TOKID_REF:        bOk = importRefToken( rStrm, false, false );                break;
    1392         [ #  # ]:          0 :                 case BIFF_TOKID_AREA:       bOk = importAreaToken( rStrm, false, false );               break;
    1393         [ #  # ]:          0 :                 case BIFF_TOKID_MEMAREA:    bOk = importMemAreaToken( rStrm, true );                    break;
    1394         [ #  # ]:          0 :                 case BIFF_TOKID_MEMERR:     bOk = importMemAreaToken( rStrm, false );                   break;
    1395         [ #  # ]:          0 :                 case BIFF_TOKID_MEMNOMEM:   bOk = importMemAreaToken( rStrm, false );                   break;
    1396         [ #  # ]:          0 :                 case BIFF_TOKID_MEMFUNC:    bOk = importMemFuncToken( rStrm );                          break;
    1397         [ #  # ]:          0 :                 case BIFF_TOKID_REFERR:     bOk = importRefToken( rStrm, true, false );                 break;
    1398         [ #  # ]:          0 :                 case BIFF_TOKID_AREAERR:    bOk = importAreaToken( rStrm, true, false );                break;
    1399         [ #  # ]:          0 :                 case BIFF_TOKID_REFN:       bOk = importRefToken( rStrm, false, true );                 break;
    1400         [ #  # ]:          0 :                 case BIFF_TOKID_AREAN:      bOk = importAreaToken( rStrm, false, true );                break;
    1401         [ #  # ]:          0 :                 case BIFF_TOKID_MEMAREAN:   bOk = importMemFuncToken( rStrm );                          break;
    1402         [ #  # ]:          0 :                 case BIFF_TOKID_MEMNOMEMN:  bOk = importMemFuncToken( rStrm );                          break;
    1403         [ #  # ]:          0 :                 case BIFF_TOKID_NAMEX:      bOk = importNameXToken( rStrm );                            break;
    1404         [ #  # ]:          0 :                 case BIFF_TOKID_REF3D:      bOk = importRef3dToken( rStrm, false, bRelativeAsOffset );  break;
    1405         [ #  # ]:          0 :                 case BIFF_TOKID_AREA3D:     bOk = importArea3dToken( rStrm, false, bRelativeAsOffset ); break;
    1406         [ #  # ]:          0 :                 case BIFF_TOKID_REFERR3D:   bOk = importRef3dToken( rStrm, true, bRelativeAsOffset );   break;
    1407         [ #  # ]:          0 :                 case BIFF_TOKID_AREAERR3D:  bOk = importArea3dToken( rStrm, true, bRelativeAsOffset );  break;
    1408                 :          0 :                 default:                    bOk = false;
    1409                 :            :             }
    1410                 :            :         }
    1411                 :            :     }
    1412                 :            : 
    1413                 :            :     // build and finalize the token sequence
    1414                 :          0 :     ApiTokenSequence aFinalTokens;
    1415 [ #  # ][ #  # ]:          0 :     if( bOk && (rStrm.tell() == nFmlaEndPos) && (mnAddDataPos == nAddDataEndPos) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1416 [ #  # ][ #  # ]:          0 :         aFinalTokens = finalizeImport();
                 [ #  # ]
    1417                 :            : 
    1418                 :            :     // seek behind token array
    1419 [ #  # ][ #  # ]:          0 :     if( (nFmlaSize >= 0) && (nAddDataSize >= 0) )
    1420         [ #  # ]:          0 :         rStrm.seek( nAddDataEndPos );
    1421                 :            : 
    1422                 :            :     // return the final token sequence
    1423                 :          0 :     return aFinalTokens;
    1424                 :            : }
    1425                 :            : 
    1426                 :            : // import token contents and create API formula token -------------------------
    1427                 :            : 
    1428                 :          0 : bool OoxFormulaParserImpl::importAttrToken( SequenceInputStream& rStrm )
    1429                 :            : {
    1430                 :          0 :     bool bOk = true;
    1431                 :            :     sal_uInt8 nType;
    1432         [ #  # ]:          0 :     rStrm >> nType;
    1433                 :            :     // equal flags in all BIFFs
    1434   [ #  #  #  #  :          0 :     switch( nType )
                      # ]
    1435                 :            :     {
    1436                 :            :         case 0:     // sometimes, tAttrSkip tokens miss the type flag
    1437                 :            :         case BIFF_TOK_ATTR_VOLATILE:
    1438                 :            :         case BIFF_TOK_ATTR_IF:
    1439                 :            :         case BIFF_TOK_ATTR_SKIP:
    1440                 :            :         case BIFF_TOK_ATTR_ASSIGN:
    1441                 :            :         case BIFF_TOK_ATTR_IFERROR:
    1442         [ #  # ]:          0 :             rStrm.skip( 2 );
    1443                 :          0 :         break;
    1444                 :            :         case BIFF_TOK_ATTR_CHOOSE:
    1445 [ #  # ][ #  # ]:          0 :             rStrm.skip( 2 * rStrm.readuInt16() + 2 );
    1446                 :          0 :         break;
    1447                 :            :         case BIFF_TOK_ATTR_SUM:
    1448         [ #  # ]:          0 :             rStrm.skip( 2 );
    1449         [ #  # ]:          0 :             bOk = pushBiff12Function( BIFF_FUNC_SUM, 1 );
    1450                 :          0 :         break;
    1451                 :            :         case BIFF_TOK_ATTR_SPACE:
    1452                 :            :         case BIFF_TOK_ATTR_SPACE_VOLATILE:
    1453         [ #  # ]:          0 :             bOk = importSpaceToken( rStrm );
    1454                 :          0 :         break;
    1455                 :            :         default:
    1456                 :          0 :             bOk = false;
    1457                 :            :     }
    1458                 :          0 :     return bOk;
    1459                 :            : }
    1460                 :            : 
    1461                 :          0 : bool OoxFormulaParserImpl::importSpaceToken( SequenceInputStream& rStrm )
    1462                 :            : {
    1463                 :            :     // equal constants in BIFF and OOX
    1464                 :            :     sal_uInt8 nType, nCount;
    1465 [ #  # ][ #  # ]:          0 :     rStrm >> nType >> nCount;
    1466   [ #  #  #  #  :          0 :     switch( nType )
                #  #  # ]
    1467                 :            :     {
    1468                 :            :         case BIFF_TOK_ATTR_SPACE_SP:
    1469         [ #  # ]:          0 :             appendLeadingSpaces( nCount, false );
    1470                 :          0 :         break;
    1471                 :            :         case BIFF_TOK_ATTR_SPACE_BR:
    1472         [ #  # ]:          0 :             appendLeadingSpaces( nCount, true );
    1473                 :          0 :         break;
    1474                 :            :         case BIFF_TOK_ATTR_SPACE_SP_OPEN:
    1475         [ #  # ]:          0 :             appendOpeningSpaces( nCount, false );
    1476                 :          0 :         break;
    1477                 :            :         case BIFF_TOK_ATTR_SPACE_BR_OPEN:
    1478         [ #  # ]:          0 :             appendOpeningSpaces( nCount, true );
    1479                 :          0 :         break;
    1480                 :            :         case BIFF_TOK_ATTR_SPACE_SP_CLOSE:
    1481         [ #  # ]:          0 :             appendClosingSpaces( nCount, false );
    1482                 :          0 :         break;
    1483                 :            :         case BIFF_TOK_ATTR_SPACE_BR_CLOSE:
    1484         [ #  # ]:          0 :             appendClosingSpaces( nCount, true );
    1485                 :          0 :         break;
    1486                 :            :     }
    1487                 :          0 :     return true;
    1488                 :            : }
    1489                 :            : 
    1490                 :          0 : bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm )
    1491                 :            : {
    1492                 :            :     sal_uInt16 nFlags, nTableId, nCol1, nCol2;
    1493         [ #  # ]:          0 :     rStrm.skip( 3 );
    1494 [ #  # ][ #  # ]:          0 :     rStrm >> nFlags >> nTableId;
    1495         [ #  # ]:          0 :     rStrm.skip( 2 );
    1496 [ #  # ][ #  # ]:          0 :     rStrm >> nCol1 >> nCol2;
    1497 [ #  # ][ #  # ]:          0 :     TableRef xTable = getTables().getTable( nTableId );
    1498         [ #  # ]:          0 :     sal_Int32 nTokenIndex = xTable.get() ? xTable->getTokenIndex() : -1;
    1499         [ #  # ]:          0 :     if( nTokenIndex >= 0 )
    1500                 :            :     {
    1501                 :          0 :         sal_Int32 nWidth = xTable->getWidth();
    1502                 :          0 :         sal_Int32 nHeight = xTable->getHeight();
    1503                 :          0 :         sal_Int32 nStartCol = 0;
    1504                 :          0 :         sal_Int32 nEndCol = nWidth - 1;
    1505                 :          0 :         sal_Int32 nStartRow = 0;
    1506                 :          0 :         sal_Int32 nEndRow = nHeight - 1;
    1507                 :          0 :         bool bFixedStartRow = true;
    1508                 :          0 :         bool bFixedHeight = false;
    1509                 :            : 
    1510                 :          0 :         bool bSingleCol = getFlag( nFlags, BIFF12_TOK_TABLE_COLUMN );
    1511                 :          0 :         bool bColRange = getFlag( nFlags, BIFF12_TOK_TABLE_COLRANGE );
    1512 [ #  # ][ #  # ]:          0 :         bool bValidRef = !bSingleCol || !bColRange;
    1513                 :            :         OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - illegal combination of single column and column range" );
    1514         [ #  # ]:          0 :         if( bValidRef )
    1515                 :            :         {
    1516         [ #  # ]:          0 :             if( bSingleCol )
    1517                 :          0 :                 nStartCol = nEndCol = nCol1;
    1518         [ #  # ]:          0 :             else if( bColRange )
    1519                 :          0 :                 { nStartCol = nCol1; nEndCol = nCol2; }
    1520 [ #  # ][ #  # ]:          0 :             bValidRef = (nStartCol <= nEndCol) && (nEndCol < nWidth);
    1521                 :            :             OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid column range" );
    1522                 :            :         }
    1523                 :            : 
    1524         [ #  # ]:          0 :         if( bValidRef )
    1525                 :            :         {
    1526                 :          0 :             bool bAllRows    = getFlag( nFlags, BIFF12_TOK_TABLE_ALL );
    1527                 :          0 :             bool bHeaderRows = getFlag( nFlags, BIFF12_TOK_TABLE_HEADERS );
    1528                 :          0 :             bool bDataRows   = getFlag( nFlags, BIFF12_TOK_TABLE_DATA );
    1529                 :          0 :             bool bTotalsRows = getFlag( nFlags, BIFF12_TOK_TABLE_TOTALS );
    1530                 :          0 :             bool bThisRow    = getFlag( nFlags, BIFF12_TOK_TABLE_THISROW );
    1531                 :            : 
    1532                 :          0 :             sal_Int32 nStartDataRow = xTable->getHeaderRows();
    1533                 :          0 :             sal_Int32 nEndDataRow = nEndRow - xTable->getTotalsRows();
    1534 [ #  # ][ #  # ]:          0 :             bValidRef = (nStartRow <= nStartDataRow) && (nStartDataRow <= nEndDataRow) && (nEndDataRow <= nEndRow);
                 [ #  # ]
    1535                 :            :             OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid data row range" );
    1536         [ #  # ]:          0 :             if( bValidRef )
    1537                 :            :             {
    1538         [ #  # ]:          0 :                 if( bAllRows )
    1539                 :            :                 {
    1540 [ #  # ][ #  # ]:          0 :                     bValidRef = !bHeaderRows && !bDataRows && !bTotalsRows && !bThisRow;
         [ #  # ][ #  # ]
    1541                 :            :                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#All] table token" );
    1542                 :            :                 }
    1543         [ #  # ]:          0 :                 else if( bHeaderRows )
    1544                 :            :                 {
    1545 [ #  # ][ #  # ]:          0 :                     bValidRef = !bTotalsRows && !bThisRow;
    1546                 :            :                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Headers] table token" );
    1547         [ #  # ]:          0 :                     nEndRow = bDataRows ? nEndDataRow : (nStartDataRow - 1);
    1548                 :          0 :                     bFixedHeight = !bDataRows;
    1549                 :            :                 }
    1550         [ #  # ]:          0 :                 else if( bDataRows )
    1551                 :            :                 {
    1552                 :          0 :                     bValidRef = !bThisRow;
    1553                 :            :                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Data] table token" );
    1554                 :          0 :                     nStartRow = nStartDataRow;
    1555         [ #  # ]:          0 :                     if( !bTotalsRows ) nEndRow = nEndDataRow;
    1556                 :            :                 }
    1557         [ #  # ]:          0 :                 else if( bTotalsRows )
    1558                 :            :                 {
    1559                 :          0 :                     bValidRef = !bThisRow;
    1560                 :            :                     OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Totals] table token" );
    1561                 :          0 :                     nStartRow = nEndDataRow + 1;
    1562                 :          0 :                     bFixedStartRow = false;
    1563                 :          0 :                     bFixedHeight = !bDataRows;
    1564                 :            :                 }
    1565         [ #  # ]:          0 :                 else if( bThisRow )
    1566                 :            :                 {
    1567                 :          0 :                     nStartRow = nEndRow = maBaseAddr.Row - xTable->getRange().StartRow;
    1568                 :          0 :                     bFixedHeight = true;
    1569                 :            :                 }
    1570                 :            :                 else
    1571                 :            :                 {
    1572                 :            :                     // nothing is the same as [#Data]
    1573                 :          0 :                     nStartRow = nStartDataRow;
    1574                 :          0 :                     nEndRow = nEndDataRow;
    1575                 :            :                 }
    1576                 :            :             }
    1577         [ #  # ]:          0 :             if( bValidRef )
    1578 [ #  # ][ #  # ]:          0 :                 bValidRef = (0 <= nStartRow) && (nStartRow <= nEndRow) && (nEndRow < nHeight);
                 [ #  # ]
    1579                 :            :         }
    1580         [ #  # ]:          0 :         if( bValidRef )
    1581                 :            :         {
    1582                 :            :             // push single database area token, if table token refers to entire table
    1583 [ #  # ][ #  # ]:          0 :             if( (nStartCol == 0) && (nEndCol + 1 == nWidth) && (nStartRow == 0) && (nEndRow + 1 == nHeight) )
         [ #  # ][ #  # ]
    1584         [ #  # ]:          0 :                 return pushValueOperand( nTokenIndex, OPCODE_DBAREA );
    1585                 :            :             // create an OFFSET function call to refer to a subrange of the table
    1586         [ #  # ]:          0 :             const FunctionInfo* pRowsInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_ROWS );
    1587         [ #  # ]:          0 :             const FunctionInfo* pColumnsInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_COLUMNS );
    1588                 :            :             return
    1589                 :            :                 pRowsInfo && pColumnsInfo &&
    1590         [ #  # ]:          0 :                 pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
    1591                 :            :                 (bFixedStartRow ?
    1592 [ #  # ][ #  # ]:          0 :                     pushValueOperandToken< double >( nStartRow ) :
                 [ #  # ]
    1593         [ #  # ]:          0 :                     (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
    1594         [ #  # ]:          0 :                      pushFunctionOperatorToken( *pRowsInfo, 1 ) &&
    1595 [ #  # ][ #  # ]:          0 :                      pushValueOperandToken< double >( nHeight - nStartRow ) &&
                 [ #  # ]
    1596         [ #  # ]:          0 :                      pushBinaryOperatorToken( OPCODE_SUB ))) &&
    1597 [ #  # ][ #  # ]:          0 :                 pushValueOperandToken< double >( nStartCol ) &&
                 [ #  # ]
    1598                 :            :                 (bFixedHeight ?
    1599 [ #  # ][ #  # ]:          0 :                     pushValueOperandToken< double >( nEndRow - nStartRow + 1 ) :
                 [ #  # ]
    1600         [ #  # ]:          0 :                     (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
    1601         [ #  # ]:          0 :                      pushFunctionOperatorToken( *pRowsInfo, 1 ) &&
    1602                 :            :                      (((nStartRow == 0) && (nEndRow + 1 == nHeight)) ||
    1603 [ #  # ][ #  # ]:          0 :                       (pushValueOperandToken< double >( nHeight - (nEndRow - nStartRow + 1) ) &&
                 [ #  # ]
    1604         [ #  # ]:          0 :                        pushBinaryOperatorToken( OPCODE_SUB ))))) &&
    1605                 :            :                 (((nStartCol == 0) && (nEndCol + 1 == nWidth)) ?
    1606         [ #  # ]:          0 :                     (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
    1607         [ #  # ]:          0 :                      pushFunctionOperatorToken( *pColumnsInfo, 1 )) :
    1608 [ #  # ][ #  # ]:          0 :                     pushValueOperandToken< double >( nEndCol - nStartCol + 1 )) &&
                 [ #  # ]
    1609 [ #  # ][ #  # ]:          0 :                 pushBiff12Function( BIFF_FUNC_OFFSET, 5 );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1610                 :            :         }
    1611                 :            :     }
    1612 [ #  # ][ #  # ]:          0 :     return pushBiffErrorOperand( BIFF_ERR_REF );
    1613                 :            : }
    1614                 :            : 
    1615                 :          0 : bool OoxFormulaParserImpl::importArrayToken( SequenceInputStream& rStrm )
    1616                 :            : {
    1617                 :          0 :     rStrm.skip( 14 );
    1618                 :            : 
    1619                 :            :     // start token array with opening brace and leading spaces
    1620                 :          0 :     pushOperand( OPCODE_ARRAY_OPEN );
    1621                 :          0 :     size_t nOpSize = popOperandSize();
    1622                 :          0 :     size_t nOldArraySize = getFormulaSize();
    1623                 :            : 
    1624                 :            :     // read array size
    1625                 :          0 :     swapStreamPosition( rStrm );
    1626                 :          0 :     sal_Int32 nRows = rStrm.readInt32();
    1627                 :          0 :     sal_Int32 nCols = rStrm.readInt32();
    1628                 :            :     OSL_ENSURE( (nCols > 0) && (nRows > 0), "OoxFormulaParserImpl::importArrayToken - empty array" );
    1629                 :            : 
    1630                 :            :     // read array values and build token array
    1631 [ #  # ][ #  # ]:          0 :     for( sal_Int32 nRow = 0; !rStrm.isEof() && (nRow < nRows); ++nRow )
                 [ #  # ]
    1632                 :            :     {
    1633         [ #  # ]:          0 :         if( nRow > 0 )
    1634                 :          0 :             appendRawToken( OPCODE_ARRAY_ROWSEP );
    1635 [ #  # ][ #  # ]:          0 :         for( sal_Int32 nCol = 0; !rStrm.isEof() && (nCol < nCols); ++nCol )
                 [ #  # ]
    1636                 :            :         {
    1637         [ #  # ]:          0 :             if( nCol > 0 )
    1638                 :          0 :                 appendRawToken( OPCODE_ARRAY_COLSEP );
    1639   [ #  #  #  #  :          0 :             switch( rStrm.readuInt8() )
                      # ]
    1640                 :            :             {
    1641                 :            :                 case BIFF_TOK_ARRAY_DOUBLE:
    1642 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= rStrm.readDouble();
    1643                 :          0 :                 break;
    1644                 :            :                 case BIFF_TOK_ARRAY_STRING:
    1645 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::readString( rStrm, false );
    1646                 :          0 :                 break;
    1647                 :            :                 case BIFF_TOK_ARRAY_BOOL:
    1648 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= (static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 ));
                 [ #  # ]
    1649                 :          0 :                 break;
    1650                 :            :                 case BIFF_TOK_ARRAY_ERROR:
    1651 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() );
    1652                 :          0 :                     rStrm.skip( 3 );
    1653                 :          0 :                 break;
    1654                 :            :                 default:
    1655                 :            :                     OSL_FAIL( "OoxFormulaParserImpl::importArrayToken - unknown data type" );
    1656 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA );
    1657                 :            :             }
    1658                 :            :         }
    1659                 :            :     }
    1660                 :          0 :     swapStreamPosition( rStrm );
    1661                 :            : 
    1662                 :            :     // close token array and set resulting operand size
    1663                 :          0 :     appendRawToken( OPCODE_ARRAY_CLOSE );
    1664                 :          0 :     pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize );
    1665                 :          0 :     return true;
    1666                 :            : }
    1667                 :            : 
    1668                 :          0 : bool OoxFormulaParserImpl::importRefToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    1669                 :            : {
    1670         [ #  # ]:          0 :     BinSingleRef2d aRef;
    1671         [ #  # ]:          0 :     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
    1672         [ #  # ]:          0 :     return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset );
    1673                 :            : }
    1674                 :            : 
    1675                 :          0 : bool OoxFormulaParserImpl::importAreaToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    1676                 :            : {
    1677         [ #  # ]:          0 :     BinComplexRef2d aRef;
    1678         [ #  # ]:          0 :     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
    1679         [ #  # ]:          0 :     return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset );
    1680                 :            : }
    1681                 :            : 
    1682                 :          0 : bool OoxFormulaParserImpl::importRef3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    1683                 :            : {
    1684         [ #  # ]:          0 :     LinkSheetRange aSheetRange = readSheetRange( rStrm );
    1685         [ #  # ]:          0 :     BinSingleRef2d aRef;
    1686         [ #  # ]:          0 :     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
    1687         [ #  # ]:          0 :     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
    1688                 :            : }
    1689                 :            : 
    1690                 :          0 : bool OoxFormulaParserImpl::importArea3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    1691                 :            : {
    1692         [ #  # ]:          0 :     LinkSheetRange aSheetRange = readSheetRange( rStrm );
    1693         [ #  # ]:          0 :     BinComplexRef2d aRef;
    1694         [ #  # ]:          0 :     aRef.readBiff12Data( rStrm, bRelativeAsOffset );
    1695         [ #  # ]:          0 :     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
    1696                 :            : }
    1697                 :            : 
    1698                 :          0 : bool OoxFormulaParserImpl::importMemAreaToken( SequenceInputStream& rStrm, bool bAddData )
    1699                 :            : {
    1700                 :          0 :     rStrm.skip( 6 );
    1701         [ #  # ]:          0 :     if( bAddData )
    1702                 :          0 :         skipMemAreaAddData( rStrm );
    1703                 :          0 :     return true;
    1704                 :            : }
    1705                 :            : 
    1706                 :          0 : bool OoxFormulaParserImpl::importMemFuncToken( SequenceInputStream& rStrm )
    1707                 :            : {
    1708                 :          0 :     rStrm.skip( 2 );
    1709                 :          0 :     return true;
    1710                 :            : }
    1711                 :            : 
    1712                 :          0 : bool OoxFormulaParserImpl::importNameToken( SequenceInputStream& rStrm )
    1713                 :            : {
    1714                 :          0 :     return pushBiff12Name( rStrm.readInt32() );
    1715                 :            : }
    1716                 :            : 
    1717                 :          0 : bool OoxFormulaParserImpl::importNameXToken( SequenceInputStream& rStrm )
    1718                 :            : {
    1719                 :          0 :     sal_Int32 nRefId = rStrm.readInt16();
    1720                 :          0 :     sal_Int32 nNameId = rStrm.readInt32();
    1721                 :          0 :     return pushBiff12ExtName( nRefId, nNameId );
    1722                 :            : }
    1723                 :            : 
    1724                 :          0 : bool OoxFormulaParserImpl::importFuncToken( SequenceInputStream& rStrm )
    1725                 :            : {
    1726                 :            :     sal_uInt16 nFuncId;
    1727         [ #  # ]:          0 :     rStrm >> nFuncId;
    1728         [ #  # ]:          0 :     return pushBiff12Function( nFuncId );
    1729                 :            : }
    1730                 :            : 
    1731                 :          0 : bool OoxFormulaParserImpl::importFuncVarToken( SequenceInputStream& rStrm )
    1732                 :            : {
    1733                 :            :     sal_uInt8 nParamCount;
    1734                 :            :     sal_uInt16 nFuncId;
    1735 [ #  # ][ #  # ]:          0 :     rStrm >> nParamCount >> nFuncId;
    1736         [ #  # ]:          0 :     return pushBiff12Function( nFuncId, nParamCount );
    1737                 :            : }
    1738                 :            : 
    1739                 :          0 : bool OoxFormulaParserImpl::importExpToken( SequenceInputStream& rStrm )
    1740                 :            : {
    1741                 :          0 :     BinAddress aBaseAddr;
    1742         [ #  # ]:          0 :     rStrm >> aBaseAddr.mnRow;
    1743         [ #  # ]:          0 :     swapStreamPosition( rStrm );
    1744         [ #  # ]:          0 :     rStrm >> aBaseAddr.mnCol;
    1745         [ #  # ]:          0 :     swapStreamPosition( rStrm );
    1746         [ #  # ]:          0 :     return pushSpecialTokenOperand( aBaseAddr, false );
    1747                 :            : }
    1748                 :            : 
    1749                 :          0 : LinkSheetRange OoxFormulaParserImpl::readSheetRange( SequenceInputStream& rStrm )
    1750                 :            : {
    1751                 :          0 :     return getExternalLinks().getSheetRange( rStrm.readInt16() );
    1752                 :            : }
    1753                 :            : 
    1754                 :          0 : void OoxFormulaParserImpl::swapStreamPosition( SequenceInputStream& rStrm )
    1755                 :            : {
    1756                 :          0 :     sal_Int64 nRecPos = rStrm.tell();
    1757                 :          0 :     rStrm.seek( mnAddDataPos );
    1758                 :          0 :     mnAddDataPos = nRecPos;
    1759                 :          0 : }
    1760                 :            : 
    1761                 :          0 : void OoxFormulaParserImpl::skipMemAreaAddData( SequenceInputStream& rStrm )
    1762                 :            : {
    1763                 :          0 :     swapStreamPosition( rStrm );
    1764                 :          0 :     rStrm.skip( 16 * rStrm.readInt32() );
    1765                 :          0 :     swapStreamPosition( rStrm );
    1766                 :          0 : }
    1767                 :            : 
    1768                 :            : // convert BIN token and push API operand or operator -------------------------
    1769                 :            : 
    1770                 :          0 : bool OoxFormulaParserImpl::pushBiff12Name( sal_Int32 nNameId )
    1771                 :            : {
    1772                 :            :     // one-based in BIFF12 formulas
    1773         [ #  # ]:          0 :     return pushDefinedNameOperand( getDefinedNames().getByIndex( nNameId - 1 ) );
    1774                 :            : }
    1775                 :            : 
    1776                 :          0 : bool OoxFormulaParserImpl::pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId )
    1777                 :            : {
    1778         [ #  # ]:          0 :     if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() )
    1779                 :            :     {
    1780         [ #  # ]:          0 :         if( pExtLink->getLinkType() == LINKTYPE_SELF )
    1781         [ #  # ]:          0 :             return pushBiff12Name( nNameId );
    1782                 :            :         // external name indexes are one-based in BIFF12
    1783         [ #  # ]:          0 :         ExternalNameRef xExtName = pExtLink->getNameByIndex( nNameId - 1 );
    1784 [ #  # ][ #  # ]:          0 :         return pushExternalNameOperand( xExtName, *pExtLink );
    1785                 :            :     }
    1786                 :          0 :     return pushBiffErrorOperand( BIFF_ERR_NAME );
    1787                 :            : }
    1788                 :            : 
    1789                 :          0 : bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId )
    1790                 :            : {
    1791         [ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) )
    1792         [ #  # ]:          0 :         if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount )
    1793                 :          0 :             return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount );
    1794                 :          0 :     return pushFunctionOperator( OPCODE_NONAME, 0 );
    1795                 :            : }
    1796                 :            : 
    1797                 :          0 : bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId, sal_uInt8 nParamCount )
    1798                 :            : {
    1799         [ #  # ]:          0 :     if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) )
    1800                 :          0 :         nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK;
    1801         [ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) )
    1802                 :          0 :         return pushFunctionOperator( *pFuncInfo, nParamCount );
    1803                 :          0 :     return pushFunctionOperator( OPCODE_NONAME, nParamCount );
    1804                 :            : }
    1805                 :            : 
    1806                 :            : // BIFF parser implementation =================================================
    1807                 :            : 
    1808                 :            : namespace {
    1809                 :            : 
    1810                 :            : /** A natural language reference struct with relative flag. */
    1811                 :            : struct BiffNlr
    1812                 :            : {
    1813                 :            :     sal_Int32           mnCol;              /// Column index.
    1814                 :            :     sal_Int32           mnRow;              /// Row index.
    1815                 :            :     bool                mbRel;              /// True = relative column/row reference.
    1816                 :            : 
    1817                 :            :     explicit            BiffNlr();
    1818                 :            : 
    1819                 :            :     void                readBiff8Data( BiffInputStream& rStrm );
    1820                 :            : };
    1821                 :            : 
    1822                 :          0 : BiffNlr::BiffNlr() :
    1823                 :            :     mnCol( 0 ),
    1824                 :            :     mnRow( 0 ),
    1825                 :          0 :     mbRel( false )
    1826                 :            : {
    1827                 :          0 : }
    1828                 :            : 
    1829                 :          0 : void BiffNlr::readBiff8Data( BiffInputStream& rStrm )
    1830                 :            : {
    1831                 :            :     sal_uInt16 nRow, nCol;
    1832 [ #  # ][ #  # ]:          0 :     rStrm >> nRow >> nCol;
    1833                 :          0 :     mnCol = nCol & BIFF_TOK_NLR_MASK;
    1834                 :          0 :     mnRow = nRow;
    1835                 :          0 :     mbRel = getFlag( nCol, BIFF_TOK_NLR_REL );
    1836                 :          0 : }
    1837                 :            : 
    1838                 :          0 : bool lclIsValidNlrStack( const BinAddress& rAddr1, const BinAddress& rAddr2, bool bRow )
    1839                 :            : {
    1840                 :            :     return bRow ?
    1841                 :            :         ((rAddr1.mnRow == rAddr2.mnRow) && (rAddr1.mnCol + 1 == rAddr2.mnCol)) :
    1842 [ #  # ][ #  # ]:          0 :         ((rAddr1.mnCol == rAddr2.mnCol) && (rAddr1.mnRow + 1 == rAddr2.mnRow));
         [ #  # ][ #  # ]
                 [ #  # ]
    1843                 :            : }
    1844                 :            : 
    1845                 :          0 : bool lclIsValidNlrRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow )
    1846                 :            : {
    1847                 :            :     return bRow ?
    1848                 :            :         ((rNlr.mnRow == rRange.maFirst.mnRow) && (rNlr.mnCol + 1 == rRange.maFirst.mnCol) && (rRange.maFirst.mnRow == rRange.maLast.mnRow)) :
    1849 [ #  # ][ #  # ]:          0 :         ((rNlr.mnCol == rRange.maFirst.mnCol) && (rNlr.mnRow + 1 == rRange.maFirst.mnRow) && (rRange.maFirst.mnCol == rRange.maLast.mnCol));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1850                 :            : }
    1851                 :            : 
    1852                 :            : } // namespace
    1853                 :            : 
    1854                 :            : // ----------------------------------------------------------------------------
    1855                 :            : 
    1856         [ #  # ]:          0 : class BiffFormulaParserImpl : public FormulaParserImpl
    1857                 :            : {
    1858                 :            : public:
    1859                 :            :     explicit            BiffFormulaParserImpl( const FormulaParser& rParent );
    1860                 :            : 
    1861                 :            :     virtual ApiTokenSequence importBiffFormula(
    1862                 :            :                             const CellAddress& rBaseAddr,
    1863                 :            :                             FormulaType eType,
    1864                 :            :                             BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize );
    1865                 :            : 
    1866                 :            : private:
    1867                 :            :     // import token contents and create API formula token ---------------------
    1868                 :            : 
    1869                 :            :     bool                importTokenNotAvailable( BiffInputStream& rStrm );
    1870                 :            :     bool                importRefTokenNotAvailable( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1871                 :            :     bool                importStrToken2( BiffInputStream& rStrm );
    1872                 :            :     bool                importStrToken8( BiffInputStream& rStrm );
    1873                 :            :     bool                importAttrToken( BiffInputStream& rStrm );
    1874                 :            :     bool                importSpaceToken3( BiffInputStream& rStrm );
    1875                 :            :     bool                importSpaceToken4( BiffInputStream& rStrm );
    1876                 :            :     bool                importSheetToken2( BiffInputStream& rStrm );
    1877                 :            :     bool                importSheetToken3( BiffInputStream& rStrm );
    1878                 :            :     bool                importEndSheetToken2( BiffInputStream& rStrm );
    1879                 :            :     bool                importEndSheetToken3( BiffInputStream& rStrm );
    1880                 :            :     bool                importNlrToken( BiffInputStream& rStrm );
    1881                 :            :     bool                importArrayToken( BiffInputStream& rStrm );
    1882                 :            :     bool                importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1883                 :            :     bool                importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1884                 :            :     bool                importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1885                 :            :     bool                importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1886                 :            :     bool                importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1887                 :            :     bool                importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1888                 :            :     bool                importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1889                 :            :     bool                importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset );
    1890                 :            :     bool                importMemAreaToken( BiffInputStream& rStrm, bool bAddData );
    1891                 :            :     bool                importMemFuncToken( BiffInputStream& rStrm );
    1892                 :            :     bool                importNameToken( BiffInputStream& rStrm );
    1893                 :            :     bool                importNameXToken( BiffInputStream& rStrm );
    1894                 :            :     bool                importFuncToken2( BiffInputStream& rStrm );
    1895                 :            :     bool                importFuncToken4( BiffInputStream& rStrm );
    1896                 :            :     bool                importFuncVarToken2( BiffInputStream& rStrm );
    1897                 :            :     bool                importFuncVarToken4( BiffInputStream& rStrm );
    1898                 :            :     bool                importFuncCEToken( BiffInputStream& rStrm );
    1899                 :            :     bool                importExpToken( BiffInputStream& rStrm );
    1900                 :            :     bool                importTblToken( BiffInputStream& rStrm );
    1901                 :            : 
    1902                 :            :     bool                importNlrAddrToken( BiffInputStream& rStrm, bool bRow );
    1903                 :            :     bool                importNlrRangeToken( BiffInputStream& rStrm );
    1904                 :            :     bool                importNlrSAddrToken( BiffInputStream& rStrm, bool bRow );
    1905                 :            :     bool                importNlrSRangeToken( BiffInputStream& rStrm );
    1906                 :            :     bool                importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nSkip );
    1907                 :            : 
    1908                 :            :     sal_Int32           readRefId( BiffInputStream& rStrm );
    1909                 :            :     sal_uInt16          readNameId( BiffInputStream& rStrm );
    1910                 :            :     LinkSheetRange      readSheetRange5( BiffInputStream& rStrm );
    1911                 :            :     LinkSheetRange      readSheetRange8( BiffInputStream& rStrm );
    1912                 :            : 
    1913                 :            :     void                swapStreamPosition( BiffInputStream& rStrm );
    1914                 :            :     void                skipMemAreaAddData( BiffInputStream& rStrm );
    1915                 :            :     bool                readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow );
    1916                 :            :     bool                readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm );
    1917                 :            : 
    1918                 :            :     // convert BIFF token and push API operand or operator --------------------
    1919                 :            : 
    1920                 :            :     bool                pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
    1921                 :            :     bool                pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset );
    1922                 :            :     bool                pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow );
    1923                 :            :     bool                pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange );
    1924                 :            :     bool                pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow );
    1925                 :            :     bool                pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow );
    1926                 :            :     bool                pushBiffName( sal_uInt16 nNameId );
    1927                 :            :     bool                pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId );
    1928                 :            :     bool                pushBiffFunction( sal_uInt16 nFuncId );
    1929                 :            :     bool                pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount );
    1930                 :            : 
    1931                 :            :     // ------------------------------------------------------------------------
    1932                 :            : private:
    1933                 :            :     typedef bool (BiffFormulaParserImpl::*ImportTokenFunc)( BiffInputStream& );
    1934                 :            :     typedef bool (BiffFormulaParserImpl::*ImportRefTokenFunc)( BiffInputStream&, bool, bool );
    1935                 :            : 
    1936                 :            :     ImportTokenFunc     mpImportStrToken;           /// Pointer to tStr import function (string constant).
    1937                 :            :     ImportTokenFunc     mpImportSpaceToken;         /// Pointer to tAttrSpace import function (spaces/line breaks).
    1938                 :            :     ImportTokenFunc     mpImportSheetToken;         /// Pointer to tSheet import function (external reference).
    1939                 :            :     ImportTokenFunc     mpImportEndSheetToken;      /// Pointer to tEndSheet import function (end of external reference).
    1940                 :            :     ImportTokenFunc     mpImportNlrToken;           /// Pointer to tNlr import function (natural language reference).
    1941                 :            :     ImportRefTokenFunc  mpImportRefToken;           /// Pointer to tRef import function (2d cell reference).
    1942                 :            :     ImportRefTokenFunc  mpImportAreaToken;          /// Pointer to tArea import function (2d area reference).
    1943                 :            :     ImportRefTokenFunc  mpImportRef3dToken;         /// Pointer to tRef3d import function (3d cell reference).
    1944                 :            :     ImportRefTokenFunc  mpImportArea3dToken;        /// Pointer to tArea3d import function (3d area reference).
    1945                 :            :     ImportTokenFunc     mpImportNameXToken;         /// Pointer to tNameX import function (external name).
    1946                 :            :     ImportTokenFunc     mpImportFuncToken;          /// Pointer to tFunc import function (function with fixed parameter count).
    1947                 :            :     ImportTokenFunc     mpImportFuncVarToken;       /// Pointer to tFuncVar import function (function with variable parameter count).
    1948                 :            :     ImportTokenFunc     mpImportFuncCEToken;        /// Pointer to tFuncCE import function (command macro call).
    1949                 :            :     sal_Int64           mnAddDataPos;               /// Current stream position for additional data (tArray, tMemArea, tNlr).
    1950                 :            :     sal_Int32           mnCurrRefId;                /// Current ref-id from tSheet token (BIFF2-BIFF4 only).
    1951                 :            :     sal_uInt16          mnAttrDataSize;             /// Size of one tAttr data element.
    1952                 :            :     sal_uInt16          mnArraySize;                /// Size of tArray data.
    1953                 :            :     sal_uInt16          mnNameSize;                 /// Size of tName data.
    1954                 :            :     sal_uInt16          mnMemAreaSize;              /// Size of tMemArea data.
    1955                 :            :     sal_uInt16          mnMemFuncSize;              /// Size of tMemFunc data.
    1956                 :            :     sal_uInt16          mnRefIdSize;                /// Size of unused data following a reference identifier.
    1957                 :            : };
    1958                 :            : 
    1959                 :            : // ----------------------------------------------------------------------------
    1960                 :            : 
    1961                 :          0 : BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) :
    1962                 :            :     FormulaParserImpl( rParent ),
    1963                 :            :     mnAddDataPos( 0 ),
    1964                 :          0 :     mnCurrRefId( 0 )
    1965                 :            : {
    1966   [ #  #  #  #  :          0 :     switch( getBiff() )
                #  #  # ]
                 [ #  # ]
    1967                 :            :     {
    1968                 :            :         case BIFF2:
    1969                 :          0 :             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
    1970                 :          0 :             mpImportSpaceToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    1971                 :          0 :             mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken2;
    1972                 :          0 :             mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken2;
    1973                 :          0 :             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    1974                 :          0 :             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
    1975                 :          0 :             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
    1976                 :          0 :             mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
    1977                 :          0 :             mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
    1978                 :          0 :             mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    1979                 :          0 :             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2;
    1980                 :          0 :             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2;
    1981                 :          0 :             mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken;
    1982                 :          0 :             mnAttrDataSize = 1;
    1983                 :          0 :             mnArraySize = 6;
    1984                 :          0 :             mnNameSize = 5;
    1985                 :          0 :             mnMemAreaSize = 4;
    1986                 :          0 :             mnMemFuncSize = 1;
    1987                 :          0 :             mnRefIdSize = 1;
    1988                 :          0 :         break;
    1989                 :            :         case BIFF3:
    1990                 :          0 :             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
    1991                 :          0 :             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken3;
    1992                 :          0 :             mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3;
    1993                 :          0 :             mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3;
    1994                 :          0 :             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    1995                 :          0 :             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
    1996                 :          0 :             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
    1997                 :          0 :             mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
    1998                 :          0 :             mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
    1999                 :          0 :             mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2000                 :          0 :             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2;
    2001                 :          0 :             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2;
    2002                 :          0 :             mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken;
    2003                 :          0 :             mnAttrDataSize = 2;
    2004                 :          0 :             mnArraySize = 7;
    2005                 :          0 :             mnNameSize = 8;
    2006                 :          0 :             mnMemAreaSize = 6;
    2007                 :          0 :             mnMemFuncSize = 2;
    2008                 :          0 :             mnRefIdSize = 2;
    2009                 :          0 :         break;
    2010                 :            :         case BIFF4:
    2011                 :          0 :             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
    2012                 :          0 :             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4;
    2013                 :          0 :             mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3;
    2014                 :          0 :             mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3;
    2015                 :          0 :             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2016                 :          0 :             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
    2017                 :          0 :             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
    2018                 :          0 :             mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
    2019                 :          0 :             mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable;
    2020                 :          0 :             mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2021                 :          0 :             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
    2022                 :          0 :             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
    2023                 :          0 :             mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2024                 :          0 :             mnAttrDataSize = 2;
    2025                 :          0 :             mnArraySize = 7;
    2026                 :          0 :             mnNameSize = 8;
    2027                 :          0 :             mnMemAreaSize = 6;
    2028                 :          0 :             mnMemFuncSize = 2;
    2029                 :          0 :             mnRefIdSize = 2;
    2030                 :          0 :         break;
    2031                 :            :         case BIFF5:
    2032                 :          0 :             mpImportStrToken = &BiffFormulaParserImpl::importStrToken2;
    2033                 :          0 :             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4;
    2034                 :          0 :             mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2035                 :          0 :             mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2036                 :          0 :             mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2037                 :          0 :             mpImportRefToken = &BiffFormulaParserImpl::importRefToken2;
    2038                 :          0 :             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2;
    2039                 :          0 :             mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken5;
    2040                 :          0 :             mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken5;
    2041                 :          0 :             mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken;
    2042                 :          0 :             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
    2043                 :          0 :             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
    2044                 :          0 :             mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2045                 :          0 :             mnAttrDataSize = 2;
    2046                 :          0 :             mnArraySize = 7;
    2047                 :          0 :             mnNameSize = 12;
    2048                 :          0 :             mnMemAreaSize = 6;
    2049                 :          0 :             mnMemFuncSize = 2;
    2050                 :          0 :             mnRefIdSize = 8;
    2051                 :          0 :         break;
    2052                 :            :         case BIFF8:
    2053                 :          0 :             mpImportStrToken = &BiffFormulaParserImpl::importStrToken8;
    2054                 :          0 :             mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4;
    2055                 :          0 :             mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2056                 :          0 :             mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2057                 :          0 :             mpImportNlrToken = &BiffFormulaParserImpl::importNlrToken;
    2058                 :          0 :             mpImportRefToken = &BiffFormulaParserImpl::importRefToken8;
    2059                 :          0 :             mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken8;
    2060                 :          0 :             mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken8;
    2061                 :          0 :             mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken8;
    2062                 :          0 :             mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken;
    2063                 :          0 :             mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4;
    2064                 :          0 :             mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4;
    2065                 :          0 :             mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable;
    2066                 :          0 :             mnAttrDataSize = 2;
    2067                 :          0 :             mnArraySize = 7;
    2068                 :          0 :             mnNameSize = 2;
    2069                 :          0 :             mnMemAreaSize = 6;
    2070                 :          0 :             mnMemFuncSize = 2;
    2071                 :          0 :             mnRefIdSize = 0;
    2072                 :          0 :         break;
    2073                 :          0 :         case BIFF_UNKNOWN: break;
    2074                 :            :     }
    2075                 :          0 : }
    2076                 :            : 
    2077                 :          0 : ApiTokenSequence BiffFormulaParserImpl::importBiffFormula( const CellAddress& rBaseAddr,
    2078                 :            :         FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
    2079                 :            : {
    2080                 :          0 :     initializeImport( rBaseAddr, eType );
    2081                 :          0 :     mnCurrRefId = 0;
    2082                 :            : 
    2083                 :          0 :     sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize );
    2084                 :          0 :     sal_Int64 nEndPos = mnAddDataPos = rStrm.tell() + nFmlaSize;
    2085                 :            : 
    2086                 :          0 :     bool bOk = true;
    2087 [ #  # ][ #  # ]:          0 :     while( bOk && !rStrm.isEof() && (rStrm.tell() < nEndPos) )
         [ #  # ][ #  # ]
    2088                 :            :     {
    2089                 :            :         sal_uInt8 nTokenId;
    2090         [ #  # ]:          0 :         rStrm >> nTokenId;
    2091                 :          0 :         sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK;
    2092                 :          0 :         sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK;
    2093                 :            : 
    2094                 :          0 :         bOk = !getFlag( nTokenId, BIFF_TOKFLAG_INVALID );
    2095         [ #  # ]:          0 :         if( bOk )
    2096                 :            :         {
    2097         [ #  # ]:          0 :             if( nTokenClass == BIFF_TOKCLASS_NONE )
    2098                 :            :             {
    2099                 :            :                 // base tokens
    2100   [ #  #  #  #  :          0 :                 switch( nBaseId )
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2101                 :            :                 {
    2102         [ #  # ]:          0 :                     case BIFF_TOKID_EXP:        bOk = importExpToken( rStrm );                          break;
    2103         [ #  # ]:          0 :                     case BIFF_TOKID_TBL:        bOk = importTblToken( rStrm );                          break;
    2104         [ #  # ]:          0 :                     case BIFF_TOKID_ADD:        bOk = pushBinaryOperator( OPCODE_ADD );                 break;
    2105         [ #  # ]:          0 :                     case BIFF_TOKID_SUB:        bOk = pushBinaryOperator( OPCODE_SUB );                 break;
    2106         [ #  # ]:          0 :                     case BIFF_TOKID_MUL:        bOk = pushBinaryOperator( OPCODE_MULT );                break;
    2107         [ #  # ]:          0 :                     case BIFF_TOKID_DIV:        bOk = pushBinaryOperator( OPCODE_DIV );                 break;
    2108         [ #  # ]:          0 :                     case BIFF_TOKID_POWER:      bOk = pushBinaryOperator( OPCODE_POWER );               break;
    2109         [ #  # ]:          0 :                     case BIFF_TOKID_CONCAT:     bOk = pushBinaryOperator( OPCODE_CONCAT );              break;
    2110         [ #  # ]:          0 :                     case BIFF_TOKID_LT:         bOk = pushBinaryOperator( OPCODE_LESS );                break;
    2111         [ #  # ]:          0 :                     case BIFF_TOKID_LE:         bOk = pushBinaryOperator( OPCODE_LESS_EQUAL );          break;
    2112         [ #  # ]:          0 :                     case BIFF_TOKID_EQ:         bOk = pushBinaryOperator( OPCODE_EQUAL );               break;
    2113         [ #  # ]:          0 :                     case BIFF_TOKID_GE:         bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL );       break;
    2114         [ #  # ]:          0 :                     case BIFF_TOKID_GT:         bOk = pushBinaryOperator( OPCODE_GREATER );             break;
    2115         [ #  # ]:          0 :                     case BIFF_TOKID_NE:         bOk = pushBinaryOperator( OPCODE_NOT_EQUAL );           break;
    2116         [ #  # ]:          0 :                     case BIFF_TOKID_ISECT:      bOk = pushBinaryOperator( OPCODE_INTERSECT );           break;
    2117         [ #  # ]:          0 :                     case BIFF_TOKID_LIST:       bOk = pushBinaryOperator( OPCODE_LIST );                break;
    2118         [ #  # ]:          0 :                     case BIFF_TOKID_RANGE:      bOk = pushBinaryOperator( OPCODE_RANGE );               break;
    2119         [ #  # ]:          0 :                     case BIFF_TOKID_UPLUS:      bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN );         break;
    2120         [ #  # ]:          0 :                     case BIFF_TOKID_UMINUS:     bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN );        break;
    2121         [ #  # ]:          0 :                     case BIFF_TOKID_PERCENT:    bOk = pushUnaryPostOperator( OPCODE_PERCENT );          break;
    2122         [ #  # ]:          0 :                     case BIFF_TOKID_PAREN:      bOk = pushParenthesesOperator();                        break;
    2123         [ #  # ]:          0 :                     case BIFF_TOKID_MISSARG:    bOk = pushOperand( OPCODE_MISSING );                    break;
    2124 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_STR:        bOk = (this->*mpImportStrToken)( rStrm );               break;
    2125 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_NLR:        bOk = (this->*mpImportNlrToken)( rStrm );               break;
    2126         [ #  # ]:          0 :                     case BIFF_TOKID_ATTR:       bOk = importAttrToken( rStrm );                         break;
    2127 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_SHEET:      bOk = (this->*mpImportSheetToken)( rStrm );             break;
    2128 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_ENDSHEET:   bOk = (this->*mpImportEndSheetToken)( rStrm );          break;
    2129 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_ERR:        bOk = pushBiffErrorOperand( rStrm.readuInt8() );        break;
    2130 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_BOOL:       bOk = pushBiffBoolOperand( rStrm.readuInt8() );         break;
    2131 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_INT:        bOk = pushValueOperand< double >( rStrm.readuInt16() ); break;
    2132 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_NUM:        bOk = pushValueOperand( rStrm.readDouble() );           break;
    2133                 :          0 :                     default:                    bOk = false;
    2134                 :            :                 }
    2135                 :            :             }
    2136                 :            :             else
    2137                 :            :             {
    2138                 :            :                 // classified tokens
    2139   [ #  #  #  #  :          0 :                 switch( nBaseId )
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    2140                 :            :                 {
    2141         [ #  # ]:          0 :                     case BIFF_TOKID_ARRAY:      bOk = importArrayToken( rStrm );                                        break;
    2142 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_FUNC:       bOk = (this->*mpImportFuncToken)( rStrm );                              break;
    2143 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_FUNCVAR:    bOk = (this->*mpImportFuncVarToken)( rStrm );                           break;
    2144         [ #  # ]:          0 :                     case BIFF_TOKID_NAME:       bOk = importNameToken( rStrm );                                         break;
    2145 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_REF:        bOk = (this->*mpImportRefToken)( rStrm, false, false );                 break;
    2146 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_AREA:       bOk = (this->*mpImportAreaToken)( rStrm, false, false );                break;
    2147         [ #  # ]:          0 :                     case BIFF_TOKID_MEMAREA:    bOk = importMemAreaToken( rStrm, true );                                break;
    2148         [ #  # ]:          0 :                     case BIFF_TOKID_MEMERR:     bOk = importMemAreaToken( rStrm, false );                               break;
    2149         [ #  # ]:          0 :                     case BIFF_TOKID_MEMNOMEM:   bOk = importMemAreaToken( rStrm, false );                               break;
    2150         [ #  # ]:          0 :                     case BIFF_TOKID_MEMFUNC:    bOk = importMemFuncToken( rStrm );                                      break;
    2151 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_REFERR:     bOk = (this->*mpImportRefToken)( rStrm, true, false );                  break;
    2152 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_AREAERR:    bOk = (this->*mpImportAreaToken)( rStrm, true, false );                 break;
    2153 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_REFN:       bOk = (this->*mpImportRefToken)( rStrm, false, true );                  break;
    2154 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_AREAN:      bOk = (this->*mpImportAreaToken)( rStrm, false, true );                 break;
    2155         [ #  # ]:          0 :                     case BIFF_TOKID_MEMAREAN:   bOk = importMemFuncToken( rStrm );                                      break;
    2156         [ #  # ]:          0 :                     case BIFF_TOKID_MEMNOMEMN:  bOk = importMemFuncToken( rStrm );                                      break;
    2157 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_FUNCCE:     bOk = (this->*mpImportFuncCEToken)( rStrm );                            break;
    2158 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_NAMEX:      bOk = (this->*mpImportNameXToken)( rStrm );                             break;
    2159 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_REF3D:      bOk = (this->*mpImportRef3dToken)( rStrm, false, mbRelativeAsOffset );  break;
    2160 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_AREA3D:     bOk = (this->*mpImportArea3dToken)( rStrm, false, mbRelativeAsOffset ); break;
    2161 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_REFERR3D:   bOk = (this->*mpImportRef3dToken)( rStrm, true, mbRelativeAsOffset );   break;
    2162 [ #  # ][ #  # ]:          0 :                     case BIFF_TOKID_AREAERR3D:  bOk = (this->*mpImportArea3dToken)( rStrm, true, mbRelativeAsOffset );  break;
    2163                 :          0 :                     default:                    bOk = false;
    2164                 :            :                 }
    2165                 :            :             }
    2166                 :            :         }
    2167                 :            :     }
    2168                 :            : 
    2169                 :            :     // build and finalize the token sequence
    2170                 :          0 :     ApiTokenSequence aFinalTokens;
    2171 [ #  # ][ #  # ]:          0 :     if( bOk && (rStrm.tell() == nEndPos) )
         [ #  # ][ #  # ]
    2172 [ #  # ][ #  # ]:          0 :         aFinalTokens = finalizeImport();
                 [ #  # ]
    2173                 :            : 
    2174                 :            :     // seek behind additional token data of tArray, tMemArea, tNlr tokens
    2175         [ #  # ]:          0 :     rStrm.seek( mnAddDataPos );
    2176                 :            : 
    2177                 :            :     // return the final token sequence
    2178                 :          0 :     return aFinalTokens;
    2179                 :            : }
    2180                 :            : 
    2181                 :            : // import token contents and create API formula token -------------------------
    2182                 :            : 
    2183                 :          0 : bool BiffFormulaParserImpl::importTokenNotAvailable( BiffInputStream& )
    2184                 :            : {
    2185                 :            :     // dummy function for pointer-to-member-function
    2186                 :          0 :     return false;
    2187                 :            : }
    2188                 :            : 
    2189                 :          0 : bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool, bool )
    2190                 :            : {
    2191                 :            :     // dummy function for pointer-to-member-function
    2192                 :          0 :     return false;
    2193                 :            : }
    2194                 :            : 
    2195                 :          0 : bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm )
    2196                 :            : {
    2197         [ #  # ]:          0 :     return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ) );
    2198                 :            : }
    2199                 :            : 
    2200                 :          0 : bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm )
    2201                 :            : {
    2202                 :            :     // read flags field for empty strings also
    2203         [ #  # ]:          0 :     return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), mbAllowNulChars ) );
    2204                 :            : }
    2205                 :            : 
    2206                 :          0 : bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm )
    2207                 :            : {
    2208                 :          0 :     bool bOk = true;
    2209                 :            :     sal_uInt8 nType;
    2210         [ #  # ]:          0 :     rStrm >> nType;
    2211   [ #  #  #  #  :          0 :     switch( nType )
                      # ]
    2212                 :            :     {
    2213                 :            :         case 0:     // sometimes, tAttrSkip tokens miss the type flag
    2214                 :            :         case BIFF_TOK_ATTR_VOLATILE:
    2215                 :            :         case BIFF_TOK_ATTR_IF:
    2216                 :            :         case BIFF_TOK_ATTR_SKIP:
    2217                 :            :         case BIFF_TOK_ATTR_ASSIGN:
    2218         [ #  # ]:          0 :             rStrm.skip( mnAttrDataSize );
    2219                 :          0 :         break;
    2220                 :            :         case BIFF_TOK_ATTR_CHOOSE:
    2221 [ #  # ][ #  # ]:          0 :             rStrm.skip( mnAttrDataSize * (1 + ((getBiff() == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16())) );
         [ #  # ][ #  # ]
                 [ #  # ]
    2222                 :          0 :         break;
    2223                 :            :         case BIFF_TOK_ATTR_SUM:
    2224         [ #  # ]:          0 :             rStrm.skip( mnAttrDataSize );
    2225         [ #  # ]:          0 :             bOk = pushBiffFunction( BIFF_FUNC_SUM, 1 );
    2226                 :          0 :         break;
    2227                 :            :         case BIFF_TOK_ATTR_SPACE:
    2228                 :            :         case BIFF_TOK_ATTR_SPACE_VOLATILE:
    2229 [ #  # ][ #  # ]:          0 :             bOk = (this->*mpImportSpaceToken)( rStrm );
    2230                 :          0 :         break;
    2231                 :            :         default:
    2232                 :          0 :             bOk = false;
    2233                 :            :     }
    2234                 :          0 :     return bOk;
    2235                 :            : }
    2236                 :            : 
    2237                 :          0 : bool BiffFormulaParserImpl::importSpaceToken3( BiffInputStream& rStrm )
    2238                 :            : {
    2239                 :          0 :     rStrm.skip( 2 );
    2240                 :          0 :     return true;
    2241                 :            : }
    2242                 :            : 
    2243                 :          0 : bool BiffFormulaParserImpl::importSpaceToken4( BiffInputStream& rStrm )
    2244                 :            : {
    2245                 :            :     sal_uInt8 nType, nCount;
    2246 [ #  # ][ #  # ]:          0 :     rStrm >> nType >> nCount;
    2247   [ #  #  #  #  :          0 :     switch( nType )
                #  #  # ]
    2248                 :            :     {
    2249                 :            :         case BIFF_TOK_ATTR_SPACE_SP:
    2250         [ #  # ]:          0 :             appendLeadingSpaces( nCount, false );
    2251                 :          0 :         break;
    2252                 :            :         case BIFF_TOK_ATTR_SPACE_BR:
    2253         [ #  # ]:          0 :             appendLeadingSpaces( nCount, true );
    2254                 :          0 :         break;
    2255                 :            :         case BIFF_TOK_ATTR_SPACE_SP_OPEN:
    2256         [ #  # ]:          0 :             appendOpeningSpaces( nCount, false );
    2257                 :          0 :         break;
    2258                 :            :         case BIFF_TOK_ATTR_SPACE_BR_OPEN:
    2259         [ #  # ]:          0 :             appendOpeningSpaces( nCount, true );
    2260                 :          0 :         break;
    2261                 :            :         case BIFF_TOK_ATTR_SPACE_SP_CLOSE:
    2262         [ #  # ]:          0 :             appendClosingSpaces( nCount, false );
    2263                 :          0 :         break;
    2264                 :            :         case BIFF_TOK_ATTR_SPACE_BR_CLOSE:
    2265         [ #  # ]:          0 :             appendClosingSpaces( nCount, true );
    2266                 :          0 :         break;
    2267                 :            :     }
    2268                 :          0 :     return true;
    2269                 :            : }
    2270                 :            : 
    2271                 :          0 : bool BiffFormulaParserImpl::importSheetToken2( BiffInputStream& rStrm )
    2272                 :            : {
    2273                 :          0 :     rStrm.skip( 4 );
    2274                 :          0 :     mnCurrRefId = readRefId( rStrm );
    2275                 :          0 :     return true;
    2276                 :            : }
    2277                 :            : 
    2278                 :          0 : bool BiffFormulaParserImpl::importSheetToken3( BiffInputStream& rStrm )
    2279                 :            : {
    2280                 :          0 :     rStrm.skip( 6 );
    2281                 :          0 :     mnCurrRefId = readRefId( rStrm );
    2282                 :          0 :     return true;
    2283                 :            : }
    2284                 :            : 
    2285                 :          0 : bool BiffFormulaParserImpl::importEndSheetToken2( BiffInputStream& rStrm )
    2286                 :            : {
    2287                 :          0 :     rStrm.skip( 3 );
    2288                 :          0 :     mnCurrRefId = 0;
    2289                 :          0 :     return true;
    2290                 :            : }
    2291                 :            : 
    2292                 :          0 : bool BiffFormulaParserImpl::importEndSheetToken3( BiffInputStream& rStrm )
    2293                 :            : {
    2294                 :          0 :     rStrm.skip( 4 );
    2295                 :          0 :     mnCurrRefId = 0;
    2296                 :          0 :     return true;
    2297                 :            : }
    2298                 :            : 
    2299                 :          0 : bool BiffFormulaParserImpl::importNlrToken( BiffInputStream& rStrm )
    2300                 :            : {
    2301                 :          0 :     bool bOk = true;
    2302                 :            :     sal_uInt8 nNlrType;
    2303         [ #  # ]:          0 :     rStrm >> nNlrType;
    2304   [ #  #  #  #  :          0 :     switch( nNlrType )
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2305                 :            :     {
    2306         [ #  # ]:          0 :         case BIFF_TOK_NLR_ERR:      bOk = importNlrErrToken( rStrm, 4 );        break;
    2307         [ #  # ]:          0 :         case BIFF_TOK_NLR_ROWR:     bOk = importNlrAddrToken( rStrm, true );    break;
    2308         [ #  # ]:          0 :         case BIFF_TOK_NLR_COLR:     bOk = importNlrAddrToken( rStrm, false );   break;
    2309         [ #  # ]:          0 :         case BIFF_TOK_NLR_ROWV:     bOk = importNlrAddrToken( rStrm, true );    break;
    2310         [ #  # ]:          0 :         case BIFF_TOK_NLR_COLV:     bOk = importNlrAddrToken( rStrm, false );   break;
    2311         [ #  # ]:          0 :         case BIFF_TOK_NLR_RANGE:    bOk = importNlrRangeToken( rStrm );         break;
    2312         [ #  # ]:          0 :         case BIFF_TOK_NLR_SRANGE:   bOk = importNlrSRangeToken( rStrm );        break;
    2313         [ #  # ]:          0 :         case BIFF_TOK_NLR_SROWR:    bOk = importNlrSAddrToken( rStrm, true );   break;
    2314         [ #  # ]:          0 :         case BIFF_TOK_NLR_SCOLR:    bOk = importNlrSAddrToken( rStrm, false );  break;
    2315         [ #  # ]:          0 :         case BIFF_TOK_NLR_SROWV:    bOk = importNlrSAddrToken( rStrm, true );   break;
    2316         [ #  # ]:          0 :         case BIFF_TOK_NLR_SCOLV:    bOk = importNlrSAddrToken( rStrm, false );  break;
    2317         [ #  # ]:          0 :         case BIFF_TOK_NLR_RANGEERR: bOk = importNlrErrToken( rStrm, 13 );       break;
    2318         [ #  # ]:          0 :         case BIFF_TOK_NLR_SXNAME:   bOk = importNlrErrToken( rStrm, 4 );        break;
    2319                 :          0 :         default:                    bOk = false;
    2320                 :            :     }
    2321                 :          0 :     return bOk;
    2322                 :            : }
    2323                 :            : 
    2324                 :          0 : bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm )
    2325                 :            : {
    2326                 :          0 :     rStrm.skip( mnArraySize );
    2327                 :            : 
    2328                 :            :     // start token array with opening brace and leading spaces
    2329                 :          0 :     pushOperand( OPCODE_ARRAY_OPEN );
    2330                 :          0 :     size_t nOpSize = popOperandSize();
    2331                 :          0 :     size_t nOldArraySize = getFormulaSize();
    2332                 :          0 :     bool bBiff8 = getBiff() == BIFF8;
    2333                 :            : 
    2334                 :            :     // read array size
    2335                 :          0 :     swapStreamPosition( rStrm );
    2336                 :          0 :     sal_uInt16 nCols = rStrm.readuInt8();
    2337                 :          0 :     sal_uInt16 nRows = rStrm.readuInt16();
    2338 [ #  # ][ #  # ]:          0 :     if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256;
    2339                 :            :     OSL_ENSURE( (nCols > 0) && (nRows > 0), "BiffFormulaParserImpl::importArrayToken - empty array" );
    2340                 :            : 
    2341                 :            :     // read array values and build token array
    2342 [ #  # ][ #  # ]:          0 :     for( sal_uInt16 nRow = 0; !rStrm.isEof() && (nRow < nRows); ++nRow )
                 [ #  # ]
    2343                 :            :     {
    2344         [ #  # ]:          0 :         if( nRow > 0 )
    2345                 :          0 :             appendRawToken( OPCODE_ARRAY_ROWSEP );
    2346 [ #  # ][ #  # ]:          0 :         for( sal_uInt16 nCol = 0; !rStrm.isEof() && (nCol < nCols); ++nCol )
                 [ #  # ]
    2347                 :            :         {
    2348         [ #  # ]:          0 :             if( nCol > 0 )
    2349                 :          0 :                 appendRawToken( OPCODE_ARRAY_COLSEP );
    2350   [ #  #  #  #  :          0 :             switch( rStrm.readuInt8() )
                   #  # ]
    2351                 :            :             {
    2352                 :            :                 case BIFF_DATATYPE_EMPTY:
    2353 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= OUString();
    2354                 :          0 :                     rStrm.skip( 8 );
    2355                 :          0 :                 break;
    2356                 :            :                 case BIFF_DATATYPE_DOUBLE:
    2357 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= rStrm.readDouble();
    2358                 :          0 :                 break;
    2359                 :            :                 case BIFF_DATATYPE_STRING:
    2360         [ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= bBiff8 ?
    2361                 :            :                         rStrm.readUniString( mbAllowNulChars ) :
    2362 [ #  # ][ #  # ]:          0 :                         rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars );
    2363                 :          0 :                 break;
    2364                 :            :                 case BIFF_DATATYPE_BOOL:
    2365 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= (static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 ));
                 [ #  # ]
    2366                 :          0 :                     rStrm.skip( 7 );
    2367                 :          0 :                 break;
    2368                 :            :                 case BIFF_DATATYPE_ERROR:
    2369 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() );
    2370                 :          0 :                     rStrm.skip( 7 );
    2371                 :          0 :                 break;
    2372                 :            :                 default:
    2373                 :            :                     OSL_FAIL( "BiffFormulaParserImpl::importArrayToken - unknown data type" );
    2374 [ #  # ][ #  # ]:          0 :                     appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA );
    2375                 :            :             }
    2376                 :            :         }
    2377                 :            :     }
    2378                 :          0 :     swapStreamPosition( rStrm );
    2379                 :            : 
    2380                 :            :     // close token array and set resulting operand size
    2381                 :          0 :     appendRawToken( OPCODE_ARRAY_CLOSE );
    2382                 :          0 :     pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize );
    2383                 :          0 :     return true;
    2384                 :            : }
    2385                 :            : 
    2386                 :          0 : bool BiffFormulaParserImpl::importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2387                 :            : {
    2388         [ #  # ]:          0 :     BinSingleRef2d aRef;
    2389         [ #  # ]:          0 :     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
    2390         [ #  # ]:          0 :     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
    2391                 :            : }
    2392                 :            : 
    2393                 :          0 : bool BiffFormulaParserImpl::importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2394                 :            : {
    2395         [ #  # ]:          0 :     BinSingleRef2d aRef;
    2396         [ #  # ]:          0 :     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
    2397         [ #  # ]:          0 :     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
    2398                 :            : }
    2399                 :            : 
    2400                 :          0 : bool BiffFormulaParserImpl::importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2401                 :            : {
    2402         [ #  # ]:          0 :     BinComplexRef2d aRef;
    2403         [ #  # ]:          0 :     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
    2404         [ #  # ]:          0 :     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
    2405                 :            : }
    2406                 :            : 
    2407                 :          0 : bool BiffFormulaParserImpl::importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2408                 :            : {
    2409         [ #  # ]:          0 :     BinComplexRef2d aRef;
    2410         [ #  # ]:          0 :     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
    2411         [ #  # ]:          0 :     return pushBiffReference( aRef, bDeleted, bRelativeAsOffset );
    2412                 :            : }
    2413                 :            : 
    2414                 :          0 : bool BiffFormulaParserImpl::importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2415                 :            : {
    2416         [ #  # ]:          0 :     LinkSheetRange aSheetRange = readSheetRange5( rStrm );
    2417         [ #  # ]:          0 :     BinSingleRef2d aRef;
    2418         [ #  # ]:          0 :     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
    2419         [ #  # ]:          0 :     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
    2420                 :            : }
    2421                 :            : 
    2422                 :          0 : bool BiffFormulaParserImpl::importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2423                 :            : {
    2424         [ #  # ]:          0 :     LinkSheetRange aSheetRange = readSheetRange8( rStrm );
    2425         [ #  # ]:          0 :     BinSingleRef2d aRef;
    2426         [ #  # ]:          0 :     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
    2427         [ #  # ]:          0 :     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
    2428                 :            : }
    2429                 :            : 
    2430                 :          0 : bool BiffFormulaParserImpl::importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2431                 :            : {
    2432         [ #  # ]:          0 :     LinkSheetRange aSheetRange = readSheetRange5( rStrm );
    2433         [ #  # ]:          0 :     BinComplexRef2d aRef;
    2434         [ #  # ]:          0 :     aRef.readBiff2Data( rStrm, bRelativeAsOffset );
    2435         [ #  # ]:          0 :     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
    2436                 :            : }
    2437                 :            : 
    2438                 :          0 : bool BiffFormulaParserImpl::importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset )
    2439                 :            : {
    2440         [ #  # ]:          0 :     LinkSheetRange aSheetRange = readSheetRange8( rStrm );
    2441         [ #  # ]:          0 :     BinComplexRef2d aRef;
    2442         [ #  # ]:          0 :     aRef.readBiff8Data( rStrm, bRelativeAsOffset );
    2443         [ #  # ]:          0 :     return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
    2444                 :            : }
    2445                 :            : 
    2446                 :          0 : bool BiffFormulaParserImpl::importMemAreaToken( BiffInputStream& rStrm, bool bAddData )
    2447                 :            : {
    2448                 :          0 :     rStrm.skip( mnMemAreaSize );
    2449         [ #  # ]:          0 :     if( bAddData )
    2450                 :          0 :         skipMemAreaAddData( rStrm );
    2451                 :          0 :     return true;
    2452                 :            : }
    2453                 :            : 
    2454                 :          0 : bool BiffFormulaParserImpl::importMemFuncToken( BiffInputStream& rStrm )
    2455                 :            : {
    2456                 :          0 :     rStrm.skip( mnMemFuncSize );
    2457                 :          0 :     return true;
    2458                 :            : }
    2459                 :            : 
    2460                 :          0 : bool BiffFormulaParserImpl::importNameToken( BiffInputStream& rStrm )
    2461                 :            : {
    2462                 :          0 :     sal_uInt16 nNameId = readNameId( rStrm );
    2463         [ #  # ]:          0 :     return (mnCurrRefId > 0) ? pushBiffExtName( mnCurrRefId, nNameId ) : pushBiffName( nNameId );
    2464                 :            : }
    2465                 :            : 
    2466                 :          0 : bool BiffFormulaParserImpl::importNameXToken( BiffInputStream& rStrm )
    2467                 :            : {
    2468                 :          0 :     sal_Int32 nRefId = readRefId( rStrm );
    2469                 :          0 :     sal_uInt16 nNameId = readNameId( rStrm );
    2470                 :          0 :     return pushBiffExtName( nRefId, nNameId );
    2471                 :            : }
    2472                 :            : 
    2473                 :          0 : bool BiffFormulaParserImpl::importFuncToken2( BiffInputStream& rStrm )
    2474                 :            : {
    2475                 :            :     sal_uInt8 nFuncId;
    2476         [ #  # ]:          0 :     rStrm >> nFuncId;
    2477         [ #  # ]:          0 :     return pushBiffFunction( nFuncId );
    2478                 :            : }
    2479                 :            : 
    2480                 :          0 : bool BiffFormulaParserImpl::importFuncToken4( BiffInputStream& rStrm )
    2481                 :            : {
    2482                 :            :     sal_uInt16 nFuncId;
    2483         [ #  # ]:          0 :     rStrm >> nFuncId;
    2484         [ #  # ]:          0 :     return pushBiffFunction( nFuncId );
    2485                 :            : }
    2486                 :            : 
    2487                 :          0 : bool BiffFormulaParserImpl::importFuncVarToken2( BiffInputStream& rStrm )
    2488                 :            : {
    2489                 :            :     sal_uInt8 nParamCount, nFuncId;
    2490 [ #  # ][ #  # ]:          0 :     rStrm >> nParamCount >> nFuncId;
    2491         [ #  # ]:          0 :     return pushBiffFunction( nFuncId, nParamCount );
    2492                 :            : }
    2493                 :            : 
    2494                 :          0 : bool BiffFormulaParserImpl::importFuncVarToken4( BiffInputStream& rStrm )
    2495                 :            : {
    2496                 :            :     sal_uInt8 nParamCount;
    2497                 :            :     sal_uInt16 nFuncId;
    2498 [ #  # ][ #  # ]:          0 :     rStrm >> nParamCount >> nFuncId;
    2499         [ #  # ]:          0 :     return pushBiffFunction( nFuncId, nParamCount & BIFF_TOK_FUNCVAR_COUNTMASK );
    2500                 :            : }
    2501                 :            : 
    2502                 :          0 : bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream& rStrm )
    2503                 :            : {
    2504                 :            :     sal_uInt8 nParamCount, nFuncId;
    2505 [ #  # ][ #  # ]:          0 :     rStrm >> nParamCount >> nFuncId;
    2506                 :          0 :     sal_uInt16 nCmdId = nFuncId;
    2507                 :          0 :     setFlag( nCmdId, BIFF_TOK_FUNCVAR_CMD );
    2508         [ #  # ]:          0 :     return pushBiffFunction( nCmdId, nParamCount );
    2509                 :            : }
    2510                 :            : 
    2511                 :          0 : bool BiffFormulaParserImpl::importExpToken( BiffInputStream& rStrm )
    2512                 :            : {
    2513                 :          0 :     BinAddress aBaseAddr;
    2514         [ #  # ]:          0 :     aBaseAddr.read( rStrm );
    2515         [ #  # ]:          0 :     return pushSpecialTokenOperand( aBaseAddr, false );
    2516                 :            : }
    2517                 :            : 
    2518                 :          0 : bool BiffFormulaParserImpl::importTblToken( BiffInputStream& rStrm )
    2519                 :            : {
    2520                 :          0 :     BinAddress aBaseAddr;
    2521         [ #  # ]:          0 :     aBaseAddr.read( rStrm );
    2522         [ #  # ]:          0 :     return pushSpecialTokenOperand( aBaseAddr, true );
    2523                 :            : }
    2524                 :            : 
    2525                 :          0 : bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream& rStrm, bool bRow )
    2526                 :            : {
    2527                 :          0 :     BiffNlr aNlr;
    2528         [ #  # ]:          0 :     aNlr.readBiff8Data( rStrm );
    2529         [ #  # ]:          0 :     return pushBiffNlrAddr( aNlr, bRow );
    2530                 :            : }
    2531                 :            : 
    2532                 :          0 : bool BiffFormulaParserImpl::importNlrRangeToken( BiffInputStream& rStrm )
    2533                 :            : {
    2534                 :          0 :     BiffNlr aNlr;
    2535         [ #  # ]:          0 :     aNlr.readBiff8Data( rStrm );
    2536         [ #  # ]:          0 :     rStrm.skip( 1 );
    2537                 :          0 :     BinRange aRange;
    2538         [ #  # ]:          0 :     rStrm >> aRange;
    2539         [ #  # ]:          0 :     return pushBiffNlrRange( aNlr, aRange );
    2540                 :            : }
    2541                 :            : 
    2542                 :          0 : bool BiffFormulaParserImpl::importNlrSAddrToken( BiffInputStream& rStrm, bool bRow )
    2543                 :            : {
    2544         [ #  # ]:          0 :     rStrm.skip( 4 );
    2545                 :          0 :     BiffNlr aNlr;
    2546 [ #  # ][ #  # ]:          0 :     return readNlrSAddrAddData( aNlr, rStrm, bRow ) ? pushBiffNlrSAddr( aNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF );
         [ #  # ][ #  # ]
    2547                 :            : }
    2548                 :            : 
    2549                 :          0 : bool BiffFormulaParserImpl::importNlrSRangeToken( BiffInputStream& rStrm )
    2550                 :            : {
    2551         [ #  # ]:          0 :     rStrm.skip( 5 );
    2552                 :          0 :     BinRange aRange;
    2553         [ #  # ]:          0 :     rStrm >> aRange;
    2554                 :          0 :     BiffNlr aNlr;
    2555                 :            :     bool bRow;
    2556 [ #  # ][ #  # ]:          0 :     return readNlrSRangeAddData( aNlr, bRow, rStrm ) ? pushBiffNlrSRange( aNlr, aRange, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF );
         [ #  # ][ #  # ]
    2557                 :            : }
    2558                 :            : 
    2559                 :          0 : bool BiffFormulaParserImpl::importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nIgnore )
    2560                 :            : {
    2561                 :          0 :     rStrm.skip( nIgnore );
    2562                 :          0 :     return pushBiffErrorOperand( BIFF_ERR_NAME );
    2563                 :            : }
    2564                 :            : 
    2565                 :          0 : sal_Int32 BiffFormulaParserImpl::readRefId( BiffInputStream& rStrm )
    2566                 :            : {
    2567                 :            :     sal_Int16 nRefId;
    2568         [ #  # ]:          0 :     rStrm >> nRefId;
    2569         [ #  # ]:          0 :     rStrm.skip( mnRefIdSize );
    2570                 :          0 :     return nRefId;
    2571                 :            : }
    2572                 :            : 
    2573                 :          0 : sal_uInt16 BiffFormulaParserImpl::readNameId( BiffInputStream& rStrm )
    2574                 :            : {
    2575                 :            :     sal_uInt16 nNameId;
    2576         [ #  # ]:          0 :     rStrm >> nNameId;
    2577         [ #  # ]:          0 :     rStrm.skip( mnNameSize );
    2578                 :          0 :     return nNameId;
    2579                 :            : }
    2580                 :            : 
    2581                 :          0 : LinkSheetRange BiffFormulaParserImpl::readSheetRange5( BiffInputStream& rStrm )
    2582                 :            : {
    2583         [ #  # ]:          0 :     sal_Int32 nRefId = readRefId( rStrm );
    2584                 :            :     sal_Int16 nTab1, nTab2;
    2585 [ #  # ][ #  # ]:          0 :     rStrm >> nTab1 >> nTab2;
    2586 [ #  # ][ #  # ]:          0 :     return getExternalLinks().getSheetRange( nRefId, nTab1, nTab2 );
    2587                 :            : }
    2588                 :            : 
    2589                 :          0 : LinkSheetRange BiffFormulaParserImpl::readSheetRange8( BiffInputStream& rStrm )
    2590                 :            : {
    2591                 :          0 :     return getExternalLinks().getSheetRange( readRefId( rStrm ) );
    2592                 :            : }
    2593                 :            : 
    2594                 :          0 : void BiffFormulaParserImpl::swapStreamPosition( BiffInputStream& rStrm )
    2595                 :            : {
    2596                 :          0 :     sal_Int64 nRecPos = rStrm.tell();
    2597                 :          0 :     rStrm.seek( mnAddDataPos );
    2598                 :          0 :     mnAddDataPos = nRecPos;
    2599                 :          0 : }
    2600                 :            : 
    2601                 :          0 : void BiffFormulaParserImpl::skipMemAreaAddData( BiffInputStream& rStrm )
    2602                 :            : {
    2603                 :          0 :     swapStreamPosition( rStrm );
    2604                 :          0 :     sal_Int32 nCount = rStrm.readuInt16();
    2605         [ #  # ]:          0 :     rStrm.skip( ((getBiff() == BIFF8) ? 8 : 6) * nCount );
    2606                 :          0 :     swapStreamPosition( rStrm );
    2607                 :          0 : }
    2608                 :            : 
    2609                 :          0 : bool BiffFormulaParserImpl::readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow )
    2610                 :            : {
    2611                 :          0 :     bool bIsRow = false;
    2612 [ #  # ][ #  # ]:          0 :     return readNlrSRangeAddData( orNlr, bIsRow, rStrm ) && (bIsRow == bRow);
                 [ #  # ]
    2613                 :            : }
    2614                 :            : 
    2615                 :          0 : bool BiffFormulaParserImpl::readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm )
    2616                 :            : {
    2617                 :          0 :     orbIsRow = false;
    2618         [ #  # ]:          0 :     swapStreamPosition( rStrm );
    2619                 :            :     // read number of cell addresses and relative flag
    2620                 :            :     sal_uInt32 nCount;
    2621         [ #  # ]:          0 :     rStrm >> nCount;
    2622                 :          0 :     bool bRel = getFlag( nCount, BIFF_TOK_NLR_ADDREL );
    2623                 :          0 :     nCount &= BIFF_TOK_NLR_ADDMASK;
    2624         [ #  # ]:          0 :     sal_Int64 nEndPos = rStrm.tell() + 4 * nCount;
    2625                 :            :     // read list of cell addresses
    2626                 :          0 :     bool bValid = false;
    2627         [ #  # ]:          0 :     if( nCount >= 2 )
    2628                 :            :     {
    2629                 :            :         // detect column/row orientation
    2630                 :          0 :         BinAddress aAddr1, aAddr2;
    2631 [ #  # ][ #  # ]:          0 :         rStrm >> aAddr1 >> aAddr2;
    2632                 :          0 :         orbIsRow = aAddr1.mnRow == aAddr2.mnRow;
    2633                 :          0 :         bValid = lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow );
    2634                 :            :         // read and verify additional cell positions
    2635 [ #  # ][ #  # ]:          0 :         for( sal_uInt32 nIndex = 2; bValid && (nIndex < nCount); ++nIndex )
                 [ #  # ]
    2636                 :            :         {
    2637                 :          0 :             aAddr1 = aAddr2;
    2638         [ #  # ]:          0 :             rStrm >> aAddr2;
    2639 [ #  # ][ #  # ]:          0 :             bValid = !rStrm.isEof() && lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow );
    2640                 :            :         }
    2641                 :            :         // check that last imported position (aAddr2) is not at the end of the sheet
    2642 [ #  # ][ #  # ]:          0 :         bValid = bValid && (orbIsRow ? (aAddr2.mnCol < mnMaxApiCol) : (aAddr2.mnRow < mnMaxApiRow));
         [ #  # ][ #  # ]
    2643                 :            :         // fill the NLR struct with the last imported position
    2644         [ #  # ]:          0 :         if( bValid )
    2645                 :            :         {
    2646                 :          0 :             orNlr.mnCol = aAddr2.mnCol;
    2647                 :          0 :             orNlr.mnRow = aAddr2.mnRow;
    2648                 :          0 :             orNlr.mbRel = bRel;
    2649                 :            :         }
    2650                 :            :     }
    2651                 :            :     // seek to end of additional data for this token
    2652         [ #  # ]:          0 :     rStrm.seek( nEndPos );
    2653         [ #  # ]:          0 :     swapStreamPosition( rStrm );
    2654                 :            : 
    2655                 :          0 :     return bValid;
    2656                 :            : }
    2657                 :            : 
    2658                 :            : // convert BIFF token and push API operand or operator ------------------------
    2659                 :            : 
    2660                 :          0 : bool BiffFormulaParserImpl::pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
    2661                 :            : {
    2662                 :            :     return (mnCurrRefId > 0) ?
    2663 [ #  # ][ #  # ]:          0 :         pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) :
         [ #  # ][ #  # ]
    2664 [ #  # ][ #  # ]:          0 :         pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset );
                 [ #  # ]
    2665                 :            : }
    2666                 :            : 
    2667                 :          0 : bool BiffFormulaParserImpl::pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset )
    2668                 :            : {
    2669                 :            :     return (mnCurrRefId > 0) ?
    2670 [ #  # ][ #  # ]:          0 :         pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) :
         [ #  # ][ #  # ]
    2671 [ #  # ][ #  # ]:          0 :         pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset );
                 [ #  # ]
    2672                 :            : }
    2673                 :            : 
    2674                 :          0 : bool BiffFormulaParserImpl::pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow )
    2675                 :            : {
    2676         [ #  # ]:          0 :     BinSingleRef2d aRef;
    2677                 :          0 :     aRef.mnCol = rNlr.mnCol;
    2678                 :          0 :     aRef.mnRow = rNlr.mnRow;
    2679                 :          0 :     aRef.mbColRel = !bRow;
    2680                 :          0 :     aRef.mbRowRel = bRow;
    2681         [ #  # ]:          0 :     return pushNlrOperand( aRef );
    2682                 :            : }
    2683                 :            : 
    2684                 :          0 : bool BiffFormulaParserImpl::pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange )
    2685                 :            : {
    2686                 :          0 :     bool bRow = rNlr.mnRow == rRange.maFirst.mnRow;
    2687                 :          0 :     return lclIsValidNlrRange( rNlr, rRange, bRow ) ?
    2688         [ #  # ]:          0 :         pushBiffNlrAddr( rNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF );
    2689                 :            : }
    2690                 :            : 
    2691                 :          0 : bool BiffFormulaParserImpl::pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow )
    2692                 :            : {
    2693                 :          0 :     BinRange aRange;
    2694         [ #  # ]:          0 :     aRange.maFirst.mnCol = rNlr.mnCol + (bRow ? 1 : 0);
    2695         [ #  # ]:          0 :     aRange.maFirst.mnRow = rNlr.mnRow + (bRow ? 0 : 1);
    2696         [ #  # ]:          0 :     aRange.maLast.mnCol = bRow ? mnMaxApiCol : rNlr.mnCol;
    2697         [ #  # ]:          0 :     aRange.maLast.mnRow = bRow ? rNlr.mnRow : mnMaxApiRow;
    2698         [ #  # ]:          0 :     return pushBiffNlrSRange( rNlr, aRange, bRow );
    2699                 :            : }
    2700                 :            : 
    2701                 :          0 : bool BiffFormulaParserImpl::pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow )
    2702                 :            : {
    2703         [ #  # ]:          0 :     if( lclIsValidNlrRange( rNlr, rRange, bRow ) )
    2704                 :            :     {
    2705         [ #  # ]:          0 :         BinComplexRef2d aRef;
    2706                 :          0 :         aRef.maRef1.mnCol = rRange.maFirst.mnCol;
    2707                 :          0 :         aRef.maRef1.mnRow = rRange.maFirst.mnRow;
    2708                 :          0 :         aRef.maRef2.mnCol = rRange.maLast.mnCol;
    2709                 :          0 :         aRef.maRef2.mnRow = rRange.maLast.mnRow;
    2710 [ #  # ][ #  # ]:          0 :         aRef.maRef1.mbColRel = aRef.maRef2.mbColRel = !bRow && rNlr.mbRel;
    2711 [ #  # ][ #  # ]:          0 :         aRef.maRef1.mbRowRel = aRef.maRef2.mbRowRel = bRow && rNlr.mbRel;
    2712         [ #  # ]:          0 :         return pushReferenceOperand( aRef, false, false );
    2713                 :            :     }
    2714                 :          0 :     return pushBiffErrorOperand( BIFF_ERR_REF );
    2715                 :            : }
    2716                 :            : 
    2717                 :          0 : bool BiffFormulaParserImpl::pushBiffName( sal_uInt16 nNameId )
    2718                 :            : {
    2719                 :            :     // one-based in BIFF formulas
    2720         [ #  # ]:          0 :     return pushDefinedNameOperand( getDefinedNames().getByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ) );
    2721                 :            : }
    2722                 :            : 
    2723                 :          0 : bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId )
    2724                 :            : {
    2725         [ #  # ]:          0 :     if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() )
    2726                 :            :     {
    2727         [ #  # ]:          0 :         if( pExtLink->getLinkType() == LINKTYPE_SELF )
    2728         [ #  # ]:          0 :             return pushBiffName( nNameId );
    2729                 :            :         // external name indexes are one-based in BIFF
    2730         [ #  # ]:          0 :         ExternalNameRef xExtName = pExtLink->getNameByIndex( static_cast< sal_Int32 >( nNameId ) - 1 );
    2731 [ #  # ][ #  # ]:          0 :         return pushExternalNameOperand( xExtName, *pExtLink );
    2732                 :            :     }
    2733                 :          0 :     return pushBiffErrorOperand( BIFF_ERR_NAME );
    2734                 :            : }
    2735                 :            : 
    2736                 :          0 : bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId )
    2737                 :            : {
    2738         [ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( nFuncId ) )
    2739         [ #  # ]:          0 :         if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount )
    2740                 :          0 :             return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount );
    2741                 :          0 :     return pushFunctionOperator( OPCODE_NONAME, 0 );
    2742                 :            : }
    2743                 :            : 
    2744                 :          0 : bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount )
    2745                 :            : {
    2746         [ #  # ]:          0 :     if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) )
    2747                 :          0 :         nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK;
    2748         [ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( nFuncId ) )
    2749                 :          0 :         return pushFunctionOperator( *pFuncInfo, nParamCount );
    2750                 :          0 :     return pushFunctionOperator( OPCODE_NONAME, nParamCount );
    2751                 :            : }
    2752                 :            : 
    2753                 :            : // ============================================================================
    2754                 :            : 
    2755                 :            : namespace {
    2756                 :            : 
    2757                 :            : /** Extracts the reference identifier and the remaining data from a formula in
    2758                 :            :     the format '[RefID]Remaining'. */
    2759                 :          0 : bool lclExtractRefId( sal_Int32& rnRefId, OUString& rRemainder, const OUString& rFormulaString )
    2760                 :            : {
    2761 [ #  # ][ #  # ]:          0 :     if( (rFormulaString.getLength() >= 4) && (rFormulaString[ 0 ] == '[') )
                 [ #  # ]
    2762                 :            :     {
    2763                 :          0 :         sal_Int32 nBracketClose = rFormulaString.indexOf( ']', 1 );
    2764         [ #  # ]:          0 :         if( nBracketClose >= 2 )
    2765                 :            :         {
    2766                 :          0 :             rnRefId = rFormulaString.copy( 1, nBracketClose - 1 ).toInt32();
    2767                 :          0 :             rRemainder = rFormulaString.copy( nBracketClose + 1 );
    2768                 :          0 :             return !rRemainder.isEmpty();
    2769                 :            :         }
    2770                 :            :     }
    2771                 :          0 :     return false;
    2772                 :            : }
    2773                 :            : 
    2774                 :            : }
    2775                 :            : 
    2776                 :            : // ----------------------------------------------------------------------------
    2777                 :            : 
    2778                 :         24 : FormulaParser::FormulaParser( const WorkbookHelper& rHelper ) :
    2779                 :         24 :     FormulaProcessorBase( rHelper )
    2780                 :            : {
    2781   [ +  -  -  - ]:         24 :     switch( getFilterType() )
                 [ +  - ]
    2782                 :            :     {
    2783 [ +  - ][ +  - ]:         24 :         case FILTER_OOXML:  mxImpl.reset( new OoxFormulaParserImpl( *this ) );  break;
    2784 [ #  # ][ #  # ]:          0 :         case FILTER_BIFF:   mxImpl.reset( new BiffFormulaParserImpl( *this ) ); break;
    2785                 :          0 :         case FILTER_UNKNOWN: break;
    2786                 :            :     }
    2787                 :         24 : }
    2788                 :            : 
    2789         [ +  - ]:         24 : FormulaParser::~FormulaParser()
    2790                 :            : {
    2791         [ -  + ]:         48 : }
    2792                 :            : 
    2793                 :        117 : ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, const OUString& rFormulaString ) const
    2794                 :            : {
    2795                 :        117 :     return mxImpl->importOoxFormula( rBaseAddress, rFormulaString );
    2796                 :            : }
    2797                 :            : 
    2798                 :          0 : ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, SequenceInputStream& rStrm ) const
    2799                 :            : {
    2800                 :          0 :     return mxImpl->importBiff12Formula( rBaseAddress, eType, rStrm );
    2801                 :            : }
    2802                 :            : 
    2803                 :          0 : ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const
    2804                 :            : {
    2805                 :          0 :     return mxImpl->importBiffFormula( rBaseAddress, eType, rStrm, pnFmlaSize );
    2806                 :            : }
    2807                 :            : 
    2808                 :          0 : ApiTokenSequence FormulaParser::convertBoolToFormula( bool bValue ) const
    2809                 :            : {
    2810 [ #  # ][ #  # ]:          0 :     if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) )
    2811                 :            :     {
    2812         [ #  # ]:          0 :         ApiTokenSequence aTokens( 3 );
    2813         [ #  # ]:          0 :         aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode;
    2814         [ #  # ]:          0 :         aTokens[ 1 ].OpCode = OPCODE_OPEN;
    2815         [ #  # ]:          0 :         aTokens[ 2 ].OpCode = OPCODE_CLOSE;
    2816 [ #  # ][ #  # ]:          0 :         return aTokens;
    2817                 :            :     }
    2818                 :          0 :     return ApiTokenSequence();
    2819                 :            : }
    2820                 :            : 
    2821                 :          0 : ApiTokenSequence FormulaParser::convertErrorToFormula( sal_uInt8 nErrorCode ) const
    2822                 :            : {
    2823                 :          0 :     ApiTokenSequence aTokens( 3 );
    2824                 :            :     // HACK: enclose all error codes into an 1x1 matrix
    2825         [ #  # ]:          0 :     aTokens[ 0 ].OpCode = OPCODE_ARRAY_OPEN;
    2826         [ #  # ]:          0 :     aTokens[ 1 ].OpCode = OPCODE_PUSH;
    2827 [ #  # ][ #  # ]:          0 :     aTokens[ 1 ].Data <<= BiffHelper::calcDoubleFromError( nErrorCode );
                 [ #  # ]
    2828         [ #  # ]:          0 :     aTokens[ 2 ].OpCode = OPCODE_ARRAY_CLOSE;
    2829                 :          0 :     return aTokens;
    2830                 :            : }
    2831                 :            : 
    2832                 :         21 : ApiTokenSequence FormulaParser::convertNameToFormula( sal_Int32 nTokenIndex ) const
    2833                 :            : {
    2834         [ -  + ]:         21 :     if( nTokenIndex < 0 )
    2835         [ #  # ]:          0 :         return convertErrorToFormula( BIFF_ERR_REF );
    2836                 :            : 
    2837         [ +  - ]:         21 :     ApiTokenSequence aTokens( 1 );
    2838         [ +  - ]:         21 :     aTokens[ 0 ].OpCode = OPCODE_NAME;
    2839                 :         21 :     NameToken aNameTokenData;
    2840                 :         21 :     aNameTokenData.Global = sal_True;
    2841                 :         21 :     aNameTokenData.Index = nTokenIndex;
    2842 [ +  - ][ +  - ]:         21 :     aTokens[ 0 ].Data <<= aNameTokenData;
    2843 [ +  - ][ +  - ]:         21 :     return aTokens;
    2844                 :            : }
    2845                 :            : 
    2846                 :          0 : OUString FormulaParser::importOleTargetLink( const OUString& rFormulaString )
    2847                 :            : {
    2848                 :          0 :     sal_Int32 nRefId = -1;
    2849                 :          0 :     OUString aRemainder;
    2850   [ #  #  #  #  :          0 :     if( lclExtractRefId( nRefId, aRemainder, rFormulaString ) && (aRemainder.getLength() >= 3) &&
             #  #  #  # ]
         [ #  # ][ #  # ]
    2851                 :          0 :             (aRemainder[ 0 ] == '!') && (aRemainder[ 1 ] == '\'') && (aRemainder[ aRemainder.getLength() - 1 ] == '\'') )
    2852         [ #  # ]:          0 :         return mxImpl->resolveOleTarget( nRefId, false );
    2853                 :          0 :     return OUString();
    2854                 :            : }
    2855                 :            : 
    2856                 :          0 : OUString FormulaParser::importOleTargetLink( SequenceInputStream& rStrm )
    2857                 :            : {
    2858                 :          0 :     OUString aTargetLink;
    2859         [ #  # ]:          0 :     sal_Int32 nFmlaSize = rStrm.readInt32();
    2860 [ #  # ][ #  # ]:          0 :     sal_Int64 nFmlaEndPos = rStrm.tell() + ::std::max< sal_Int32 >( nFmlaSize, 0 );
    2861 [ #  # ][ #  # ]:          0 :     if( (nFmlaSize == 7) && (rStrm.getRemaining() >= 7) )
         [ #  # ][ #  # ]
    2862                 :            :     {
    2863                 :            :         sal_uInt8 nToken;
    2864                 :            :         sal_Int16 nRefId;
    2865                 :            :         sal_Int32 nNameId;
    2866 [ #  # ][ #  # ]:          0 :         rStrm >> nToken >> nRefId >> nNameId;
                 [ #  # ]
    2867         [ #  # ]:          0 :         if( nToken == (BIFF_TOKCLASS_VAL|BIFF_TOKID_NAMEX) )
    2868         [ #  # ]:          0 :             aTargetLink = mxImpl->resolveOleTarget( nRefId, true );
    2869                 :            :     }
    2870         [ #  # ]:          0 :     rStrm.seek( nFmlaEndPos );
    2871                 :          0 :     return aTargetLink;
    2872                 :            : }
    2873                 :            : 
    2874                 :          0 : OUString FormulaParser::importMacroName( const OUString& rFormulaString )
    2875                 :            : {
    2876                 :            :     /*  Valid macros are either sheet macros or VBA macros. OOXML and all BIFF
    2877                 :            :         documents store defined names for sheet macros, but OOXML documents do
    2878                 :            :         not store any defined name for VBA macros (while BIFF documents do).
    2879                 :            :         Sheet macros may be defined locally to a sheet, or globally to the
    2880                 :            :         document. As a result, all of the following macro specifiers are valid:
    2881                 :            : 
    2882                 :            :         1) Macros located in the own document:
    2883                 :            :             [0]!MySheetMacro    (global sheet macro 'MySheetMacro')
    2884                 :            :             Macro1!MyMacro      (sheet-local sheet macro 'MyMacro')
    2885                 :            :             [0]!MyVBAProc       (VBA macro 'MyVBAProc')
    2886                 :            :             [0]!Mod1.MyVBAProc  (VBA macro 'MyVBAProc' from code module 'Mod1')
    2887                 :            : 
    2888                 :            :         2) Macros from an external document:
    2889                 :            :             [2]!MySheetMacro    (global external sheet macro 'MySheetMacro')
    2890                 :            :             [2]Macro1!MyMacro   (sheet-local external sheet macro 'MyMacro')
    2891                 :            :             [2]!MyVBAProc       (external VBA macro 'MyVBAProc')
    2892                 :            :             [2]!Mod1.MyVBAProc  (external VBA macro from code module 'Mod1')
    2893                 :            : 
    2894                 :            :         This implementation is only interested in VBA macros from the own
    2895                 :            :         document, ignoring the valid syntax 'Macro1!MyMacro' for sheet-local
    2896                 :            :         sheet macros.
    2897                 :            :      */
    2898                 :          0 :     sal_Int32 nRefId = -1;
    2899                 :          0 :     OUString aRemainder;
    2900 [ #  # ][ #  # ]:          0 :     if( lclExtractRefId( nRefId, aRemainder, rFormulaString ) && (aRemainder.getLength() > 1) && (aRemainder[ 0 ] == '!') )
         [ #  # ][ #  # ]
    2901                 :            :     {
    2902                 :            :         /*  In BIFF12 documents, the reference identifier is always the
    2903                 :            :             one-based index of the external link as it is in OOXML documents
    2904                 :            :             (it is not an index into the list of reference sheets as used in
    2905                 :            :             cell formulas). Index 0 is an implicit placeholder for the own
    2906                 :            :             document. In BIFF12 documents, the reference to the own document is
    2907                 :            :             stored explicitly, mostly at the top of the list, so index 1 may
    2908                 :            :             resolve to the own document too.
    2909                 :            :             Passing 'false' to getExternalLink() specifies to ignore the
    2910                 :            :             reference sheets list (if existing) and to access the list of
    2911                 :            :             external links directly. */
    2912 [ #  # ][ #  # ]:          0 :         const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId, false ).get();
                 [ #  # ]
    2913                 :            :         OSL_ENSURE( pExtLink, "FormulaParser::importMacroName - missing link" );
    2914                 :            :         // do not accept macros in external documents (not supported)
    2915 [ #  # ][ #  # ]:          0 :         if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_SELF) )
                 [ #  # ]
    2916                 :            :         {
    2917                 :            :             // ignore sheet macros (defined name for VBA macros may not exist, see above)
    2918                 :          0 :             OUString aMacroName = aRemainder.copy( 1 );
    2919 [ #  # ][ #  # ]:          0 :             const DefinedName* pDefName = getDefinedNames().getByModelName( aMacroName ).get();
                 [ #  # ]
    2920 [ #  # ][ #  # ]:          0 :             if( !pDefName || pDefName->isVBName() )
                 [ #  # ]
    2921         [ #  # ]:          0 :                 return aMacroName;
    2922                 :            :         }
    2923                 :            :     }
    2924                 :          0 :     return OUString();
    2925                 :            : }
    2926                 :            : 
    2927                 :            : // ============================================================================
    2928                 :            : 
    2929                 :            : } // namespace xls
    2930 [ +  - ][ +  - ]:         24 : } // namespace oox
    2931                 :            : 
    2932                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10