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: 281 649 43.3 %
Date: 2012-12-17 Functions: 70 132 53.0 %
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          38 : 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       29910 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaDoubleToken )
      45             : // Need a lot of FormulaByteToken
      46       50214 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaByteToken )
      47             : // Need several FormulaStringToken
      48       11406 : 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      113714 : FormulaToken::~FormulaToken()
      65             : {
      66      113714 : }
      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       11714 : sal_uInt8 FormulaToken::GetParamCount() const
      92             : {
      93       11714 :     if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
      94             :             eOp != ocIf && eOp != ocChose && eOp != ocPercentSign )
      95         106 :         return 0;       // parameters and specials
      96             :                         // ocIf and ocChose not for FAP, have cByte then
      97             : //2do: bool parameter whether FAP or not?
      98       11608 :     else if ( GetByte() )
      99        2284 :         return GetByte();   // all functions, also ocExternal and ocMacro
     100        9324 :     else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
     101        9158 :         return 2;           // binary
     102         166 :     else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
     103             :             || eOp == ocPercentSign)
     104          94 :         return 1;           // unary
     105          72 :     else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
     106          62 :         return 0;           // no parameter
     107          10 :     else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
     108           0 :         return 1;           // one parameter
     109          10 :     else if ( eOp == ocIf || eOp == ocChose )
     110           0 :         return 1;           // only the condition counts as parameter
     111             :     else
     112          10 :         return 0;           // all the rest, no Parameter, or
     113             :                             // if so then it should be in cByte
     114             : }
     115             : 
     116       68284 : bool FormulaToken::IsExternalRef() const
     117             : {
     118       68284 :     bool bRet = false;
     119       68284 :     switch (eType)
     120             :     {
     121             :         case svExternalSingleRef:
     122             :         case svExternalDoubleRef:
     123             :         case svExternalName:
     124          82 :             bRet = true;
     125          82 :             break;
     126             :         default:
     127       68202 :             bRet = false;
     128       68202 :             break;
     129             :     }
     130       68284 :     return bRet;
     131             : }
     132             : 
     133          56 : bool FormulaToken::operator==( const FormulaToken& rToken ) const
     134             : {
     135             :     // don't compare reference count!
     136          56 :     return  eType == rToken.eType && GetOpCode() == rToken.GetOpCode();
     137             : }
     138             : 
     139             : 
     140             : // --- virtual dummy methods -------------------------------------------------
     141             : 
     142       16156 : sal_uInt8 FormulaToken::GetByte() const
     143             : {
     144             :     // ok to be called for any derived class
     145       16156 :     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         328 : bool FormulaToken::HasForceArray() const
     154             : {
     155             :     // ok to be called for any derived class
     156         328 :     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           4 : bool FormulaToken::TextEqual( const FormulaToken& rToken ) const
     238             : {
     239           4 :     return *this == rToken;
     240             : }
     241             : // ==========================================================================
     242             : // real implementations of virtual functions
     243             : // --------------------------------------------------------------------------
     244             : 
     245             : 
     246       25514 : sal_uInt8 FormulaByteToken::GetByte() const                       { return nByte; }
     247        7100 : void FormulaByteToken::SetByte( sal_uInt8 n )                     { nByte = n; }
     248       32332 : bool FormulaByteToken::HasForceArray() const                 { return bHasForceArray; }
     249           0 : void FormulaByteToken::SetForceArray( bool b )               { bHasForceArray = b; }
     250          48 : bool FormulaByteToken::operator==( const FormulaToken& r ) const
     251             : {
     252          96 :     return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
     253          96 :         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         200 : 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          78 : FormulaJumpToken::~FormulaJumpToken()
     269             : {
     270          26 :     delete [] pJump;
     271          52 : }
     272             : 
     273             : 
     274         250 : bool FormulaTokenArray::AddFormulaToken(const sheet::FormulaToken& _aToken,ExternalReferenceHelper* /*_pRef*/)
     275             : {
     276         250 :     bool bError = false;
     277         250 :     const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode);      //! assuming equal values for the moment
     278             : 
     279         250 :     const uno::TypeClass eClass = _aToken.Data.getValueTypeClass();
     280         250 :     switch ( eClass )
     281             :     {
     282             :         case uno::TypeClass_VOID:
     283             :             // empty data -> use AddOpCode (does some special cases)
     284          90 :             AddOpCode( eOpCode );
     285          90 :             break;
     286             :         case uno::TypeClass_DOUBLE:
     287             :             // double is only used for "push"
     288          60 :             if ( eOpCode == ocPush )
     289          60 :                 AddDouble( _aToken.Data.get<double>() );
     290             :             else
     291           0 :                 bError = true;
     292          60 :             break;
     293             :         case uno::TypeClass_LONG:
     294             :             {
     295             :                 // long is svIndex, used for name / database area, or "byte" for spaces
     296           4 :                 sal_Int32 nValue = _aToken.Data.get<sal_Int32>();
     297           4 :                 if ( eOpCode == ocDBArea )
     298           0 :                     AddToken( formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) );
     299           4 :                 else if ( eOpCode == ocSpaces )
     300           4 :                     AddToken( formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) );
     301             :                 else
     302           0 :                     bError = true;
     303             :             }
     304           4 :             break;
     305             :         case uno::TypeClass_STRING:
     306             :             {
     307           6 :                 String aStrVal( _aToken.Data.get<rtl::OUString>() );
     308           6 :                 if ( eOpCode == ocPush )
     309           0 :                     AddString( aStrVal );
     310           6 :                 else if ( eOpCode == ocBad )
     311           6 :                     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           6 :             break;
     320             :         default:
     321          90 :             bError = true;
     322             :     } // switch ( eClass )
     323         250 :     return bError;
     324             : }
     325         152 : bool FormulaTokenArray::Fill(const uno::Sequence< sheet::FormulaToken >& _aSequence,ExternalReferenceHelper* _pRef)
     326             : {
     327         152 :     bool bError = false;
     328         152 :     const sal_Int32 nCount = _aSequence.getLength();
     329         402 :     for (sal_Int32 nPos=0; nPos<nCount; nPos++)
     330             :     {
     331         250 :         bool bOneError = AddFormulaToken( _aSequence[nPos] ,_pRef);
     332         250 :         if (bOneError)
     333             :         {
     334           0 :             AddOpCode( ocErrName);  // add something that indicates an error
     335           0 :             bError = true;
     336             :         }
     337             :     }
     338         152 :     return bError;
     339             : }
     340        2724 : FormulaToken* FormulaTokenArray::GetNextReference()
     341             : {
     342        6884 :     while( nIndex < nLen )
     343             :     {
     344        3288 :         FormulaToken* t = pCode[ nIndex++ ];
     345        3288 :         switch( t->GetType() )
     346             :         {
     347             :             case svSingleRef:
     348             :             case svDoubleRef:
     349             :             case svExternalSingleRef:
     350             :             case svExternalDoubleRef:
     351        1852 :                 return t;
     352             :             default:
     353             :             {
     354             :                 // added to avoid warnings
     355             :             }
     356             :         }
     357             :     }
     358         872 :     return NULL;
     359             : }
     360             : 
     361          76 : FormulaToken* FormulaTokenArray::GetNextColRowName()
     362             : {
     363         304 :     while( nIndex < nLen )
     364             :     {
     365         152 :         FormulaToken* t = pCode[ nIndex++ ];
     366         152 :         if ( t->GetOpCode() == ocColRowName )
     367           0 :             return t;
     368             :     }
     369          76 :     return NULL;
     370             : }
     371             : 
     372       22434 : FormulaToken* FormulaTokenArray::GetNextReferenceRPN()
     373             : {
     374       72148 :     while( nIndex < nRPN )
     375             :     {
     376       42904 :         FormulaToken* t = pRPN[ nIndex++ ];
     377       42904 :         switch( t->GetType() )
     378             :         {
     379             :             case svSingleRef:
     380             :             case svDoubleRef:
     381             :             case svExternalSingleRef:
     382             :             case svExternalDoubleRef:
     383       15624 :                 return t;
     384             :             default:
     385             :             {
     386             :                 // added to avoid warnings
     387             :             }
     388             :         }
     389             :     }
     390        6810 :     return NULL;
     391             : }
     392             : 
     393         530 : FormulaToken* FormulaTokenArray::GetNextReferenceOrName()
     394             : {
     395         530 :     if( pCode )
     396             :     {
     397        1332 :         while ( nIndex < nLen )
     398             :         {
     399         600 :             FormulaToken* t = pCode[ nIndex++ ];
     400         600 :             switch( t->GetType() )
     401             :             {
     402             :                 case svSingleRef:
     403             :                 case svDoubleRef:
     404             :                 case svIndex:
     405             :                 case svExternalSingleRef:
     406             :                 case svExternalDoubleRef:
     407             :                 case svExternalName:
     408         328 :                     return t;
     409             :                 default:
     410             :                 {
     411             :                     // added to avoid warnings
     412             :                 }
     413             :              }
     414             :          }
     415             :      }
     416         202 :     return NULL;
     417             : }
     418             : 
     419         122 : FormulaToken* FormulaTokenArray::GetNextName()
     420             : {
     421         122 :     if( pCode )
     422             :     {
     423         394 :         while ( nIndex < nLen )
     424             :         {
     425         190 :             FormulaToken* t = pCode[ nIndex++ ];
     426         190 :             if( t->GetType() == svIndex )
     427          40 :                 return t;
     428             :         }
     429             :     } // if( pCode )
     430          82 :     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       75650 : FormulaToken* FormulaTokenArray::Next()
     445             : {
     446       75650 :     if( pCode && nIndex < nLen )
     447       68212 :         return pCode[ nIndex++ ];
     448             :     else
     449        7438 :         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         590 : FormulaToken* FormulaTokenArray::NextRPN()
     465             : {
     466         590 :     if( pRPN && nIndex < nRPN )
     467         448 :         return pRPN[ nIndex++ ];
     468             :     else
     469         142 :         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       13910 : void FormulaTokenArray::DelRPN()
     481             : {
     482       13910 :     if( nRPN )
     483             :     {
     484        6146 :         FormulaToken** p = pRPN;
     485       46592 :         for( sal_uInt16 i = 0; i < nRPN; i++ )
     486             :         {
     487       40446 :             (*p++)->DecRef();
     488             :         }
     489        6146 :         delete [] pRPN;
     490             :     }
     491       13910 :     pRPN = NULL;
     492       13910 :     nRPN = nIndex = 0;
     493       13910 : }
     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         318 : FormulaToken* FormulaTokenArray::PeekNextNoSpaces()
     511             : {
     512         318 :     if( pCode && nIndex < nLen )
     513             :     {
     514          56 :         sal_uInt16 j = nIndex;
     515         112 :         while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
     516           0 :             j++;
     517          56 :         if ( j < nLen )
     518          56 :             return pCode[ j ];
     519             :         else
     520           0 :             return NULL;
     521             :     }
     522             :     else
     523         262 :         return NULL;
     524             : }
     525             : 
     526         318 : FormulaToken* FormulaTokenArray::PeekPrevNoSpaces()
     527             : {
     528         318 :     if( pCode && nIndex > 1 )
     529             :     {
     530          50 :         sal_uInt16 j = nIndex - 2;
     531         100 :         while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
     532           0 :             j--;
     533          50 :         if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
     534          50 :             return pCode[ j ];
     535             :         else
     536           0 :             return NULL;
     537             :     }
     538             :     else
     539         268 :         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        6042 : bool FormulaTokenArray::HasOpCode( OpCode eOp ) const
     553             : {
     554       70036 :     for ( sal_uInt16 j=0; j < nLen; j++ )
     555             :     {
     556       63996 :         if ( pCode[j]->GetOpCode() == eOp )
     557           2 :             return true;
     558             :     }
     559        6040 :     return false;
     560             : }
     561             : 
     562         734 : bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp ) const
     563             : {
     564        2700 :     for ( sal_uInt16 j=0; j < nRPN; j++ )
     565             :     {
     566        1966 :         if ( pRPN[j]->GetOpCode() == eOp )
     567           0 :             return true;
     568             :     }
     569         734 :     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        4342 : FormulaTokenArray::FormulaTokenArray()
     584             : {
     585        4342 :     pCode = NULL; pRPN = NULL;
     586        4342 :     nError = nLen = nIndex = nRPN = nRefs = 0;
     587        4342 :     bHyperLink = false;
     588        4342 :     ClearRecalcMode();
     589        4342 : }
     590             : 
     591        7704 : FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray& rArr )
     592             : {
     593        7704 :     Assign( rArr );
     594        7704 : }
     595             : 
     596       11576 : FormulaTokenArray::~FormulaTokenArray()
     597             : {
     598       11576 :     Clear();
     599       11576 : }
     600             : 
     601        7704 : void FormulaTokenArray::Assign( const FormulaTokenArray& r )
     602             : {
     603        7704 :     nLen   = r.nLen;
     604        7704 :     nRPN   = r.nRPN;
     605        7704 :     nIndex = r.nIndex;
     606        7704 :     nError = r.nError;
     607        7704 :     nRefs  = r.nRefs;
     608        7704 :     nMode  = r.nMode;
     609        7704 :     bHyperLink = r.bHyperLink;
     610        7704 :     pCode  = NULL;
     611        7704 :     pRPN   = NULL;
     612             :     FormulaToken** pp;
     613        7704 :     if( nLen )
     614             :     {
     615        7682 :         pp = pCode = new FormulaToken*[ nLen ];
     616        7682 :         memcpy( pp, r.pCode, nLen * sizeof( FormulaToken* ) );
     617       74178 :         for( sal_uInt16 i = 0; i < nLen; i++ )
     618       66496 :             (*pp++)->IncRef();
     619             :     }
     620        7704 :     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        7704 : }
     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       17444 : void FormulaTokenArray::Clear()
     688             : {
     689       17444 :     if( nRPN ) DelRPN();
     690       17444 :     if( pCode )
     691             :     {
     692       16564 :         FormulaToken** p = pCode;
     693      151044 :         for( sal_uInt16 i = 0; i < nLen; i++ )
     694             :         {
     695      134480 :             (*p++)->DecRef();
     696             :         }
     697       16564 :         delete [] pCode;
     698             :     }
     699       17444 :     pCode = NULL; pRPN = NULL;
     700       17444 :     nError = nLen = nIndex = nRPN = nRefs = 0;
     701       17444 :     bHyperLink = false;
     702       17444 :     ClearRecalcMode();
     703       17444 : }
     704             : 
     705          18 : FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r )
     706             : {
     707          18 :     return Add( r.Clone() );
     708             : }
     709             : 
     710           0 : FormulaToken* FormulaTokenArray::MergeArray( )
     711             : {
     712           0 :     return NULL;
     713             : }
     714             : 
     715       66762 : FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
     716             : {
     717       66762 :     if( !pCode )
     718        7916 :         pCode = new FormulaToken*[ MAXCODE ];
     719       66762 :     if( nLen < MAXCODE-1 )
     720             :     {
     721       66762 :         pCode[ nLen++ ] = t;
     722      103426 :         if( t->GetOpCode() == ocPush
     723       36664 :             && ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
     724       14390 :             nRefs++;
     725       66762 :         t->IncRef();
     726       66762 :         if( t->GetOpCode() == ocArrayClose )
     727          10 :             return MergeArray();
     728       66752 :         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        5380 : FormulaToken* FormulaTokenArray::AddString( const String& rStr )
     749             : {
     750        5380 :     return Add( new FormulaStringToken( rStr ) );
     751             : }
     752             : 
     753        2262 : FormulaToken* FormulaTokenArray::AddDouble( double fVal )
     754             : {
     755        2262 :     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           2 : FormulaToken* FormulaTokenArray::AddExternal( const String& rStr,
     764             :         OpCode eOp /* = ocExternal */ )
     765             : {
     766           2 :     return Add( new FormulaExternalToken( eOp, rStr ) );
     767             : }
     768             : 
     769           6 : FormulaToken* FormulaTokenArray::AddBad( const String& rStr )
     770             : {
     771           6 :     return Add( new FormulaStringOpToken( ocBad, rStr ) );
     772             : }
     773             : 
     774         810 : FormulaToken* FormulaTokenArray::AddStringXML( const String& rStr )
     775             : {
     776         810 :     return Add( new FormulaStringOpToken( ocStringXML, rStr ) );
     777             : }
     778             : 
     779             : 
     780             : 
     781          40 : void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
     782             : {
     783             :     //! Reihenfolge ist wichtig
     784          40 :     if ( nBits & RECALCMODE_ALWAYS )
     785           0 :         SetRecalcModeAlways();
     786          40 :     else if ( !IsRecalcModeAlways() )
     787             :     {
     788          40 :         if ( nBits & RECALCMODE_ONLOAD )
     789           0 :             SetRecalcModeOnLoad();
     790          40 :         else if ( nBits & RECALCMODE_ONLOAD_ONCE && !IsRecalcModeOnLoad() )
     791           0 :             SetRecalcModeOnLoadOnce();
     792             :     }
     793          40 :     SetCombinedBitsRecalcMode( nBits );
     794          40 : }
     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          90 : inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
     873             : {
     874          90 :     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          90 :             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          82 : bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
    1052             : {
    1053         172 :     for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
    1054             :     {
    1055          90 :         if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
    1056           0 :             return true;
    1057             :     }
    1058          82 :     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        6046 : FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray& rArr )
    1199             : {
    1200        6046 :     pCur = NULL;
    1201        6046 :     Push( &rArr );
    1202        6046 : }
    1203             : 
    1204        6046 : FormulaTokenIterator::~FormulaTokenIterator()
    1205             : {
    1206       18138 :     while( pCur )
    1207        6046 :         Pop();
    1208        6046 : }
    1209             : 
    1210        6064 : void FormulaTokenIterator::Push( const FormulaTokenArray* pArr )
    1211             : {
    1212        6064 :     ImpTokenIterator* p = new ImpTokenIterator;
    1213        6064 :     p->pArr  = pArr;
    1214        6064 :     p->nPC   = -1;
    1215        6064 :     p->nStop = SHRT_MAX;
    1216        6064 :     p->pNext = pCur;
    1217        6064 :     pCur     = p;
    1218        6064 : }
    1219             : 
    1220        6064 : void FormulaTokenIterator::Pop()
    1221             : {
    1222        6064 :     ImpTokenIterator* p = pCur;
    1223        6064 :     if( p )
    1224             :     {
    1225        6064 :         pCur = p->pNext;
    1226        6064 :         delete p;
    1227             :     }
    1228        6064 : }
    1229             : 
    1230        6046 : void FormulaTokenIterator::Reset()
    1231             : {
    1232       12092 :     while( pCur->pNext )
    1233           0 :         Pop();
    1234        6046 :     pCur->nPC = -1;
    1235        6046 : }
    1236             : 
    1237       33790 : const FormulaToken* FormulaTokenIterator::Next()
    1238             : {
    1239       33790 :     const FormulaToken* t = GetNonEndOfPathToken( ++pCur->nPC );
    1240       33790 :     if( !t && pCur->pNext )
    1241             :     {
    1242          18 :         Pop();
    1243          18 :         t = Next();
    1244             :     }
    1245       33790 :     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          24 : void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
    1270             : {
    1271          24 :     pCur->nPC = nNext;
    1272          24 :     if( nStart != nNext )
    1273             :     {
    1274          18 :         Push( pCur->pArr );
    1275          18 :         pCur->nPC = nStart;
    1276          18 :         pCur->nStop = nStop;
    1277             :     }
    1278          24 : }
    1279             : 
    1280       33790 : const FormulaToken* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx ) const
    1281             : {
    1282       33790 :     if (nIdx < pCur->pArr->nRPN && nIdx < pCur->nStop)
    1283             :     {
    1284       27748 :         const FormulaToken* t = pCur->pArr->pRPN[ nIdx ];
    1285             :         // such an OpCode ends an IF() or CHOOSE() path
    1286       27748 :         return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? NULL : t;
    1287             :     }
    1288        6042 :     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       15174 : 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         342 : 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         820 : const String& FormulaStringOpToken::GetString() const             { return aString; }
    1317          44 : bool FormulaStringOpToken::operator==( const FormulaToken& r ) const
    1318             : {
    1319          44 :     return FormulaByteToken::operator==( r ) && aString == r.GetString();
    1320             : }
    1321             : 
    1322         454 : sal_uInt16  FormulaIndexToken::GetIndex() const             { return nIndex; }
    1323          28 : void        FormulaIndexToken::SetIndex( sal_uInt16 n )     { nIndex = n; }
    1324         420 : bool        FormulaIndexToken::IsGlobal() const             { return mbGlobal; }
    1325          28 : 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           2 : 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         386 : 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         114 : } // formula
    1384             : // -----------------------------------------------------------------------------
    1385             : 
    1386             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10