LCOV - code coverage report
Current view: top level - formula/source/core/api - token.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 389 721 54.0 %
Date: 2014-11-03 Functions: 96 156 61.5 %
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             : 
      28             : #include "formula/token.hxx"
      29             : #include "formula/tokenarray.hxx"
      30             : #include "formula/FormulaCompiler.hxx"
      31             : #include <formula/compiler.hrc>
      32             : #include <svl/sharedstringpool.hxx>
      33             : #include <boost/scoped_array.hpp>
      34             : 
      35             : namespace formula
      36             : {
      37             :     using namespace com::sun::star;
      38             : 
      39             : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
      40             : 
      41             : // Need a lot of FormulaDoubleToken
      42       83572 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaDoubleToken )
      43             : // Need a lot of FormulaByteToken
      44       91922 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaByteToken )
      45             : // Need several FormulaStringToken
      46       16358 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaStringToken )
      47             : 
      48             : 
      49             : // --- helpers --------------------------------------------------------------
      50             : 
      51           0 : inline bool lcl_IsReference( OpCode eOp, StackVar eType )
      52             : {
      53             :     return
      54           0 :         (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
      55           0 :         || (eOp == ocColRowNameAuto && eType == svDoubleRef)
      56           0 :         || (eOp == ocColRowName && eType == svSingleRef)
      57           0 :         || (eOp == ocMatRef && eType == svSingleRef)
      58             :         ;
      59             : }
      60             : 
      61             : // --- class FormulaToken --------------------------------------------------------
      62             : 
      63      191149 : FormulaToken::FormulaToken( StackVar eTypeP, OpCode e ) :
      64      191149 :     eOp(e), eType( eTypeP ), mnRefCnt(0)
      65             : {
      66      191149 : }
      67             : 
      68       51132 : FormulaToken::FormulaToken( const FormulaToken& r ) :
      69       51132 :     IFormulaToken(), eOp(r.eOp), eType( r.eType ), mnRefCnt(0)
      70             : {
      71       51132 : }
      72             : 
      73      289381 : FormulaToken::~FormulaToken()
      74             : {
      75      289381 : }
      76             : 
      77           0 : bool FormulaToken::IsFunction() const
      78             : {
      79           0 :     return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
      80           0 :             eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
      81           0 :            (GetByte() != 0                                                  // x parameters
      82           0 :         || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)   // no parameter
      83           0 :         || (ocIf == eOp || ocIfError == eOp || ocIfNA == eOp || ocChose == eOp ) // @ jump commands
      84           0 :         || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)     // one parameter
      85           0 :         || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)     // x parameters (cByte==0 in
      86             :                                                                             // FuncAutoPilot)
      87           0 :         || eOp == ocMacro || eOp == ocExternal                  // macros, AddIns
      88           0 :         || eOp == ocAnd || eOp == ocOr                          // former binary, now x parameters
      89           0 :         || eOp == ocNot || eOp == ocNeg                         // unary but function
      90           0 :         || (eOp >= ocInternalBegin && eOp <= ocInternalEnd)     // internal
      91           0 :         ));
      92             : }
      93             : 
      94             : 
      95      119607 : sal_uInt8 FormulaToken::GetParamCount() const
      96             : {
      97      176209 :     if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
      98      169738 :          eOp != ocIf && eOp != ocIfError && eOp != ocIfNA && eOp != ocChose &&
      99       56558 :          eOp != ocPercentSign )
     100       56558 :         return 0;       // parameters and specials
     101             :                         // ocIf, ocIfError, ocIfNA and ocChose not for FAP, have cByte then
     102             : //2do: bool parameter whether FAP or not?
     103       63049 :     else if ( GetByte() )
     104       29717 :         return GetByte();   // all functions, also ocExternal and ocMacro
     105       33332 :     else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
     106       32750 :         return 2;           // binary
     107         582 :     else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
     108         400 :             || eOp == ocPercentSign)
     109         182 :         return 1;           // unary
     110         400 :     else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
     111         168 :         return 0;           // no parameter
     112         232 :     else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
     113           0 :         return 1;           // one parameter
     114         232 :     else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose )
     115          44 :         return 1;           // only the condition counts as parameter
     116             :     else
     117         188 :         return 0;           // all the rest, no Parameter, or
     118             :                             // if so then it should be in cByte
     119             : }
     120             : 
     121      205546 : bool FormulaToken::IsExternalRef() const
     122             : {
     123      205546 :     bool bRet = false;
     124      205546 :     switch (eType)
     125             :     {
     126             :         case svExternalSingleRef:
     127             :         case svExternalDoubleRef:
     128             :         case svExternalName:
     129         362 :             bRet = true;
     130         362 :             break;
     131             :         default:
     132      205184 :             bRet = false;
     133      205184 :             break;
     134             :     }
     135      205546 :     return bRet;
     136             : }
     137             : 
     138         806 : bool FormulaToken::IsRef() const
     139             : {
     140         806 :     switch (eType)
     141             :     {
     142             :         case svSingleRef:
     143             :         case svDoubleRef:
     144             :         case svExternalSingleRef:
     145             :         case svExternalDoubleRef:
     146         794 :             return true;
     147             :         default:
     148             :             ;
     149             :     }
     150             : 
     151          12 :     return false;
     152             : }
     153             : 
     154          98 : bool FormulaToken::operator==( const FormulaToken& rToken ) const
     155             : {
     156             :     // don't compare reference count!
     157          98 :     return  eType == rToken.eType && GetOpCode() == rToken.GetOpCode();
     158             : }
     159             : 
     160             : 
     161             : // --- virtual dummy methods -------------------------------------------------
     162             : 
     163       52705 : sal_uInt8 FormulaToken::GetByte() const
     164             : {
     165             :     // ok to be called for any derived class
     166       52705 :     return 0;
     167             : }
     168             : 
     169           0 : void FormulaToken::SetByte( sal_uInt8 )
     170             : {
     171             :     SAL_WARN( "formula.core", "FormulaToken::SetByte: virtual dummy called" );
     172           0 : }
     173             : 
     174        1204 : bool FormulaToken::HasForceArray() const
     175             : {
     176             :     // ok to be called for any derived class
     177        1204 :     return false;
     178             : }
     179             : 
     180           0 : void FormulaToken::SetForceArray( bool )
     181             : {
     182             :     SAL_WARN( "formula.core", "FormulaToken::SetForceArray: virtual dummy called" );
     183           0 : }
     184             : 
     185           0 : double FormulaToken::GetDouble() const
     186             : {
     187             :     SAL_WARN( "formula.core", "FormulaToken::GetDouble: virtual dummy called" );
     188           0 :     return 0.0;
     189             : }
     190             : 
     191           0 : double & FormulaToken::GetDoubleAsReference()
     192             : {
     193             :     SAL_WARN( "formula.core", "FormulaToken::GetDouble: virtual dummy called" );
     194             :     static double fVal = 0.0;
     195           0 :     return fVal;
     196             : }
     197             : 
     198           0 : svl::SharedString FormulaToken::GetString() const
     199             : {
     200             :     SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
     201           0 :     return svl::SharedString(); // invalid string
     202             : }
     203             : 
     204           0 : sal_uInt16 FormulaToken::GetIndex() const
     205             : {
     206             :     SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" );
     207           0 :     return 0;
     208             : }
     209             : 
     210           0 : void FormulaToken::SetIndex( sal_uInt16 )
     211             : {
     212             :     SAL_WARN( "formula.core", "FormulaToken::SetIndex: virtual dummy called" );
     213           0 : }
     214             : 
     215           0 : bool FormulaToken::IsGlobal() const
     216             : {
     217             :     SAL_WARN( "formula.core", "FormulaToken::IsGlobal: virtual dummy called" );
     218           0 :     return true;
     219             : }
     220             : 
     221           0 : void FormulaToken::SetGlobal( bool )
     222             : {
     223             :     SAL_WARN( "formula.core", "FormulaToken::SetGlobal: virtual dummy called" );
     224           0 : }
     225             : 
     226           0 : short* FormulaToken::GetJump() const
     227             : {
     228             :     SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" );
     229           0 :     return NULL;
     230             : }
     231             : 
     232             : 
     233           0 : const OUString& FormulaToken::GetExternal() const
     234             : {
     235             :     SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" );
     236           0 :     static  OUString              aDummyString;
     237           0 :     return aDummyString;
     238             : }
     239             : 
     240           0 : FormulaToken* FormulaToken::GetFAPOrigToken() const
     241             : {
     242             :     SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" );
     243           0 :     return NULL;
     244             : }
     245             : 
     246           0 : sal_uInt16 FormulaToken::GetError() const
     247             : {
     248             :     SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" );
     249           0 :     return 0;
     250             : }
     251             : 
     252           0 : void FormulaToken::SetError( sal_uInt16 )
     253             : {
     254             :     SAL_WARN( "formula.core", "FormulaToken::SetError: virtual dummy called" );
     255           0 : }
     256             : 
     257           0 : const ScSingleRefData* FormulaToken::GetSingleRef() const
     258             : {
     259             :     OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
     260           0 :     return nullptr;
     261             : }
     262             : 
     263           0 : ScSingleRefData* FormulaToken::GetSingleRef()
     264             : {
     265             :     OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
     266           0 :     return nullptr;
     267             : }
     268             : 
     269           0 : const ScComplexRefData* FormulaToken::GetDoubleRef() const
     270             : {
     271             :     OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
     272           0 :     return nullptr;
     273             : }
     274             : 
     275           0 : ScComplexRefData* FormulaToken::GetDoubleRef()
     276             : {
     277             :     OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
     278           0 :     return nullptr;
     279             : }
     280             : 
     281           0 : const ScSingleRefData* FormulaToken::GetSingleRef2() const
     282             : {
     283             :     OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
     284           0 :     return nullptr;
     285             : }
     286             : 
     287           0 : ScSingleRefData* FormulaToken::GetSingleRef2()
     288             : {
     289             :     OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
     290           0 :     return nullptr;
     291             : }
     292             : 
     293           0 : const ScMatrix* FormulaToken::GetMatrix() const
     294             : {
     295             :     OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
     296           0 :     return NULL;
     297             : }
     298             : 
     299           0 : ScMatrix* FormulaToken::GetMatrix()
     300             : {
     301             :     OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
     302           0 :     return NULL;
     303             : }
     304             : 
     305           0 : ScJumpMatrix* FormulaToken::GetJumpMatrix() const
     306             : {
     307             :     OSL_FAIL( "FormulaToken::GetJumpMatrix: virtual dummy called" );
     308           0 :     return NULL;
     309             : }
     310           0 : const std::vector<ScComplexRefData>* FormulaToken::GetRefList() const
     311             : {
     312             :     OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
     313           0 :     return NULL;
     314             : }
     315             : 
     316           0 : std::vector<ScComplexRefData>* FormulaToken::GetRefList()
     317             : {
     318             :     OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
     319           0 :     return NULL;
     320             : }
     321             : 
     322           4 : bool FormulaToken::TextEqual( const FormulaToken& rToken ) const
     323             : {
     324           4 :     return *this == rToken;
     325             : }
     326             : 
     327             : // real implementations of virtual functions
     328             : 
     329             : 
     330             : 
     331      156251 : sal_uInt8 FormulaByteToken::GetByte() const                       { return nByte; }
     332       11560 : void FormulaByteToken::SetByte( sal_uInt8 n )                     { nByte = n; }
     333       65097 : bool FormulaByteToken::HasForceArray() const                 { return bHasForceArray; }
     334           0 : void FormulaByteToken::SetForceArray( bool b )               { bHasForceArray = b; }
     335          46 : bool FormulaByteToken::operator==( const FormulaToken& r ) const
     336             : {
     337          92 :     return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
     338          92 :         bHasForceArray == r.HasForceArray();
     339             : }
     340             : 
     341             : 
     342           0 : FormulaToken* FormulaFAPToken::GetFAPOrigToken() const { return pOrigToken.get(); }
     343           0 : bool FormulaFAPToken::operator==( const FormulaToken& r ) const
     344             : {
     345           0 :     return FormulaByteToken::operator==( r ) && pOrigToken == r.GetFAPOrigToken();
     346             : }
     347             : 
     348             : 
     349         418 : short* FormulaJumpToken::GetJump() const                     { return pJump; }
     350         492 : bool FormulaJumpToken::HasForceArray() const                 { return bHasForceArray; }
     351           0 : void FormulaJumpToken::SetForceArray( bool b )               { bHasForceArray = b; }
     352           0 : bool FormulaJumpToken::operator==( const FormulaToken& r ) const
     353             : {
     354           0 :     return FormulaToken::operator==( r ) && pJump[0] == r.GetJump()[0] &&
     355           0 :         memcmp( pJump+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0 &&
     356           0 :         bHasForceArray == r.HasForceArray();
     357             : }
     358         420 : FormulaJumpToken::~FormulaJumpToken()
     359             : {
     360         140 :     delete [] pJump;
     361         280 : }
     362             : 
     363             : 
     364         216 : bool FormulaTokenArray::AddFormulaToken(
     365             :     const sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, ExternalReferenceHelper* /*pExtRef*/)
     366             : {
     367         216 :     bool bError = false;
     368         216 :     const OpCode eOpCode = static_cast<OpCode>(rToken.OpCode);      //! assuming equal values for the moment
     369             : 
     370         216 :     const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
     371         216 :     switch ( eClass )
     372             :     {
     373             :         case uno::TypeClass_VOID:
     374             :             // empty data -> use AddOpCode (does some special cases)
     375          12 :             AddOpCode( eOpCode );
     376          12 :             break;
     377             :         case uno::TypeClass_DOUBLE:
     378             :             // double is only used for "push"
     379          22 :             if ( eOpCode == ocPush )
     380          22 :                 AddDouble( rToken.Data.get<double>() );
     381             :             else
     382           0 :                 bError = true;
     383          22 :             break;
     384             :         case uno::TypeClass_LONG:
     385             :             {
     386             :                 // long is svIndex, used for name / database area, or "byte" for spaces
     387           0 :                 sal_Int32 nValue = rToken.Data.get<sal_Int32>();
     388           0 :                 if ( eOpCode == ocDBArea )
     389           0 :                     AddToken( formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) );
     390           0 :                 else if ( eOpCode == ocSpaces )
     391           0 :                     AddToken( formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) );
     392             :                 else
     393           0 :                     bError = true;
     394             :             }
     395           0 :             break;
     396             :         case uno::TypeClass_STRING:
     397             :             {
     398           0 :                 OUString aStrVal( rToken.Data.get<OUString>() );
     399           0 :                 if ( eOpCode == ocPush )
     400           0 :                     AddString(rSPool.intern(aStrVal));
     401           0 :                 else if ( eOpCode == ocBad )
     402           0 :                     AddBad( aStrVal );
     403           0 :                 else if ( eOpCode == ocStringXML )
     404           0 :                     AddStringXML( aStrVal );
     405           0 :                 else if ( eOpCode == ocExternal || eOpCode == ocMacro )
     406           0 :                     AddToken( formula::FormulaExternalToken( eOpCode, aStrVal ) );
     407             :                 else
     408           0 :                     bError = true;      // unexpected string: don't know what to do with it
     409             :             }
     410           0 :             break;
     411             :         default:
     412         182 :             bError = true;
     413             :     } // switch ( eClass )
     414         216 :     return bError;
     415             : }
     416             : 
     417         214 : bool FormulaTokenArray::Fill(
     418             :     const uno::Sequence<sheet::FormulaToken>& rSequence,
     419             :     svl::SharedStringPool& rSPool, ExternalReferenceHelper* pExtRef )
     420             : {
     421         214 :     bool bError = false;
     422         214 :     const sal_Int32 nCount = rSequence.getLength();
     423         430 :     for (sal_Int32 nPos=0; nPos<nCount; nPos++)
     424             :     {
     425         216 :         bool bOneError = AddFormulaToken(rSequence[nPos], rSPool, pExtRef);
     426         216 :         if (bOneError)
     427             :         {
     428           0 :             AddOpCode( ocErrName);  // add something that indicates an error
     429           0 :             bError = true;
     430             :         }
     431             :     }
     432         214 :     return bError;
     433             : }
     434        6258 : FormulaToken* FormulaTokenArray::GetNextReference()
     435             : {
     436       14910 :     while( nIndex < nLen )
     437             :     {
     438        5776 :         FormulaToken* t = pCode[ nIndex++ ];
     439        5776 :         switch( t->GetType() )
     440             :         {
     441             :             case svSingleRef:
     442             :             case svDoubleRef:
     443             :             case svExternalSingleRef:
     444             :             case svExternalDoubleRef:
     445        3382 :                 return t;
     446             :             default:
     447             :             {
     448             :                 // added to avoid warnings
     449             :             }
     450             :         }
     451             :     }
     452        2876 :     return NULL;
     453             : }
     454             : 
     455         170 : FormulaToken* FormulaTokenArray::GetNextColRowName()
     456             : {
     457         652 :     while( nIndex < nLen )
     458             :     {
     459         312 :         FormulaToken* t = pCode[ nIndex++ ];
     460         312 :         if ( t->GetOpCode() == ocColRowName )
     461           0 :             return t;
     462             :     }
     463         170 :     return NULL;
     464             : }
     465             : 
     466       89096 : FormulaToken* FormulaTokenArray::GetNextReferenceRPN()
     467             : {
     468      261582 :     while( nIndex < nRPN )
     469             :     {
     470      141816 :         FormulaToken* t = pRPN[ nIndex++ ];
     471      141816 :         switch( t->GetType() )
     472             :         {
     473             :             case svSingleRef:
     474             :             case svDoubleRef:
     475             :             case svExternalSingleRef:
     476             :             case svExternalDoubleRef:
     477       58426 :                 return t;
     478             :             default:
     479             :             {
     480             :                 // added to avoid warnings
     481             :             }
     482             :         }
     483             :     }
     484       30670 :     return NULL;
     485             : }
     486             : 
     487        5172 : FormulaToken* FormulaTokenArray::GetNextReferenceOrName()
     488             : {
     489        5172 :     if( pCode )
     490             :     {
     491       16222 :         while ( nIndex < nLen )
     492             :         {
     493        9210 :             FormulaToken* t = pCode[ nIndex++ ];
     494        9210 :             switch( t->GetType() )
     495             :             {
     496             :                 case svSingleRef:
     497             :                 case svDoubleRef:
     498             :                 case svIndex:
     499             :                 case svExternalSingleRef:
     500             :                 case svExternalDoubleRef:
     501             :                 case svExternalName:
     502        3192 :                     return t;
     503             :                 default:
     504             :                 {
     505             :                     // added to avoid warnings
     506             :                 }
     507             :              }
     508             :          }
     509             :      }
     510        1980 :     return NULL;
     511             : }
     512             : 
     513        2002 : FormulaToken* FormulaTokenArray::GetNextName()
     514             : {
     515        2002 :     if( pCode )
     516             :     {
     517       12818 :         while ( nIndex < nLen )
     518             :         {
     519        9046 :             FormulaToken* t = pCode[ nIndex++ ];
     520        9046 :             if( t->GetType() == svIndex )
     521          92 :                 return t;
     522             :         }
     523             :     } // if( pCode )
     524        1910 :     return NULL;
     525             : }
     526             : 
     527      171948 : FormulaToken* FormulaTokenArray::Next()
     528             : {
     529      171948 :     if( pCode && nIndex < nLen )
     530      149992 :         return pCode[ nIndex++ ];
     531             :     else
     532       21956 :         return NULL;
     533             : }
     534             : 
     535          10 : FormulaToken* FormulaTokenArray::NextNoSpaces()
     536             : {
     537          10 :     if( pCode )
     538             :     {
     539          20 :         while( (nIndex < nLen) && (pCode[ nIndex ]->GetOpCode() == ocSpaces) )
     540           0 :             ++nIndex;
     541          10 :         if( nIndex < nLen )
     542          10 :             return pCode[ nIndex++ ];
     543             :     }
     544           0 :     return NULL;
     545             : }
     546             : 
     547        1660 : FormulaToken* FormulaTokenArray::NextRPN()
     548             : {
     549        1660 :     if( pRPN && nIndex < nRPN )
     550        1208 :         return pRPN[ nIndex++ ];
     551             :     else
     552         452 :         return NULL;
     553             : }
     554             : 
     555           0 : FormulaToken* FormulaTokenArray::PrevRPN()
     556             : {
     557           0 :     if( pRPN && nIndex )
     558           0 :         return pRPN[ --nIndex ];
     559             :     else
     560           0 :         return NULL;
     561             : }
     562             : 
     563       38066 : void FormulaTokenArray::DelRPN()
     564             : {
     565       38066 :     if( nRPN )
     566             :     {
     567       20192 :         FormulaToken** p = pRPN;
     568      108222 :         for( sal_uInt16 i = 0; i < nRPN; i++ )
     569             :         {
     570       88030 :             (*p++)->DecRef();
     571             :         }
     572       20192 :         delete [] pRPN;
     573             :     }
     574       38066 :     pRPN = NULL;
     575       38066 :     nRPN = nIndex = 0;
     576       38066 : }
     577             : 
     578           0 : FormulaToken* FormulaTokenArray::PeekPrev( sal_uInt16 & nIdx )
     579             : {
     580           0 :     if (0 < nIdx && nIdx <= nLen)
     581           0 :         return pCode[--nIdx];
     582           0 :     return NULL;
     583             : }
     584             : 
     585           0 : FormulaToken* FormulaTokenArray::PeekNext()
     586             : {
     587           0 :     if( pCode && nIndex < nLen )
     588           0 :         return pCode[ nIndex ];
     589             :     else
     590           0 :         return NULL;
     591             : }
     592             : 
     593         722 : FormulaToken* FormulaTokenArray::PeekNextNoSpaces()
     594             : {
     595         722 :     if( pCode && nIndex < nLen )
     596             :     {
     597         120 :         sal_uInt16 j = nIndex;
     598         240 :         while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
     599           0 :             j++;
     600         120 :         if ( j < nLen )
     601         120 :             return pCode[ j ];
     602             :         else
     603           0 :             return NULL;
     604             :     }
     605             :     else
     606         602 :         return NULL;
     607             : }
     608             : 
     609         918 : FormulaToken* FormulaTokenArray::PeekPrevNoSpaces()
     610             : {
     611         918 :     if( pCode && nIndex > 1 )
     612             :     {
     613         302 :         sal_uInt16 j = nIndex - 2;
     614         604 :         while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
     615           0 :             j--;
     616         302 :         if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
     617         302 :             return pCode[ j ];
     618             :         else
     619           0 :             return NULL;
     620             :     }
     621             :     else
     622         616 :         return NULL;
     623             : }
     624             : 
     625         806 : bool FormulaTokenArray::HasReferences() const
     626             : {
     627         818 :     for (sal_uInt16 i = 0; i < nLen; ++i)
     628             :     {
     629         806 :         if (pCode[i]->IsRef())
     630         794 :             return true;
     631             :     }
     632             : 
     633          12 :     return false;
     634             : }
     635             : 
     636           0 : bool FormulaTokenArray::HasExternalRef() const
     637             : {
     638           0 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     639             :     {
     640           0 :         if (pCode[j]->IsExternalRef())
     641           0 :             return true;
     642             :     }
     643           0 :     return false;
     644             : }
     645             : 
     646       19422 : bool FormulaTokenArray::HasOpCode( OpCode eOp ) const
     647             : {
     648      169530 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     649             :     {
     650      150112 :         if ( pCode[j]->GetOpCode() == eOp )
     651           4 :             return true;
     652             :     }
     653       19418 :     return false;
     654             : }
     655             : 
     656        8898 : bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp ) const
     657             : {
     658       50792 :     for ( sal_uInt16 j=0; j < nRPN; j++ )
     659             :     {
     660       43054 :         if ( pRPN[j]->GetOpCode() == eOp )
     661        1160 :             return true;
     662             :     }
     663        7738 :     return false;
     664             : }
     665             : 
     666           4 : bool FormulaTokenArray::HasNameOrColRowName() const
     667             : {
     668           8 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     669             :     {
     670           4 :         if( pCode[j]->GetType() == svIndex || pCode[j]->GetOpCode() == ocColRowName )
     671           0 :             return true;
     672             :     }
     673           4 :     return false;
     674             : }
     675             : 
     676          28 : bool FormulaTokenArray::HasOpCodes( const boost::unordered_set<OpCode>& rOpCodes ) const
     677             : {
     678          28 :     FormulaToken** p = pCode;
     679          28 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
     680         116 :     for (; p != pEnd; ++p)
     681             :     {
     682          98 :         OpCode eOp = (*p)->GetOpCode();
     683          98 :         if (rOpCodes.count(eOp) > 0)
     684          10 :             return true;
     685             :     }
     686             : 
     687          18 :     return false;
     688             : }
     689             : 
     690       21082 : FormulaTokenArray::FormulaTokenArray() :
     691             :     pCode(NULL),
     692             :     pRPN(NULL),
     693             :     nLen(0),
     694             :     nRPN(0),
     695             :     nIndex(0),
     696             :     nError(0),
     697             :     nRefs(0),
     698             :     nMode(RECALCMODE_NORMAL),
     699       21082 :     bHyperLink(false)
     700             : {
     701       21082 : }
     702             : 
     703       21688 : FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray& rArr )
     704             : {
     705       21688 :     Assign( rArr );
     706       21688 : }
     707             : 
     708       42714 : FormulaTokenArray::~FormulaTokenArray()
     709             : {
     710       42702 :     Clear();
     711       42714 : }
     712             : 
     713       21688 : void FormulaTokenArray::Assign( const FormulaTokenArray& r )
     714             : {
     715       21688 :     nLen   = r.nLen;
     716       21688 :     nRPN   = r.nRPN;
     717       21688 :     nIndex = r.nIndex;
     718       21688 :     nError = r.nError;
     719       21688 :     nRefs  = r.nRefs;
     720       21688 :     nMode  = r.nMode;
     721       21688 :     bHyperLink = r.bHyperLink;
     722       21688 :     pCode  = NULL;
     723       21688 :     pRPN   = NULL;
     724             :     FormulaToken** pp;
     725       21688 :     if( nLen )
     726             :     {
     727       21666 :         pp = pCode = new FormulaToken*[ nLen ];
     728       21666 :         memcpy( pp, r.pCode, nLen * sizeof( FormulaToken* ) );
     729      151708 :         for( sal_uInt16 i = 0; i < nLen; i++ )
     730      130042 :             (*pp++)->IncRef();
     731             :     }
     732       21688 :     if( nRPN )
     733             :     {
     734        2300 :         pp = pRPN = new FormulaToken*[ nRPN ];
     735        2300 :         memcpy( pp, r.pRPN, nRPN * sizeof( FormulaToken* ) );
     736       15836 :         for( sal_uInt16 i = 0; i < nRPN; i++ )
     737       13536 :             (*pp++)->IncRef();
     738             :     }
     739       21688 : }
     740             : 
     741             : /// Optimisation for efficiently creating StringXML placeholders
     742        1648 : void FormulaTokenArray::Assign( sal_uInt16 nCode, FormulaToken **pTokens )
     743             : {
     744             :     assert( nLen == 0 );
     745             :     assert( pCode == NULL );
     746             : 
     747        1648 :     nLen = nCode;
     748        1648 :     pCode = new FormulaToken*[ nLen ];
     749             : 
     750        3296 :     for( sal_uInt16 i = 0; i < nLen; i++ )
     751             :     {
     752        1648 :         FormulaToken *t = pTokens[ i ];
     753             :         assert( t->GetOpCode() == ocStringXML );
     754        1648 :         pCode[ i ] = t;
     755        1648 :         t->IncRef();
     756             :     }
     757        1648 : }
     758             : 
     759           0 : FormulaTokenArray& FormulaTokenArray::operator=( const FormulaTokenArray& rArr )
     760             : {
     761           0 :     Clear();
     762           0 :     Assign( rArr );
     763           0 :     return *this;
     764             : }
     765             : 
     766           0 : FormulaTokenArray* FormulaTokenArray::Clone() const
     767             : {
     768           0 :     FormulaTokenArray* p = new FormulaTokenArray;
     769           0 :     p->nLen = nLen;
     770           0 :     p->nRPN = nRPN;
     771           0 :     p->nRefs = nRefs;
     772           0 :     p->nMode = nMode;
     773           0 :     p->nError = nError;
     774           0 :     p->bHyperLink = bHyperLink;
     775             :     FormulaToken** pp;
     776           0 :     if( nLen )
     777             :     {
     778           0 :         pp = p->pCode = new FormulaToken*[ nLen ];
     779           0 :         memcpy( pp, pCode, nLen * sizeof( FormulaToken* ) );
     780           0 :         for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
     781             :         {
     782           0 :             *pp = (*pp)->Clone();
     783           0 :             (*pp)->IncRef();
     784             :         }
     785             :     }
     786           0 :     if( nRPN )
     787             :     {
     788           0 :         pp = p->pRPN = new FormulaToken*[ nRPN ];
     789           0 :         memcpy( pp, pRPN, nRPN * sizeof( FormulaToken* ) );
     790           0 :         for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
     791             :         {
     792           0 :             FormulaToken* t = *pp;
     793           0 :             if( t->GetRef() > 1 )
     794             :             {
     795           0 :                 FormulaToken** p2 = pCode;
     796           0 :                 sal_uInt16 nIdx = 0xFFFF;
     797           0 :                 for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
     798             :                 {
     799           0 :                     if( *p2 == t )
     800             :                     {
     801           0 :                         nIdx = j; break;
     802             :                     }
     803             :                 }
     804           0 :                 if( nIdx == 0xFFFF )
     805           0 :                     *pp = t->Clone();
     806             :                 else
     807           0 :                     *pp = p->pCode[ nIdx ];
     808             :             }
     809             :             else
     810           0 :                 *pp = t->Clone();
     811           0 :             (*pp)->IncRef();
     812             :         }
     813             :     }
     814           0 :     return p;
     815             : }
     816             : 
     817       50732 : void FormulaTokenArray::Clear()
     818             : {
     819       50732 :     if( nRPN ) DelRPN();
     820       50732 :     if( pCode )
     821             :     {
     822       48180 :         FormulaToken** p = pCode;
     823      310594 :         for( sal_uInt16 i = 0; i < nLen; i++ )
     824             :         {
     825      262414 :             (*p++)->DecRef();
     826             :         }
     827       48180 :         delete [] pCode;
     828             :     }
     829       50732 :     pCode = NULL; pRPN = NULL;
     830       50732 :     nError = nLen = nIndex = nRPN = nRefs = 0;
     831       50732 :     bHyperLink = false;
     832       50732 :     ClearRecalcMode();
     833       50732 : }
     834             : 
     835          96 : void FormulaTokenArray::CheckToken( const FormulaToken& /*r*/ )
     836             : {
     837             :     // Do nothing.
     838          96 : }
     839             : 
     840         166 : FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r )
     841             : {
     842         166 :     return Add( r.Clone() );
     843             : }
     844             : 
     845           0 : FormulaToken* FormulaTokenArray::MergeArray( )
     846             : {
     847           0 :     return NULL;
     848             : }
     849             : 
     850      103024 : FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
     851             : {
     852      103024 :     if( !pCode )
     853       18190 :         pCode = new FormulaToken*[ FORMULA_MAXTOKENS ];
     854      103024 :     if( nLen < FORMULA_MAXTOKENS - 1 )
     855             :     {
     856      103024 :         CheckToken(*t);
     857      103024 :         pCode[ nLen++ ] = t;
     858      206048 :         if( t->GetOpCode() == ocPush
     859      103024 :             && ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
     860       26672 :             nRefs++;
     861      103024 :         t->IncRef();
     862      103024 :         if( t->GetOpCode() == ocArrayClose )
     863          36 :             return MergeArray();
     864      102988 :         return t;
     865             :     }
     866             :     else
     867             :     {
     868           0 :         t->Delete();
     869           0 :         if ( nLen == FORMULA_MAXTOKENS - 1 )
     870             :         {
     871           0 :             t = new FormulaByteToken( ocStop );
     872           0 :             pCode[ nLen++ ] = t;
     873           0 :             t->IncRef();
     874             :         }
     875           0 :         return NULL;
     876             :     }
     877             : }
     878             : 
     879        5474 : FormulaToken* FormulaTokenArray::AddString( const svl::SharedString& rStr )
     880             : {
     881        5474 :     return Add( new FormulaStringToken( rStr ) );
     882             : }
     883             : 
     884        2864 : FormulaToken* FormulaTokenArray::AddDouble( double fVal )
     885             : {
     886        2864 :     return Add( new FormulaDoubleToken( fVal ) );
     887             : }
     888             : 
     889           0 : FormulaToken* FormulaTokenArray::AddExternal( const sal_Unicode* pStr )
     890             : {
     891           0 :     return AddExternal( OUString( pStr ) );
     892             : }
     893             : 
     894           2 : FormulaToken* FormulaTokenArray::AddExternal( const OUString& rStr,
     895             :         OpCode eOp /* = ocExternal */ )
     896             : {
     897           2 :     return Add( new FormulaExternalToken( eOp, rStr ) );
     898             : }
     899             : 
     900           0 : FormulaToken* FormulaTokenArray::AddBad( const OUString& rStr )
     901             : {
     902           0 :     return Add( new FormulaStringOpToken( ocBad, rStr ) );
     903             : }
     904             : 
     905         302 : FormulaToken* FormulaTokenArray::AddStringXML( const OUString& rStr )
     906             : {
     907         302 :     return Add( new FormulaStringOpToken( ocStringXML, rStr ) );
     908             : }
     909             : 
     910             : 
     911             : 
     912         700 : void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
     913             : {
     914             :     //! Reihenfolge ist wichtig
     915         700 :     if ( nBits & RECALCMODE_ALWAYS )
     916           0 :         SetExclusiveRecalcModeAlways();
     917         700 :     else if ( !IsRecalcModeAlways() )
     918             :     {
     919         700 :         if ( nBits & RECALCMODE_ONLOAD )
     920         246 :             SetExclusiveRecalcModeOnLoad();
     921         454 :         else if ( nBits & RECALCMODE_ONLOAD_ONCE && !IsRecalcModeOnLoad() )
     922           0 :             SetExclusiveRecalcModeOnLoadOnce();
     923             :     }
     924         700 :     SetCombinedBitsRecalcMode( nBits );
     925         700 : }
     926             : 
     927             : 
     928           0 : bool FormulaTokenArray::HasMatrixDoubleRefOps()
     929             : {
     930           0 :     if ( pRPN && nRPN )
     931             :     {
     932             :         // RPN-Interpreter Simulation
     933             :         // als Ergebnis jeder Funktion wird einfach ein Double angenommen
     934           0 :         boost::scoped_array<FormulaToken*> pStack(new FormulaToken* [nRPN]);
     935           0 :         FormulaToken* pResult = new FormulaDoubleToken( 0.0 );
     936           0 :         short sp = 0;
     937           0 :         for ( sal_uInt16 j = 0; j < nRPN; j++ )
     938             :         {
     939           0 :             FormulaToken* t = pRPN[j];
     940           0 :             OpCode eOp = t->GetOpCode();
     941           0 :             sal_uInt8 nParams = t->GetParamCount();
     942           0 :             switch ( eOp )
     943             :             {
     944             :                 case ocAdd :
     945             :                 case ocSub :
     946             :                 case ocMul :
     947             :                 case ocDiv :
     948             :                 case ocPow :
     949             :                 case ocPower :
     950             :                 case ocAmpersand :
     951             :                 case ocEqual :
     952             :                 case ocNotEqual :
     953             :                 case ocLess :
     954             :                 case ocGreater :
     955             :                 case ocLessEqual :
     956             :                 case ocGreaterEqual :
     957             :                 {
     958           0 :                     for ( sal_uInt8 k = nParams; k; k-- )
     959             :                     {
     960           0 :                         if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
     961             :                         {
     962           0 :                             pResult->Delete();
     963           0 :                             return true;
     964             :                         }
     965             :                     }
     966             :                 }
     967           0 :                 break;
     968             :                 default:
     969             :                 {
     970             :                     // added to avoid warnings
     971             :                 }
     972             :             }
     973           0 :             if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() )  )
     974           0 :                 pStack[sp++] = t;
     975           0 :             else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose )
     976             :             {   // ignore Jumps, pop previous Result (Condition)
     977           0 :                 if ( sp )
     978           0 :                     --sp;
     979             :             }
     980             :             else
     981             :             {   // pop parameters, push result
     982           0 :                 sp = sal::static_int_cast<short>( sp - nParams );
     983           0 :                 if ( sp < 0 )
     984             :                 {
     985             :                     SAL_WARN("formula.core", "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
     986           0 :                     sp = 0;
     987             :                 }
     988           0 :                 pStack[sp++] = pResult;
     989             :             }
     990             :         }
     991           0 :         pResult->Delete();
     992             :     }
     993             : 
     994           0 :     return false;
     995             : }
     996             : 
     997             : 
     998             : 
     999             : // --- POF (plain old formula) rewrite of a token array ---------------------
    1000             : 
    1001        9084 : inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
    1002             : {
    1003        9084 :     switch (eOp)
    1004             :     {
    1005             :         case ocGammaDist:
    1006             :         case ocPoissonDist:
    1007             :         case ocAddress:
    1008             :         case ocLogNormDist:
    1009             :         case ocNormDist:
    1010          12 :             return true;
    1011             :         case ocMissing:
    1012             :         case ocLog:
    1013           0 :             return !isODFF();   // rewrite only for PODF
    1014             :         default:
    1015        9072 :             return false;
    1016             :     }
    1017             : }
    1018             : 
    1019             : class FormulaMissingContext
    1020             : {
    1021             :     public:
    1022             :             const FormulaToken* mpFunc;
    1023             :             int                 mnCurArg;
    1024             : 
    1025          12 :                     void    Clear() { mpFunc = NULL; mnCurArg = 0; }
    1026             :             inline  bool    AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const;
    1027             :                     bool    AddMissingExternal( FormulaTokenArray* pNewArr ) const;
    1028             :                     bool    AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const;
    1029             :                     void    AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const;
    1030             : };
    1031             : 
    1032          12 : void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const
    1033             : {
    1034          12 :     if ( !mpFunc )
    1035          12 :         return;
    1036             : 
    1037          12 :     switch (mpFunc->GetOpCode())
    1038             :     {
    1039             :         case ocGammaDist:
    1040           0 :             if (mnCurArg == 2)
    1041             :             {
    1042           0 :                 pNewArr->AddOpCode( ocSep );
    1043           0 :                 pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
    1044             :             }
    1045           0 :             break;
    1046             :         case ocPoissonDist:
    1047           0 :             if (mnCurArg == 1)
    1048             :             {
    1049           0 :                 pNewArr->AddOpCode( ocSep );
    1050           0 :                 pNewArr->AddDouble( 1.0 );      // 3rd, Cumulative=true()
    1051             :             }
    1052           0 :             break;
    1053             :         case ocNormDist:
    1054           0 :             if ( mnCurArg == 2 )
    1055             :             {
    1056           0 :                 pNewArr->AddOpCode( ocSep );
    1057           0 :                 pNewArr->AddDouble( 1.0 );      // 4th, Cumulative=true()
    1058             :             }
    1059           0 :             break;
    1060             :         case ocLogNormDist:
    1061           0 :             if ( mnCurArg == 0 )
    1062             :             {
    1063           0 :                 pNewArr->AddOpCode( ocSep );
    1064           0 :                 pNewArr->AddDouble( 0.0 );      // 2nd, mean = 0.0
    1065             :             }
    1066           0 :             if ( mnCurArg <= 1 )
    1067             :             {
    1068           0 :                 pNewArr->AddOpCode( ocSep );
    1069           0 :                 pNewArr->AddDouble( 1.0 );      // 3rd, standard deviation = 1.0
    1070             :             }
    1071           0 :             break;
    1072             :         case ocLog:
    1073           0 :             if ( !rConv.isODFF() && mnCurArg == 0 )
    1074             :             {
    1075           0 :                 pNewArr->AddOpCode( ocSep );
    1076           0 :                 pNewArr->AddDouble( 10.0 );     // 2nd, basis 10
    1077             :             }
    1078           0 :             break;
    1079             :         default:
    1080          12 :             break;
    1081             :     }
    1082             : }
    1083             : 
    1084           4 : inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
    1085             : {
    1086           4 :     if (mnCurArg == nArg)
    1087             :     {
    1088           0 :         pNewArr->AddDouble( f );
    1089           0 :         return true;
    1090             :     }
    1091           4 :     return false;
    1092             : }
    1093             : 
    1094           0 : bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray *pNewArr ) const
    1095             : {
    1096             :     // Only called for PODF, not ODFF. No need to distinguish.
    1097             : 
    1098           0 :     const OUString &rName = mpFunc->GetExternal();
    1099             : 
    1100             :     // initial (fast) check:
    1101           0 :     sal_Unicode nLastChar = rName[ rName.getLength() - 1];
    1102           0 :     if ( nLastChar != 't' && nLastChar != 'm' )
    1103           0 :         return false;
    1104             : 
    1105           0 :     if (rName.equalsIgnoreAsciiCase(
    1106             :                 "com.sun.star.sheet.addin.Analysis.getAccrint" ))
    1107             :     {
    1108           0 :         return AddDefaultArg( pNewArr, 4, 1000.0 );
    1109             :     }
    1110           0 :     if (rName.equalsIgnoreAsciiCase(
    1111             :                 "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
    1112             :     {
    1113           0 :         return AddDefaultArg( pNewArr, 3, 1000.0 );
    1114             :     }
    1115           0 :     return false;
    1116             : }
    1117             : 
    1118           4 : bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv  ) const
    1119             : {
    1120           4 :     if ( !mpFunc )
    1121           0 :         return false;
    1122             : 
    1123           4 :     bool bRet = false;
    1124           4 :     const OpCode eOp = mpFunc->GetOpCode();
    1125             : 
    1126             :     // Add for both, PODF and ODFF
    1127           4 :     switch (eOp)
    1128             :     {
    1129             :         case ocAddress:
    1130           4 :             return AddDefaultArg( pNewArr, 2, 1.0 );    // abs
    1131             :         default:
    1132           0 :             break;
    1133             :     }
    1134             : 
    1135           0 :     if (rConv.isODFF())
    1136             :     {
    1137             :         // Add for ODFF
    1138             :     }
    1139             :     else
    1140             :     {
    1141             :         // Add for PODF
    1142           0 :         switch (eOp)
    1143             :         {
    1144             :             case ocFixed:
    1145           0 :                 return AddDefaultArg( pNewArr, 1, 2.0 );
    1146             :             case ocBetaDist:
    1147             :             case ocBetaInv:
    1148             :             case ocRMZ:     // PMT
    1149           0 :                 return AddDefaultArg( pNewArr, 3, 0.0 );
    1150             :             case ocZinsZ:   // IPMT
    1151             :             case ocKapz:    // PPMT
    1152           0 :                 return AddDefaultArg( pNewArr, 4, 0.0 );
    1153             :             case ocBW:      // PV
    1154             :             case ocZW:      // FV
    1155           0 :                 bRet |= AddDefaultArg( pNewArr, 2, 0.0 );   // pmt
    1156           0 :                 bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // [fp]v
    1157           0 :                 break;
    1158             :             case ocZins:    // RATE
    1159           0 :                 bRet |= AddDefaultArg( pNewArr, 1, 0.0 );   // pmt
    1160           0 :                 bRet |= AddDefaultArg( pNewArr, 3, 0.0 );   // fv
    1161           0 :                 bRet |= AddDefaultArg( pNewArr, 4, 0.0 );   // type
    1162           0 :                 break;
    1163             :             case ocExternal:
    1164           0 :                 return AddMissingExternal( pNewArr );
    1165             : 
    1166             :                 // --- more complex cases ---
    1167             : 
    1168             :             case ocOffset:
    1169             :                 // FIXME: rather tough.
    1170             :                 // if arg 3 (height) omitted, export arg1 (rows)
    1171           0 :                 break;
    1172             :             default:
    1173           0 :                 break;
    1174             :         }
    1175             :     }
    1176             : 
    1177           0 :     return bRet;
    1178             : }
    1179             : 
    1180        1564 : bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
    1181             : {
    1182       10636 :     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
    1183             :     {
    1184        9084 :         if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
    1185          12 :             return true;
    1186             :     }
    1187        1552 :     return false;
    1188             : }
    1189             : 
    1190             : 
    1191          12 : FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvention & rConv )
    1192             : {
    1193          12 :     const size_t nAlloc = 256;
    1194             :     FormulaMissingContext aCtx[ nAlloc ];
    1195             :     int aOpCodeAddressStack[ nAlloc ];  // use of ADDRESS() function
    1196          12 :     const int nOmitAddressArg = 3;      // ADDRESS() 4th parameter A1/R1C1
    1197          12 :     sal_uInt16 nTokens = GetLen() + 1;
    1198          12 :     FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
    1199          12 :     int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
    1200             :     // Never go below 0, never use 0, mpFunc always NULL.
    1201          12 :     pCtx[0].Clear();
    1202          12 :     int nFn = 0;
    1203          12 :     int nOcas = 0;
    1204             : 
    1205          12 :     FormulaTokenArray *pNewArr = new FormulaTokenArray;
    1206             :     // At least RECALCMODE_ALWAYS needs to be set.
    1207          12 :     pNewArr->AddRecalcMode( GetRecalcMode());
    1208             : 
    1209         108 :     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
    1210             :     {
    1211          96 :         bool bAdd = true;
    1212             :         // Don't write the expression of the new inserted ADDRESS() parameter.
    1213             :         // Do NOT omit the new second parameter of INDIRECT() though. If that
    1214             :         // was done for both, INDIRECT() actually could calculate different and
    1215             :         // valid (but wrong) results with the then changed return value of
    1216             :         // ADDRESS(). Better let it generate an error instead.
    1217         192 :         for (int i = nOcas; i-- > 0 && bAdd; )
    1218             :         {
    1219           0 :             if (pCtx[ pOcas[ i ] ].mnCurArg == nOmitAddressArg)
    1220             :             {
    1221             :                 // Omit erverything except a trailing separator, the leading
    1222             :                 // separator is omitted below. The other way around would leave
    1223             :                 // an extraneous separator if no parameter followed.
    1224           0 :                 if (!(pOcas[ i ] == nFn && pCur->GetOpCode() == ocSep))
    1225           0 :                     bAdd = false;
    1226             :             }
    1227             :         }
    1228          96 :         switch ( pCur->GetOpCode() )
    1229             :         {
    1230             :             case ocOpen:
    1231          12 :                 ++nFn;      // all following operations on _that_ function
    1232          12 :                 pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
    1233          12 :                 pCtx[ nFn ].mnCurArg = 0;
    1234          12 :                 if (pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress && !rConv.isODFF())
    1235           0 :                     pOcas[ nOcas++ ] = nFn;     // entering ADDRESS() if PODF
    1236          12 :                 break;
    1237             :             case ocClose:
    1238          12 :                 pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
    1239             :                 DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissingToPof: underflow");
    1240          12 :                 if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
    1241           0 :                     --nOcas;                    // leaving ADDRESS()
    1242          12 :                 if (nFn > 0)
    1243          12 :                     --nFn;
    1244          12 :                 break;
    1245             :             case ocSep:
    1246          24 :                 pCtx[ nFn ].mnCurArg++;
    1247             :                 // Omit leading separator of ADDRESS() parameter.
    1248          24 :                 if (nOcas && pOcas[ nOcas-1 ] == nFn && pCtx[ nFn ].mnCurArg == nOmitAddressArg)
    1249             :                 {
    1250           0 :                     bAdd = false;
    1251             :                 }
    1252          24 :                 break;
    1253             :             case ocMissing:
    1254           4 :                 if (bAdd)
    1255           4 :                     bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
    1256           4 :                 break;
    1257             :             default:
    1258          44 :                 break;
    1259             :         }
    1260          96 :         if (bAdd)
    1261          96 :             pNewArr->AddToken( *pCur );
    1262             :     }
    1263             : 
    1264          12 :     if (pOcas != &aOpCodeAddressStack[0])
    1265           0 :         delete [] pOcas;
    1266          12 :     if (pCtx != &aCtx[0])
    1267           0 :         delete [] pCtx;
    1268             : 
    1269          12 :     return pNewArr;
    1270             : }
    1271             : 
    1272           0 : bool FormulaTokenArray::MayReferenceFollow()
    1273             : {
    1274           0 :     if ( pCode && nLen > 0 )
    1275             :     {
    1276             :         // ignore trailing spaces
    1277           0 :         sal_uInt16 i = nLen - 1;
    1278           0 :         while ( i > 0 && pCode[i]->GetOpCode() == SC_OPCODE_SPACES )
    1279             :         {
    1280           0 :             --i;
    1281             :         }
    1282           0 :         if ( i > 0 || pCode[i]->GetOpCode() != SC_OPCODE_SPACES )
    1283             :         {
    1284           0 :             OpCode eOp = pCode[i]->GetOpCode();
    1285           0 :             if ( (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) ||
    1286           0 :                  (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP ) ||
    1287           0 :                  eOp == SC_OPCODE_OPEN || eOp == SC_OPCODE_SEP )
    1288             :             {
    1289           0 :                 return true;
    1290             :             }
    1291             :         }
    1292             :     }
    1293           0 :     return false;
    1294             : }
    1295           0 : FormulaToken* FormulaTokenArray::AddOpCode( OpCode eOp )
    1296             : {
    1297           0 :     FormulaToken* pRet = NULL;
    1298           0 :     switch ( eOp )
    1299             :     {
    1300             :         case ocOpen:
    1301             :         case ocClose:
    1302             :         case ocSep:
    1303             :         case ocArrayOpen:
    1304             :         case ocArrayClose:
    1305             :         case ocArrayRowSep:
    1306             :         case ocArrayColSep:
    1307           0 :             pRet = new FormulaToken( svSep,eOp );
    1308           0 :             break;
    1309             :         case ocIf:
    1310             :         case ocIfError:
    1311             :         case ocIfNA:
    1312             :         case ocChose:
    1313             :             {
    1314             :                 short nJump[FORMULA_MAXJUMPCOUNT + 1];
    1315           0 :                 if ( eOp == ocIf )
    1316           0 :                     nJump[ 0 ] = 3;
    1317           0 :                 else if ( eOp == ocChose )
    1318           0 :                     nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
    1319             :                 else
    1320           0 :                     nJump[ 0 ] = 2;
    1321           0 :                 pRet = new FormulaJumpToken( eOp, (short*)nJump );
    1322             :             }
    1323           0 :             break;
    1324             :         default:
    1325           0 :             pRet = new FormulaByteToken( eOp, 0, false );
    1326           0 :             break;
    1327             :     }
    1328           0 :     return AddToken( *pRet );
    1329             : }
    1330             : 
    1331             : 
    1332             : /*----------------------------------------------------------------------*/
    1333             : 
    1334       20377 : FormulaTokenIterator::Item::Item(const FormulaTokenArray* pArray, short pc, short stop) :
    1335       20377 :     pArr(pArray), nPC(pc), nStop(stop)
    1336             : {
    1337       20377 : }
    1338             : 
    1339       20313 : FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray& rArr )
    1340             : {
    1341       20313 :     maStack = new std::vector<FormulaTokenIterator::Item> ();
    1342       20313 :     Push( &rArr );
    1343       20313 : }
    1344             : 
    1345       20313 : FormulaTokenIterator::~FormulaTokenIterator()
    1346             : {
    1347       20313 :     delete maStack;
    1348       20313 : }
    1349             : 
    1350       20377 : void FormulaTokenIterator::Push( const FormulaTokenArray* pArr )
    1351             : {
    1352       20377 :     FormulaTokenIterator::Item item(pArr, -1, SHRT_MAX);
    1353             : 
    1354       20377 :     maStack->push_back(item);
    1355       20377 : }
    1356             : 
    1357          64 : void FormulaTokenIterator::Pop()
    1358             : {
    1359          64 :     maStack->pop_back();
    1360          64 : }
    1361             : 
    1362       20313 : void FormulaTokenIterator::Reset()
    1363             : {
    1364       40626 :     while( maStack->size() > 1 )
    1365           0 :         maStack->pop_back();
    1366             : 
    1367       20313 :     maStack->back().nPC = -1;
    1368       20313 : }
    1369             : 
    1370      102057 : const FormulaToken* FormulaTokenIterator::Next()
    1371             : {
    1372      102057 :     const FormulaToken* t = GetNonEndOfPathToken( ++maStack->back().nPC );
    1373      102057 :     if( !t && maStack->size() > 1 )
    1374             :     {
    1375          56 :         Pop();
    1376          56 :         t = Next();
    1377             :     }
    1378      102057 :     return t;
    1379             : }
    1380             : 
    1381           0 : const FormulaToken* FormulaTokenIterator::PeekNextOperator()
    1382             : {
    1383           0 :     const FormulaToken* t = NULL;
    1384           0 :     short nIdx = maStack->back().nPC;
    1385           0 :     while (!t && ((t = GetNonEndOfPathToken( ++nIdx)) != NULL))
    1386             :     {
    1387           0 :         if (t->GetOpCode() == ocPush)
    1388           0 :             t = NULL;   // ignore operands
    1389             :     }
    1390           0 :     if (!t && maStack->size() > 1)
    1391             :     {
    1392           0 :         FormulaTokenIterator::Item pHere = maStack->back();
    1393           0 :         maStack->pop_back();
    1394           0 :         t = PeekNextOperator();
    1395           0 :         maStack->push_back(pHere);
    1396             :     }
    1397           0 :     return t;
    1398             : }
    1399             : 
    1400             : //! The nPC counts after a Push() are -1
    1401             : 
    1402          94 : void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
    1403             : {
    1404          94 :     maStack->back().nPC = nNext;
    1405          94 :     if( nStart != nNext )
    1406             :     {
    1407          64 :         Push( maStack->back().pArr );
    1408          64 :         maStack->back().nPC = nStart;
    1409          64 :         maStack->back().nStop = nStop;
    1410             :     }
    1411          94 : }
    1412             : 
    1413      102065 : const FormulaToken* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx ) const
    1414             : {
    1415      102065 :     FormulaTokenIterator::Item cur = maStack->back();
    1416             : 
    1417      102065 :     if (nIdx < cur.pArr->nRPN && nIdx < cur.nStop)
    1418             :     {
    1419       81750 :         const FormulaToken* t = cur.pArr->pRPN[ nIdx ];
    1420             :         // such an OpCode ends an IF() or CHOOSE() path
    1421       81750 :         return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? NULL : t;
    1422             :     }
    1423       20315 :     return NULL;
    1424             : }
    1425             : 
    1426           8 : bool FormulaTokenIterator::IsEndOfPath() const
    1427             : {
    1428           8 :     return GetNonEndOfPathToken( maStack->back().nPC + 1) == NULL;
    1429             : }
    1430             : 
    1431             : 
    1432             : 
    1433             : // real implementations of virtual functions
    1434             : 
    1435             : 
    1436       74549 : double      FormulaDoubleToken::GetDouble() const            { return fDouble; }
    1437          10 : double &    FormulaDoubleToken::GetDoubleAsReference()       { return fDouble; }
    1438           0 : bool FormulaDoubleToken::operator==( const FormulaToken& r ) const
    1439             : {
    1440           0 :     return FormulaToken::operator==( r ) && fDouble == r.GetDouble();
    1441             : }
    1442             : 
    1443        7884 : FormulaStringToken::FormulaStringToken( const svl::SharedString& r ) :
    1444        7884 :     FormulaToken( svString ), maString( r )
    1445             : {
    1446        7884 : }
    1447             : 
    1448         250 : FormulaStringToken::FormulaStringToken( const FormulaStringToken& r ) :
    1449         250 :     FormulaToken( r ), maString( r.maString ) {}
    1450             : 
    1451         250 : FormulaToken* FormulaStringToken::Clone() const
    1452             : {
    1453         250 :     return new FormulaStringToken(*this);
    1454             : }
    1455             : 
    1456       13962 : svl::SharedString FormulaStringToken::GetString() const
    1457             : {
    1458       13962 :     return maString;
    1459             : }
    1460             : 
    1461           0 : bool FormulaStringToken::operator==( const FormulaToken& r ) const
    1462             : {
    1463           0 :     return FormulaToken::operator==( r ) && maString == r.GetString();
    1464             : }
    1465             : 
    1466        1982 : FormulaStringOpToken::FormulaStringOpToken( OpCode e, const svl::SharedString& r ) :
    1467        1982 :     FormulaByteToken( e, 0, svString, false ), maString( r ) {}
    1468             : 
    1469          14 : FormulaStringOpToken::FormulaStringOpToken( const FormulaStringOpToken& r ) :
    1470          14 :     FormulaByteToken( r ), maString( r.maString ) {}
    1471             : 
    1472          14 : FormulaToken* FormulaStringOpToken::Clone() const
    1473             : {
    1474          14 :     return new FormulaStringOpToken(*this);
    1475             : }
    1476             : 
    1477        1876 : svl::SharedString FormulaStringOpToken::GetString() const
    1478             : {
    1479        1876 :     return maString;
    1480             : }
    1481             : 
    1482          42 : bool FormulaStringOpToken::operator==( const FormulaToken& r ) const
    1483             : {
    1484          42 :     return FormulaByteToken::operator==( r ) && maString == r.GetString();
    1485             : }
    1486             : 
    1487        1416 : sal_uInt16  FormulaIndexToken::GetIndex() const             { return nIndex; }
    1488          92 : void        FormulaIndexToken::SetIndex( sal_uInt16 n )     { nIndex = n; }
    1489        1300 : bool        FormulaIndexToken::IsGlobal() const             { return mbGlobal; }
    1490          92 : void        FormulaIndexToken::SetGlobal( bool b )          { mbGlobal = b; }
    1491           0 : bool FormulaIndexToken::operator==( const FormulaToken& r ) const
    1492             : {
    1493           0 :     return FormulaToken::operator==( r ) && nIndex == r.GetIndex() &&
    1494           0 :         mbGlobal == r.IsGlobal();
    1495             : }
    1496         270 : const OUString&   FormulaExternalToken::GetExternal() const    { return aExternal; }
    1497         348 : sal_uInt8            FormulaExternalToken::GetByte() const        { return nByte; }
    1498         174 : void            FormulaExternalToken::SetByte( sal_uInt8 n )      { nByte = n; }
    1499           0 : bool FormulaExternalToken::operator==( const FormulaToken& r ) const
    1500             : {
    1501           0 :     return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
    1502           0 :         aExternal == r.GetExternal();
    1503             : }
    1504             : 
    1505             : 
    1506        1436 : sal_uInt16          FormulaErrorToken::GetError() const          { return nError; }
    1507           0 : void            FormulaErrorToken::SetError( sal_uInt16 nErr )   { nError = nErr; }
    1508           0 : bool FormulaErrorToken::operator==( const FormulaToken& r ) const
    1509             : {
    1510           0 :     return FormulaToken::operator==( r ) &&
    1511           0 :         nError == static_cast< const FormulaErrorToken & >(r).GetError();
    1512             : }
    1513           0 : double          FormulaMissingToken::GetDouble() const       { return 0.0; }
    1514             : 
    1515           0 : svl::SharedString FormulaMissingToken::GetString() const
    1516             : {
    1517           0 :     return svl::SharedString::getEmptyString();
    1518             : }
    1519             : 
    1520           0 : bool FormulaMissingToken::operator==( const FormulaToken& r ) const
    1521             : {
    1522           0 :     return FormulaToken::operator==( r );
    1523             : }
    1524             : 
    1525             : 
    1526           0 : FormulaSubroutineToken::FormulaSubroutineToken( const FormulaSubroutineToken& r ) :
    1527             :     FormulaToken( r ),
    1528           0 :     mpArray( r.mpArray->Clone())
    1529             : {
    1530           0 : }
    1531           0 : FormulaSubroutineToken::~FormulaSubroutineToken()
    1532             : {
    1533           0 :     delete mpArray;
    1534           0 : }
    1535           0 : bool FormulaSubroutineToken::operator==( const FormulaToken& r ) const
    1536             : {
    1537             :     // Arrays don't equal..
    1538           0 :     return FormulaToken::operator==( r ) &&
    1539           0 :         (mpArray == static_cast<const FormulaSubroutineToken&>(r).mpArray);
    1540             : }
    1541             : 
    1542             : 
    1543           0 : bool FormulaUnknownToken::operator==( const FormulaToken& r ) const
    1544             : {
    1545           0 :     return FormulaToken::operator==( r );
    1546             : }
    1547             : 
    1548             : 
    1549         276 : } // formula
    1550             : 
    1551             : 
    1552             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10