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

Generated by: LCOV version 1.10