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

Generated by: LCOV version 1.10