LCOV - code coverage report
Current view: top level - formula/source/core/api - FormulaCompiler.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1062 0.0 %
Date: 2014-04-14 Functions: 0 92 0.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             : #include <sal/macros.h>
      20             : #include "formula/FormulaCompiler.hxx"
      21             : #include "formula/errorcodes.hxx"
      22             : #include "formula/token.hxx"
      23             : #include "formula/tokenarray.hxx"
      24             : #include "core_resource.hxx"
      25             : #include "core_resource.hrc"
      26             : 
      27             : #include "osl/mutex.hxx"
      28             : 
      29             : #include <svl/zforlist.hxx>
      30             : #include <tools/rc.hxx>
      31             : #include <tools/rcid.h>
      32             : #include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp>
      33             : #include <com/sun/star/sheet/FormulaMapGroup.hpp>
      34             : #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
      35             : #include <rtl/strbuf.hxx>
      36             : #include <stdio.h>
      37             : 
      38             : namespace formula
      39             : {
      40             :     using namespace ::com::sun::star;
      41             : 
      42             :     static const sal_Char* pInternal[2] = { "TTT", "__DEBUG_VAR" };
      43             : 
      44             : namespace {
      45             : 
      46             : class FormulaCompilerRecursionGuard
      47             : {
      48             : private:
      49             :             short&              rRecursion;
      50             : public:
      51           0 :                                 FormulaCompilerRecursionGuard( short& rRec )
      52           0 :                                     : rRecursion( rRec ) { ++rRecursion; }
      53           0 :                                 ~FormulaCompilerRecursionGuard() { --rRecursion; }
      54             : };
      55             : 
      56           0 : short lcl_GetRetFormat( OpCode eOpCode )
      57             : {
      58           0 :     switch (eOpCode)
      59             :     {
      60             :         case ocEqual:
      61             :         case ocNotEqual:
      62             :         case ocLess:
      63             :         case ocGreater:
      64             :         case ocLessEqual:
      65             :         case ocGreaterEqual:
      66             :         case ocAnd:
      67             :         case ocOr:
      68             :         case ocXor:
      69             :         case ocNot:
      70             :         case ocTrue:
      71             :         case ocFalse:
      72             :         case ocIsEmpty:
      73             :         case ocIsString:
      74             :         case ocIsNonString:
      75             :         case ocIsLogical:
      76             :         case ocIsRef:
      77             :         case ocIsValue:
      78             :         case ocIsFormula:
      79             :         case ocIsNA:
      80             :         case ocIsErr:
      81             :         case ocIsError:
      82             :         case ocIsEven:
      83             :         case ocIsOdd:
      84             :         case ocExact:
      85           0 :             return NUMBERFORMAT_LOGICAL;
      86             :         case ocGetActDate:
      87             :         case ocGetDate:
      88             :         case ocEasterSunday :
      89           0 :             return NUMBERFORMAT_DATE;
      90             :         case ocGetActTime:
      91           0 :             return NUMBERFORMAT_DATETIME;
      92             :         case ocGetTime:
      93           0 :             return NUMBERFORMAT_TIME;
      94             :         case ocNPV:
      95             :         case ocBW:
      96             :         case ocDIA:
      97             :         case ocGDA:
      98             :         case ocGDA2:
      99             :         case ocVBD:
     100             :         case ocLIA:
     101             :         case ocRMZ:
     102             :         case ocZW:
     103             :         case ocZinsZ:
     104             :         case ocKapz:
     105             :         case ocKumZinsZ:
     106             :         case ocKumKapZ:
     107           0 :             return NUMBERFORMAT_CURRENCY;
     108             :         case ocZins:
     109             :         case ocIRR:
     110             :         case ocMIRR:
     111             :         case ocZGZ:
     112             :         case ocEffektiv:
     113             :         case ocNominal:
     114             :         case ocPercentSign:
     115           0 :             return NUMBERFORMAT_PERCENT;
     116             :         default:
     117           0 :             return NUMBERFORMAT_NUMBER;
     118             :     }
     119             : }
     120             : 
     121           0 : inline void lclPushOpCodeMapEntry( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec,
     122             :         const OUString* pTable, sal_uInt16 nOpCode )
     123             : {
     124           0 :     sheet::FormulaOpCodeMapEntry aEntry;
     125           0 :     aEntry.Token.OpCode = nOpCode;
     126           0 :     aEntry.Name = pTable[nOpCode];
     127           0 :     rVec.push_back( aEntry);
     128           0 : }
     129             : 
     130           0 : void lclPushOpCodeMapEntries( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec,
     131             :         const OUString* pTable, sal_uInt16 nOpCodeBeg, sal_uInt16 nOpCodeEnd )
     132             : {
     133           0 :     for (sal_uInt16 nOpCode = nOpCodeBeg; nOpCode < nOpCodeEnd; ++nOpCode)
     134           0 :         lclPushOpCodeMapEntry( rVec, pTable, nOpCode );
     135           0 : }
     136             : 
     137           0 : void lclPushOpCodeMapEntries( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec,
     138             :         const OUString* pTable, const sal_uInt16* pnOpCodes, size_t nCount )
     139             : {
     140           0 :     for (const sal_uInt16* pnEnd = pnOpCodes + nCount; pnOpCodes < pnEnd; ++pnOpCodes)
     141           0 :         lclPushOpCodeMapEntry( rVec, pTable, *pnOpCodes );
     142           0 : }
     143             : 
     144           0 : class OpCodeList : public Resource        // temp object for resource
     145             : {
     146             : public:
     147             : 
     148             :     OpCodeList( sal_uInt16, FormulaCompiler::NonConstOpCodeMapPtr,
     149             :             FormulaCompiler::SeparatorType = FormulaCompiler::SEMICOLON_BASE );
     150             : 
     151             : private:
     152             :     bool getOpCodeString( OUString& rStr, sal_uInt16 nOp );
     153             :     void putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp );
     154             : 
     155             : private:
     156             :     FormulaCompiler::SeparatorType meSepType;
     157             : };
     158             : 
     159           0 : OpCodeList::OpCodeList( sal_uInt16 nRID, FormulaCompiler::NonConstOpCodeMapPtr xMap,
     160             :         FormulaCompiler::SeparatorType eSepType ) :
     161           0 :     Resource( ResId( nRID, *ResourceManager::getResManager()))
     162           0 :     , meSepType( eSepType)
     163             : {
     164           0 :     if (meSepType == FormulaCompiler::RESOURCE_BASE)
     165             :     {
     166           0 :         for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
     167             :         {
     168           0 :             putDefaultOpCode( xMap, i);
     169             :         }
     170             :     }
     171             :     else
     172             :     {
     173           0 :         for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
     174             :         {
     175           0 :             OUString aOpStr;
     176           0 :             if ( getOpCodeString( aOpStr, i) )
     177           0 :                 xMap->putOpCode( aOpStr, OpCode(i));
     178             :             else
     179           0 :                 putDefaultOpCode( xMap, i);
     180           0 :         }
     181             :     }
     182             : 
     183           0 :     FreeResource();
     184           0 : }
     185             : 
     186           0 : bool OpCodeList::getOpCodeString( OUString& rStr, sal_uInt16 nOp )
     187             : {
     188           0 :     switch (nOp)
     189             :     {
     190             :         case SC_OPCODE_SEP:
     191             :         {
     192           0 :             if (meSepType == FormulaCompiler::COMMA_BASE)
     193             :             {
     194           0 :                 rStr = ",";
     195           0 :                 return true;
     196             :             }
     197           0 :             else if (meSepType == FormulaCompiler::SEMICOLON_BASE)
     198             :             {
     199           0 :                 rStr = ";";
     200           0 :                 return true;
     201             :             }
     202             :         }
     203           0 :         break;
     204             :         case SC_OPCODE_ARRAY_COL_SEP:
     205             :         {
     206           0 :             if (meSepType == FormulaCompiler::COMMA_BASE)
     207             :             {
     208           0 :                 rStr = ",";
     209           0 :                 return true;
     210             :             }
     211           0 :             else if (meSepType == FormulaCompiler::SEMICOLON_BASE)
     212             :             {
     213           0 :                 rStr = ";";
     214           0 :                 return true;
     215             :             }
     216             :         }
     217           0 :         break;
     218             :         case SC_OPCODE_ARRAY_ROW_SEP:
     219             :         {
     220           0 :             if (meSepType == FormulaCompiler::COMMA_BASE)
     221             :             {
     222           0 :                 rStr = ";";
     223           0 :                 return true;
     224             :             }
     225           0 :             else if (meSepType == FormulaCompiler::SEMICOLON_BASE)
     226             :             {
     227           0 :                 rStr = "|";
     228           0 :                 return true;
     229             :             }
     230             :         }
     231           0 :         break;
     232             :     }
     233             : 
     234           0 :     return false;
     235             : }
     236             : 
     237           0 : void OpCodeList::putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp )
     238             : {
     239           0 :     ResId aRes( nOp, *ResourceManager::getResManager());
     240           0 :     aRes.SetRT( RSC_STRING);
     241           0 :     if (IsAvailableRes( aRes))
     242           0 :         xMap->putOpCode( aRes.toString(), OpCode( nOp));
     243           0 : }
     244             : 
     245             : // static
     246           0 : const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr, sal_Unicode c )
     247             : {
     248           0 :     if ( !pStr )
     249           0 :         return NULL;
     250           0 :     while ( *pStr )
     251             :     {
     252           0 :         if ( *pStr == c )
     253           0 :             return pStr;
     254           0 :         pStr++;
     255             :     }
     256           0 :     return NULL;
     257             : }
     258             : 
     259           0 : struct OpCodeMapData
     260             : {
     261             :     FormulaCompiler::NonConstOpCodeMapPtr mxSymbolMap;
     262             :     osl::Mutex maMtx;
     263             : };
     264             : 
     265             : 
     266             : } // namespace
     267             : 
     268             : 
     269           0 : void FormulaCompiler::OpCodeMap::putExternal( const OUString & rSymbol, const OUString & rAddIn )
     270             : {
     271             :     // Different symbols may map to the same AddIn, but the same AddIn may not
     272             :     // map to different symbols, the first pair wins. Same symbol of course may
     273             :     // not map to different AddIns, again the first pair wins and also the
     274             :     // AddIn->symbol mapping is not inserted in other cases.
     275           0 :     bool bOk = mpExternalHashMap->insert( ExternalHashMap::value_type( rSymbol, rAddIn)).second;
     276             :     SAL_WARN_IF( !bOk, "formula.core", "OpCodeMap::putExternal: symbol not inserted, " << rSymbol << " -> " << rAddIn);
     277           0 :     if (bOk)
     278             :     {
     279           0 :         bOk = mpReverseExternalHashMap->insert( ExternalHashMap::value_type( rAddIn, rSymbol)).second;
     280             :         // Failed insertion of the AddIn is ok for different symbols mapping to
     281             :         // the same AddIn. Make this INFO only.
     282             :         SAL_INFO_IF( !bOk, "formula.core", "OpCodeMap::putExternal: AddIn not inserted, " << rAddIn << " -> " << rSymbol);
     283             :     }
     284           0 : }
     285             : 
     286           0 : void FormulaCompiler::OpCodeMap::putExternalSoftly( const OUString & rSymbol, const OUString & rAddIn )
     287             : {
     288           0 :     bool bOk = mpReverseExternalHashMap->insert( ExternalHashMap::value_type( rAddIn, rSymbol)).second;
     289           0 :     if (bOk)
     290           0 :         mpExternalHashMap->insert( ExternalHashMap::value_type( rSymbol, rAddIn));
     291           0 : }
     292             : 
     293           0 : uno::Sequence< sheet::FormulaToken > FormulaCompiler::OpCodeMap::createSequenceOfFormulaTokens(
     294             :         const FormulaCompiler& rCompiler, const uno::Sequence< OUString >& rNames ) const
     295             : {
     296           0 :     const sal_Int32 nLen = rNames.getLength();
     297           0 :     uno::Sequence< sheet::FormulaToken > aTokens( nLen);
     298           0 :     sheet::FormulaToken* pToken = aTokens.getArray();
     299           0 :     OUString const * pName = rNames.getConstArray();
     300           0 :     OUString const * const pStop = pName + nLen;
     301           0 :     for ( ; pName < pStop; ++pName, ++pToken)
     302             :     {
     303           0 :         OpCodeHashMap::const_iterator iLook( mpHashMap->find( *pName));
     304           0 :         if (iLook != mpHashMap->end())
     305           0 :             pToken->OpCode = (*iLook).second;
     306             :         else
     307             :         {
     308           0 :             OUString aIntName;
     309           0 :             if (hasExternals())
     310             :             {
     311           0 :                 ExternalHashMap::const_iterator iExt( mpExternalHashMap->find( *pName));
     312           0 :                 if (iExt != mpExternalHashMap->end())
     313           0 :                     aIntName = (*iExt).second;
     314             :                 // Check for existence not needed here, only name-mapping is of
     315             :                 // interest.
     316             :             }
     317           0 :             if (aIntName.isEmpty())
     318           0 :                 aIntName = rCompiler.FindAddInFunction(*pName, !isEnglish());    // bLocalFirst=false for english
     319           0 :             if (aIntName.isEmpty())
     320           0 :                 pToken->OpCode = getOpCodeUnknown();
     321             :             else
     322             :             {
     323           0 :                 pToken->OpCode = ocExternal;
     324           0 :                 pToken->Data <<= aIntName;
     325           0 :             }
     326             :         }
     327             :     }
     328           0 :     return aTokens;
     329             : }
     330             : 
     331           0 : uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::createSequenceOfAvailableMappings(
     332             :         const FormulaCompiler& rCompiler, const sal_Int32 nGroups ) const
     333             : {
     334             :     using namespace sheet;
     335             : 
     336             :     // Unfortunately uno::Sequence can't grow without cumbersome reallocs. As
     337             :     // we don't know in advance how many elements it will have we use a
     338             :     // temporary vector to add elements and then copy to Sequence :-(
     339           0 :     ::std::vector< FormulaOpCodeMapEntry > aVec;
     340             : 
     341           0 :     if (nGroups == FormulaMapGroup::SPECIAL)
     342             :     {
     343             :         // Use specific order, keep in sync with
     344             :         // offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
     345             :         static const struct
     346             :         {
     347             :             sal_Int32 nOff;
     348             :             OpCode    eOp;
     349             :         } aMap[] = {
     350             :             { FormulaMapGroupSpecialOffset::PUSH              , ocPush }           ,
     351             :             { FormulaMapGroupSpecialOffset::CALL              , ocCall }           ,
     352             :             { FormulaMapGroupSpecialOffset::STOP              , ocStop }           ,
     353             :             { FormulaMapGroupSpecialOffset::EXTERNAL          , ocExternal }       ,
     354             :             { FormulaMapGroupSpecialOffset::NAME              , ocName }           ,
     355             :             { FormulaMapGroupSpecialOffset::NO_NAME           , ocNoName }         ,
     356             :             { FormulaMapGroupSpecialOffset::MISSING           , ocMissing }        ,
     357             :             { FormulaMapGroupSpecialOffset::BAD               , ocBad }            ,
     358             :             { FormulaMapGroupSpecialOffset::SPACES            , ocSpaces }         ,
     359             :             { FormulaMapGroupSpecialOffset::MAT_REF           , ocMatRef }         ,
     360             :             { FormulaMapGroupSpecialOffset::DB_AREA           , ocDBArea }         ,
     361             :             { FormulaMapGroupSpecialOffset::MACRO             , ocMacro }          ,
     362             :             { FormulaMapGroupSpecialOffset::COL_ROW_NAME      , ocColRowName }
     363             :         };
     364           0 :         const size_t nCount = sizeof(aMap)/sizeof(aMap[0]);
     365             :         // Preallocate vector elements.
     366           0 :         if (aVec.size() < nCount)
     367             :         {
     368           0 :             FormulaOpCodeMapEntry aEntry;
     369           0 :             aEntry.Token.OpCode = getOpCodeUnknown();
     370           0 :             aVec.resize( nCount, aEntry);
     371             :         } // if (aVec.size() < nCount)
     372             : 
     373           0 :         FormulaOpCodeMapEntry aEntry;
     374           0 :         for (size_t i=0; i < nCount; ++i)
     375             :         {
     376           0 :             size_t nIndex = static_cast< size_t >( aMap[i].nOff );
     377           0 :             if (aVec.size() <= nIndex)
     378             :             {
     379             :                 // The offsets really should be aligned with the size, so if
     380             :                 // the vector was preallocated above this code to resize it is
     381             :                 // just a measure in case the table isn't in sync with the API,
     382             :                 // usually it isn't executed.
     383           0 :                 aEntry.Token.OpCode = getOpCodeUnknown();
     384           0 :                 aVec.resize( nIndex + 1, aEntry );
     385             :             }
     386           0 :             aEntry.Token.OpCode = aMap[i].eOp;
     387           0 :             aVec[nIndex] = aEntry;
     388           0 :         }
     389             :     }
     390             :     else
     391             :     {
     392             :         /* FIXME: Once we support error constants in formulas we'll need a map
     393             :          * group for that, e.g. FormulaMapGroup::ERROR_CONSTANTS, and fill
     394             :          * SC_OPCODE_START_ERRORS to SC_OPCODE_STOP_ERRORS. */
     395             : 
     396             :         // Anything else but SPECIAL.
     397           0 :         if ((nGroups & FormulaMapGroup::SEPARATORS) != 0)
     398             :         {
     399             :             static const sal_uInt16 aOpCodes[] = {
     400             :                 SC_OPCODE_OPEN,
     401             :                 SC_OPCODE_CLOSE,
     402             :                 SC_OPCODE_SEP,
     403             :             };
     404           0 :             lclPushOpCodeMapEntries( aVec, mpTable, aOpCodes, sizeof(aOpCodes)/sizeof(aOpCodes[0]) );
     405             :         }
     406           0 :         if ((nGroups & FormulaMapGroup::ARRAY_SEPARATORS) != 0)
     407             :         {
     408             :             static const sal_uInt16 aOpCodes[] = {
     409             :                 SC_OPCODE_ARRAY_OPEN,
     410             :                 SC_OPCODE_ARRAY_CLOSE,
     411             :                 SC_OPCODE_ARRAY_ROW_SEP,
     412             :                 SC_OPCODE_ARRAY_COL_SEP
     413             :             };
     414           0 :             lclPushOpCodeMapEntries( aVec, mpTable, aOpCodes, sizeof(aOpCodes)/sizeof(aOpCodes[0]) );
     415             :         }
     416           0 :         if ((nGroups & FormulaMapGroup::UNARY_OPERATORS) != 0)
     417             :         {
     418             :             // Due to the nature of the percent operator following its operand
     419             :             // it isn't sorted into unary operators for compiler interna.
     420           0 :             lclPushOpCodeMapEntry( aVec, mpTable, ocPercentSign );
     421             :             // "+" can be used as unary operator too, push only if binary group is not set
     422           0 :             if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) == 0)
     423           0 :                 lclPushOpCodeMapEntry( aVec, mpTable, ocAdd );
     424             :             // regular unary operators
     425           0 :             for (sal_uInt16 nOp = SC_OPCODE_START_UN_OP; nOp < SC_OPCODE_STOP_UN_OP && nOp < mnSymbols; ++nOp)
     426             :             {
     427           0 :                 switch (nOp)
     428             :                 {
     429             :                     // NOT and NEG in fact are functions but for legacy reasons
     430             :                     // are sorted into unary operators for compiler interna.
     431             :                     case SC_OPCODE_NOT :
     432             :                     case SC_OPCODE_NEG :
     433           0 :                         break;   // nothing,
     434             :                     default:
     435           0 :                         lclPushOpCodeMapEntry( aVec, mpTable, nOp );
     436             :                 }
     437             :             }
     438             :         }
     439           0 :         if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) != 0)
     440             :         {
     441           0 :             for (sal_uInt16 nOp = SC_OPCODE_START_BIN_OP; nOp < SC_OPCODE_STOP_BIN_OP && nOp < mnSymbols; ++nOp)
     442             :             {
     443           0 :                 switch (nOp)
     444             :                 {
     445             :                     // AND and OR in fact are functions but for legacy reasons
     446             :                     // are sorted into binary operators for compiler interna.
     447             :                     case SC_OPCODE_AND :
     448             :                     case SC_OPCODE_OR :
     449           0 :                         break;   // nothing,
     450             :                     default:
     451           0 :                         lclPushOpCodeMapEntry( aVec, mpTable, nOp );
     452             :                 }
     453             :             }
     454             :         }
     455           0 :         if ((nGroups & FormulaMapGroup::FUNCTIONS) != 0)
     456             :         {
     457             :             // Function names are not consecutive, skip the gaps between
     458             :             // functions with no parameter, functions with 1 parameter
     459             :             lclPushOpCodeMapEntries( aVec, mpTable, SC_OPCODE_START_NO_PAR,
     460           0 :                     ::std::min< sal_uInt16 >( SC_OPCODE_STOP_NO_PAR, mnSymbols ) );
     461             :             lclPushOpCodeMapEntries( aVec, mpTable, SC_OPCODE_START_1_PAR,
     462           0 :                     ::std::min< sal_uInt16 >( SC_OPCODE_STOP_1_PAR, mnSymbols ) );
     463             :             // Additional functions not within range of functions.
     464             :             static const sal_uInt16 aOpCodes[] = {
     465             :                 SC_OPCODE_IF,
     466             :                 SC_OPCODE_IF_ERROR,
     467             :                 SC_OPCODE_IF_NA,
     468             :                 SC_OPCODE_CHOSE,
     469             :                 SC_OPCODE_AND,
     470             :                 SC_OPCODE_OR,
     471             :                 SC_OPCODE_NOT,
     472             :                 SC_OPCODE_NEG
     473             :             };
     474           0 :             lclPushOpCodeMapEntries( aVec, mpTable, aOpCodes, sizeof(aOpCodes)/sizeof(aOpCodes[0]) );
     475             :             // functions with 2 or more parameters.
     476           0 :             for (sal_uInt16 nOp = SC_OPCODE_START_2_PAR; nOp < SC_OPCODE_STOP_2_PAR && nOp < mnSymbols; ++nOp)
     477             :             {
     478           0 :                 switch (nOp)
     479             :                 {
     480             :                     // NO_NAME is in SPECIAL.
     481             :                     case SC_OPCODE_NO_NAME :
     482           0 :                         break;   // nothing,
     483             :                     default:
     484           0 :                         lclPushOpCodeMapEntry( aVec, mpTable, nOp );
     485             :                 }
     486             :             }
     487             :             // If AddIn functions are present in this mapping, use them, and only those.
     488           0 :             if (hasExternals())
     489             :             {
     490           0 :                 for (ExternalHashMap::const_iterator it( mpExternalHashMap->begin());it != mpExternalHashMap->end(); ++it)
     491             :                 {
     492           0 :                     FormulaOpCodeMapEntry aEntry;
     493           0 :                     aEntry.Name = (*it).first;
     494           0 :                     aEntry.Token.Data <<= OUString( (*it).second);
     495           0 :                     aEntry.Token.OpCode = ocExternal;
     496           0 :                     aVec.push_back( aEntry);
     497           0 :                 }
     498             :             }
     499             :             else
     500             :             {
     501           0 :                 rCompiler.fillAddInToken( aVec, isEnglish());
     502             :             }
     503             :         }
     504             :     }
     505           0 :     const FormulaOpCodeMapEntry* pRet = aVec.empty() ? 0 : &aVec[0];
     506           0 :     return uno::Sequence< FormulaOpCodeMapEntry >( pRet, aVec.size());
     507             : }
     508             : 
     509             : 
     510           0 : void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode eOp )
     511             : {
     512             :     DBG_ASSERT( 0 < eOp && sal_uInt16(eOp) < mnSymbols, "OpCodeMap::putOpCode: OpCode out of range");
     513           0 :     if (0 < eOp && sal_uInt16(eOp) < mnSymbols)
     514             :     {
     515             :         SAL_WARN_IF( !(mpTable[eOp].isEmpty() || (mpTable[eOp] == rStr) ||
     516             :                     (eOp == ocCurrency) || (eOp == ocSep) || (eOp == ocArrayColSep) ||
     517             :                     (eOp == ocArrayRowSep)), "formula.core",
     518             :                 "OpCodeMap::putOpCode: reusing OpCode " << eOp
     519             :                 << ", replacing '" << mpTable[eOp] << "' with '" << rStr << "' in "
     520             :                 << (mbEnglish ? "" : "non-") << "English map 0x" << ::std::hex << meGrammar);
     521           0 :         mpTable[eOp] = rStr;
     522           0 :         mpHashMap->insert( OpCodeHashMap::value_type( rStr, eOp));
     523             :     }
     524           0 : }
     525             : 
     526             : // class FormulaCompiler
     527             : 
     528           0 : FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr )
     529             :         :
     530             :         pArr( &rArr ),
     531             :         pCode( NULL ),
     532             :         pStack( NULL ),
     533             :         eLastOp( ocPush ),
     534             :         nRecursion( 0 ),
     535             :         nNumFmt( NUMBERFORMAT_UNDEFINED ),
     536             :         pc( 0 ),
     537             :         meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ),
     538             :         bAutoCorrect( false ),
     539             :         bCorrected( false ),
     540             :         bCompileForFAP( false ),
     541             :         bIgnoreErrors( false ),
     542           0 :         glSubTotal( false )
     543             : 
     544             : {
     545           0 : }
     546             : 
     547           0 : FormulaCompiler::FormulaCompiler()
     548             :         :
     549             :         pArr( NULL ),
     550             :         pStack( NULL ),
     551             :         nRecursion(0),
     552             :         nNumFmt( NUMBERFORMAT_UNDEFINED ),
     553             :         meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ),
     554             :         bAutoCorrect( false ),
     555             :         bCorrected( false ),
     556             :         bCompileForFAP( false ),
     557           0 :         bIgnoreErrors( false )
     558             : 
     559             : {
     560           0 : }
     561             : 
     562           0 : FormulaCompiler::~FormulaCompiler()
     563             : {
     564           0 : }
     565             : 
     566           0 : FormulaCompiler::OpCodeMapPtr FormulaCompiler::GetOpCodeMap( const sal_Int32 nLanguage ) const
     567             : {
     568           0 :     FormulaCompiler::OpCodeMapPtr xMap;
     569             :     using namespace sheet;
     570           0 :     switch (nLanguage)
     571             :     {
     572             :         case FormulaLanguage::ODFF :
     573           0 :             if (!mxSymbolsODFF)
     574           0 :                 InitSymbolsODFF();
     575           0 :             xMap = mxSymbolsODFF;
     576           0 :             break;
     577             :         case FormulaLanguage::ODF_11 :
     578           0 :             if (!mxSymbolsPODF)
     579           0 :                 InitSymbolsPODF();
     580           0 :             xMap = mxSymbolsPODF;
     581           0 :             break;
     582             :         case FormulaLanguage::ENGLISH :
     583           0 :             if (!mxSymbolsEnglish)
     584           0 :                 InitSymbolsEnglish();
     585           0 :             xMap = mxSymbolsEnglish;
     586           0 :             break;
     587             :         case FormulaLanguage::NATIVE :
     588           0 :             if (!mxSymbolsNative)
     589           0 :                 InitSymbolsNative();
     590           0 :             xMap = mxSymbolsNative;
     591           0 :             break;
     592             :         case FormulaLanguage::XL_ENGLISH:
     593           0 :             if (!mxSymbolsEnglishXL)
     594           0 :                 InitSymbolsEnglishXL();
     595           0 :             xMap = mxSymbolsEnglishXL;
     596           0 :             break;
     597             :         case FormulaLanguage::OOXML:
     598           0 :             if (!mxSymbolsOOXML)
     599           0 :                 InitSymbolsOOXML();
     600           0 :             xMap = mxSymbolsOOXML;
     601           0 :             break;
     602             :         default:
     603             :             ;   // nothing, NULL map returned
     604             :     }
     605           0 :     return xMap;
     606             : }
     607             : 
     608           0 : OUString FormulaCompiler::FindAddInFunction( const OUString& /*rUpperName*/, bool /*bLocalFirst*/ ) const
     609             : {
     610           0 :     return OUString();
     611             : }
     612             : 
     613           0 : FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap(
     614             :         const uno::Sequence<
     615             :         const sheet::FormulaOpCodeMapEntry > & rMapping,
     616             :         bool bEnglish )
     617             : {
     618             :     using sheet::FormulaOpCodeMapEntry;
     619             :     // Filter / API maps are never Core
     620             :     NonConstOpCodeMapPtr xMap( new OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, false,
     621             :                 FormulaGrammar::mergeToGrammar( FormulaGrammar::setEnglishBit(
     622           0 :                         FormulaGrammar::GRAM_EXTERNAL, bEnglish), FormulaGrammar::CONV_UNSPECIFIED)));
     623           0 :     FormulaOpCodeMapEntry const * pArr2 = rMapping.getConstArray();
     624           0 :     FormulaOpCodeMapEntry const * const pStop = pArr2 + rMapping.getLength();
     625           0 :     for ( ; pArr2 < pStop; ++pArr2)
     626             :     {
     627           0 :         OpCode eOp = OpCode(pArr2->Token.OpCode);
     628           0 :         if (eOp != ocExternal)
     629           0 :             xMap->putOpCode( pArr2->Name, eOp);
     630             :         else
     631             :         {
     632           0 :             OUString aExternalName;
     633           0 :             if (pArr2->Token.Data >>= aExternalName)
     634           0 :                 xMap->putExternal( pArr2->Name, aExternalName);
     635             :             else
     636             :             {
     637             :                 SAL_WARN( "formula.core", "FormulaCompiler::CreateOpCodeMap: no Token.Data external name");
     638           0 :             }
     639             :         }
     640             :     }
     641           0 :     return xMap;
     642             : }
     643             : 
     644           0 : void lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, bool bDestroy = false )
     645             : {
     646           0 :     static OpCodeMapData aSymbolMap;
     647           0 :     osl::MutexGuard aGuard(&aSymbolMap.maMtx);
     648             : 
     649           0 :     if ( bDestroy )
     650             :     {
     651           0 :         aSymbolMap.mxSymbolMap.reset();
     652             :     }
     653           0 :     else if (!aSymbolMap.mxSymbolMap)
     654             :     {
     655             :         // Core
     656             :         aSymbolMap.mxSymbolMap.reset(
     657             :             new FormulaCompiler::OpCodeMap(
     658           0 :                 SC_OPCODE_LAST_OPCODE_ID + 1, true, FormulaGrammar::GRAM_NATIVE_UI));
     659           0 :         OModuleClient aModuleClient;
     660           0 :         OpCodeList aOpCodeListNative(RID_STRLIST_FUNCTION_NAMES, aSymbolMap.mxSymbolMap);
     661             :         // No AddInMap for native core mapping.
     662             :     }
     663             : 
     664           0 :     xMap = aSymbolMap.mxSymbolMap;
     665           0 : }
     666             : 
     667           0 : const OUString& FormulaCompiler::GetNativeSymbol( OpCode eOp )
     668             : {
     669           0 :     NonConstOpCodeMapPtr xSymbolsNative;
     670           0 :     lcl_fillNativeSymbols( xSymbolsNative);
     671           0 :     return xSymbolsNative->getSymbol( eOp );
     672             : }
     673             : 
     674           0 : sal_Unicode FormulaCompiler::GetNativeSymbolChar( OpCode eOp )
     675             : {
     676           0 :     return GetNativeSymbol(eOp)[0];
     677             : }
     678             : 
     679           0 : void FormulaCompiler::InitSymbolsNative() const
     680             : {
     681           0 :     lcl_fillNativeSymbols( mxSymbolsNative);
     682           0 : }
     683             : 
     684           0 : void FormulaCompiler::InitSymbolsEnglish() const
     685             : {
     686           0 :     static OpCodeMapData aMap;
     687           0 :     osl::MutexGuard aGuard(&aMap.maMtx);
     688           0 :     if (!aMap.mxSymbolMap)
     689           0 :         loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, aMap.mxSymbolMap);
     690           0 :     mxSymbolsEnglish = aMap.mxSymbolMap;
     691           0 : }
     692             : 
     693           0 : void FormulaCompiler::InitSymbolsPODF() const
     694             : {
     695           0 :     static OpCodeMapData aMap;
     696           0 :     osl::MutexGuard aGuard(&aMap.maMtx);
     697           0 :     if (!aMap.mxSymbolMap)
     698           0 :         loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_PODF, aMap.mxSymbolMap, RESOURCE_BASE);
     699           0 :     mxSymbolsPODF = aMap.mxSymbolMap;
     700           0 : }
     701             : 
     702           0 : void FormulaCompiler::InitSymbolsODFF() const
     703             : {
     704           0 :     static OpCodeMapData aMap;
     705           0 :     osl::MutexGuard aGuard(&aMap.maMtx);
     706           0 :     if (!aMap.mxSymbolMap)
     707           0 :         loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF, FormulaGrammar::GRAM_ODFF, aMap.mxSymbolMap, RESOURCE_BASE);
     708           0 :     mxSymbolsODFF = aMap.mxSymbolMap;
     709           0 : }
     710             : 
     711           0 : void FormulaCompiler::InitSymbolsEnglishXL() const
     712             : {
     713           0 :     static OpCodeMapData aMap;
     714           0 :     osl::MutexGuard aGuard(&aMap.maMtx);
     715           0 :     if (!aMap.mxSymbolMap)
     716           0 :         loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, aMap.mxSymbolMap);
     717           0 :     mxSymbolsEnglishXL = aMap.mxSymbolMap;
     718             : 
     719             :     // TODO: For now, just replace the separators to the Excel English
     720             :     // variants. Later, if we want to properly map Excel functions with Calc
     721             :     // functions, we'll need to do a little more work here.
     722           0 :     mxSymbolsEnglishXL->putOpCode( OUString(','), ocSep);
     723           0 :     mxSymbolsEnglishXL->putOpCode( OUString(','), ocArrayColSep);
     724           0 :     mxSymbolsEnglishXL->putOpCode( OUString(';'), ocArrayRowSep);
     725           0 : }
     726             : 
     727           0 : void FormulaCompiler::InitSymbolsOOXML() const
     728             : {
     729           0 :     static OpCodeMapData aMap;
     730           0 :     osl::MutexGuard aGuard(&aMap.maMtx);
     731           0 :     if (!aMap.mxSymbolMap)
     732           0 :         loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML, FormulaGrammar::GRAM_OOXML, aMap.mxSymbolMap, RESOURCE_BASE);
     733           0 :     mxSymbolsOOXML = aMap.mxSymbolMap;
     734           0 : }
     735             : 
     736             : 
     737           0 : void FormulaCompiler::loadSymbols( sal_uInt16 nSymbols, FormulaGrammar::Grammar eGrammar,
     738             :         NonConstOpCodeMapPtr& rxMap, SeparatorType eSepType) const
     739             : {
     740           0 :     if ( !rxMap.get() )
     741             :     {
     742             :         // not Core
     743           0 :         rxMap.reset( new OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, eGrammar != FormulaGrammar::GRAM_ODFF, eGrammar ));
     744           0 :         OModuleClient aModuleClient;
     745           0 :         OpCodeList aOpCodeList( nSymbols, rxMap, eSepType);
     746             : 
     747           0 :         fillFromAddInMap( rxMap, eGrammar);
     748             :         // Fill from collection for AddIns not already present.
     749           0 :         if ( FormulaGrammar::GRAM_ENGLISH != eGrammar )
     750           0 :             fillFromAddInCollectionUpperName( rxMap);
     751             :         else
     752           0 :             fillFromAddInCollectionEnglishName( rxMap);
     753             :     }
     754           0 : }
     755             : 
     756           0 : void FormulaCompiler::fillFromAddInCollectionUpperName( NonConstOpCodeMapPtr /*xMap */) const
     757             : {
     758           0 : }
     759             : 
     760           0 : void FormulaCompiler::fillFromAddInCollectionEnglishName( NonConstOpCodeMapPtr /*xMap */) const
     761             : {
     762           0 : }
     763             : 
     764           0 : void FormulaCompiler::fillFromAddInMap( NonConstOpCodeMapPtr /*xMap*/, FormulaGrammar::Grammar /*_eGrammar */) const
     765             : {
     766           0 : }
     767             : 
     768           0 : OpCode FormulaCompiler::GetEnglishOpCode( const OUString& rName ) const
     769             : {
     770           0 :     FormulaCompiler::OpCodeMapPtr xMap = GetOpCodeMap( sheet::FormulaLanguage::ENGLISH);
     771             : 
     772           0 :     formula::OpCodeHashMap::const_iterator iLook( xMap->getHashMap()->find( rName ) );
     773           0 :     bool bFound = (iLook != xMap->getHashMap()->end());
     774           0 :     return bFound ? (*iLook).second : OpCode(ocNone);
     775             : }
     776             : 
     777           0 : bool FormulaCompiler::IsOpCodeVolatile( OpCode eOp )
     778             : {
     779           0 :     bool bRet = false;
     780           0 :     switch (eOp)
     781             :     {
     782             :         // no parameters:
     783             :         case ocRandom:
     784             :         case ocGetActDate:
     785             :         case ocGetActTime:
     786             :         // one parameter:
     787             :         case ocFormula:
     788             :         case ocInfo:
     789             :         // more than one parameters:
     790             :             // ocIndirect/ocIndirectXL otherwise would have to do
     791             :             // StopListening and StartListening on a reference for every
     792             :             // interpreted value.
     793             :         case ocIndirect:
     794             :         case ocIndirectXL:
     795             :             // ocOffset results in indirect references.
     796             :         case ocOffset:
     797             :             // ocDebugVar shows internal value that may change as the internal state changes.
     798             :         case ocDebugVar:
     799           0 :             bRet = true;
     800           0 :             break;
     801             :         default:
     802           0 :             bRet = false;
     803           0 :             break;
     804             :     }
     805           0 :     return bRet;
     806             : }
     807             : 
     808             : // Remove quotes, escaped quotes are unescaped.
     809           0 : bool FormulaCompiler::DeQuote( OUString& rStr )
     810             : {
     811           0 :     sal_Int32 nLen = rStr.getLength();
     812           0 :     if ( nLen > 1 && rStr[0] == '\'' && rStr[ nLen-1 ] == '\'' )
     813             :     {
     814           0 :         rStr = rStr.copy( 1, nLen-2 );
     815           0 :         rStr = rStr.replaceAll( "\\\'", "\'" );
     816           0 :         return true;
     817             :     }
     818           0 :     return false;
     819             : }
     820             : 
     821           0 : void FormulaCompiler::fillAddInToken(
     822             :         ::std::vector< sheet::FormulaOpCodeMapEntry >& /*_rVec*/,
     823             :         bool /*_bIsEnglish*/) const
     824             : {
     825           0 : }
     826             : 
     827           0 : bool FormulaCompiler::IsMatrixFunction( OpCode eOpCode )
     828             : {
     829           0 :     switch (eOpCode)
     830             :     {
     831             :         case ocDde :
     832             :         case ocGrowth :
     833             :         case ocTrend :
     834             :         case ocRKP :
     835             :         case ocRGP :
     836             :         case ocFrequency :
     837             :         case ocMatTrans :
     838             :         case ocMatMult :
     839             :         case ocMatInv :
     840             :         case ocMatrixUnit :
     841             :         case ocModalValue_Multi :
     842           0 :             return true;
     843             :         default:
     844             :         {
     845             :             // added to avoid warnings
     846             :         }
     847             :     }
     848           0 :     return false;
     849             : }
     850             : 
     851             : 
     852           0 : FormulaCompiler::OpCodeMap::~OpCodeMap()
     853             : {
     854           0 :     delete mpReverseExternalHashMap;
     855           0 :     delete mpExternalHashMap;
     856           0 :     delete [] mpTable;
     857           0 :     delete mpHashMap;
     858           0 : }
     859             : 
     860           0 : void FormulaCompiler::OpCodeMap::putCopyOpCode( const OUString& rSymbol, OpCode eOp )
     861             : {
     862             :     SAL_WARN_IF( !mpTable[eOp].isEmpty() && rSymbol.isEmpty(), "formula.core",
     863             :             "OpCodeMap::putCopyOpCode: NOT replacing OpCode " << eOp << " '" << mpTable[eOp] << "' with empty name!");
     864           0 :     if (!mpTable[eOp].isEmpty() && rSymbol.isEmpty())
     865           0 :         mpHashMap->insert( OpCodeHashMap::value_type( mpTable[eOp], eOp));
     866             :     else
     867             :     {
     868           0 :         mpTable[eOp] = rSymbol;
     869           0 :         mpHashMap->insert( OpCodeHashMap::value_type( rSymbol, eOp));
     870             :     }
     871           0 : }
     872             : 
     873           0 : void FormulaCompiler::OpCodeMap::copyFrom( const OpCodeMap& r, bool bOverrideKnownBad )
     874             : {
     875           0 :     delete mpHashMap;
     876           0 :     mpHashMap = new OpCodeHashMap( mnSymbols);
     877             : 
     878           0 :     sal_uInt16 n = r.getSymbolCount();
     879             :     SAL_WARN_IF( n != mnSymbols, "formula.core",
     880             :             "OpCodeMap::copyFrom: unequal size, this: " << mnSymbols << "  that: " << n);
     881           0 :     if (n > mnSymbols)
     882           0 :         n = mnSymbols;
     883             : 
     884             :     // OpCode 0 (ocPush) should never be in a map.
     885             :     SAL_WARN_IF( !mpTable[0].isEmpty() || !r.mpTable[0].isEmpty(), "formula.core",
     886             :             "OpCodeMap::copyFrom: OpCode 0 assigned, this: '"
     887             :             << mpTable[0] << "'  that: '" << r.mpTable[0] << "'");
     888             : 
     889             :     // For bOverrideKnownBad when copying from the English core map (ODF 1.1
     890             :     // and API) to the native map (UI "use English function names") replace the
     891             :     // known bad legacy function names with correct ones.
     892           0 :     if (bOverrideKnownBad && r.mbCore &&
     893           0 :             FormulaGrammar::extractFormulaLanguage( meGrammar) == sheet::FormulaLanguage::NATIVE &&
     894           0 :             FormulaGrammar::extractFormulaLanguage( r.meGrammar) == sheet::FormulaLanguage::ENGLISH)
     895             :     {
     896           0 :         for (sal_uInt16 i = 1; i < n; ++i)
     897             :         {
     898           0 :             OUString aSymbol;
     899           0 :             OpCode eOp = OpCode(i);
     900           0 :             switch (eOp)
     901             :             {
     902             :                 case ocZGZ:
     903           0 :                     aSymbol = "RRI";
     904           0 :                     break;
     905             :                 case ocTableOp:
     906           0 :                     aSymbol = "MULTIPLE.OPERATIONS";
     907           0 :                     break;
     908             :                 default:
     909           0 :                     aSymbol = r.mpTable[i];
     910             :             }
     911           0 :             putCopyOpCode( aSymbol, eOp);
     912           0 :         }
     913             :     }
     914             :     else
     915             :     {
     916           0 :         for (sal_uInt16 i = 1; i < n; ++i)
     917             :         {
     918           0 :             OpCode eOp = OpCode(i);
     919           0 :             const OUString& rSymbol = r.mpTable[i];
     920           0 :             putCopyOpCode( rSymbol, eOp);
     921             :         }
     922             :     }
     923             : 
     924             :     // TODO: maybe copy the external maps too?
     925           0 : }
     926             : 
     927             : 
     928           0 : sal_uInt16 FormulaCompiler::GetErrorConstant( const OUString& rName ) const
     929             : {
     930           0 :     sal_uInt16 nError = 0;
     931           0 :     OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName));
     932           0 :     if (iLook != mxSymbols->getHashMap()->end())
     933             :     {
     934           0 :         switch ((*iLook).second)
     935             :         {
     936             :             // Not all may make sense in a formula, but these we know as
     937             :             // opcodes.
     938             :             case ocErrNull:
     939           0 :                 nError = errNoCode;
     940           0 :                 break;
     941             :             case ocErrDivZero:
     942           0 :                 nError = errDivisionByZero;
     943           0 :                 break;
     944             :             case ocErrValue:
     945           0 :                 nError = errNoValue;
     946           0 :                 break;
     947             :             case ocErrRef:
     948           0 :                 nError = errNoRef;
     949           0 :                 break;
     950             :             case ocErrName:
     951           0 :                 nError = errNoName;
     952           0 :                 break;
     953             :             case ocErrNum:
     954           0 :                 nError = errIllegalFPOperation;
     955           0 :                 break;
     956             :             case ocErrNA:
     957           0 :                 nError = NOTAVAILABLE;
     958           0 :                 break;
     959             :             default:
     960             :                 ;   // nothing
     961             :         }
     962             :     }
     963           0 :     return nError;
     964             : }
     965             : 
     966             : 
     967           0 : void FormulaCompiler::AppendErrorConstant( OUStringBuffer& rBuffer, sal_uInt16 nError ) const
     968             : {
     969             :     OpCode eOp;
     970           0 :     switch (nError)
     971             :     {
     972             :         default:
     973             :         case errNoCode:
     974           0 :             eOp = ocErrNull;
     975           0 :             break;
     976             :         case errDivisionByZero:
     977           0 :             eOp = ocErrDivZero;
     978           0 :             break;
     979             :         case errNoValue:
     980           0 :             eOp = ocErrValue;
     981           0 :             break;
     982             :         case errNoRef:
     983           0 :             eOp = ocErrRef;
     984           0 :             break;
     985             :         case errNoName:
     986           0 :             eOp = ocErrName;
     987           0 :             break;
     988             :         case errIllegalFPOperation:
     989           0 :             eOp = ocErrNum;
     990           0 :             break;
     991             :         case NOTAVAILABLE:
     992           0 :             eOp = ocErrNA;
     993           0 :             break;
     994             :     }
     995           0 :     rBuffer.append( mxSymbols->getSymbol( eOp));
     996           0 : }
     997             : 
     998             : 
     999           0 : sal_Int32 FormulaCompiler::OpCodeMap::getOpCodeUnknown()
    1000             : {
    1001             :     static const sal_Int32 kOpCodeUnknown = -1;
    1002           0 :     return kOpCodeUnknown;
    1003             : }
    1004             : 
    1005           0 : bool FormulaCompiler::GetToken()
    1006             : {
    1007             :     static const short nRecursionMax = 42;
    1008           0 :     FormulaCompilerRecursionGuard aRecursionGuard( nRecursion );
    1009           0 :     if ( nRecursion > nRecursionMax )
    1010             :     {
    1011           0 :         SetError( errStackOverflow );
    1012           0 :         mpToken = new FormulaByteToken( ocStop );
    1013           0 :         return false;
    1014             :     }
    1015           0 :     if ( bAutoCorrect && !pStack )
    1016             :     {   // don't merge stacked subroutine code into entered formula
    1017           0 :         aCorrectedFormula += aCorrectedSymbol;
    1018           0 :         aCorrectedSymbol = "";
    1019             :     }
    1020           0 :     bool bStop = false;
    1021           0 :     if( pArr->GetCodeError() && !bIgnoreErrors )
    1022           0 :         bStop = true;
    1023             :     else
    1024             :     {
    1025             :         short nWasColRowName;
    1026           0 :         if ( pArr->nIndex
    1027           0 :           && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
    1028           0 :              nWasColRowName = 1;
    1029             :         else
    1030           0 :              nWasColRowName = 0;
    1031           0 :         mpToken = pArr->Next();
    1032           0 :         while( mpToken && mpToken->GetOpCode() == ocSpaces )
    1033             :         {
    1034           0 :             if ( nWasColRowName )
    1035           0 :                 nWasColRowName++;
    1036           0 :             if ( bAutoCorrect && !pStack )
    1037           0 :                 CreateStringFromToken( aCorrectedFormula, mpToken.get(), false );
    1038           0 :             mpToken = pArr->Next();
    1039             :         }
    1040           0 :         if ( bAutoCorrect && !pStack && mpToken )
    1041           0 :             CreateStringFromToken( aCorrectedSymbol, mpToken.get(), false );
    1042           0 :         if( !mpToken )
    1043             :         {
    1044           0 :             if( pStack )
    1045             :             {
    1046           0 :                 PopTokenArray();
    1047           0 :                 return GetToken();
    1048             :             }
    1049             :             else
    1050           0 :                 bStop = true;
    1051             :         }
    1052             :         else
    1053             :         {
    1054           0 :             if ( nWasColRowName >= 2 && mpToken->GetOpCode() == ocColRowName )
    1055             :             {   // convert an ocSpaces to ocIntersect in RPN
    1056           0 :                 mpToken = new FormulaByteToken( ocIntersect );
    1057           0 :                 pArr->nIndex--;     // we advanced to the second ocColRowName, step back
    1058             :             }
    1059             :         }
    1060             :     }
    1061           0 :     if( bStop )
    1062             :     {
    1063           0 :         mpToken = new FormulaByteToken( ocStop );
    1064           0 :         return false;
    1065             :     }
    1066           0 :     if( mpToken->GetOpCode() == ocSubTotal )
    1067           0 :         glSubTotal = true;
    1068           0 :     else if ( mpToken->IsExternalRef() )
    1069             :     {
    1070           0 :         return HandleExternalReference(*mpToken);
    1071             :     }
    1072           0 :     else if( mpToken->GetOpCode() == ocName )
    1073             :     {
    1074           0 :         return HandleRange();
    1075             :     }
    1076           0 :     else if( mpToken->GetOpCode() == ocColRowName )
    1077             :     {
    1078           0 :         return HandleSingleRef();
    1079             :     }
    1080           0 :     else if( mpToken->GetOpCode() == ocDBArea )
    1081             :     {
    1082           0 :         return HandleDbData();
    1083             :     }
    1084           0 :     else if( mpToken->GetType() == svSingleRef )
    1085             :     {
    1086           0 :         pArr->nRefs++;
    1087             :     }
    1088           0 :     else if( mpToken->GetType() == svDoubleRef )
    1089             :     {
    1090           0 :         pArr->nRefs++;
    1091             :     }
    1092           0 :     return true;
    1093             : }
    1094             : 
    1095             : 
    1096             : // RPN creation by recursion
    1097           0 : void FormulaCompiler::Factor()
    1098             : {
    1099           0 :     if ( pArr->GetCodeError() && !bIgnoreErrors )
    1100           0 :         return;
    1101             : 
    1102           0 :     CurrentFactor pFacToken( this );
    1103             : 
    1104           0 :     OpCode eOp = mpToken->GetOpCode();
    1105           0 :     if( eOp == ocPush || eOp == ocColRowNameAuto || eOp == ocMatRef ||
    1106             :             eOp == ocDBArea
    1107           0 :             || (bCompileForFAP && ((eOp == ocName) || (eOp == ocDBArea)
    1108           0 :             || (eOp == ocColRowName) || (eOp == ocBad)))
    1109             :         )
    1110             :     {
    1111           0 :         PutCode( mpToken );
    1112           0 :         eOp = NextToken();
    1113           0 :         if( eOp == ocOpen )
    1114             :         {
    1115             :             // PUSH( is an error that may be caused by an unknown function.
    1116             :             SetError(
    1117           0 :                 ( mpToken->GetType() == svString
    1118           0 :                || mpToken->GetType() == svSingleRef )
    1119           0 :                ? errNoName : errOperatorExpected );
    1120           0 :             if ( bAutoCorrect && !pStack )
    1121             :             {   // assume multiplication
    1122           0 :                 aCorrectedFormula += mxSymbols->getSymbol( ocMul);
    1123           0 :                 bCorrected = true;
    1124           0 :                 NextToken();
    1125           0 :                 eOp = Expression();
    1126           0 :                 if( eOp != ocClose )
    1127           0 :                     SetError( errPairExpected);
    1128             :                 else
    1129           0 :                     eOp = NextToken();
    1130             :             }
    1131             :         }
    1132             :     }
    1133           0 :     else if( eOp == ocOpen )
    1134             :     {
    1135           0 :         NextToken();
    1136           0 :         eOp = Expression();
    1137           0 :         while ((eOp == ocSep) && (!pArr->GetCodeError() || bIgnoreErrors))
    1138             :         {   // range list  (A1;A2)  converted to  (A1~A2)
    1139           0 :             pFacToken = mpToken;
    1140           0 :             NextToken();
    1141           0 :             eOp = Expression();
    1142             :             // Do not ignore error here, regardless of bIgnoreErrors, otherwise
    1143             :             // errors like =(1;) would also result in display of =(1~)
    1144           0 :             if (!pArr->GetCodeError())
    1145             :             {
    1146           0 :                 pFacToken->NewOpCode( ocUnion, FormulaToken::PrivateAccess());
    1147           0 :                 PutCode( pFacToken);
    1148             :             }
    1149             :         }
    1150           0 :         if (eOp != ocClose)
    1151           0 :             SetError( errPairExpected);
    1152             :         else
    1153           0 :             eOp = NextToken();
    1154             :     }
    1155             :     else
    1156             :     {
    1157           0 :         if( nNumFmt == NUMBERFORMAT_UNDEFINED )
    1158           0 :             nNumFmt = lcl_GetRetFormat( eOp );
    1159             : 
    1160           0 :         if ( IsOpCodeVolatile( eOp) )
    1161           0 :             pArr->SetExclusiveRecalcModeAlways();
    1162             :         else
    1163             :         {
    1164           0 :             switch( eOp )
    1165             :             {
    1166             :                     // Functions recalculated on every document load.
    1167             :                     // Don't use SetExclusiveRecalcModeOnLoad() which would
    1168             :                     // override ModeAlways, use
    1169             :                     // AddRecalcMode(RECALCMODE_ONLOAD) instead.
    1170             :                 case ocConvert :
    1171             :                 case ocDde:
    1172             :                 case ocMacro:
    1173             :                 case ocExternal:
    1174           0 :                     pArr->AddRecalcMode( RECALCMODE_ONLOAD );
    1175           0 :                 break;
    1176             :                     // If the referred cell is moved the value changes.
    1177             :                 case ocColumn :
    1178             :                 case ocRow :
    1179           0 :                     pArr->SetRecalcModeOnRefMove();
    1180           0 :                 break;
    1181             :                     // ocCell needs recalc on move for some possible type values.
    1182             :                     // and recalc mode on load, fdo#60646
    1183             :                 case ocCell :
    1184           0 :                     pArr->SetRecalcModeOnRefMove();
    1185           0 :                     pArr->AddRecalcMode( RECALCMODE_ONLOAD );
    1186           0 :                 break;
    1187             :                 case ocHyperLink :
    1188             :                     // cell with hyperlink needs to be calculated on load to
    1189             :                     // get its matrix result generated.
    1190           0 :                     pArr->AddRecalcMode( RECALCMODE_ONLOAD );
    1191           0 :                     pArr->SetHyperLink( true);
    1192           0 :                 break;
    1193             :                 default:
    1194             :                     ;   // nothing
    1195             :             }
    1196             :         }
    1197           0 :         if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
    1198             :         {
    1199           0 :             pFacToken = mpToken;
    1200           0 :             eOp = NextToken();
    1201           0 :             if (eOp != ocOpen)
    1202             :             {
    1203           0 :                 SetError( errPairExpected);
    1204           0 :                 PutCode( pFacToken );
    1205             :             }
    1206             :             else
    1207             :             {
    1208           0 :                 eOp = NextToken();
    1209           0 :                 if (eOp != ocClose)
    1210           0 :                     SetError( errPairExpected);
    1211           0 :                 PutCode( pFacToken);
    1212           0 :                 eOp = NextToken();
    1213             :             }
    1214             :         }
    1215             :         // special cases NOT() and NEG()
    1216           0 :         else if( eOp == ocNot || eOp == ocNeg
    1217           0 :               || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) )
    1218             :         {
    1219           0 :             pFacToken = mpToken;
    1220           0 :             eOp = NextToken();
    1221           0 :             if( nNumFmt == NUMBERFORMAT_UNDEFINED && eOp == ocNot )
    1222           0 :                 nNumFmt = NUMBERFORMAT_LOGICAL;
    1223           0 :             if (eOp == ocOpen)
    1224             :             {
    1225           0 :                 NextToken();
    1226           0 :                 eOp = Expression();
    1227             :             }
    1228             :             else
    1229           0 :                 SetError( errPairExpected);
    1230           0 :             if (eOp != ocClose)
    1231           0 :                 SetError( errPairExpected);
    1232           0 :             else if ( !pArr->GetCodeError() )
    1233           0 :                 pFacToken->SetByte( 1 );
    1234           0 :             PutCode( pFacToken );
    1235           0 :             eOp = NextToken();
    1236             :         }
    1237           0 :         else if ((SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)
    1238           0 :                 || eOp == ocExternal
    1239           0 :                 || eOp == ocMacro
    1240           0 :                 || eOp == ocAnd
    1241           0 :                 || eOp == ocOr
    1242           0 :                 || eOp == ocBad
    1243           0 :                 || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
    1244           0 :                 || ( bCompileForFAP
    1245           0 :                      && ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose ) )
    1246             :             )
    1247             :         {
    1248           0 :             pFacToken = mpToken;
    1249           0 :             OpCode eMyLastOp = eOp;
    1250           0 :             eOp = NextToken();
    1251           0 :             bool bNoParam = false;
    1252           0 :             bool bBadName = false;
    1253           0 :             if (eOp == ocOpen)
    1254             :             {
    1255           0 :                 eOp = NextToken();
    1256           0 :                 if (eOp == ocClose)
    1257           0 :                     bNoParam = true;
    1258             :                 else
    1259           0 :                     eOp = Expression();
    1260             :             }
    1261           0 :             else if (eMyLastOp == ocBad)
    1262             :             {
    1263             :                 // Just a bad name, not an unknown function, no parameters, no
    1264             :                 // closing expected.
    1265           0 :                 bBadName = true;
    1266           0 :                 bNoParam = true;
    1267             :             }
    1268             :             else
    1269           0 :                 SetError( errPairExpected);
    1270           0 :             sal_uInt8 nSepCount = 0;
    1271           0 :             if( !bNoParam )
    1272             :             {
    1273           0 :                 nSepCount++;
    1274           0 :                 while ( (eOp == ocSep) && (!pArr->GetCodeError() || bIgnoreErrors) )
    1275             :                 {
    1276           0 :                     nSepCount++;
    1277           0 :                     NextToken();
    1278           0 :                     eOp = Expression();
    1279             :                 }
    1280             :             }
    1281           0 :             if (bBadName)
    1282             :                 ;   // nothing, keep current token for return
    1283           0 :             else if (eOp != ocClose)
    1284           0 :                 SetError( errPairExpected);
    1285             :             else
    1286           0 :                 eOp = NextToken();
    1287             :             // Jumps are just normal functions for the FunctionAutoPilot tree view
    1288           0 :             if ( bCompileForFAP && pFacToken->GetType() == svJump )
    1289           0 :                 pFacToken = new FormulaFAPToken( pFacToken->GetOpCode(), nSepCount, pFacToken );
    1290             :             else
    1291           0 :                 pFacToken->SetByte( nSepCount );
    1292           0 :             PutCode( pFacToken );
    1293             :         }
    1294           0 :         else if (eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose)
    1295             :         {
    1296             :             // the PC counters are -1
    1297           0 :             pFacToken = mpToken;
    1298           0 :             switch (eOp)
    1299             :             {
    1300             :                 case ocIf:
    1301           0 :                     pFacToken->GetJump()[ 0 ] = 3;  // if, else, behind
    1302           0 :                     break;
    1303             :                 case ocChose:
    1304           0 :                     pFacToken->GetJump()[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
    1305           0 :                     break;
    1306             :                 case ocIfError:
    1307             :                 case ocIfNA:
    1308           0 :                     pFacToken->GetJump()[ 0 ] = 2;  // if, behind
    1309           0 :                     break;
    1310             :                 default:
    1311             :                     SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump count case?");
    1312             :             }
    1313           0 :             eOp = NextToken();
    1314           0 :             if (eOp == ocOpen)
    1315             :             {
    1316           0 :                 NextToken();
    1317           0 :                 eOp = Expression();
    1318             :             }
    1319             :             else
    1320           0 :                 SetError( errPairExpected);
    1321           0 :             PutCode( pFacToken );
    1322             :             // During AutoCorrect (since pArr->GetCodeError() is
    1323             :             // ignored) an unlimited ocIf would crash because
    1324             :             // ScRawToken::Clone() allocates the JumpBuffer according to
    1325             :             // nJump[0]*2+2, which is 3*2+2 on ocIf and 2*2+2 ocIfError and ocIfNA.
    1326             :             short nJumpMax;
    1327           0 :             OpCode eFacOpCode = pFacToken->GetOpCode();
    1328           0 :             switch (eFacOpCode)
    1329             :             {
    1330             :                 case ocIf:
    1331           0 :                     nJumpMax = 3;
    1332           0 :                     break;
    1333             :                 case ocChose:
    1334           0 :                     nJumpMax = FORMULA_MAXJUMPCOUNT;
    1335           0 :                     break;
    1336             :                 case ocIfError:
    1337             :                 case ocIfNA:
    1338           0 :                     nJumpMax = 2;
    1339           0 :                     break;
    1340             :                 default:
    1341           0 :                     nJumpMax = 0;
    1342             :                     SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump max case?");
    1343             :             }
    1344           0 :             short nJumpCount = 0;
    1345           0 :             while ( (nJumpCount < (FORMULA_MAXJUMPCOUNT - 1)) && (eOp == ocSep)
    1346           0 :                     && (!pArr->GetCodeError() || bIgnoreErrors) )
    1347             :             {
    1348           0 :                 if ( ++nJumpCount <= nJumpMax )
    1349           0 :                     pFacToken->GetJump()[nJumpCount] = pc-1;
    1350           0 :                 NextToken();
    1351           0 :                 eOp = Expression();
    1352             :                 // ocSep or ocClose terminate the subexpression
    1353           0 :                 PutCode( mpToken );
    1354             :             }
    1355           0 :             if (eOp != ocClose)
    1356           0 :                 SetError( errPairExpected);
    1357             :             else
    1358             :             {
    1359           0 :                 eOp = NextToken();
    1360             :                 // always limit to nJumpMax, no arbitrary overwrites
    1361           0 :                 if ( ++nJumpCount <= nJumpMax )
    1362           0 :                     pFacToken->GetJump()[ nJumpCount ] = pc-1;
    1363           0 :                 eFacOpCode = pFacToken->GetOpCode();
    1364             :                 bool bLimitOk;
    1365           0 :                 switch (eFacOpCode)
    1366             :                 {
    1367             :                     case ocIf:
    1368           0 :                         bLimitOk = (nJumpCount <= 3);
    1369           0 :                         break;
    1370             :                     case ocChose:
    1371           0 :                         bLimitOk = (nJumpCount < FORMULA_MAXJUMPCOUNT); /* TODO: check, really <, not <=? */
    1372           0 :                         break;
    1373             :                     case ocIfError:
    1374             :                     case ocIfNA:
    1375           0 :                         bLimitOk = (nJumpCount <= 2);
    1376           0 :                         break;
    1377             :                     default:
    1378           0 :                         bLimitOk = false;
    1379             :                         SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump limit case?");
    1380             :                 }
    1381           0 :                 if (bLimitOk)
    1382           0 :                     pFacToken->GetJump()[ 0 ] = nJumpCount;
    1383             :                 else
    1384           0 :                     SetError( errIllegalParameter);
    1385           0 :             }
    1386             :         }
    1387           0 :         else if ( eOp == ocMissing )
    1388             :         {
    1389           0 :             PutCode( mpToken );
    1390           0 :             eOp = NextToken();
    1391             :         }
    1392           0 :         else if ( eOp == ocClose )
    1393             :         {
    1394           0 :             SetError( errParameterExpected );
    1395             :         }
    1396           0 :         else if ( eOp == ocSep )
    1397             :         {   // Subsequent ocSep
    1398           0 :             SetError( errParameterExpected );
    1399           0 :             if ( bAutoCorrect && !pStack )
    1400             :             {
    1401           0 :                 aCorrectedSymbol = "";
    1402           0 :                 bCorrected = true;
    1403             :             }
    1404             :         }
    1405           0 :         else if ( mpToken->IsExternalRef() )
    1406             :         {
    1407           0 :             PutCode( mpToken);
    1408           0 :             eOp = NextToken();
    1409             :         }
    1410             :         else
    1411             :         {
    1412           0 :             SetError( errUnknownToken );
    1413           0 :             if ( bAutoCorrect && !pStack )
    1414             :             {
    1415           0 :                 if ( eOp == ocStop )
    1416             :                 {   // trailing operator w/o operand
    1417           0 :                     sal_Int32 nLen = aCorrectedFormula.getLength();
    1418           0 :                     if ( nLen )
    1419           0 :                         aCorrectedFormula = aCorrectedFormula.copy( 0, nLen - 1 );
    1420           0 :                     aCorrectedSymbol = "";
    1421           0 :                     bCorrected = true;
    1422             :                 }
    1423             :             }
    1424             :         }
    1425           0 :     }
    1426             : }
    1427             : 
    1428           0 : void FormulaCompiler::RangeLine()
    1429             : {
    1430           0 :     Factor();
    1431           0 :     while (mpToken->GetOpCode() == ocRange)
    1432             :     {
    1433           0 :         FormulaToken** pCode1 = pCode - 1;
    1434           0 :         FormulaTokenRef p = mpToken;
    1435           0 :         NextToken();
    1436           0 :         Factor();
    1437           0 :         FormulaToken** pCode2 = pCode - 1;
    1438           0 :         if (!MergeRangeReference( pCode1, pCode2))
    1439           0 :             PutCode(p);
    1440           0 :     }
    1441           0 : }
    1442             : 
    1443           0 : void FormulaCompiler::IntersectionLine()
    1444             : {
    1445           0 :     RangeLine();
    1446           0 :     while (mpToken->GetOpCode() == ocIntersect)
    1447             :     {
    1448           0 :         FormulaTokenRef p = mpToken;
    1449           0 :         NextToken();
    1450           0 :         RangeLine();
    1451           0 :         PutCode(p);
    1452           0 :     }
    1453           0 : }
    1454             : 
    1455           0 : void FormulaCompiler::UnionLine()
    1456             : {
    1457           0 :     IntersectionLine();
    1458           0 :     while (mpToken->GetOpCode() == ocUnion)
    1459             :     {
    1460           0 :         FormulaTokenRef p = mpToken;
    1461           0 :         NextToken();
    1462           0 :         IntersectionLine();
    1463           0 :         PutCode(p);
    1464           0 :     }
    1465           0 : }
    1466             : 
    1467           0 : void FormulaCompiler::UnaryLine()
    1468             : {
    1469           0 :     if( mpToken->GetOpCode() == ocAdd )
    1470           0 :         GetToken();
    1471           0 :     else if (SC_OPCODE_START_UN_OP <= mpToken->GetOpCode() &&
    1472           0 :             mpToken->GetOpCode() < SC_OPCODE_STOP_UN_OP)
    1473             :     {
    1474           0 :         FormulaTokenRef p = mpToken;
    1475           0 :         NextToken();
    1476           0 :         UnaryLine();
    1477           0 :         PutCode( p );
    1478             :     }
    1479             :     else
    1480           0 :         UnionLine();
    1481           0 : }
    1482             : 
    1483           0 : void FormulaCompiler::PostOpLine()
    1484             : {
    1485           0 :     UnaryLine();
    1486           0 :     while ( mpToken->GetOpCode() == ocPercentSign )
    1487             :     {   // this operator _follows_ its operand
    1488           0 :         PutCode( mpToken );
    1489           0 :         NextToken();
    1490             :     }
    1491           0 : }
    1492             : 
    1493           0 : void FormulaCompiler::PowLine()
    1494             : {
    1495           0 :     PostOpLine();
    1496           0 :     while (mpToken->GetOpCode() == ocPow)
    1497             :     {
    1498           0 :         FormulaTokenRef p = mpToken;
    1499           0 :         NextToken();
    1500           0 :         PostOpLine();
    1501           0 :         PutCode(p);
    1502           0 :     }
    1503           0 : }
    1504             : 
    1505           0 : void FormulaCompiler::MulDivLine()
    1506             : {
    1507           0 :     PowLine();
    1508           0 :     while (mpToken->GetOpCode() == ocMul || mpToken->GetOpCode() == ocDiv)
    1509             :     {
    1510           0 :         FormulaTokenRef p = mpToken;
    1511           0 :         NextToken();
    1512           0 :         PowLine();
    1513           0 :         PutCode(p);
    1514           0 :     }
    1515           0 : }
    1516             : 
    1517           0 : void FormulaCompiler::AddSubLine()
    1518             : {
    1519           0 :     MulDivLine();
    1520           0 :     while (mpToken->GetOpCode() == ocAdd || mpToken->GetOpCode() == ocSub)
    1521             :     {
    1522           0 :         FormulaTokenRef p = mpToken;
    1523           0 :         NextToken();
    1524           0 :         MulDivLine();
    1525           0 :         PutCode(p);
    1526           0 :     }
    1527           0 : }
    1528             : 
    1529           0 : void FormulaCompiler::ConcatLine()
    1530             : {
    1531           0 :     AddSubLine();
    1532           0 :     while (mpToken->GetOpCode() == ocAmpersand)
    1533             :     {
    1534           0 :         FormulaTokenRef p = mpToken;
    1535           0 :         NextToken();
    1536           0 :         AddSubLine();
    1537           0 :         PutCode(p);
    1538           0 :     }
    1539           0 : }
    1540             : 
    1541           0 : void FormulaCompiler::CompareLine()
    1542             : {
    1543           0 :     ConcatLine();
    1544           0 :     while (mpToken->GetOpCode() >= ocEqual && mpToken->GetOpCode() <= ocGreaterEqual)
    1545             :     {
    1546           0 :         FormulaTokenRef p = mpToken;
    1547           0 :         NextToken();
    1548           0 :         ConcatLine();
    1549           0 :         PutCode(p);
    1550           0 :     }
    1551           0 : }
    1552             : 
    1553           0 : void FormulaCompiler::NotLine()
    1554             : {
    1555           0 :     CompareLine();
    1556           0 :     while (mpToken->GetOpCode() == ocNot)
    1557             :     {
    1558           0 :         FormulaTokenRef p = mpToken;
    1559           0 :         NextToken();
    1560           0 :         CompareLine();
    1561           0 :         PutCode(p);
    1562           0 :     }
    1563           0 : }
    1564             : 
    1565           0 : OpCode FormulaCompiler::Expression()
    1566             : {
    1567             :     static const short nRecursionMax = 42;
    1568           0 :     FormulaCompilerRecursionGuard aRecursionGuard( nRecursion );
    1569           0 :     if ( nRecursion > nRecursionMax )
    1570             :     {
    1571           0 :         SetError( errStackOverflow );
    1572           0 :         return ocStop;      //! generate token instead?
    1573             :     }
    1574           0 :     NotLine();
    1575           0 :     while (mpToken->GetOpCode() == ocAnd || mpToken->GetOpCode() == ocOr)
    1576             :     {
    1577           0 :         FormulaTokenRef p = mpToken;
    1578           0 :         mpToken->SetByte( 2 );       // 2 parameters!
    1579           0 :         NextToken();
    1580           0 :         NotLine();
    1581           0 :         PutCode(p);
    1582           0 :     }
    1583           0 :     return mpToken->GetOpCode();
    1584             : }
    1585             : 
    1586             : 
    1587           0 : void FormulaCompiler::SetError( sal_uInt16 /*nError*/ )
    1588             : {
    1589           0 : }
    1590             : 
    1591           0 : FormulaTokenRef FormulaCompiler::ExtendRangeReference( FormulaToken & /*rTok1*/, FormulaToken & /*rTok2*/,
    1592             :         bool /*bReuseDoubleRef*/ )
    1593             : {
    1594           0 :     return FormulaTokenRef();
    1595             : }
    1596             : 
    1597           0 : bool FormulaCompiler::MergeRangeReference( FormulaToken * * const pCode1, FormulaToken * const * const pCode2 )
    1598             : {
    1599             :     FormulaToken *p1, *p2;
    1600           0 :     if (pc < 2 || !pCode1 || !pCode2 ||
    1601           0 :             (pCode2 - pCode1 != 1) || (pCode - pCode2 != 1) ||
    1602           0 :             ((p1 = *pCode1) == 0) || ((p2 = *pCode2) == 0) )
    1603           0 :         return false;
    1604             : 
    1605           0 :     FormulaTokenRef p = ExtendRangeReference( *p1, *p2, true);
    1606           0 :     if (!p)
    1607           0 :         return false;
    1608             : 
    1609           0 :     p->IncRef();
    1610           0 :     p1->DecRef();
    1611           0 :     p2->DecRef();
    1612           0 :     *pCode1 = p.get();
    1613           0 :     --pCode, --pc;
    1614           0 :     pArr->nRefs--;
    1615             : 
    1616           0 :     return true;
    1617             : }
    1618             : 
    1619           0 : bool FormulaCompiler::CompileTokenArray()
    1620             : {
    1621           0 :     glSubTotal = false;
    1622           0 :     bCorrected = false;
    1623           0 :     if( !pArr->GetCodeError() || bIgnoreErrors )
    1624             :     {
    1625           0 :         if ( bAutoCorrect )
    1626             :         {
    1627           0 :             aCorrectedFormula = "";
    1628           0 :             aCorrectedSymbol = "";
    1629             :         }
    1630           0 :         pArr->nRefs = 0;    // count from start
    1631           0 :         pArr->DelRPN();
    1632           0 :         pStack = NULL;
    1633             :         FormulaToken* pData[ FORMULA_MAXTOKENS ];
    1634           0 :         pCode = pData;
    1635           0 :         bool bWasForced = pArr->IsRecalcModeForced();
    1636           0 :         if ( bWasForced )
    1637             :         {
    1638           0 :             if ( bAutoCorrect )
    1639           0 :                 aCorrectedFormula = "=";
    1640             :         }
    1641           0 :         pArr->ClearRecalcMode();
    1642           0 :         pArr->Reset();
    1643           0 :         eLastOp = ocOpen;
    1644           0 :         pc = 0;
    1645           0 :         NextToken();
    1646           0 :         OpCode eOp = Expression();
    1647             :         // Some trailing garbage that doesn't form an expression?
    1648           0 :         if (eOp != ocStop)
    1649           0 :             SetError( errOperatorExpected);
    1650             : 
    1651           0 :         sal_uInt16 nErrorBeforePop = pArr->GetCodeError();
    1652             : 
    1653           0 :         while( pStack )
    1654           0 :             PopTokenArray();
    1655           0 :         if( pc )
    1656             :         {
    1657           0 :             pArr->pRPN = new FormulaToken*[ pc ];
    1658           0 :             pArr->nRPN = pc;
    1659           0 :             memcpy( pArr->pRPN, pData, pc * sizeof( FormulaToken* ) );
    1660             :         }
    1661             : 
    1662             :         // once an error, always an error
    1663           0 :         if( !pArr->GetCodeError() && nErrorBeforePop )
    1664           0 :             pArr->SetCodeError( nErrorBeforePop);
    1665             : 
    1666           0 :         if( pArr->GetCodeError() && !bIgnoreErrors )
    1667             :         {
    1668           0 :             pArr->DelRPN();
    1669           0 :             pArr->SetHyperLink( false);
    1670             :         }
    1671             : 
    1672           0 :         if ( bWasForced )
    1673           0 :             pArr->SetRecalcModeForced();
    1674             :     }
    1675           0 :     if( nNumFmt == NUMBERFORMAT_UNDEFINED )
    1676           0 :         nNumFmt = NUMBERFORMAT_NUMBER;
    1677           0 :     return glSubTotal;
    1678             : }
    1679             : 
    1680           0 : void FormulaCompiler::PopTokenArray()
    1681             : {
    1682           0 :     if( pStack )
    1683             :     {
    1684           0 :         FormulaArrayStack* p = pStack;
    1685           0 :         pStack = p->pNext;
    1686           0 :         p->pArr->nRefs = sal::static_int_cast<short>( p->pArr->nRefs + pArr->nRefs );
    1687             :         // obtain special RecalcMode from SharedFormula
    1688           0 :         if ( pArr->IsRecalcModeAlways() )
    1689           0 :             p->pArr->SetExclusiveRecalcModeAlways();
    1690           0 :         else if ( !pArr->IsRecalcModeNormal() && p->pArr->IsRecalcModeNormal() )
    1691           0 :             p->pArr->SetMaskedRecalcMode( pArr->GetRecalcMode() );
    1692           0 :         p->pArr->SetCombinedBitsRecalcMode( pArr->GetRecalcMode() );
    1693           0 :         if( p->bTemp )
    1694           0 :             delete pArr;
    1695           0 :         pArr = p->pArr;
    1696           0 :         delete p;
    1697             :     }
    1698           0 : }
    1699             : 
    1700           0 : void FormulaCompiler::CreateStringFromTokenArray( OUString& rFormula )
    1701             : {
    1702           0 :     OUStringBuffer aBuffer( pArr->GetLen() * 5 );
    1703           0 :     CreateStringFromTokenArray( aBuffer );
    1704           0 :     rFormula = aBuffer.makeStringAndClear();
    1705           0 : }
    1706             : 
    1707           0 : void FormulaCompiler::CreateStringFromTokenArray( OUStringBuffer& rBuffer )
    1708             : {
    1709           0 :     rBuffer.setLength(0);
    1710           0 :     if( !pArr->GetLen() )
    1711           0 :         return;
    1712             : 
    1713           0 :     FormulaTokenArray* pSaveArr = pArr;
    1714           0 :     bool bODFF = FormulaGrammar::isODFF( meGrammar);
    1715           0 :     if (bODFF || FormulaGrammar::isPODF( meGrammar) )
    1716             :     {
    1717             :         // Scan token array for missing args and re-write if present.
    1718           0 :         MissingConvention aConv( bODFF);
    1719           0 :         if (pArr->NeedsPofRewrite( aConv))
    1720           0 :             pArr = pArr->RewriteMissingToPof( aConv);
    1721             :     }
    1722             : 
    1723             :     // At least one character per token, plus some are references, some are
    1724             :     // function names, some are numbers, ...
    1725           0 :     rBuffer.ensureCapacity( pArr->GetLen() * 5 );
    1726             : 
    1727           0 :     if ( pArr->IsRecalcModeForced() )
    1728           0 :         rBuffer.append( '=');
    1729           0 :     FormulaToken* t = pArr->First();
    1730           0 :     while( t )
    1731           0 :         t = CreateStringFromToken( rBuffer, t, true );
    1732             : 
    1733           0 :     if (pSaveArr != pArr)
    1734             :     {
    1735           0 :         delete pArr;
    1736           0 :         pArr = pSaveArr;
    1737             :     }
    1738             : }
    1739             : 
    1740           0 : FormulaToken* FormulaCompiler::CreateStringFromToken( OUString& rFormula, FormulaToken* pTokenP,bool bAllowArrAdvance )
    1741             : {
    1742           0 :     OUStringBuffer aBuffer;
    1743           0 :     FormulaToken* p = CreateStringFromToken( aBuffer, pTokenP, bAllowArrAdvance );
    1744           0 :     rFormula += aBuffer.makeStringAndClear();
    1745           0 :     return p;
    1746             : }
    1747             : 
    1748           0 : FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuffer, FormulaToken* pTokenP, bool bAllowArrAdvance )
    1749             : {
    1750           0 :     bool bNext = true;
    1751           0 :     bool bSpaces = false;
    1752           0 :     FormulaToken* t = pTokenP;
    1753           0 :     OpCode eOp = t->GetOpCode();
    1754           0 :     if( eOp >= ocAnd && eOp <= ocOr )
    1755             :     {
    1756             :         // AND, OR infix?
    1757           0 :         if ( bAllowArrAdvance )
    1758           0 :             t = pArr->Next();
    1759             :         else
    1760           0 :             t = pArr->PeekNext();
    1761           0 :         bNext = false;
    1762           0 :         bSpaces = ( !t || t->GetOpCode() != ocOpen );
    1763             :     }
    1764           0 :     if( bSpaces )
    1765           0 :         rBuffer.append( ' ');
    1766             : 
    1767           0 :     if( eOp == ocSpaces )
    1768             :     {
    1769           0 :         bool bIntersectionOp = mxSymbols->isODFF();
    1770           0 :         if (bIntersectionOp)
    1771             :         {
    1772           0 :             const FormulaToken* p = pArr->PeekPrevNoSpaces();
    1773           0 :             bIntersectionOp = (p && p->GetOpCode() == ocColRowName);
    1774           0 :             if (bIntersectionOp)
    1775             :             {
    1776           0 :                 p = pArr->PeekNextNoSpaces();
    1777           0 :                 bIntersectionOp = (p && p->GetOpCode() == ocColRowName);
    1778             :             }
    1779             :         }
    1780           0 :         if (bIntersectionOp)
    1781           0 :             rBuffer.appendAscii( "!!");
    1782             :         else
    1783             :         {
    1784             :             // most times it's just one blank
    1785           0 :             sal_uInt8 n = t->GetByte();
    1786           0 :             for ( sal_uInt8 j=0; j<n; ++j )
    1787             :             {
    1788           0 :                 rBuffer.append( ' ');
    1789             :             }
    1790             :         }
    1791             :     }
    1792           0 :     else if( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
    1793           0 :         rBuffer.appendAscii( pInternal[ eOp - ocInternalBegin ] );
    1794           0 :     else if( (sal_uInt16) eOp < mxSymbols->getSymbolCount())        // Keyword:
    1795           0 :         rBuffer.append( mxSymbols->getSymbol( eOp));
    1796             :     else
    1797             :     {
    1798             :         SAL_WARN( "formula.core","unknown OpCode");
    1799           0 :         rBuffer.append( GetNativeSymbol( ocErrName ));
    1800             :     }
    1801           0 :     if( bNext )
    1802             :     {
    1803           0 :         if (t->IsExternalRef())
    1804             :         {
    1805           0 :             CreateStringFromExternal( rBuffer, pTokenP);
    1806             :         }
    1807             :         else
    1808             :         {
    1809           0 :             switch( t->GetType() )
    1810             :             {
    1811             :             case svDouble:
    1812           0 :                 AppendDouble( rBuffer, t->GetDouble() );
    1813           0 :             break;
    1814             : 
    1815             :             case svString:
    1816           0 :                 if( eOp == ocBad || eOp == ocStringXML )
    1817           0 :                     rBuffer.append( t->GetString().getString());
    1818             :                 else
    1819           0 :                     AppendString( rBuffer, t->GetString().getString() );
    1820           0 :                 break;
    1821             :             case svSingleRef:
    1822           0 :                 CreateStringFromSingleRef( rBuffer, t);
    1823           0 :                 break;
    1824             :             case svDoubleRef:
    1825           0 :                 CreateStringFromDoubleRef( rBuffer, t);
    1826           0 :                 break;
    1827             :             case svMatrix:
    1828           0 :                 CreateStringFromMatrix( rBuffer, t );
    1829           0 :                 break;
    1830             : 
    1831             :             case svIndex:
    1832           0 :                 CreateStringFromIndex( rBuffer, t );
    1833           0 :                 break;
    1834             :             case svExternal:
    1835             :             {
    1836             :                 // mapped or translated name of AddIns
    1837           0 :                 OUString aAddIn( t->GetExternal() );
    1838           0 :                 bool bMapped = mxSymbols->isPODF();     // ODF 1.1 directly uses programmatical name
    1839           0 :                 if (!bMapped && mxSymbols->hasExternals())
    1840             :                 {
    1841           0 :                     ExternalHashMap::const_iterator iLook = mxSymbols->getReverseExternalHashMap()->find( aAddIn);
    1842           0 :                     if (iLook != mxSymbols->getReverseExternalHashMap()->end())
    1843             :                     {
    1844           0 :                         aAddIn = (*iLook).second;
    1845           0 :                         bMapped = true;
    1846             :                     }
    1847             :                 }
    1848           0 :                 if (!bMapped && !mxSymbols->isEnglish())
    1849           0 :                     LocalizeString( aAddIn );
    1850           0 :                 rBuffer.append( aAddIn);
    1851             :             }
    1852           0 :             break;
    1853             :             case svError:
    1854           0 :                 AppendErrorConstant( rBuffer, t->GetError());
    1855           0 :             break;
    1856             :             case svByte:
    1857             :             case svJump:
    1858             :             case svFAP:
    1859             :             case svMissing:
    1860             :             case svSep:
    1861           0 :                 break;      // Opcodes
    1862             :             default:
    1863             :                 OSL_FAIL("FormulaCompiler:: GetStringFromToken errUnknownVariable");
    1864             :             } // of switch
    1865             :         }
    1866             :     }
    1867           0 :     if( bSpaces )
    1868           0 :         rBuffer.append( ' ');
    1869           0 :     if ( bAllowArrAdvance )
    1870             :     {
    1871           0 :         if( bNext )
    1872           0 :             t = pArr->Next();
    1873           0 :         return t;
    1874             :     }
    1875           0 :     return pTokenP;
    1876             : }
    1877             : 
    1878             : 
    1879           0 : void FormulaCompiler::AppendDouble( OUStringBuffer& rBuffer, double fVal ) const
    1880             : {
    1881           0 :     if ( mxSymbols->isEnglish() )
    1882             :     {
    1883             :         ::rtl::math::doubleToUStringBuffer( rBuffer, fVal,
    1884             :                 rtl_math_StringFormat_Automatic,
    1885           0 :                 rtl_math_DecimalPlaces_Max, '.', true );
    1886             :     }
    1887             :     else
    1888             :     {
    1889           0 :         SvtSysLocale aSysLocale;
    1890             :         ::rtl::math::doubleToUStringBuffer( rBuffer, fVal,
    1891             :                 rtl_math_StringFormat_Automatic,
    1892             :                 rtl_math_DecimalPlaces_Max,
    1893           0 :                 aSysLocale.GetLocaleDataPtr()->getNumDecimalSep()[0],
    1894           0 :                 true );
    1895             :     }
    1896           0 : }
    1897             : 
    1898           0 : void FormulaCompiler::AppendBoolean( OUStringBuffer& rBuffer, bool bVal ) const
    1899             : {
    1900           0 :     rBuffer.append( mxSymbols->getSymbol( static_cast<OpCode>(bVal ? ocTrue : ocFalse)) );
    1901           0 : }
    1902             : 
    1903           0 : void FormulaCompiler::AppendString( OUStringBuffer& rBuffer, const OUString & rStr ) const
    1904             : {
    1905           0 :     rBuffer.append( '"');
    1906           0 :     if ( lcl_UnicodeStrChr( rStr.getStr(), '"' ) == NULL )
    1907           0 :         rBuffer.append( rStr );
    1908             :     else
    1909             :     {
    1910           0 :         OUString aStr = rStr.replaceAll( "\"", "\"\"" );
    1911           0 :         rBuffer.append(aStr);
    1912             :     }
    1913           0 :     rBuffer.append( '"');
    1914           0 : }
    1915             : 
    1916           0 : void FormulaCompiler::UpdateSeparatorsNative(
    1917             :     const OUString& rSep, const OUString& rArrayColSep, const OUString& rArrayRowSep )
    1918             : {
    1919           0 :     NonConstOpCodeMapPtr xSymbolsNative;
    1920           0 :     lcl_fillNativeSymbols( xSymbolsNative);
    1921           0 :     xSymbolsNative->putOpCode( rSep, ocSep);
    1922           0 :     xSymbolsNative->putOpCode( rArrayColSep, ocArrayColSep);
    1923           0 :     xSymbolsNative->putOpCode( rArrayRowSep, ocArrayRowSep);
    1924           0 : }
    1925             : 
    1926           0 : void FormulaCompiler::ResetNativeSymbols()
    1927             : {
    1928           0 :     NonConstOpCodeMapPtr xSymbolsNative;
    1929           0 :     lcl_fillNativeSymbols( xSymbolsNative, true);
    1930           0 :     lcl_fillNativeSymbols( xSymbolsNative);
    1931           0 : }
    1932             : 
    1933           0 : void FormulaCompiler::SetNativeSymbols( const OpCodeMapPtr& xMap )
    1934             : {
    1935           0 :     NonConstOpCodeMapPtr xSymbolsNative;
    1936           0 :     lcl_fillNativeSymbols( xSymbolsNative);
    1937           0 :     xSymbolsNative->copyFrom( *xMap, true);
    1938           0 : }
    1939             : 
    1940             : 
    1941           0 : OpCode FormulaCompiler::NextToken()
    1942             : {
    1943           0 :     if( !GetToken() )
    1944           0 :         return ocStop;
    1945           0 :     OpCode eOp = mpToken->GetOpCode();
    1946             :     // There must be an operator before a push
    1947           0 :     if ( (eOp == ocPush || eOp == ocColRowNameAuto) &&
    1948           0 :             !( (eLastOp == ocOpen) || (eLastOp == ocSep) ||
    1949           0 :                 (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)) )
    1950           0 :         SetError( errOperatorExpected);
    1951             :     // Operator and Plus => operator
    1952           0 :     if (eOp == ocAdd && (eLastOp == ocOpen || eLastOp == ocSep ||
    1953           0 :                 (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)))
    1954           0 :         eOp = NextToken();
    1955             :     else
    1956             :     {
    1957             :         // Before an operator there must not be another operator, with the
    1958             :         // exception of AND and OR.
    1959           0 :         if ( eOp != ocAnd && eOp != ocOr &&
    1960           0 :                 (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP )
    1961           0 :                 && (eLastOp == ocOpen || eLastOp == ocSep ||
    1962           0 :                     (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)))
    1963             :         {
    1964           0 :             SetError( errVariableExpected);
    1965           0 :             if ( bAutoCorrect && !pStack )
    1966             :             {
    1967           0 :                 if ( eOp == eLastOp || eLastOp == ocOpen )
    1968             :                 {   // throw away duplicated operator
    1969           0 :                     aCorrectedSymbol = "";
    1970           0 :                     bCorrected = true;
    1971             :                 }
    1972             :                 else
    1973             :                 {
    1974           0 :                     sal_Int32 nPos = aCorrectedFormula.getLength();
    1975           0 :                     if ( nPos )
    1976             :                     {
    1977           0 :                         nPos--;
    1978           0 :                         sal_Unicode c = aCorrectedFormula[ nPos ];
    1979           0 :                         switch ( eOp )
    1980             :                         {   // swap operators
    1981             :                             case ocGreater:
    1982           0 :                                 if ( c == mxSymbols->getSymbolChar( ocEqual) )
    1983             :                                 {   // >= instead of =>
    1984           0 :                                     aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1,
    1985           0 :                                         OUString( mxSymbols->getSymbolChar(ocGreater) ) );
    1986           0 :                                     aCorrectedSymbol = OUString(c);
    1987           0 :                                     bCorrected = true;
    1988             :                                 }
    1989           0 :                             break;
    1990             :                             case ocLess:
    1991           0 :                                 if ( c == mxSymbols->getSymbolChar( ocEqual) )
    1992             :                                 {   // <= instead of =<
    1993           0 :                                     aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1,
    1994           0 :                                         OUString( mxSymbols->getSymbolChar(ocLess) ) );
    1995           0 :                                     aCorrectedSymbol = OUString(c);
    1996           0 :                                     bCorrected = true;
    1997             :                                 }
    1998           0 :                                 else if ( c == mxSymbols->getSymbolChar( ocGreater) )
    1999             :                                 {   // <> instead of ><
    2000           0 :                                     aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1,
    2001           0 :                                         OUString( mxSymbols->getSymbolChar(ocLess) ) );
    2002           0 :                                     aCorrectedSymbol = OUString(c);
    2003           0 :                                     bCorrected = true;
    2004             :                                 }
    2005           0 :                             break;
    2006             :                             case ocMul:
    2007           0 :                                 if ( c == mxSymbols->getSymbolChar( ocSub) )
    2008             :                                 {   // *- instead of -*
    2009           0 :                                     aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1,
    2010           0 :                                         OUString( mxSymbols->getSymbolChar(ocMul) ) );
    2011           0 :                                     aCorrectedSymbol = OUString(c);
    2012           0 :                                     bCorrected = true;
    2013             :                                 }
    2014           0 :                             break;
    2015             :                             case ocDiv:
    2016           0 :                                 if ( c == mxSymbols->getSymbolChar( ocSub) )
    2017             :                                 {   // /- instead of -/
    2018           0 :                                     aCorrectedFormula = aCorrectedFormula.replaceAt( nPos, 1,
    2019           0 :                                         OUString( mxSymbols->getSymbolChar(ocDiv) ) );
    2020           0 :                                     aCorrectedSymbol = OUString(c);
    2021           0 :                                     bCorrected = true;
    2022             :                                 }
    2023           0 :                             break;
    2024             :                             default:
    2025             :                                 ;   // nothing
    2026             :                         }
    2027             :                     }
    2028             :                 }
    2029             :             }
    2030             :         }
    2031           0 :         eLastOp = eOp;
    2032             :     }
    2033           0 :     return eOp;
    2034             : }
    2035           0 : void FormulaCompiler::PutCode( FormulaTokenRef& p )
    2036             : {
    2037           0 :     if( pc >= FORMULA_MAXTOKENS - 1 )
    2038             :     {
    2039           0 :         if ( pc == FORMULA_MAXTOKENS - 1 )
    2040             :         {
    2041           0 :             p = new FormulaByteToken( ocStop );
    2042           0 :             p->IncRef();
    2043           0 :             *pCode++ = p.get();
    2044           0 :             ++pc;
    2045             :         }
    2046           0 :         SetError( errCodeOverflow);
    2047           0 :         return;
    2048             :     }
    2049           0 :     if( pArr->GetCodeError() && !bCompileForFAP )
    2050           0 :         return;
    2051           0 :     ForceArrayOperator( p, pCurrentFactorToken);
    2052           0 :     p->IncRef();
    2053           0 :     *pCode++ = p.get();
    2054           0 :     pc++;
    2055             : }
    2056             : 
    2057             : 
    2058           0 : bool FormulaCompiler::HandleExternalReference( const FormulaToken& /*_aToken*/)
    2059             : {
    2060           0 :     return true;
    2061             : }
    2062             : 
    2063           0 : bool FormulaCompiler::HandleRange()
    2064             : {
    2065           0 :     return true;
    2066             : }
    2067             : 
    2068           0 : bool FormulaCompiler::HandleSingleRef()
    2069             : {
    2070           0 :     return true;
    2071             : }
    2072             : 
    2073           0 : bool FormulaCompiler::HandleDbData()
    2074             : {
    2075           0 :     return true;
    2076             : }
    2077             : 
    2078           0 : void FormulaCompiler::CreateStringFromSingleRef( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
    2079             : {
    2080           0 : }
    2081             : 
    2082           0 : void FormulaCompiler::CreateStringFromDoubleRef( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
    2083             : {
    2084           0 : }
    2085             : 
    2086           0 : void FormulaCompiler::CreateStringFromIndex( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
    2087             : {
    2088           0 : }
    2089             : 
    2090           0 : void FormulaCompiler::CreateStringFromMatrix( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
    2091             : {
    2092           0 : }
    2093             : 
    2094           0 : void FormulaCompiler::CreateStringFromExternal( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
    2095             : {
    2096           0 : }
    2097             : 
    2098           0 : void FormulaCompiler::LocalizeString( OUString& /*rName*/ ) const
    2099             : {
    2100           0 : }
    2101             : 
    2102           0 : void FormulaCompiler::PushTokenArray( FormulaTokenArray* pa, bool bTemp )
    2103             : {
    2104           0 :     if ( bAutoCorrect && !pStack )
    2105             :     {   // don't merge stacked subroutine code into entered formula
    2106           0 :         aCorrectedFormula += aCorrectedSymbol;
    2107           0 :         aCorrectedSymbol = "";
    2108             :     }
    2109           0 :     FormulaArrayStack* p = new FormulaArrayStack;
    2110           0 :     p->pNext      = pStack;
    2111           0 :     p->pArr       = pArr;
    2112           0 :     p->bTemp      = bTemp;
    2113           0 :     pStack        = p;
    2114           0 :     pArr          = pa;
    2115           0 : }
    2116             : 
    2117             : } // namespace formula
    2118             : 
    2119             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10