LCOV - code coverage report
Current view: top level - formula/source/core/api - token.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 417 783 53.3 %
Date: 2015-06-13 12:38:46 Functions: 99 159 62.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <cstddef>
      22             : #include <cstdio>
      23             : 
      24             : #include <string.h>
      25             : #include <limits.h>
      26             : #include <tools/debug.hxx>
      27             : #include <osl/diagnose.h>
      28             : 
      29             : #include "formula/token.hxx"
      30             : #include "formula/tokenarray.hxx"
      31             : #include "formula/FormulaCompiler.hxx"
      32             : #include <formula/compiler.hrc>
      33             : #include <svl/sharedstringpool.hxx>
      34             : #include <boost/scoped_array.hpp>
      35             : 
      36             : namespace formula
      37             : {
      38             :     using namespace com::sun::star;
      39             : 
      40             : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
      41             : 
      42             : // Need a lot of FormulaDoubleToken
      43       46424 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaDoubleToken )
      44             : // Need a lot of FormulaByteToken
      45       50159 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaByteToken )
      46             : // Need several FormulaStringToken
      47        8746 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaStringToken )
      48             : 
      49             : 
      50             : // --- helpers --------------------------------------------------------------
      51             : 
      52           0 : inline bool lcl_IsReference( OpCode eOp, StackVar eType )
      53             : {
      54             :     return
      55           0 :         (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
      56           0 :         || (eOp == ocColRowNameAuto && eType == svDoubleRef)
      57           0 :         || (eOp == ocColRowName && eType == svSingleRef)
      58           0 :         || (eOp == ocMatRef && eType == svSingleRef)
      59             :         ;
      60             : }
      61             : 
      62             : // --- class FormulaToken --------------------------------------------------------
      63             : 
      64      108092 : FormulaToken::FormulaToken( StackVar eTypeP, OpCode e ) :
      65      108092 :     eOp(e), eType( eTypeP ), mnRefCnt(0)
      66             : {
      67      108092 : }
      68             : 
      69       26235 : FormulaToken::FormulaToken( const FormulaToken& r ) :
      70       26235 :     IFormulaToken(), eOp(r.eOp), eType( r.eType ), mnRefCnt(0)
      71             : {
      72       26235 : }
      73             : 
      74      153511 : FormulaToken::~FormulaToken()
      75             : {
      76      153511 : }
      77             : 
      78           0 : bool FormulaToken::IsFunction() const
      79             : {
      80           0 :     return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
      81           0 :             eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
      82           0 :             eOp != ocTableRef &&
      83           0 :            (GetByte() != 0                                                  // x parameters
      84           0 :         || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)   // no parameter
      85           0 :         || (ocIf == eOp || ocIfError == eOp || ocIfNA == eOp || ocChoose == eOp ) // @ jump commands
      86           0 :         || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)     // one parameter
      87           0 :         || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)     // x parameters (cByte==0 in
      88             :                                                                             // FuncAutoPilot)
      89           0 :         || eOp == ocMacro || eOp == ocExternal                  // macros, AddIns
      90           0 :         || eOp == ocAnd || eOp == ocOr                          // former binary, now x parameters
      91           0 :         || eOp == ocNot || eOp == ocNeg                         // unary but function
      92           0 :         || (eOp >= ocInternalBegin && eOp <= ocInternalEnd)     // internal
      93           0 :         ));
      94             : }
      95             : 
      96             : 
      97       62645 : sal_uInt8 FormulaToken::GetParamCount() const
      98             : {
      99       91716 :     if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
     100       87175 :          eOp != ocIf && eOp != ocIfError && eOp != ocIfNA && eOp != ocChoose &&
     101       29047 :          eOp != ocPercentSign )
     102       29047 :         return 0;       // parameters and specials
     103             :                         // ocIf, ocIfError, ocIfNA and ocChoose not for FAP, have cByte then
     104             : //2do: bool parameter whether FAP or not?
     105       33598 :     else if ( GetByte() )
     106       16519 :         return GetByte();   // all functions, also ocExternal and ocMacro
     107       17079 :     else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
     108       16660 :         return 2;           // binary
     109         419 :     else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
     110         242 :             || eOp == ocPercentSign)
     111         177 :         return 1;           // unary
     112         242 :     else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
     113         113 :         return 0;           // no parameter
     114         129 :     else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
     115           0 :         return 1;           // one parameter
     116         129 :     else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChoose )
     117          24 :         return 1;           // only the condition counts as parameter
     118             :     else
     119         105 :         return 0;           // all the rest, no Parameter, or
     120             :                             // if so then it should be in cByte
     121             : }
     122             : 
     123      114281 : bool FormulaToken::IsExternalRef() const
     124             : {
     125      114281 :     bool bRet = false;
     126      114281 :     switch (eType)
     127             :     {
     128             :         case svExternalSingleRef:
     129             :         case svExternalDoubleRef:
     130             :         case svExternalName:
     131         296 :             bRet = true;
     132         296 :             break;
     133             :         default:
     134      113985 :             bRet = false;
     135      113985 :             break;
     136             :     }
     137      114281 :     return bRet;
     138             : }
     139             : 
     140         474 : bool FormulaToken::IsRef() const
     141             : {
     142         474 :     switch (eType)
     143             :     {
     144             :         case svSingleRef:
     145             :         case svDoubleRef:
     146             :         case svExternalSingleRef:
     147             :         case svExternalDoubleRef:
     148         468 :             return true;
     149             :         default:
     150             :             ;
     151             :     }
     152             : 
     153           6 :     return false;
     154             : }
     155             : 
     156          50 : bool FormulaToken::operator==( const FormulaToken& rToken ) const
     157             : {
     158             :     // don't compare reference count!
     159          50 :     return  eType == rToken.eType && GetOpCode() == rToken.GetOpCode();
     160             : }
     161             : 
     162             : 
     163             : // --- virtual dummy methods -------------------------------------------------
     164             : 
     165       29642 : sal_uInt8 FormulaToken::GetByte() const
     166             : {
     167             :     // ok to be called for any derived class
     168       29642 :     return 0;
     169             : }
     170             : 
     171           0 : void FormulaToken::SetByte( sal_uInt8 )
     172             : {
     173             :     SAL_WARN( "formula.core", "FormulaToken::SetByte: virtual dummy called" );
     174           0 : }
     175             : 
     176         755 : bool FormulaToken::HasForceArray() const
     177             : {
     178             :     // ok to be called for any derived class
     179         755 :     return false;
     180             : }
     181             : 
     182           0 : void FormulaToken::SetForceArray( bool )
     183             : {
     184             :     SAL_WARN( "formula.core", "FormulaToken::SetForceArray: virtual dummy called" );
     185           0 : }
     186             : 
     187           0 : double FormulaToken::GetDouble() const
     188             : {
     189             :     SAL_WARN( "formula.core", "FormulaToken::GetDouble: virtual dummy called" );
     190           0 :     return 0.0;
     191             : }
     192             : 
     193           0 : double & FormulaToken::GetDoubleAsReference()
     194             : {
     195             :     SAL_WARN( "formula.core", "FormulaToken::GetDouble: virtual dummy called" );
     196             :     static double fVal = 0.0;
     197           0 :     return fVal;
     198             : }
     199             : 
     200           0 : svl::SharedString FormulaToken::GetString() const
     201             : {
     202             :     SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
     203           0 :     return svl::SharedString(); // invalid string
     204             : }
     205             : 
     206           0 : sal_uInt16 FormulaToken::GetIndex() const
     207             : {
     208             :     SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" );
     209           0 :     return 0;
     210             : }
     211             : 
     212           0 : void FormulaToken::SetIndex( sal_uInt16 )
     213             : {
     214             :     SAL_WARN( "formula.core", "FormulaToken::SetIndex: virtual dummy called" );
     215           0 : }
     216             : 
     217           0 : bool FormulaToken::IsGlobal() const
     218             : {
     219             :     SAL_WARN( "formula.core", "FormulaToken::IsGlobal: virtual dummy called" );
     220           0 :     return true;
     221             : }
     222             : 
     223           0 : void FormulaToken::SetGlobal( bool )
     224             : {
     225             :     SAL_WARN( "formula.core", "FormulaToken::SetGlobal: virtual dummy called" );
     226           0 : }
     227             : 
     228           0 : short* FormulaToken::GetJump() const
     229             : {
     230             :     SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" );
     231           0 :     return NULL;
     232             : }
     233             : 
     234             : 
     235           0 : const OUString& FormulaToken::GetExternal() const
     236             : {
     237             :     SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" );
     238           0 :     static  OUString              aDummyString;
     239           0 :     return aDummyString;
     240             : }
     241             : 
     242           0 : FormulaToken* FormulaToken::GetFAPOrigToken() const
     243             : {
     244             :     SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" );
     245           0 :     return NULL;
     246             : }
     247             : 
     248           0 : sal_uInt16 FormulaToken::GetError() const
     249             : {
     250             :     SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" );
     251           0 :     return 0;
     252             : }
     253             : 
     254           0 : void FormulaToken::SetError( sal_uInt16 )
     255             : {
     256             :     SAL_WARN( "formula.core", "FormulaToken::SetError: virtual dummy called" );
     257           0 : }
     258             : 
     259           0 : const ScSingleRefData* FormulaToken::GetSingleRef() const
     260             : {
     261             :     OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
     262           0 :     return nullptr;
     263             : }
     264             : 
     265           0 : ScSingleRefData* FormulaToken::GetSingleRef()
     266             : {
     267             :     OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
     268           0 :     return nullptr;
     269             : }
     270             : 
     271           0 : const ScComplexRefData* FormulaToken::GetDoubleRef() const
     272             : {
     273             :     OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
     274           0 :     return nullptr;
     275             : }
     276             : 
     277           0 : ScComplexRefData* FormulaToken::GetDoubleRef()
     278             : {
     279             :     OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
     280           0 :     return nullptr;
     281             : }
     282             : 
     283           0 : const ScSingleRefData* FormulaToken::GetSingleRef2() const
     284             : {
     285             :     OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
     286           0 :     return nullptr;
     287             : }
     288             : 
     289           0 : ScSingleRefData* FormulaToken::GetSingleRef2()
     290             : {
     291             :     OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
     292           0 :     return nullptr;
     293             : }
     294             : 
     295           0 : const ScMatrix* FormulaToken::GetMatrix() const
     296             : {
     297             :     OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
     298           0 :     return NULL;
     299             : }
     300             : 
     301           0 : ScMatrix* FormulaToken::GetMatrix()
     302             : {
     303             :     OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
     304           0 :     return NULL;
     305             : }
     306             : 
     307           0 : ScJumpMatrix* FormulaToken::GetJumpMatrix() const
     308             : {
     309             :     OSL_FAIL( "FormulaToken::GetJumpMatrix: virtual dummy called" );
     310           0 :     return NULL;
     311             : }
     312           0 : const std::vector<ScComplexRefData>* FormulaToken::GetRefList() const
     313             : {
     314             :     OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
     315           0 :     return NULL;
     316             : }
     317             : 
     318           0 : std::vector<ScComplexRefData>* FormulaToken::GetRefList()
     319             : {
     320             :     OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
     321           0 :     return NULL;
     322             : }
     323             : 
     324           2 : bool FormulaToken::TextEqual( const FormulaToken& rToken ) const
     325             : {
     326           2 :     return *this == rToken;
     327             : }
     328             : 
     329             : // real implementations of virtual functions
     330             : 
     331             : 
     332             : 
     333       83575 : sal_uInt8 FormulaByteToken::GetByte() const                       { return nByte; }
     334        6575 : void FormulaByteToken::SetByte( sal_uInt8 n )                     { nByte = n; }
     335       36494 : bool FormulaByteToken::HasForceArray() const                 { return bHasForceArray; }
     336          13 : void FormulaByteToken::SetForceArray( bool b )               { bHasForceArray = b; }
     337          23 : bool FormulaByteToken::operator==( const FormulaToken& r ) const
     338             : {
     339          46 :     return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
     340          46 :         bHasForceArray == r.HasForceArray();
     341             : }
     342             : 
     343             : 
     344           0 : FormulaToken* FormulaFAPToken::GetFAPOrigToken() const { return pOrigToken.get(); }
     345           0 : bool FormulaFAPToken::operator==( const FormulaToken& r ) const
     346             : {
     347           0 :     return FormulaByteToken::operator==( r ) && pOrigToken == r.GetFAPOrigToken();
     348             : }
     349             : 
     350             : 
     351         275 : short* FormulaJumpToken::GetJump() const                     { return pJump; }
     352         333 : bool FormulaJumpToken::HasForceArray() const                 { return bHasForceArray; }
     353           0 : void FormulaJumpToken::SetForceArray( bool b )               { bHasForceArray = b; }
     354           0 : bool FormulaJumpToken::operator==( const FormulaToken& r ) const
     355             : {
     356           0 :     return FormulaToken::operator==( r ) && pJump[0] == r.GetJump()[0] &&
     357           0 :         memcmp( pJump+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0 &&
     358           0 :         bHasForceArray == r.HasForceArray();
     359             : }
     360         222 : FormulaJumpToken::~FormulaJumpToken()
     361             : {
     362          74 :     delete [] pJump;
     363         148 : }
     364             : 
     365             : 
     366         476 : bool FormulaTokenArray::AddFormulaToken(
     367             :     const sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, ExternalReferenceHelper* /*pExtRef*/)
     368             : {
     369         476 :     bool bError = false;
     370         476 :     const OpCode eOpCode = static_cast<OpCode>(rToken.OpCode);      //! assuming equal values for the moment
     371             : 
     372         476 :     const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
     373         476 :     switch ( eClass )
     374             :     {
     375             :         case uno::TypeClass_VOID:
     376             :             // empty data -> use AddOpCode (does some special cases)
     377          40 :             AddOpCode( eOpCode );
     378          40 :             break;
     379             :         case uno::TypeClass_DOUBLE:
     380             :             // double is only used for "push"
     381          77 :             if ( eOpCode == ocPush )
     382          77 :                 AddDouble( rToken.Data.get<double>() );
     383             :             else
     384           0 :                 bError = true;
     385          77 :             break;
     386             :         case uno::TypeClass_LONG:
     387             :             {
     388             :                 // long is svIndex, used for name / database area, or "byte" for spaces
     389           0 :                 sal_Int32 nValue = rToken.Data.get<sal_Int32>();
     390           0 :                 if ( eOpCode == ocDBArea )
     391           0 :                     AddToken( formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) );
     392           0 :                 else if ( eOpCode == ocTableRef )
     393           0 :                     bError = true;  /* TODO: implementation */
     394           0 :                 else if ( eOpCode == ocSpaces )
     395           0 :                     AddToken( formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) );
     396             :                 else
     397           0 :                     bError = true;
     398             :             }
     399           0 :             break;
     400             :         case uno::TypeClass_STRING:
     401             :             {
     402           0 :                 OUString aStrVal( rToken.Data.get<OUString>() );
     403           0 :                 if ( eOpCode == ocPush )
     404           0 :                     AddString(rSPool.intern(aStrVal));
     405           0 :                 else if ( eOpCode == ocBad )
     406           0 :                     AddBad( aStrVal );
     407           0 :                 else if ( eOpCode == ocStringXML )
     408           0 :                     AddStringXML( aStrVal );
     409           0 :                 else if ( eOpCode == ocExternal || eOpCode == ocMacro )
     410           0 :                     AddToken( formula::FormulaExternalToken( eOpCode, aStrVal ) );
     411             :                 else
     412           0 :                     bError = true;      // unexpected string: don't know what to do with it
     413             :             }
     414           0 :             break;
     415             :         default:
     416         359 :             bError = true;
     417             :     } // switch ( eClass )
     418         476 :     return bError;
     419             : }
     420             : 
     421         407 : bool FormulaTokenArray::Fill(
     422             :     const uno::Sequence<sheet::FormulaToken>& rSequence,
     423             :     svl::SharedStringPool& rSPool, ExternalReferenceHelper* pExtRef )
     424             : {
     425         407 :     bool bError = false;
     426         407 :     const sal_Int32 nCount = rSequence.getLength();
     427         883 :     for (sal_Int32 nPos=0; nPos<nCount; nPos++)
     428             :     {
     429         476 :         bool bOneError = AddFormulaToken(rSequence[nPos], rSPool, pExtRef);
     430         476 :         if (bOneError)
     431             :         {
     432           0 :             AddOpCode( ocErrName);  // add something that indicates an error
     433           0 :             bError = true;
     434             :         }
     435             :     }
     436         407 :     return bError;
     437             : }
     438        3449 : FormulaToken* FormulaTokenArray::GetNextReference()
     439             : {
     440        8099 :     while( nIndex < nLen )
     441             :     {
     442        3063 :         FormulaToken* t = pCode[ nIndex++ ];
     443        3063 :         switch( t->GetType() )
     444             :         {
     445             :             case svSingleRef:
     446             :             case svDoubleRef:
     447             :             case svExternalSingleRef:
     448             :             case svExternalDoubleRef:
     449        1862 :                 return t;
     450             :             default:
     451             :             {
     452             :                 // added to avoid warnings
     453             :             }
     454             :         }
     455             :     }
     456        1587 :     return NULL;
     457             : }
     458             : 
     459          85 : FormulaToken* FormulaTokenArray::GetNextColRowName()
     460             : {
     461         321 :     while( nIndex < nLen )
     462             :     {
     463         151 :         FormulaToken* t = pCode[ nIndex++ ];
     464         151 :         if ( t->GetOpCode() == ocColRowName )
     465           0 :             return t;
     466             :     }
     467          85 :     return NULL;
     468             : }
     469             : 
     470       26964 : FormulaToken* FormulaTokenArray::GetNextReferenceRPN()
     471             : {
     472       77454 :     while( nIndex < nRPN )
     473             :     {
     474       37459 :         FormulaToken* t = pRPN[ nIndex++ ];
     475       37459 :         switch( t->GetType() )
     476             :         {
     477             :             case svSingleRef:
     478             :             case svDoubleRef:
     479             :             case svExternalSingleRef:
     480             :             case svExternalDoubleRef:
     481       13933 :                 return t;
     482             :             default:
     483             :             {
     484             :                 // added to avoid warnings
     485             :             }
     486             :         }
     487             :     }
     488       13031 :     return NULL;
     489             : }
     490             : 
     491        2952 : FormulaToken* FormulaTokenArray::GetNextReferenceOrName()
     492             : {
     493        2952 :     if( pCode )
     494             :     {
     495        9038 :         while ( nIndex < nLen )
     496             :         {
     497        4981 :             FormulaToken* t = pCode[ nIndex++ ];
     498        4981 :             switch( t->GetType() )
     499             :             {
     500             :                 case svSingleRef:
     501             :                 case svDoubleRef:
     502             :                 case svIndex:
     503             :                 case svExternalSingleRef:
     504             :                 case svExternalDoubleRef:
     505             :                 case svExternalName:
     506        1777 :                     return t;
     507             :                 default:
     508             :                 {
     509             :                     // added to avoid warnings
     510             :                 }
     511             :              }
     512             :          }
     513             :      }
     514        1175 :     return NULL;
     515             : }
     516             : 
     517        1182 : FormulaToken* FormulaTokenArray::GetNextName()
     518             : {
     519        1182 :     if( pCode )
     520             :     {
     521        7082 :         while ( nIndex < nLen )
     522             :         {
     523        4836 :             FormulaToken* t = pCode[ nIndex++ ];
     524        4836 :             if( t->GetType() == svIndex )
     525          48 :                 return t;
     526             :         }
     527             :     } // if( pCode )
     528        1134 :     return NULL;
     529             : }
     530             : 
     531      109790 : FormulaToken* FormulaTokenArray::Next()
     532             : {
     533      109790 :     if( pCode && nIndex < nLen )
     534       95575 :         return pCode[ nIndex++ ];
     535             :     else
     536       14215 :         return NULL;
     537             : }
     538             : 
     539           5 : FormulaToken* FormulaTokenArray::NextNoSpaces()
     540             : {
     541           5 :     if( pCode )
     542             :     {
     543          10 :         while( (nIndex < nLen) && (pCode[ nIndex ]->GetOpCode() == ocSpaces) )
     544           0 :             ++nIndex;
     545           5 :         if( nIndex < nLen )
     546           5 :             return pCode[ nIndex++ ];
     547             :     }
     548           0 :     return NULL;
     549             : }
     550             : 
     551         895 : FormulaToken* FormulaTokenArray::NextRPN()
     552             : {
     553         895 :     if( pRPN && nIndex < nRPN )
     554         651 :         return pRPN[ nIndex++ ];
     555             :     else
     556         244 :         return NULL;
     557             : }
     558             : 
     559           0 : FormulaToken* FormulaTokenArray::PrevRPN()
     560             : {
     561           0 :     if( pRPN && nIndex )
     562           0 :         return pRPN[ --nIndex ];
     563             :     else
     564           0 :         return NULL;
     565             : }
     566             : 
     567       21911 : void FormulaTokenArray::DelRPN()
     568             : {
     569       21911 :     if( nRPN )
     570             :     {
     571       10627 :         FormulaToken** p = pRPN;
     572       55593 :         for( sal_uInt16 i = 0; i < nRPN; i++ )
     573             :         {
     574       44966 :             (*p++)->DecRef();
     575             :         }
     576       10627 :         delete [] pRPN;
     577             :     }
     578       21911 :     pRPN = NULL;
     579       21911 :     nRPN = nIndex = 0;
     580       21911 : }
     581             : 
     582           0 : FormulaToken* FormulaTokenArray::PeekPrev( sal_uInt16 & nIdx )
     583             : {
     584           0 :     if (0 < nIdx && nIdx <= nLen)
     585           0 :         return pCode[--nIdx];
     586           0 :     return NULL;
     587             : }
     588             : 
     589           0 : FormulaToken* FormulaTokenArray::PeekNext()
     590             : {
     591           0 :     if( pCode && nIndex < nLen )
     592           0 :         return pCode[ nIndex ];
     593             :     else
     594           0 :         return NULL;
     595             : }
     596             : 
     597         431 : FormulaToken* FormulaTokenArray::PeekNextNoSpaces()
     598             : {
     599         431 :     if( pCode && nIndex < nLen )
     600             :     {
     601         120 :         sal_uInt16 j = nIndex;
     602         240 :         while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
     603           0 :             j++;
     604         120 :         if ( j < nLen )
     605         120 :             return pCode[ j ];
     606             :         else
     607           0 :             return NULL;
     608             :     }
     609             :     else
     610         311 :         return NULL;
     611             : }
     612             : 
     613        3108 : FormulaToken* FormulaTokenArray::PeekPrevNoSpaces()
     614             : {
     615        3108 :     if( pCode && nIndex > 1 )
     616             :     {
     617        2287 :         sal_uInt16 j = nIndex - 2;
     618        4747 :         while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
     619         173 :             j--;
     620        2287 :         if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
     621        2287 :             return pCode[ j ];
     622             :         else
     623           0 :             return NULL;
     624             :     }
     625             :     else
     626         821 :         return NULL;
     627             : }
     628             : 
     629         474 : bool FormulaTokenArray::HasReferences() const
     630             : {
     631         480 :     for (sal_uInt16 i = 0; i < nLen; ++i)
     632             :     {
     633         474 :         if (pCode[i]->IsRef())
     634         468 :             return true;
     635             :     }
     636             : 
     637           6 :     return false;
     638             : }
     639             : 
     640           0 : bool FormulaTokenArray::HasExternalRef() const
     641             : {
     642           0 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     643             :     {
     644           0 :         if (pCode[j]->IsExternalRef())
     645           0 :             return true;
     646             :     }
     647           0 :     return false;
     648             : }
     649             : 
     650       10255 : bool FormulaTokenArray::HasOpCode( OpCode eOp ) const
     651             : {
     652       86650 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     653             :     {
     654       76397 :         if ( pCode[j]->GetOpCode() == eOp )
     655           2 :             return true;
     656             :     }
     657       10253 :     return false;
     658             : }
     659             : 
     660        5158 : bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp ) const
     661             : {
     662       28443 :     for ( sal_uInt16 j=0; j < nRPN; j++ )
     663             :     {
     664       23865 :         if ( pRPN[j]->GetOpCode() == eOp )
     665         580 :             return true;
     666             :     }
     667        4578 :     return false;
     668             : }
     669             : 
     670           3 : bool FormulaTokenArray::HasNameOrColRowName() const
     671             : {
     672           5 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     673             :     {
     674           3 :         if( pCode[j]->GetType() == svIndex || pCode[j]->GetOpCode() == ocColRowName )
     675           1 :             return true;
     676             :     }
     677           2 :     return false;
     678             : }
     679             : 
     680          14 : bool FormulaTokenArray::HasOpCodes(const unordered_opcode_set& rOpCodes) const
     681             : {
     682          14 :     FormulaToken** p = pCode;
     683          14 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
     684          58 :     for (; p != pEnd; ++p)
     685             :     {
     686          49 :         OpCode eOp = (*p)->GetOpCode();
     687          49 :         if (rOpCodes.count(eOp) > 0)
     688           5 :             return true;
     689             :     }
     690             : 
     691           9 :     return false;
     692             : }
     693             : 
     694       13220 : FormulaTokenArray::FormulaTokenArray() :
     695             :     pCode(NULL),
     696             :     pRPN(NULL),
     697             :     nLen(0),
     698             :     nRPN(0),
     699             :     nIndex(0),
     700             :     nError(0),
     701             :     nMode(ScRecalcMode::NORMAL),
     702       13220 :     bHyperLink(false)
     703             : {
     704       13220 : }
     705             : 
     706       12857 : FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray& rArr )
     707             : {
     708       12857 :     Assign( rArr );
     709       12857 : }
     710             : 
     711       25672 : FormulaTokenArray::~FormulaTokenArray()
     712             : {
     713       25403 :     Clear();
     714       25672 : }
     715             : 
     716       12857 : void FormulaTokenArray::Assign( const FormulaTokenArray& r )
     717             : {
     718       12857 :     nLen   = r.nLen;
     719       12857 :     nRPN   = r.nRPN;
     720       12857 :     nIndex = r.nIndex;
     721       12857 :     nError = r.nError;
     722       12857 :     nMode  = r.nMode;
     723       12857 :     bHyperLink = r.bHyperLink;
     724       12857 :     pCode  = NULL;
     725       12857 :     pRPN   = NULL;
     726             :     FormulaToken** pp;
     727       12857 :     if( nLen )
     728             :     {
     729       12846 :         pp = pCode = new FormulaToken*[ nLen ];
     730       12846 :         memcpy( pp, r.pCode, nLen * sizeof( FormulaToken* ) );
     731       88157 :         for( sal_uInt16 i = 0; i < nLen; i++ )
     732       75311 :             (*pp++)->IncRef();
     733             :     }
     734       12857 :     if( nRPN )
     735             :     {
     736        1150 :         pp = pRPN = new FormulaToken*[ nRPN ];
     737        1150 :         memcpy( pp, r.pRPN, nRPN * sizeof( FormulaToken* ) );
     738        7918 :         for( sal_uInt16 i = 0; i < nRPN; i++ )
     739        6768 :             (*pp++)->IncRef();
     740             :     }
     741       12857 : }
     742             : 
     743             : /// Optimisation for efficiently creating StringXML placeholders
     744        1505 : void FormulaTokenArray::Assign( sal_uInt16 nCode, FormulaToken **pTokens )
     745             : {
     746             :     assert( nLen == 0 );
     747             :     assert( pCode == NULL );
     748             : 
     749        1505 :     nLen = nCode;
     750        1505 :     pCode = new FormulaToken*[ nLen ];
     751             : 
     752        3010 :     for( sal_uInt16 i = 0; i < nLen; i++ )
     753             :     {
     754        1505 :         FormulaToken *t = pTokens[ i ];
     755             :         assert( t->GetOpCode() == ocStringXML );
     756        1505 :         pCode[ i ] = t;
     757        1505 :         t->IncRef();
     758             :     }
     759        1505 : }
     760             : 
     761           0 : FormulaTokenArray& FormulaTokenArray::operator=( const FormulaTokenArray& rArr )
     762             : {
     763           0 :     Clear();
     764           0 :     Assign( rArr );
     765           0 :     return *this;
     766             : }
     767             : 
     768           0 : FormulaTokenArray* FormulaTokenArray::Clone() const
     769             : {
     770           0 :     FormulaTokenArray* p = new FormulaTokenArray;
     771           0 :     p->nLen = nLen;
     772           0 :     p->nRPN = nRPN;
     773           0 :     p->nMode = nMode;
     774           0 :     p->nError = nError;
     775           0 :     p->bHyperLink = bHyperLink;
     776             :     FormulaToken** pp;
     777           0 :     if( nLen )
     778             :     {
     779           0 :         pp = p->pCode = new FormulaToken*[ nLen ];
     780           0 :         memcpy( pp, pCode, nLen * sizeof( FormulaToken* ) );
     781           0 :         for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
     782             :         {
     783           0 :             *pp = (*pp)->Clone();
     784           0 :             (*pp)->IncRef();
     785             :         }
     786             :     }
     787           0 :     if( nRPN )
     788             :     {
     789           0 :         pp = p->pRPN = new FormulaToken*[ nRPN ];
     790           0 :         memcpy( pp, pRPN, nRPN * sizeof( FormulaToken* ) );
     791           0 :         for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
     792             :         {
     793           0 :             FormulaToken* t = *pp;
     794           0 :             if( t->GetRef() > 1 )
     795             :             {
     796           0 :                 FormulaToken** p2 = pCode;
     797           0 :                 sal_uInt16 nIdx = 0xFFFF;
     798           0 :                 for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
     799             :                 {
     800           0 :                     if( *p2 == t )
     801             :                     {
     802           0 :                         nIdx = j; break;
     803             :                     }
     804             :                 }
     805           0 :                 if( nIdx == 0xFFFF )
     806           0 :                     *pp = t->Clone();
     807             :                 else
     808           0 :                     *pp = p->pCode[ nIdx ];
     809             :             }
     810             :             else
     811           0 :                 *pp = t->Clone();
     812           0 :             (*pp)->IncRef();
     813             :         }
     814             :     }
     815           0 :     return p;
     816             : }
     817             : 
     818       30133 : void FormulaTokenArray::Clear()
     819             : {
     820       30133 :     if( nRPN ) DelRPN();
     821       30133 :     if( pCode )
     822             :     {
     823       28128 :         FormulaToken** p = pCode;
     824      171456 :         for( sal_uInt16 i = 0; i < nLen; i++ )
     825             :         {
     826      143328 :             (*p++)->DecRef();
     827             :         }
     828       28128 :         delete [] pCode;
     829             :     }
     830       30133 :     pCode = NULL; pRPN = NULL;
     831       30133 :     nError = nLen = nIndex = nRPN = 0;
     832       30133 :     bHyperLink = false;
     833       30133 :     ClearRecalcMode();
     834       30133 : }
     835             : 
     836        3423 : void FormulaTokenArray::CheckToken( const FormulaToken& /*r*/ )
     837             : {
     838             :     // Do nothing.
     839        3423 : }
     840             : 
     841        3504 : FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r )
     842             : {
     843        3504 :     return Add( r.Clone() );
     844             : }
     845             : 
     846           0 : FormulaToken* FormulaTokenArray::MergeArray( )
     847             : {
     848           0 :     return NULL;
     849             : }
     850             : 
     851           0 : FormulaToken* FormulaTokenArray::ReplaceToken( sal_uInt16 nOffset, FormulaToken* t )
     852             : {
     853           0 :     if (nOffset < nLen)
     854             :     {
     855           0 :         CheckToken(*t);
     856           0 :         sal_uInt16 nPos = nLen - nOffset - 1;
     857           0 :         t->IncRef();
     858           0 :         pCode[nPos]->DecRef();
     859           0 :         pCode[nPos] = t;
     860           0 :         return t;
     861             :     }
     862             :     else
     863             :     {
     864           0 :         t->Delete();
     865           0 :         return NULL;
     866             :     }
     867             : }
     868             : 
     869       61276 : FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
     870             : {
     871       61276 :     if( !pCode )
     872       11213 :         pCode = new FormulaToken*[ FORMULA_MAXTOKENS ];
     873       61276 :     if( nLen < FORMULA_MAXTOKENS - 1 )
     874             :     {
     875       61276 :         CheckToken(*t);
     876       61276 :         pCode[ nLen++ ] = t;
     877       61276 :         t->IncRef();
     878       61276 :         if( t->GetOpCode() == ocArrayClose )
     879          71 :             return MergeArray();
     880       61205 :         return t;
     881             :     }
     882             :     else
     883             :     {
     884           0 :         t->Delete();
     885           0 :         if ( nLen == FORMULA_MAXTOKENS - 1 )
     886             :         {
     887           0 :             t = new FormulaByteToken( ocStop );
     888           0 :             pCode[ nLen++ ] = t;
     889           0 :             t->IncRef();
     890             :         }
     891           0 :         return NULL;
     892             :     }
     893             : }
     894             : 
     895        2738 : FormulaToken* FormulaTokenArray::AddString( const svl::SharedString& rStr )
     896             : {
     897        2738 :     return Add( new FormulaStringToken( rStr ) );
     898             : }
     899             : 
     900        1499 : FormulaToken* FormulaTokenArray::AddDouble( double fVal )
     901             : {
     902        1499 :     return Add( new FormulaDoubleToken( fVal ) );
     903             : }
     904             : 
     905           0 : FormulaToken* FormulaTokenArray::AddExternal( const sal_Unicode* pStr )
     906             : {
     907           0 :     return AddExternal( OUString( pStr ) );
     908             : }
     909             : 
     910           1 : FormulaToken* FormulaTokenArray::AddExternal( const OUString& rStr,
     911             :         OpCode eOp /* = ocExternal */ )
     912             : {
     913           1 :     return Add( new FormulaExternalToken( eOp, rStr ) );
     914             : }
     915             : 
     916           0 : FormulaToken* FormulaTokenArray::AddBad( const OUString& rStr )
     917             : {
     918           0 :     return Add( new FormulaStringOpToken( ocBad, rStr ) );
     919             : }
     920             : 
     921         177 : FormulaToken* FormulaTokenArray::AddStringXML( const OUString& rStr )
     922             : {
     923         177 :     return Add( new FormulaStringOpToken( ocStringXML, rStr ) );
     924             : }
     925             : 
     926             : 
     927             : 
     928         658 : void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
     929             : {
     930             :     //! Order is important.
     931         658 :     if ( nBits & ScRecalcMode::ALWAYS )
     932           0 :         SetExclusiveRecalcModeAlways();
     933         658 :     else if ( !IsRecalcModeAlways() )
     934             :     {
     935         658 :         if ( nBits & ScRecalcMode::ONLOAD )
     936         168 :             SetExclusiveRecalcModeOnLoad();
     937         490 :         else if ( nBits & ScRecalcMode::ONLOAD_ONCE && !IsRecalcModeOnLoad() )
     938           0 :             SetExclusiveRecalcModeOnLoadOnce();
     939             :     }
     940         658 :     SetCombinedBitsRecalcMode( nBits );
     941         658 : }
     942             : 
     943             : 
     944           0 : bool FormulaTokenArray::HasMatrixDoubleRefOps()
     945             : {
     946           0 :     if ( pRPN && nRPN )
     947             :     {
     948             :         // RPN-Interpreter simulation.
     949             :         // Simply assumes a double as return value of each function.
     950           0 :         boost::scoped_array<FormulaToken*> pStack(new FormulaToken* [nRPN]);
     951           0 :         FormulaToken* pResult = new FormulaDoubleToken( 0.0 );
     952           0 :         short sp = 0;
     953           0 :         for ( sal_uInt16 j = 0; j < nRPN; j++ )
     954             :         {
     955           0 :             FormulaToken* t = pRPN[j];
     956           0 :             OpCode eOp = t->GetOpCode();
     957           0 :             sal_uInt8 nParams = t->GetParamCount();
     958           0 :             switch ( eOp )
     959             :             {
     960             :                 case ocAdd :
     961             :                 case ocSub :
     962             :                 case ocMul :
     963             :                 case ocDiv :
     964             :                 case ocPow :
     965             :                 case ocPower :
     966             :                 case ocAmpersand :
     967             :                 case ocEqual :
     968             :                 case ocNotEqual :
     969             :                 case ocLess :
     970             :                 case ocGreater :
     971             :                 case ocLessEqual :
     972             :                 case ocGreaterEqual :
     973             :                 {
     974           0 :                     for ( sal_uInt8 k = nParams; k; k-- )
     975             :                     {
     976           0 :                         if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
     977             :                         {
     978           0 :                             pResult->Delete();
     979           0 :                             return true;
     980             :                         }
     981             :                     }
     982             :                 }
     983           0 :                 break;
     984             :                 default:
     985             :                 {
     986             :                     // added to avoid warnings
     987             :                 }
     988             :             }
     989           0 :             if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() )  )
     990           0 :                 pStack[sp++] = t;
     991           0 :             else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChoose )
     992             :             {   // ignore Jumps, pop previous Result (Condition)
     993           0 :                 if ( sp )
     994           0 :                     --sp;
     995             :             }
     996             :             else
     997             :             {   // pop parameters, push result
     998           0 :                 sp = sal::static_int_cast<short>( sp - nParams );
     999           0 :                 if ( sp < 0 )
    1000             :                 {
    1001             :                     SAL_WARN("formula.core", "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
    1002           0 :                     sp = 0;
    1003             :                 }
    1004           0 :                 pStack[sp++] = pResult;
    1005             :             }
    1006             :         }
    1007           0 :         pResult->Delete();
    1008             :     }
    1009             : 
    1010           0 :     return false;
    1011             : }
    1012             : 
    1013             : // --- Formula rewrite of a token array
    1014             : 
    1015        8171 : inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp ) const
    1016             : {
    1017        8171 :     switch (eOp)
    1018             :     {
    1019             :         case ocGammaDist:
    1020             :         case ocPoissonDist:
    1021             :         case ocAddress:
    1022             :         case ocLogNormDist:
    1023             :         case ocNormDist:
    1024          16 :             return true;
    1025             :         case ocMissing:
    1026             :         case ocLog:
    1027           2 :             return isPODF();    // rewrite only for PODF
    1028             :         default:
    1029        8153 :             return false;
    1030             :     }
    1031             : }
    1032             : 
    1033             : /*
    1034             :  fdo 81596
    1035             : To be implemented yet:
    1036             :   ocExternal:    ?
    1037             :   ocMacro:       ?
    1038             :   ocIndex:       INDEX() ?
    1039             : */
    1040        2627 : inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp )
    1041             : {
    1042        2627 :     switch (eOp)
    1043             :     {
    1044             :         case ocIf:
    1045             : 
    1046             :         case ocExternal:
    1047             :         case ocEuroConvert:
    1048             :         case ocMacro:
    1049             : 
    1050             :         case ocRound:
    1051             :         case ocRoundUp:
    1052             :         case ocRoundDown:
    1053             : 
    1054             :         case ocIndex:
    1055             : 
    1056             :         case ocCeil:
    1057             : 
    1058             :         case ocGammaDist:
    1059             :         case ocFDist_LT:
    1060             :         case ocPoissonDist:
    1061             :         case ocNormDist:
    1062             :         case ocLogNormDist:
    1063         253 :             return true;
    1064             :         default:
    1065        2374 :             return false;
    1066             :     }
    1067             : }
    1068             : 
    1069             : class FormulaMissingContext
    1070             : {
    1071             :     public:
    1072             :             const FormulaToken* mpFunc;
    1073             :             int                 mnCurArg;
    1074             : 
    1075         269 :                     void    Clear() { mpFunc = NULL; mnCurArg = 0; }
    1076             :             inline  bool    AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const;
    1077             :                     bool    AddMissingExternal( FormulaTokenArray* pNewArr ) const;
    1078             :                     bool    AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const;
    1079             :                     void    AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const;
    1080             : };
    1081             : 
    1082         520 : void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const
    1083             : {
    1084         520 :     if ( !mpFunc )
    1085         520 :         return;
    1086             : 
    1087         520 :     switch (rConv.getConvention())
    1088             :     {
    1089             :         case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF:
    1090             :         case MissingConvention::FORMULA_MISSING_CONVENTION_PODF:
    1091             :             {
    1092          16 :                 switch (mpFunc->GetOpCode())
    1093             :                 {
    1094             :                     case ocGammaDist:
    1095           2 :                         if (mnCurArg == 2)
    1096             :                         {
    1097           0 :                             pNewArr->AddOpCode( ocSep );
    1098           0 :                             pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
    1099             :                         }
    1100           2 :                         break;
    1101             :                     case ocPoissonDist:
    1102           2 :                         if (mnCurArg == 1)
    1103             :                         {
    1104           0 :                             pNewArr->AddOpCode( ocSep );
    1105           0 :                             pNewArr->AddDouble( 1.0 );      // 3rd, Cumulative=true()
    1106             :                         }
    1107           2 :                         break;
    1108             :                     case ocNormDist:
    1109           4 :                         if ( mnCurArg == 2 )
    1110             :                         {
    1111           0 :                             pNewArr->AddOpCode( ocSep );
    1112           0 :                             pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
    1113             :                         }
    1114           4 :                         break;
    1115             :                     case ocLogNormDist:
    1116           2 :                         if ( mnCurArg == 0 )
    1117             :                         {
    1118           0 :                             pNewArr->AddOpCode( ocSep );
    1119           0 :                             pNewArr->AddDouble( 0.0 );      // 2nd, mean = 0.0
    1120             :                         }
    1121           2 :                         if ( mnCurArg <= 1 )
    1122             :                         {
    1123           0 :                             pNewArr->AddOpCode( ocSep );
    1124           0 :                             pNewArr->AddDouble( 1.0 );      // 3rd, standard deviation = 1.0
    1125             :                         }
    1126           2 :                         break;
    1127             :                     case ocLog:
    1128           0 :                         if ( rConv.isPODF() && mnCurArg == 0 )
    1129             :                         {
    1130           0 :                             pNewArr->AddOpCode( ocSep );
    1131           0 :                             pNewArr->AddDouble( 10.0 );     // 2nd, basis 10
    1132             :                         }
    1133           0 :                         break;
    1134             :                     default:
    1135           6 :                         break;
    1136             :                 }
    1137             :             }
    1138          16 :             break;
    1139             :         case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML:
    1140             :             {
    1141         504 :                 switch (mpFunc->GetOpCode())
    1142             :                 {
    1143             :                     case ocIf:
    1144           0 :                         if( mnCurArg == 0 )
    1145             :                         {
    1146             :                             // Excel needs at least two parameters in IF function
    1147           0 :                             pNewArr->AddOpCode( ocSep );
    1148           0 :                             pNewArr->AddOpCode( ocTrue );   // 2nd, true() as function
    1149           0 :                             pNewArr->AddOpCode( ocOpen );   // so the result is of logical type
    1150           0 :                             pNewArr->AddOpCode( ocClose );  // and survives roundtrip
    1151             :                         }
    1152           0 :                         break;
    1153             : 
    1154             :                     case ocEuroConvert:
    1155           0 :                         if ( mnCurArg == 2 )
    1156             :                         {
    1157           0 :                             pNewArr->AddOpCode( ocSep );
    1158           0 :                             pNewArr->AddDouble( 0.0 );      // 4th, FullPrecision = false()
    1159             :                         }
    1160           0 :                         break;
    1161             : 
    1162             :                     case ocPoissonDist:
    1163           0 :                         if (mnCurArg == 1)
    1164             :                         {
    1165           0 :                             pNewArr->AddOpCode( ocSep );
    1166           0 :                             pNewArr->AddDouble( 1.0 );      // 3rd, Cumulative=true()
    1167             :                         }
    1168           0 :                         break;
    1169             : 
    1170             :                     case ocGammaDist:
    1171             :                     case ocFDist_LT:
    1172             :                     case ocNormDist:
    1173           2 :                         if (mnCurArg == 2)
    1174             :                         {
    1175           0 :                             pNewArr->AddOpCode( ocSep );
    1176           0 :                             pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
    1177             :                         }
    1178           2 :                         break;
    1179             : 
    1180             :                     case ocLogNormDist:
    1181           0 :                         if ( mnCurArg == 0 )
    1182             :                         {
    1183           0 :                             pNewArr->AddOpCode( ocSep );
    1184           0 :                             pNewArr->AddDouble( 0.0 );      // 2nd, mean = 0.0
    1185             :                         }
    1186           0 :                         if ( mnCurArg <= 1 )
    1187             :                         {
    1188           0 :                             pNewArr->AddOpCode( ocSep );
    1189           0 :                             pNewArr->AddDouble( 1.0 );      // 3rd, standard deviation = 1.0
    1190             :                         }
    1191           0 :                         break;
    1192             : 
    1193             :                     case ocRound:
    1194             :                     case ocRoundUp:
    1195             :                     case ocRoundDown:
    1196         502 :                         if( mnCurArg == 0 )
    1197             :                         {
    1198             :                             // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
    1199           0 :                             pNewArr->AddOpCode( ocSep );
    1200           0 :                             pNewArr->AddDouble( 0.0 );      // 2nd, 0.0
    1201             :                         }
    1202         502 :                         break;
    1203             : 
    1204             :                     default:
    1205           0 :                         break;
    1206             :                 }
    1207             :             }
    1208         504 :             break;
    1209             :     }
    1210             : 
    1211             : }
    1212             : 
    1213           2 : inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
    1214             : {
    1215           2 :     if (mnCurArg == nArg)
    1216             :     {
    1217           0 :         pNewArr->AddDouble( f );
    1218           0 :         return true;
    1219             :     }
    1220           2 :     return false;
    1221             : }
    1222             : 
    1223           0 : bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray *pNewArr ) const
    1224             : {
    1225             :     // Only called for PODF, not ODFF. No need to distinguish.
    1226             : 
    1227           0 :     const OUString &rName = mpFunc->GetExternal();
    1228             : 
    1229             :     // initial (fast) check:
    1230           0 :     sal_Unicode nLastChar = rName[ rName.getLength() - 1];
    1231           0 :     if ( nLastChar != 't' && nLastChar != 'm' )
    1232           0 :         return false;
    1233             : 
    1234           0 :     if (rName.equalsIgnoreAsciiCase(
    1235             :                 "com.sun.star.sheet.addin.Analysis.getAccrint" ))
    1236             :     {
    1237           0 :         return AddDefaultArg( pNewArr, 4, 1000.0 );
    1238             :     }
    1239           0 :     if (rName.equalsIgnoreAsciiCase(
    1240             :                 "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
    1241             :     {
    1242           0 :         return AddDefaultArg( pNewArr, 3, 1000.0 );
    1243             :     }
    1244           0 :     return false;
    1245             : }
    1246             : 
    1247           2 : bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const
    1248             : {
    1249           2 :     if ( !mpFunc )
    1250           0 :         return false;
    1251             : 
    1252           2 :     bool bRet = false;
    1253           2 :     const OpCode eOp = mpFunc->GetOpCode();
    1254             : 
    1255           2 :     switch (rConv.getConvention())
    1256             :     {
    1257             :         case MissingConvention::FORMULA_MISSING_CONVENTION_ODFF:
    1258             :             {
    1259             :                 // Add for ODFF
    1260           2 :                 switch (eOp)
    1261             :                 {
    1262             :                     case ocAddress:
    1263           2 :                         return AddDefaultArg( pNewArr, 2, 1.0 );    // abs
    1264             :                     default:
    1265           0 :                         break;
    1266             :                 }
    1267             :             }
    1268           0 :             break;
    1269             :         case MissingConvention::FORMULA_MISSING_CONVENTION_PODF:
    1270             :             {
    1271             :                 // Add for PODF
    1272           0 :                 switch (eOp)
    1273             :                 {
    1274             :                     case ocAddress:
    1275           0 :                         return AddDefaultArg( pNewArr, 2, 1.0 );    // abs
    1276             :                     case ocFixed:
    1277           0 :                         return AddDefaultArg( pNewArr, 1, 2.0 );
    1278             :                     case ocBetaDist:
    1279             :                     case ocBetaInv:
    1280             :                     case ocPMT:
    1281           0 :                         return AddDefaultArg( pNewArr, 3, 0.0 );
    1282             :                     case ocIpmt:
    1283             :                     case ocPpmt:
    1284           0 :                         return AddDefaultArg( pNewArr, 4, 0.0 );
    1285             :                     case ocPV:
    1286             :                     case ocFV:
    1287           0 :                         bRet |= AddDefaultArg( pNewArr, 2, 0.0 );   // pmt
    1288           0 :                         bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // [fp]v
    1289           0 :                         break;
    1290             :                     case ocRate:
    1291           0 :                         bRet |= AddDefaultArg( pNewArr, 1, 0.0 );   // pmt
    1292           0 :                         bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // fv
    1293           0 :                         bRet |= AddDefaultArg( pNewArr, 4, 0.0 );   // type
    1294           0 :                         break;
    1295             :                     case ocExternal:
    1296           0 :                         return AddMissingExternal( pNewArr );
    1297             : 
    1298             :                         // --- more complex cases ---
    1299             : 
    1300             :                     case ocOffset:
    1301             :                         // FIXME: rather tough.
    1302             :                         // if arg 3 (height) omitted, export arg1 (rows)
    1303           0 :                         break;
    1304             :                     default:
    1305           0 :                         break;
    1306             :                 }
    1307             :             }
    1308           0 :             break;
    1309             :         case MissingConvention::FORMULA_MISSING_CONVENTION_OOXML:
    1310             :             {
    1311           0 :                 switch (eOp)
    1312             :                 {
    1313             :                     case ocExternal:
    1314           0 :                         return AddMissingExternal( pNewArr );
    1315             :                     default:
    1316           0 :                         break;
    1317             :                 }
    1318             :             }
    1319           0 :             break;
    1320             :     }
    1321             : 
    1322           0 :     return bRet;
    1323             : }
    1324             : 
    1325        1354 : bool FormulaTokenArray::NeedsPodfRewrite( const MissingConventionODF & rConv )
    1326             : {
    1327        9509 :     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
    1328             :     {
    1329        8171 :         if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
    1330          16 :             return true;
    1331             :     }
    1332        1338 :     return false;
    1333             : }
    1334             : 
    1335         560 : bool FormulaTokenArray::NeedsOoxmlRewrite()
    1336             : {
    1337        2934 :     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
    1338             :     {
    1339        2627 :         if ( MissingConventionOOXML::isRewriteNeeded( pCur->GetOpCode()))
    1340         253 :             return true;
    1341             :     }
    1342         307 :     return false;
    1343             : }
    1344             : 
    1345             : 
    1346         269 : FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & rConv )
    1347             : {
    1348         269 :     const size_t nAlloc = 256;
    1349             :     FormulaMissingContext aCtx[ nAlloc ];
    1350             :     int aOpCodeAddressStack[ nAlloc ];  // use of ADDRESS() function
    1351         269 :     const int nOmitAddressArg = 3;      // ADDRESS() 4th parameter A1/R1C1
    1352         269 :     sal_uInt16 nTokens = GetLen() + 1;
    1353         269 :     FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
    1354         269 :     int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
    1355             :     // Never go below 0, never use 0, mpFunc always NULL.
    1356         269 :     pCtx[0].Clear();
    1357         269 :     int nFn = 0;
    1358         269 :     int nOcas = 0;
    1359             : 
    1360         269 :     FormulaTokenArray *pNewArr = new FormulaTokenArray;
    1361             :     // At least ScRecalcMode::ALWAYS needs to be set.
    1362         269 :     pNewArr->AddRecalcMode( GetRecalcMode());
    1363             : 
    1364        3692 :     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
    1365             :     {
    1366        3423 :         bool bAdd = true;
    1367             :         // Don't write the expression of the new inserted ADDRESS() parameter.
    1368             :         // Do NOT omit the new second parameter of INDIRECT() though. If that
    1369             :         // was done for both, INDIRECT() actually could calculate different and
    1370             :         // valid (but wrong) results with the then changed return value of
    1371             :         // ADDRESS(). Better let it generate an error instead.
    1372        6846 :         for (int i = nOcas; i-- > 0 && bAdd; )
    1373             :         {
    1374           0 :             if (pCtx[ pOcas[ i ] ].mnCurArg == nOmitAddressArg)
    1375             :             {
    1376             :                 // Omit erverything except a trailing separator, the leading
    1377             :                 // separator is omitted below. The other way around would leave
    1378             :                 // an extraneous separator if no parameter followed.
    1379           0 :                 if (!(pOcas[ i ] == nFn && pCur->GetOpCode() == ocSep))
    1380           0 :                     bAdd = false;
    1381             :             }
    1382             :         }
    1383        3423 :         switch ( pCur->GetOpCode() )
    1384             :         {
    1385             :             case ocOpen:
    1386         520 :                 ++nFn;      // all following operations on _that_ function
    1387         520 :                 pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
    1388         520 :                 pCtx[ nFn ].mnCurArg = 0;
    1389         520 :                 if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
    1390           0 :                     pOcas[ nOcas++ ] = nFn;     // entering ADDRESS() if PODF
    1391         520 :                 break;
    1392             :             case ocClose:
    1393         520 :                 pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
    1394             :                 DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissing: underflow");
    1395         520 :                 if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
    1396           0 :                     --nOcas;                    // leaving ADDRESS()
    1397         520 :                 if (nFn > 0)
    1398         520 :                     --nFn;
    1399         520 :                 break;
    1400             :             case ocSep:
    1401         546 :                 pCtx[ nFn ].mnCurArg++;
    1402             :                 // Omit leading separator of ADDRESS() parameter.
    1403         546 :                 if (nOcas && pOcas[ nOcas-1 ] == nFn && pCtx[ nFn ].mnCurArg == nOmitAddressArg)
    1404             :                 {
    1405           0 :                     bAdd = false;
    1406             :                 }
    1407         546 :                 break;
    1408             :             case ocMissing:
    1409           2 :                 if ( bAdd )
    1410           2 :                     bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
    1411           2 :                 break;
    1412             :             default:
    1413        1835 :                 break;
    1414             :         }
    1415        3423 :         if (bAdd)
    1416             :         {
    1417        3423 :             if ( pCur->GetOpCode() == ocCeil &&
    1418           0 :                  rConv.getConvention() == MissingConvention::FORMULA_MISSING_CONVENTION_OOXML )
    1419             :             {
    1420           0 :                 FormulaToken *pToken = new FormulaToken( svByte, ocCeil_Math );
    1421           0 :                 pNewArr->AddToken( *pToken );
    1422             :             }
    1423             :             else
    1424        3423 :                 pNewArr->AddToken( *pCur );
    1425             :         }
    1426             :     }
    1427             : 
    1428         269 :     if (pOcas != &aOpCodeAddressStack[0])
    1429           0 :         delete [] pOcas;
    1430         269 :     if (pCtx != &aCtx[0])
    1431           0 :         delete [] pCtx;
    1432             : 
    1433         269 :     return pNewArr;
    1434             : }
    1435             : 
    1436           0 : bool FormulaTokenArray::MayReferenceFollow()
    1437             : {
    1438           0 :     if ( pCode && nLen > 0 )
    1439             :     {
    1440             :         // ignore trailing spaces
    1441           0 :         sal_uInt16 i = nLen - 1;
    1442           0 :         while ( i > 0 && pCode[i]->GetOpCode() == SC_OPCODE_SPACES )
    1443             :         {
    1444           0 :             --i;
    1445             :         }
    1446           0 :         if ( i > 0 || pCode[i]->GetOpCode() != SC_OPCODE_SPACES )
    1447             :         {
    1448           0 :             OpCode eOp = pCode[i]->GetOpCode();
    1449           0 :             if ( (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) ||
    1450           0 :                  (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP ) ||
    1451           0 :                  eOp == SC_OPCODE_OPEN || eOp == SC_OPCODE_SEP )
    1452             :             {
    1453           0 :                 return true;
    1454             :             }
    1455             :         }
    1456             :     }
    1457           0 :     return false;
    1458             : }
    1459           0 : FormulaToken* FormulaTokenArray::AddOpCode( OpCode eOp )
    1460             : {
    1461           0 :     FormulaToken* pRet = NULL;
    1462           0 :     switch ( eOp )
    1463             :     {
    1464             :         case ocOpen:
    1465             :         case ocClose:
    1466             :         case ocSep:
    1467             :         case ocArrayOpen:
    1468             :         case ocArrayClose:
    1469             :         case ocArrayRowSep:
    1470             :         case ocArrayColSep:
    1471           0 :             pRet = new FormulaToken( svSep,eOp );
    1472           0 :             break;
    1473             :         case ocIf:
    1474             :         case ocIfError:
    1475             :         case ocIfNA:
    1476             :         case ocChoose:
    1477             :             {
    1478             :                 short nJump[FORMULA_MAXJUMPCOUNT + 1];
    1479           0 :                 if ( eOp == ocIf )
    1480           0 :                     nJump[ 0 ] = 3;
    1481           0 :                 else if ( eOp == ocChoose )
    1482           0 :                     nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
    1483             :                 else
    1484           0 :                     nJump[ 0 ] = 2;
    1485           0 :                 pRet = new FormulaJumpToken( eOp, nJump );
    1486             :             }
    1487           0 :             break;
    1488             :         default:
    1489           0 :             pRet = new FormulaByteToken( eOp, 0, false );
    1490           0 :             break;
    1491             :     }
    1492           0 :     return AddToken( *pRet );
    1493             : }
    1494             : 
    1495             : 
    1496             : /*----------------------------------------------------------------------*/
    1497             : 
    1498       11867 : FormulaTokenIterator::Item::Item(const FormulaTokenArray* pArray, short pc, short stop) :
    1499       11867 :     pArr(pArray), nPC(pc), nStop(stop)
    1500             : {
    1501       11867 : }
    1502             : 
    1503       11804 : FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray& rArr )
    1504             : {
    1505       11804 :     maStack = new std::vector<FormulaTokenIterator::Item> ();
    1506       11804 :     Push( &rArr );
    1507       11804 : }
    1508             : 
    1509       11804 : FormulaTokenIterator::~FormulaTokenIterator()
    1510             : {
    1511       11804 :     delete maStack;
    1512       11804 : }
    1513             : 
    1514       11867 : void FormulaTokenIterator::Push( const FormulaTokenArray* pArr )
    1515             : {
    1516       11867 :     FormulaTokenIterator::Item item(pArr, -1, SHRT_MAX);
    1517             : 
    1518       11867 :     maStack->push_back(item);
    1519       11867 : }
    1520             : 
    1521          63 : void FormulaTokenIterator::Pop()
    1522             : {
    1523          63 :     maStack->pop_back();
    1524          63 : }
    1525             : 
    1526       11804 : void FormulaTokenIterator::Reset()
    1527             : {
    1528       23608 :     while( maStack->size() > 1 )
    1529           0 :         maStack->pop_back();
    1530             : 
    1531       11804 :     maStack->back().nPC = -1;
    1532       11804 : }
    1533             : 
    1534       57515 : const FormulaToken* FormulaTokenIterator::Next()
    1535             : {
    1536       57515 :     const FormulaToken* t = GetNonEndOfPathToken( ++maStack->back().nPC );
    1537       57515 :     if( !t && maStack->size() > 1 )
    1538             :     {
    1539          38 :         Pop();
    1540          38 :         t = Next();
    1541             :     }
    1542       57515 :     return t;
    1543             : }
    1544             : 
    1545           0 : const FormulaToken* FormulaTokenIterator::PeekNextOperator()
    1546             : {
    1547           0 :     const FormulaToken* t = NULL;
    1548           0 :     short nIdx = maStack->back().nPC;
    1549           0 :     while (!t && ((t = GetNonEndOfPathToken( ++nIdx)) != NULL))
    1550             :     {
    1551           0 :         if (t->GetOpCode() == ocPush)
    1552           0 :             t = NULL;   // ignore operands
    1553             :     }
    1554           0 :     if (!t && maStack->size() > 1)
    1555             :     {
    1556           0 :         FormulaTokenIterator::Item pHere = maStack->back();
    1557           0 :         maStack->pop_back();
    1558           0 :         t = PeekNextOperator();
    1559           0 :         maStack->push_back(pHere);
    1560             :     }
    1561           0 :     return t;
    1562             : }
    1563             : 
    1564             : //! The nPC counts after a Push() are -1
    1565             : 
    1566          85 : void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
    1567             : {
    1568          85 :     maStack->back().nPC = nNext;
    1569          85 :     if( nStart != nNext )
    1570             :     {
    1571          63 :         Push( maStack->back().pArr );
    1572          63 :         maStack->back().nPC = nStart;
    1573          63 :         maStack->back().nStop = nStop;
    1574             :     }
    1575          85 : }
    1576             : 
    1577       57550 : const FormulaToken* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx ) const
    1578             : {
    1579       57550 :     FormulaTokenIterator::Item cur = maStack->back();
    1580             : 
    1581       57550 :     if (nIdx < cur.pArr->nRPN && nIdx < cur.nStop)
    1582             :     {
    1583       45724 :         const FormulaToken* t = cur.pArr->pRPN[ nIdx ];
    1584             :         // such an OpCode ends an IF() or CHOOSE() path
    1585       45724 :         return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? NULL : t;
    1586             :     }
    1587       11826 :     return NULL;
    1588             : }
    1589             : 
    1590          35 : bool FormulaTokenIterator::IsEndOfPath() const
    1591             : {
    1592          35 :     return GetNonEndOfPathToken( maStack->back().nPC + 1) == NULL;
    1593             : }
    1594             : 
    1595             : 
    1596             : 
    1597             : // real implementations of virtual functions
    1598             : 
    1599             : 
    1600       42719 : double      FormulaDoubleToken::GetDouble() const            { return fDouble; }
    1601           5 : double &    FormulaDoubleToken::GetDoubleAsReference()       { return fDouble; }
    1602           0 : bool FormulaDoubleToken::operator==( const FormulaToken& r ) const
    1603             : {
    1604           0 :     return FormulaToken::operator==( r ) && fDouble == r.GetDouble();
    1605             : }
    1606             : 
    1607        4342 : FormulaStringToken::FormulaStringToken( const svl::SharedString& r ) :
    1608        4342 :     FormulaToken( svString ), maString( r )
    1609             : {
    1610        4342 : }
    1611             : 
    1612         126 : FormulaStringToken::FormulaStringToken( const FormulaStringToken& r ) :
    1613         126 :     FormulaToken( r ), maString( r.maString ) {}
    1614             : 
    1615         126 : FormulaToken* FormulaStringToken::Clone() const
    1616             : {
    1617         126 :     return new FormulaStringToken(*this);
    1618             : }
    1619             : 
    1620        7741 : svl::SharedString FormulaStringToken::GetString() const
    1621             : {
    1622        7741 :     return maString;
    1623             : }
    1624             : 
    1625           0 : bool FormulaStringToken::operator==( const FormulaToken& r ) const
    1626             : {
    1627           0 :     return FormulaToken::operator==( r ) && maString == r.GetString();
    1628             : }
    1629             : 
    1630        1699 : FormulaStringOpToken::FormulaStringOpToken( OpCode e, const svl::SharedString& r ) :
    1631        1699 :     FormulaByteToken( e, 0, svString, false ), maString( r ) {}
    1632             : 
    1633           7 : FormulaStringOpToken::FormulaStringOpToken( const FormulaStringOpToken& r ) :
    1634           7 :     FormulaByteToken( r ), maString( r.maString ) {}
    1635             : 
    1636           7 : FormulaToken* FormulaStringOpToken::Clone() const
    1637             : {
    1638           7 :     return new FormulaStringOpToken(*this);
    1639             : }
    1640             : 
    1641        1642 : svl::SharedString FormulaStringOpToken::GetString() const
    1642             : {
    1643        1642 :     return maString;
    1644             : }
    1645             : 
    1646          21 : bool FormulaStringOpToken::operator==( const FormulaToken& r ) const
    1647             : {
    1648          21 :     return FormulaByteToken::operator==( r ) && maString == r.GetString();
    1649             : }
    1650             : 
    1651         820 : sal_uInt16  FormulaIndexToken::GetIndex() const             { return nIndex; }
    1652          48 : void        FormulaIndexToken::SetIndex( sal_uInt16 n )     { nIndex = n; }
    1653         753 : bool        FormulaIndexToken::IsGlobal() const             { return mbGlobal; }
    1654          48 : void        FormulaIndexToken::SetGlobal( bool b )          { mbGlobal = b; }
    1655           0 : bool FormulaIndexToken::operator==( const FormulaToken& r ) const
    1656             : {
    1657           0 :     return FormulaToken::operator==( r ) && nIndex == r.GetIndex() &&
    1658           0 :         mbGlobal == r.IsGlobal();
    1659             : }
    1660         245 : const OUString&   FormulaExternalToken::GetExternal() const    { return aExternal; }
    1661         468 : sal_uInt8            FormulaExternalToken::GetByte() const        { return nByte; }
    1662         102 : void            FormulaExternalToken::SetByte( sal_uInt8 n )      { nByte = n; }
    1663           0 : bool FormulaExternalToken::operator==( const FormulaToken& r ) const
    1664             : {
    1665           0 :     return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
    1666           0 :         aExternal == r.GetExternal();
    1667             : }
    1668             : 
    1669             : 
    1670         764 : sal_uInt16          FormulaErrorToken::GetError() const          { return nError; }
    1671           0 : void            FormulaErrorToken::SetError( sal_uInt16 nErr )   { nError = nErr; }
    1672           0 : bool FormulaErrorToken::operator==( const FormulaToken& r ) const
    1673             : {
    1674           0 :     return FormulaToken::operator==( r ) &&
    1675           0 :         nError == static_cast< const FormulaErrorToken & >(r).GetError();
    1676             : }
    1677           0 : double          FormulaMissingToken::GetDouble() const       { return 0.0; }
    1678             : 
    1679           0 : svl::SharedString FormulaMissingToken::GetString() const
    1680             : {
    1681           0 :     return svl::SharedString::getEmptyString();
    1682             : }
    1683             : 
    1684           0 : bool FormulaMissingToken::operator==( const FormulaToken& r ) const
    1685             : {
    1686           0 :     return FormulaToken::operator==( r );
    1687             : }
    1688             : 
    1689             : 
    1690           0 : FormulaSubroutineToken::FormulaSubroutineToken( const FormulaSubroutineToken& r ) :
    1691             :     FormulaToken( r ),
    1692           0 :     mpArray( r.mpArray->Clone())
    1693             : {
    1694           0 : }
    1695           0 : FormulaSubroutineToken::~FormulaSubroutineToken()
    1696             : {
    1697           0 :     delete mpArray;
    1698           0 : }
    1699           0 : bool FormulaSubroutineToken::operator==( const FormulaToken& r ) const
    1700             : {
    1701             :     // Arrays don't equal..
    1702           0 :     return FormulaToken::operator==( r ) &&
    1703           0 :         (mpArray == static_cast<const FormulaSubroutineToken&>(r).mpArray);
    1704             : }
    1705             : 
    1706             : 
    1707           0 : bool FormulaUnknownToken::operator==( const FormulaToken& r ) const
    1708             : {
    1709           0 :     return FormulaToken::operator==( r );
    1710             : }
    1711             : 
    1712             : 
    1713         183 : } // formula
    1714             : 
    1715             : 
    1716             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11