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

Generated by: LCOV version 1.10