/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#include "xeformula.hxx"

#include <list>
#include <map>
#include <memory>
#include "addincol.hxx"
#include "compiler.hxx"
#include "document.hxx"
#include "externalrefmgr.hxx"
#include "rangelst.hxx"
#include "token.hxx"
#include "tokenarray.hxx"
#include "xehelper.hxx"
#include "xelink.hxx"
#include "xename.hxx"
#include "xestream.hxx"

using namespace ::formula;

// External reference log =====================================================

XclExpRefLogEntry::XclExpRefLogEntry() :
    mpUrl( 0 ),
    mpFirstTab( 0 ),
    mpLastTab( 0 ),
    mnFirstXclTab( EXC_TAB_DELETED ),
    mnLastXclTab( EXC_TAB_DELETED )
{
}

// Formula compiler ===========================================================

namespace {

/** Wrapper structure for a processed Calc formula token with additional
    settings (whitespaces). */
struct XclExpScToken
{
    const FormulaToken* mpScToken;          /// Currently processed Calc token.
    sal_uInt8           mnSpaces;           /// Number of spaces before the Calc token.

    inline explicit     XclExpScToken() : mpScToken( 0 ), mnSpaces( 0 ) {}
    inline bool         Is() const { return mpScToken != 0; }
    inline StackVar     GetType() const { return mpScToken ? mpScToken->GetType() : static_cast< StackVar >( svUnknown ); }
    inline OpCode       GetOpCode() const { return mpScToken ? mpScToken->GetOpCode() : static_cast< OpCode >( ocNone ); }
};

// ----------------------------------------------------------------------------

/** Effective token class conversion types. */
enum XclExpClassConv
{
    EXC_CLASSCONV_ORG,          /// Keep original class of the token.
    EXC_CLASSCONV_VAL,          /// Convert ARR tokens to VAL class (REF remains uncahnged).
    EXC_CLASSCONV_ARR           /// Convert VAL tokens to ARR class (REF remains uncahnged).
};

// ----------------------------------------------------------------------------

/** Token class conversion and position of a token in the token array. */
struct XclExpTokenConvInfo
{
    sal_uInt16          mnTokPos;       /// Position of the token in the token array.
    XclFuncParamConv    meConv;         /// Token class conversion type.
    bool                mbValType;      /// Data type (false = REFTYPE, true = VALTYPE).
};

/** Vector of token position and conversion for all operands of an operator,
    or for all parameters of a function. */
struct XclExpOperandList : public ::std::vector< XclExpTokenConvInfo >
{
    inline explicit     XclExpOperandList() { reserve( 2 ); }
    void                AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType );
};

void XclExpOperandList::AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType )
{
    resize( size() + 1 );
    XclExpTokenConvInfo& rConvInfo = back();
    rConvInfo.mnTokPos = nTokPos;
    rConvInfo.meConv = eConv;
    rConvInfo.mbValType = bValType;
}

typedef ScfRef< XclExpOperandList > XclExpOperandListRef;
typedef ::std::vector< XclExpOperandListRef > XclExpOperandListVector;

// ----------------------------------------------------------------------------

/** Encapsulates all data needed for a call to an external function (macro, add-in). */
struct XclExpExtFuncData
{
    String              maFuncName;         /// Name of the function.
    bool                mbVBasic;           /// True = Visual Basic macro call.
    bool                mbHidden;           /// True = Create hidden defined name.

    inline explicit     XclExpExtFuncData() : mbVBasic( false ), mbHidden( false ) {}
    void                Set( const String& rFuncName, bool bVBasic, bool bHidden );
};

void XclExpExtFuncData::Set( const String& rFuncName, bool bVBasic, bool bHidden )
{
    maFuncName = rFuncName;
    mbVBasic = bVBasic;
    mbHidden = bHidden;
}

// ----------------------------------------------------------------------------

/** Encapsulates all data needed to process an entire function. */
class XclExpFuncData
{
public:
    explicit            XclExpFuncData(
                            const XclExpScToken& rTokData,
                            const XclFunctionInfo& rFuncInfo,
                            const XclExpExtFuncData& rExtFuncData );

    inline const FormulaToken& GetScToken() const { return *mrTokData.mpScToken; }
    inline OpCode       GetOpCode() const { return mrFuncInfo.meOpCode; }
    inline sal_uInt16   GetXclFuncIdx() const { return mrFuncInfo.mnXclFunc; }
    inline bool         IsVolatile() const { return mrFuncInfo.IsVolatile(); }
    inline bool         IsFixedParamCount() const { return mrFuncInfo.IsFixedParamCount(); }
    inline bool         IsMacroFunc() const { return mrFuncInfo.IsMacroFunc(); }
    inline sal_uInt8    GetSpaces() const { return mrTokData.mnSpaces; }
    inline const XclExpExtFuncData& GetExtFuncData() const { return maExtFuncData; }
    inline sal_uInt8    GetReturnClass() const { return mrFuncInfo.mnRetClass; }

    const XclFuncParamInfo& GetParamInfo() const;
    bool                IsCalcOnlyParam() const;
    bool                IsExcelOnlyParam() const;
    void                IncParamInfoIdx();

    inline sal_uInt8    GetMinParamCount() const { return mrFuncInfo.mnMinParamCount; }
    inline sal_uInt8    GetMaxParamCount() const { return mrFuncInfo.mnMaxParamCount; }
    inline sal_uInt8    GetParamCount() const { return static_cast< sal_uInt8 >( mxOperands->size() ); }
    void                FinishParam( sal_uInt16 nTokPos );
    inline XclExpOperandListRef GetOperandList() const { return mxOperands; }

    inline ScfUInt16Vec& GetAttrPosVec() { return maAttrPosVec; }
    inline void         AppendAttrPos( sal_uInt16 nPos ) { maAttrPosVec.push_back( nPos ); }

private:
    ScfUInt16Vec        maAttrPosVec;       /// Token array positions of tAttr tokens.
    const XclExpScToken& mrTokData;         /// Data about processed function name token.
    const XclFunctionInfo& mrFuncInfo;      /// Constant data about processed function.
    XclExpExtFuncData   maExtFuncData;      /// Data for external functions (macro, add-in).
    XclExpOperandListRef mxOperands;        /// Class conversion and position of all parameters.
    const XclFuncParamInfo* mpParamInfo;    /// Information for current parameter.
};

XclExpFuncData::XclExpFuncData( const XclExpScToken& rTokData,
        const XclFunctionInfo& rFuncInfo, const XclExpExtFuncData& rExtFuncData ) :
    mrTokData( rTokData ),
    mrFuncInfo( rFuncInfo ),
    maExtFuncData( rExtFuncData ),
    mxOperands( new XclExpOperandList ),
    mpParamInfo( rFuncInfo.mpParamInfos )
{
    DBG_ASSERT( mrTokData.mpScToken, "XclExpFuncData::XclExpFuncData - missing core token" );
    // set name of an add-in function
    if( (maExtFuncData.maFuncName.Len() == 0) && dynamic_cast< const FormulaExternalToken* >( mrTokData.mpScToken ) )
        maExtFuncData.Set( GetScToken().GetExternal(), true, false );
}

const XclFuncParamInfo& XclExpFuncData::GetParamInfo() const
{
    static const XclFuncParamInfo saInvalidInfo = { EXC_PARAM_NONE, EXC_PARAMCONV_ORG, false };
    return mpParamInfo ? *mpParamInfo : saInvalidInfo;
}

bool XclExpFuncData::IsCalcOnlyParam() const
{
    return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_CALCONLY);
}

bool XclExpFuncData::IsExcelOnlyParam() const
{
    return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_EXCELONLY);
}

void XclExpFuncData::IncParamInfoIdx()
{
    if( mpParamInfo )
    {
        // move pointer to next entry, if something explicit follows
        if( (static_cast< size_t >( mpParamInfo - mrFuncInfo.mpParamInfos + 1 ) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
            ++mpParamInfo;
        // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
        else if( IsExcelOnlyParam() || IsCalcOnlyParam() )
            mpParamInfo = 0;
        // points to last info, but parameter pairs expected, move to previous info
        else if( mrFuncInfo.IsParamPairs() )
            --mpParamInfo;
        // otherwise: repeat last parameter class
    }
}

void XclExpFuncData::FinishParam( sal_uInt16 nTokPos )
{
    // write token class conversion info for this parameter
    const XclFuncParamInfo& rParamInfo = GetParamInfo();
    mxOperands->AppendOperand( nTokPos, rParamInfo.meConv, rParamInfo.mbValType );
    // move to next parameter info structure
    IncParamInfoIdx();
}

// compiler configuration -----------------------------------------------------

/** Type of token class handling. */
enum XclExpFmlaClassType
{
    EXC_CLASSTYPE_CELL,         /// Cell formula, shared formula.
    EXC_CLASSTYPE_ARRAY,        /// Array formula, conditional formatting, data validation.
    EXC_CLASSTYPE_NAME          /// Defined name, range list.
};

/** Configuration data of the formula compiler. */
struct XclExpCompConfig
{
    XclFormulaType      meType;         /// Type of the formula to be created.
    XclExpFmlaClassType meClassType;    /// Token class handling type.
    bool                mbLocalLinkMgr; /// True = local (per-sheet) link manager, false = global.
    bool                mbFromCell;     /// True = Any kind of cell formula (cell, array, shared).
    bool                mb3DRefOnly;    /// True = Only 3D references allowed (e.g. names).
    bool                mbAllowArrays;  /// True = Allow inline arrays.
};

/** The table containing configuration data for all formula types. */
static const XclExpCompConfig spConfigTable[] =
{
    // formula type         token class type     lclLM  inCell 3dOnly allowArray
    { EXC_FMLATYPE_CELL,    EXC_CLASSTYPE_CELL,  true,  true,  false, true  },
    { EXC_FMLATYPE_SHARED,  EXC_CLASSTYPE_CELL,  true,  true,  false, true  },
    { EXC_FMLATYPE_MATRIX,  EXC_CLASSTYPE_ARRAY, true,  true,  false, true  },
    { EXC_FMLATYPE_CONDFMT, EXC_CLASSTYPE_ARRAY, true,  false, false, false },
    { EXC_FMLATYPE_DATAVAL, EXC_CLASSTYPE_ARRAY, true,  false, false, false },
    { EXC_FMLATYPE_NAME,    EXC_CLASSTYPE_NAME,  false, false, true,  true  },
    { EXC_FMLATYPE_CHART,   EXC_CLASSTYPE_NAME,  true,  false, true,  true  },
    { EXC_FMLATYPE_CONTROL, EXC_CLASSTYPE_NAME,  true,  false, false, false },
    { EXC_FMLATYPE_WQUERY,  EXC_CLASSTYPE_NAME,  true,  false, true,  false },
    { EXC_FMLATYPE_LISTVAL, EXC_CLASSTYPE_NAME,  true,  false, false, false }
};

// ----------------------------------------------------------------------------

/** Working data of the formula compiler. Used to push onto a stack for recursive calls. */
struct XclExpCompData
{
    typedef ScfRef< ScTokenArray > ScTokenArrayRef;

    const XclExpCompConfig& mrCfg;          /// Configuration for current formula type.
    ScTokenArrayRef     mxOwnScTokArr;      /// Own clone of a Calc token array.
    XclTokenArrayIterator maTokArrIt;       /// Iterator in Calc token array.
    XclExpLinkManager*  mpLinkMgr;          /// Link manager for current context (local/global).
    XclExpRefLog*       mpRefLog;           /// Log for external references.
    const ScAddress*    mpScBasePos;        /// Current cell position of the formula.

    ScfUInt8Vec         maTokVec;           /// Byte vector containing token data.
    ScfUInt8Vec         maExtDataVec;       /// Byte vector containing extended data (arrays, stacked NLRs).
    XclExpOperandListVector maOpListVec;    /// Formula structure, maps operators to their operands.
    ScfUInt16Vec        maOpPosStack;       /// Stack with positions of operand tokens waiting for an operator.
    bool                mbStopAtSep;        /// True = Stop subexpression creation at an ocSep token.
    bool                mbVolatile;         /// True = Formula contains volatile function.
    bool                mbOk;               /// Current state of the compiler.

    explicit            XclExpCompData( const XclExpCompConfig* pCfg );
};

XclExpCompData::XclExpCompData( const XclExpCompConfig* pCfg ) :
    mrCfg( pCfg ? *pCfg : spConfigTable[ 0 ] ),
    mpLinkMgr( 0 ),
    mpRefLog( 0 ),
    mpScBasePos( 0 ),
    mbStopAtSep( false ),
    mbVolatile( false ),
    mbOk( pCfg != 0 )
{
    DBG_ASSERT( pCfg, "XclExpFmlaCompImpl::Init - unknown formula type" );
}

} // namespace

// ----------------------------------------------------------------------------

/** Implementation class of the export formula compiler. */
class XclExpFmlaCompImpl : protected XclExpRoot, protected XclTokenArrayHelper
{
public:
    explicit            XclExpFmlaCompImpl( const XclExpRoot& rRoot );

    /** Creates an Excel token array from the passed Calc token array. */
    XclTokenArrayRef    CreateFormula(
                            XclFormulaType eType, const ScTokenArray& rScTokArr,
                            const ScAddress* pScBasePos = 0, XclExpRefLog* pRefLog = 0 );
    /** Creates a single error token containing the passed error code. */
    XclTokenArrayRef    CreateErrorFormula( sal_uInt8 nErrCode );
    /** Creates a single token for a special cell reference. */
    XclTokenArrayRef    CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos );
    /** Creates a single tNameXR token for a reference to an external name. */
    XclTokenArrayRef    CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName );

    /** Returns true, if the passed formula type allows 3D references only. */
    bool                Is3DRefOnly( XclFormulaType eType ) const;

    // ------------------------------------------------------------------------
private:
    const XclExpCompConfig* GetConfigForType( XclFormulaType eType ) const;
    inline sal_uInt16   GetSize() const { return static_cast< sal_uInt16 >( mxData->maTokVec.size() ); }

    void                Init( XclFormulaType eType );
    void                Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
                            const ScAddress* pScBasePos, XclExpRefLog* pRefLog );

    void                RecalcTokenClasses();
    void                RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass );

    void                FinalizeFormula();
    XclTokenArrayRef    CreateTokenArray();

    // compiler ---------------------------------------------------------------
    // XclExpScToken: pass-by-value and return-by-value is intended

    const FormulaToken* GetNextRawToken();
    const FormulaToken* PeekNextRawToken( bool bSkipSpaces ) const;

    bool                GetNextToken( XclExpScToken& rTokData );
    XclExpScToken       GetNextToken();

    XclExpScToken       Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep );
    XclExpScToken       SkipExpression( XclExpScToken aTokData, bool bStopAtSep );

    XclExpScToken       OrTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       AndTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       CompareTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       ConcatTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       AddSubTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       MulDivTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       PowTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       ListTerm( XclExpScToken aTokData, bool bInParentheses );
    XclExpScToken       IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp );
    XclExpScToken       RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp );
    XclExpScToken       Factor( XclExpScToken aTokData );

    // formula structure ------------------------------------------------------

    void                ProcessDouble( const XclExpScToken& rTokData );
    void                ProcessString( const XclExpScToken& rTokData );
    void                ProcessError( const XclExpScToken& rTokData );
    void                ProcessMissing( const XclExpScToken& rTokData );
    void                ProcessBad( const XclExpScToken& rTokData );
    void                ProcessParentheses( const XclExpScToken& rTokData );
    void                ProcessBoolean( const XclExpScToken& rTokData );
    void                ProcessDdeLink( const XclExpScToken& rTokData );
    void                ProcessExternal( const XclExpScToken& rTokData );
    void                ProcessMatrix( const XclExpScToken& rTokData );

    void                ProcessFunction( const XclExpScToken& rTokData );
    void                PrepareFunction( XclExpFuncData& rFuncData );
    void                FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces );
    void                FinishIfFunction( XclExpFuncData& rFuncData );
    void                FinishChooseFunction( XclExpFuncData& rFuncData );

    XclExpScToken       ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData );
    void                PrepareParam( XclExpFuncData& rFuncData );
    void                FinishParam( XclExpFuncData& rFuncData );
    void                AppendDefaultParam( XclExpFuncData& rFuncData );
    void                AppendTrailingParam( XclExpFuncData& rFuncData );

    // reference handling -----------------------------------------------------

    SCTAB               GetScTab( const ScSingleRefData& rRefData ) const;
    bool                IsRef2D( const ScSingleRefData& rRefData ) const;
    bool                IsRef2D( const ScComplexRefData& rRefData ) const;

    void                ConvertRefData( ScSingleRefData& rRefData, XclAddress& rXclPos,
                            bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const;
    void                ConvertRefData( ScComplexRefData& rRefData, XclRange& rXclRange,
                            bool bNatLangRef ) const;

    XclExpRefLogEntry*  GetNewRefLogEntry();
    void                ProcessCellRef( const XclExpScToken& rTokData );
    void                ProcessRangeRef( const XclExpScToken& rTokData );
    void                ProcessExternalCellRef( const XclExpScToken& rTokData );
    void                ProcessExternalRangeRef( const XclExpScToken& rTokData );
    void                ProcessDefinedName( const XclExpScToken& rTokData );
    void                ProcessExternalName( const XclExpScToken& rTokData );
    void                ProcessDatabaseArea( const XclExpScToken& rTokData );

    // token vector -----------------------------------------------------------

    void                PushOperandPos( sal_uInt16 nTokPos );
    void                PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands );
    sal_uInt16          PopOperandPos();

    void                Append( sal_uInt8 nData );
    void                Append( sal_uInt8 nData, size_t nCount );
    void                Append( sal_uInt16 nData );
    void                Append( sal_uInt32 nData );
    void                Append( double fData );
    void                Append( const String& rString );

    void                AppendAddress( const XclAddress& rXclPos );
    void                AppendRange( const XclRange& rXclRange );

    void                AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount );

    void                AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
    void                AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces = 0 );
    void                AppendNumToken( double fValue, sal_uInt8 nSpaces = 0 );
    void                AppendBoolToken( bool bValue, sal_uInt8 nSpaces = 0 );
    void                AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces = 0 );
    void                AppendMissingToken( sal_uInt8 nSpaces = 0 );
    void                AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces = 0 );
    void                AppendMissingNameToken( const String& rName, sal_uInt8 nSpaces = 0 );
    void                AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces = 0 );
    void                AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
    void                AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
    void                AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );

    void                AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces = 0 );
    void                AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
    void                AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces = 0 );
    void                AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount );
    void                AppendFuncToken( const XclExpFuncData& rFuncData );

    void                AppendParenToken( sal_uInt8 nOpenSpaces = 0, sal_uInt8 nCloseSpaces = 0 );
    void                AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType );

    void                InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize );
    void                Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset );

    void                UpdateAttrGoto( sal_uInt16 nAttrPos );

    bool                IsSpaceToken( sal_uInt16 nPos ) const;
    void                RemoveTrailingParen();

    void                AppendExt( sal_uInt8 nData );
    void                AppendExt( sal_uInt8 nData, size_t nCount );
    void                AppendExt( sal_uInt16 nData );
    void                AppendExt( sal_uInt32 nData );
    void                AppendExt( double fData );
    void                AppendExt( const String& rString );

    // ------------------------------------------------------------------------
private:
    typedef ::std::map< XclFormulaType, XclExpCompConfig >  XclExpCompConfigMap;
    typedef ScfRef< XclExpCompData >                        XclExpCompDataRef;
    typedef ::std::vector< XclExpCompDataRef >              XclExpCompDataVector;

    XclExpCompConfigMap maCfgMap;       /// Compiler configuration map for all formula types.
    XclFunctionProvider maFuncProv;     /// Excel function data provider.
    XclExpCompDataRef   mxData;         /// Working data for current formula.
    XclExpCompDataVector maDataStack;   /// Stack for working data, when compiler is called recursively.
    const XclBiff       meBiff;         /// Cached BIFF version to save GetBiff() calls.
    const SCsCOL        mnMaxAbsCol;    /// Maximum column index.
    const SCsROW        mnMaxAbsRow;    /// Maximum row index.
    const SCsCOL        mnMaxScCol;     /// Maximum column index in Calc itself.
    const SCsROW        mnMaxScRow;     /// Maximum row index in Calc itself.
    const sal_uInt16    mnMaxColMask;   /// Mask to delete invalid bits in column fields.
    const sal_uInt16    mnMaxRowMask;   /// Mask to delete invalid bits in row fields.
};

// ----------------------------------------------------------------------------

XclExpFmlaCompImpl::XclExpFmlaCompImpl( const XclExpRoot& rRoot ) :
    XclExpRoot( rRoot ),
    maFuncProv( rRoot ),
    meBiff( rRoot.GetBiff() ),
    mnMaxAbsCol( static_cast< SCsCOL >( rRoot.GetXclMaxPos().Col() ) ),
    mnMaxAbsRow( static_cast< SCsROW >( rRoot.GetXclMaxPos().Row() ) ),
    mnMaxScCol( static_cast< SCsCOL >( rRoot.GetScMaxPos().Col() ) ),
    mnMaxScRow( static_cast< SCsROW >( rRoot.GetScMaxPos().Row() ) ),
    mnMaxColMask( static_cast< sal_uInt16 >( rRoot.GetXclMaxPos().Col() ) ),
    mnMaxRowMask( static_cast< sal_uInt16 >( rRoot.GetXclMaxPos().Row() ) )
{
    // build the configuration map
    for( const XclExpCompConfig* pEntry = spConfigTable; pEntry != STATIC_ARRAY_END( spConfigTable ); ++pEntry )
        maCfgMap[ pEntry->meType ] = *pEntry;
}

XclTokenArrayRef XclExpFmlaCompImpl::CreateFormula( XclFormulaType eType,
        const ScTokenArray& rScTokArr, const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
{
    // initialize the compiler
    Init( eType, rScTokArr, pScBasePos, pRefLog );

    // start compilation, if initialization didn't fail
    if( mxData->mbOk )
    {
        XclExpScToken aTokData( GetNextToken() );
        sal_uInt16 nScError = rScTokArr.GetCodeError();
        if( (nScError != 0) && (!aTokData.Is() || (aTokData.GetOpCode() == ocStop)) )
        {
            // #i50253# convert simple ocStop token to error code formula (e.g. =#VALUE!)
            AppendErrorToken( XclTools::GetXclErrorCode( nScError ), aTokData.mnSpaces );
        }
        else if( aTokData.Is() )
        {
            aTokData = Expression( aTokData, false, false );
        }
        else
        {
            DBG_ERRORFILE( "XclExpFmlaCompImpl::CreateFormula - empty token array" );
            mxData->mbOk = false;
        }

        if( mxData->mbOk )
        {
            // #i44907# auto-generated SUBTOTAL formula cells have trailing ocStop token
            mxData->mbOk = !aTokData.Is() || (aTokData.GetOpCode() == ocStop);
            DBG_ASSERT( mxData->mbOk, "XclExpFmlaCompImpl::CreateFormula - unknown garbage behind formula" );
        }
    }

    // finalize (add tAttrVolatile token, calculate all token classes)
    RecalcTokenClasses();
    FinalizeFormula();

    // leave recursive call, create and return the final token array
    return CreateTokenArray();
}

XclTokenArrayRef XclExpFmlaCompImpl::CreateErrorFormula( sal_uInt8 nErrCode )
{
    Init( EXC_FMLATYPE_NAME );
    AppendErrorToken( nErrCode );
    return CreateTokenArray();
}

XclTokenArrayRef XclExpFmlaCompImpl::CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos )
{
    Init( EXC_FMLATYPE_NAME );
    AppendOperandTokenId( nTokenId );
    Append( rXclPos.mnRow );
    Append( rXclPos.mnCol );    // do not use AppendAddress(), we always need 16-bit column here
    return CreateTokenArray();
}

XclTokenArrayRef XclExpFmlaCompImpl::CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName )
{
    Init( EXC_FMLATYPE_NAME );
    AppendNameXToken( nExtSheet, nExtName );
    return CreateTokenArray();
}

bool XclExpFmlaCompImpl::Is3DRefOnly( XclFormulaType eType ) const
{
    const XclExpCompConfig* pCfg = GetConfigForType( eType );
    return pCfg && pCfg->mb3DRefOnly;
}

// private --------------------------------------------------------------------

const XclExpCompConfig* XclExpFmlaCompImpl::GetConfigForType( XclFormulaType eType ) const
{
    XclExpCompConfigMap::const_iterator aIt = maCfgMap.find( eType );
    DBG_ASSERT( aIt != maCfgMap.end(), "XclExpFmlaCompImpl::GetConfigForType - unknown formula type" );
    return (aIt == maCfgMap.end()) ? 0 : &aIt->second;
}

void XclExpFmlaCompImpl::Init( XclFormulaType eType )
{
    // compiler invoked recursively? - store old working data
    if( mxData.get() )
        maDataStack.push_back( mxData );
    // new compiler working data structure
    mxData.reset( new XclExpCompData( GetConfigForType( eType ) ) );
}

void XclExpFmlaCompImpl::Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
        const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
{
    // common initialization
    Init( eType );

    // special initialization
    if( mxData->mbOk ) switch( mxData->mrCfg.meType )
    {
        case EXC_FMLATYPE_CELL:
        case EXC_FMLATYPE_MATRIX:
        case EXC_FMLATYPE_CHART:
            mxData->mbOk = pScBasePos != 0;
            DBG_ASSERT( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
            mxData->mpScBasePos = pScBasePos;
        break;
        case EXC_FMLATYPE_SHARED:
            mxData->mbOk = pScBasePos != 0;
            DBG_ASSERT( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
            // clone the passed token array, convert references relative to current cell position
            mxData->mxOwnScTokArr.reset( rScTokArr.Clone() );
            ScCompiler::MoveRelWrap( *mxData->mxOwnScTokArr, GetDocPtr(), *pScBasePos, MAXCOL, MAXROW );
            // don't remember pScBasePos in mxData->mpScBasePos, shared formulas use real relative refs
        break;
        default:;
    }

    if( mxData->mbOk )
    {
        // link manager to be used
        mxData->mpLinkMgr = mxData->mrCfg.mbLocalLinkMgr ? &GetLocalLinkManager() : &GetGlobalLinkManager();

        // token array iterator (use cloned token array if present)
        mxData->maTokArrIt.Init( mxData->mxOwnScTokArr.is() ? *mxData->mxOwnScTokArr : rScTokArr, false );
        mxData->mpRefLog = pRefLog;
    }
}

void XclExpFmlaCompImpl::RecalcTokenClasses()
{
    if( mxData->mbOk )
    {
        mxData->mbOk = mxData->maOpPosStack.size() == 1;
        DBG_ASSERT( mxData->mbOk, "XclExpFmlaCompImpl::RecalcTokenClasses - position of root token expected on stack" );
        if( mxData->mbOk )
        {
            /*  Cell and array formulas start with VAL conversion and VALTYPE
                parameter type, defined names start with ARR conversion and
                REFTYPE parameter type for the root token. */
            XclExpOperandList aOperands;
            bool bNameFmla = mxData->mrCfg.meClassType == EXC_CLASSTYPE_NAME;
            XclFuncParamConv eParamConv = bNameFmla ? EXC_PARAMCONV_ARR : EXC_PARAMCONV_VAL;
            XclExpClassConv eClassConv = bNameFmla ? EXC_CLASSCONV_ARR : EXC_CLASSCONV_VAL;
            XclExpTokenConvInfo aConvInfo = { PopOperandPos(), eParamConv, !bNameFmla };
            RecalcTokenClass( aConvInfo, eParamConv, eClassConv, bNameFmla );
        }

        // clear operand vectors (calls to the expensive InsertZeros() may follow)
        mxData->maOpListVec.clear();
        mxData->maOpPosStack.clear();
    }
}

void XclExpFmlaCompImpl::RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo,
        XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass )
{
    DBG_ASSERT( rConvInfo.mnTokPos < GetSize(), "XclExpFmlaCompImpl::RecalcTokenClass - invalid token position" );
    sal_uInt8& rnTokenId = mxData->maTokVec[ rConvInfo.mnTokPos ];
    sal_uInt8 nTokClass = GetTokenClass( rnTokenId );

    // REF tokens in VALTYPE parameters behave like VAL tokens
    if( rConvInfo.mbValType && (nTokClass == EXC_TOKCLASS_REF) )
        ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_VAL );

    // replace RPO conversion of operator with parent conversion
    XclFuncParamConv eConv = (rConvInfo.meConv == EXC_PARAMCONV_RPO) ? ePrevConv : rConvInfo.meConv;

    // find the effective token class conversion to be performed for this token
    XclExpClassConv eClassConv = EXC_CLASSCONV_ORG;
    switch( eConv )
    {
        case EXC_PARAMCONV_ORG:
            // conversion is forced independent of parent conversion
            eClassConv = EXC_CLASSCONV_ORG;
        break;
        case EXC_PARAMCONV_VAL:
            // conversion is forced independent of parent conversion
            eClassConv = EXC_CLASSCONV_VAL;
        break;
        case EXC_PARAMCONV_ARR:
            // conversion is forced independent of parent conversion
            eClassConv = EXC_CLASSCONV_ARR;
        break;
        case EXC_PARAMCONV_RPT:
            switch( ePrevConv )
            {
                case EXC_PARAMCONV_ORG:
                case EXC_PARAMCONV_VAL:
                case EXC_PARAMCONV_ARR:
                    /*  If parent token has REF class (REF token in REFTYPE
                        function parameter), then RPT does not repeat the
                        previous explicit ORG or ARR conversion, but always
                        falls back to VAL conversion. */
                    eClassConv = bWasRefClass ? EXC_CLASSCONV_VAL : ePrevClassConv;
                break;
                case EXC_PARAMCONV_RPT:
                    // nested RPT repeats the previous effective conversion
                    eClassConv = ePrevClassConv;
                break;
                case EXC_PARAMCONV_RPX:
                    /*  If parent token has REF class (REF token in REFTYPE
                        function parameter), then RPX repeats the previous
                        effective conversion (wich will be either ORG or ARR,
                        but never VAL), otherwise falls back to ORG conversion. */
                    eClassConv = bWasRefClass ? ePrevClassConv : EXC_CLASSCONV_ORG;
                break;
                case EXC_PARAMCONV_RPO: // does not occur
                break;
            }
        break;
        case EXC_PARAMCONV_RPX:
            /*  If current token still has REF class, set previous effective
                conversion as current conversion. This will not have an effect
                on the REF token but is needed for RPT parameters of this
                function that want to repeat this conversion type. If current
                token is VAL or ARR class, the previous ARR conversion will be
                repeated on the token, but VAL conversion will not. */
            eClassConv = ((nTokClass == EXC_TOKCLASS_REF) || (ePrevClassConv == EXC_CLASSCONV_ARR)) ?
                ePrevClassConv : EXC_CLASSCONV_ORG;
        break;
        case EXC_PARAMCONV_RPO: // does not occur (see above)
        break;
    }

    // do the token class conversion
    switch( eClassConv )
    {
        case EXC_CLASSCONV_ORG:
            /*  Cell formulas: leave the current token class. Cell formulas
                are the only type of formulas where all tokens can keep
                their original token class.
                Array and defined name formulas: convert VAL to ARR. */
            if( (mxData->mrCfg.meClassType != EXC_CLASSTYPE_CELL) && (nTokClass == EXC_TOKCLASS_VAL) )
                ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_ARR );
        break;
        case EXC_CLASSCONV_VAL:
            // convert ARR to VAL
            if( nTokClass == EXC_TOKCLASS_ARR )
                ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_VAL );
        break;
        case EXC_CLASSCONV_ARR:
            // convert VAL to ARR
            if( nTokClass == EXC_TOKCLASS_VAL )
                ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_ARR );
        break;
    }

    // do conversion for nested operands, if token is an operator or function
    if( rConvInfo.mnTokPos < mxData->maOpListVec.size() )
        if( const XclExpOperandList* pOperands = mxData->maOpListVec[ rConvInfo.mnTokPos ].get() )
            for( XclExpOperandList::const_iterator aIt = pOperands->begin(), aEnd = pOperands->end(); aIt != aEnd; ++aIt )
                RecalcTokenClass( *aIt, eConv, eClassConv, nTokClass == EXC_TOKCLASS_REF );
}

void XclExpFmlaCompImpl::FinalizeFormula()
{
    if( mxData->mbOk )
    {
        // Volatile? Add a tAttrVolatile token at the beginning of the token array.
        if( mxData->mbVolatile )
        {
            // tAttrSpace token can be extended with volatile flag
            if( !IsSpaceToken( 0 ) )
            {
                InsertZeros( 0, 4 );
                mxData->maTokVec[ 0 ] = EXC_TOKID_ATTR;
            }
            mxData->maTokVec[ 1 ] |= EXC_TOK_ATTR_VOLATILE;
        }

        // Token array too long? -> error
        mxData->mbOk = mxData->maTokVec.size() <= EXC_TOKARR_MAXLEN;
    }

    if( !mxData->mbOk )
    {
        // Any unrecoverable error? -> Create a =#NA formula.
        mxData->maTokVec.clear();
        mxData->maExtDataVec.clear();
        mxData->mbVolatile = false;
        AppendErrorToken( EXC_ERR_NA );
    }
}

XclTokenArrayRef XclExpFmlaCompImpl::CreateTokenArray()
{
    // create the Excel token array from working data before resetting mxData
    DBG_ASSERT( mxData->mrCfg.mbAllowArrays || mxData->maExtDataVec.empty(), "XclExpFmlaCompImpl::CreateTokenArray - unexpected extended data" );
    if( !mxData->mrCfg.mbAllowArrays )
        mxData->maExtDataVec.clear();
    XclTokenArrayRef xTokArr( new XclTokenArray( mxData->maTokVec, mxData->maExtDataVec, mxData->mbVolatile ) );
    mxData.reset();

    // compiler invoked recursively? - restore old working data
    if( !maDataStack.empty() )
    {
        mxData = maDataStack.back();
        maDataStack.pop_back();
    }

    return xTokArr;
}

// compiler -------------------------------------------------------------------

const FormulaToken* XclExpFmlaCompImpl::GetNextRawToken()
{
    const FormulaToken* pScToken = mxData->maTokArrIt.Get();
    ++mxData->maTokArrIt;
    return pScToken;
}

const FormulaToken* XclExpFmlaCompImpl::PeekNextRawToken( bool bSkipSpaces ) const
{
    /*  Returns pointer to next raw token in the token array. The token array
        iterator already points to the next token (A call to GetNextToken()
        always increases the iterator), so this function just returns the token
        the iterator points to. To skip space tokens, a copy of the iterator is
        created and set to the passed skip-spaces mode. If spaces have to be
        skipped, and the iterator currently points to a space token, the
        constructor will move it to the next non-space token. */
    XclTokenArrayIterator aTempIt( mxData->maTokArrIt, bSkipSpaces );
    return aTempIt.Get();
}

bool XclExpFmlaCompImpl::GetNextToken( XclExpScToken& rTokData )
{
    rTokData.mpScToken = GetNextRawToken();
    rTokData.mnSpaces = (rTokData.GetOpCode() == ocSpaces) ? rTokData.mpScToken->GetByte() : 0;
    while( rTokData.GetOpCode() == ocSpaces )
        rTokData.mpScToken = GetNextRawToken();
    return rTokData.Is();
}

XclExpScToken XclExpFmlaCompImpl::GetNextToken()
{
    XclExpScToken aTokData;
    GetNextToken( aTokData );
    return aTokData;
}

namespace {

/** Returns the Excel token ID of a comparison operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetCompareTokenId( OpCode eOpCode )
{
    switch( eOpCode )
    {
        case ocLess:            return EXC_TOKID_LT;
        case ocLessEqual:       return EXC_TOKID_LE;
        case ocEqual:           return EXC_TOKID_EQ;
        case ocGreaterEqual:    return EXC_TOKID_GE;
        case ocGreater:         return EXC_TOKID_GT;
        case ocNotEqual:        return EXC_TOKID_NE;
        default:;
    }
    return EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a string concatenation operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetConcatTokenId( OpCode eOpCode )
{
    return (eOpCode == ocAmpersand) ? EXC_TOKID_CONCAT : EXC_TOKID_NONE;
}

/** Returns the Excel token ID of an addition/subtraction operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetAddSubTokenId( OpCode eOpCode )
{
    switch( eOpCode )
    {
        case ocAdd:     return EXC_TOKID_ADD;
        case ocSub:     return EXC_TOKID_SUB;
        default:;
    }
    return EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a multiplication/division operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetMulDivTokenId( OpCode eOpCode )
{
    switch( eOpCode )
    {
        case ocMul:     return EXC_TOKID_MUL;
        case ocDiv:     return EXC_TOKID_DIV;
        default:;
    }
    return EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a power operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetPowTokenId( OpCode eOpCode )
{
    return (eOpCode == ocPow) ? EXC_TOKID_POWER : EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a trailing unary operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetUnaryPostTokenId( OpCode eOpCode )
{
    return (eOpCode == ocPercentSign) ? EXC_TOKID_PERCENT : EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a leading unary operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetUnaryPreTokenId( OpCode eOpCode )
{
    switch( eOpCode )
    {
        case ocAdd:     return EXC_TOKID_UPLUS;     // +(1)
        case ocNeg:     return EXC_TOKID_UMINUS;    // NEG(1)
        case ocNegSub:  return EXC_TOKID_UMINUS;    // -(1)
        default:;
    }
    return EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a reference list operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetListTokenId( OpCode eOpCode, bool bStopAtSep )
{
    return ((eOpCode == ocUnion) || (!bStopAtSep && (eOpCode == ocSep))) ? EXC_TOKID_LIST : EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a reference intersection operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetIntersectTokenId( OpCode eOpCode )
{
    return (eOpCode == ocIntersect) ? EXC_TOKID_ISECT : EXC_TOKID_NONE;
}

/** Returns the Excel token ID of a reference range operator or EXC_TOKID_NONE. */
inline sal_uInt8 lclGetRangeTokenId( OpCode eOpCode )
{
    return (eOpCode == ocRange) ? EXC_TOKID_RANGE : EXC_TOKID_NONE;
}

} // namespace

XclExpScToken XclExpFmlaCompImpl::Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep )
{
    if( mxData->mbOk && aTokData.Is() )
    {
        // remember old stop-at-ocSep mode, restored below
        bool bOldStopAtSep = mxData->mbStopAtSep;
        mxData->mbStopAtSep = bStopAtSep;
        // start compilation of the subexpression
        aTokData = OrTerm( aTokData, bInParentheses );
        // restore old stop-at-ocSep mode
        mxData->mbStopAtSep = bOldStopAtSep;
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::SkipExpression( XclExpScToken aTokData, bool bStopAtSep )
{
    while( mxData->mbOk && aTokData.Is() && (aTokData.GetOpCode() != ocClose) && (!bStopAtSep || (aTokData.GetOpCode() != ocSep)) )
    {
        if( aTokData.GetOpCode() == ocOpen )
        {
            aTokData = SkipExpression( GetNextToken(), false );
            if( mxData->mbOk ) mxData->mbOk = aTokData.GetOpCode() == ocClose;
        }
        aTokData = GetNextToken();
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::OrTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = AndTerm( aTokData, bInParentheses );
    sal_uInt8 nParamCount = 1;
    while( mxData->mbOk && (aTokData.GetOpCode() == ocOr) )
    {
        RemoveTrailingParen();
        aTokData = AndTerm( GetNextToken(), bInParentheses );
        RemoveTrailingParen();
        ++nParamCount;
        if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
    }
    if( mxData->mbOk && (nParamCount > 1) )
        AppendLogicalOperatorToken( EXC_FUNCID_OR, nParamCount );
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::AndTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = CompareTerm( aTokData, bInParentheses );
    sal_uInt8 nParamCount = 1;
    while( mxData->mbOk && (aTokData.GetOpCode() == ocAnd) )
    {
        RemoveTrailingParen();
        aTokData = CompareTerm( GetNextToken(), bInParentheses );
        RemoveTrailingParen();
        ++nParamCount;
        if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
    }
    if( mxData->mbOk && (nParamCount > 1) )
        AppendLogicalOperatorToken( EXC_FUNCID_AND, nParamCount );
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::CompareTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = ConcatTerm( aTokData, bInParentheses );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetCompareTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = ConcatTerm( GetNextToken(), bInParentheses );
        AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::ConcatTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = AddSubTerm( aTokData, bInParentheses );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetConcatTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = AddSubTerm( GetNextToken(), bInParentheses );
        AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::AddSubTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = MulDivTerm( aTokData, bInParentheses );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetAddSubTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = MulDivTerm( GetNextToken(), bInParentheses );
        AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::MulDivTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = PowTerm( aTokData, bInParentheses );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetMulDivTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = PowTerm( GetNextToken(), bInParentheses );
        AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::PowTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = UnaryPostTerm( aTokData, bInParentheses );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetPowTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = UnaryPostTerm( GetNextToken(), bInParentheses );
        AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses )
{
    aTokData = UnaryPreTerm( aTokData, bInParentheses );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetUnaryPostTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        AppendUnaryOperatorToken( nOpTokenId, aTokData.mnSpaces );
        GetNextToken( aTokData );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses )
{
    sal_uInt8 nOpTokenId = mxData->mbOk ? lclGetUnaryPreTokenId( aTokData.GetOpCode() ) : EXC_TOKID_NONE;
    if( nOpTokenId != EXC_TOKID_NONE )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = UnaryPreTerm( GetNextToken(), bInParentheses );
        AppendUnaryOperatorToken( nOpTokenId, nSpaces );
    }
    else
    {
        aTokData = ListTerm( aTokData, bInParentheses );
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::ListTerm( XclExpScToken aTokData, bool bInParentheses )
{
    sal_uInt16 nSubExprPos = GetSize();
    bool bHasAnyRefOp = false;
    bool bHasListOp = false;
    aTokData = IntersectTerm( aTokData, bHasAnyRefOp );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetListTokenId( aTokData.GetOpCode(), mxData->mbStopAtSep )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = IntersectTerm( GetNextToken(), bHasAnyRefOp );
        AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
        bHasAnyRefOp = bHasListOp = true;
    }
    if( bHasAnyRefOp )
    {
        // add a tMemFunc token enclosing the entire reference subexpression
        sal_uInt16 nSubExprSize = GetSize() - nSubExprPos;
        InsertZeros( nSubExprPos, 3 );
        mxData->maTokVec[ nSubExprPos ] = GetTokenId( EXC_TOKID_MEMFUNC, EXC_TOKCLASS_REF );
        Overwrite( nSubExprPos + 1, nSubExprSize );
        // update the operand/operator stack (set the list expression as operand of the tMemFunc)
        XclExpOperandListRef xOperands( new XclExpOperandList );
        xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_VAL, false );
        PushOperatorPos( nSubExprPos, xOperands );
    }
    // #i86439# enclose list operator into parentheses, e.g. Calc's =AREAS(A1~A2) to Excel's =AREAS((A1;A2))
    if( bHasListOp && !bInParentheses )
        AppendParenToken();
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp )
{
    aTokData = RangeTerm( aTokData, rbHasRefOp );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetIntersectTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = RangeTerm( GetNextToken(), rbHasRefOp );
        AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
        rbHasRefOp = true;
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp )
{
    aTokData = Factor( aTokData );
    sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
    while( mxData->mbOk && ((nOpTokenId = lclGetRangeTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
    {
        sal_uInt8 nSpaces = aTokData.mnSpaces;
        aTokData = Factor( GetNextToken() );
        AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
        rbHasRefOp = true;
    }
    return aTokData;
}

XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData )
{
    if( !mxData->mbOk || !aTokData.Is() ) return XclExpScToken();

    switch( aTokData.GetType() )
    {
        case svUnknown:             mxData->mbOk = false;                   break;
        case svDouble:              ProcessDouble( aTokData );              break;
        case svString:              ProcessString( aTokData );              break;
#if 0   // erAck
        case svError:               ProcessError( aTokData );               break;
#endif
        case svSingleRef:           ProcessCellRef( aTokData );             break;
        case svDoubleRef:           ProcessRangeRef( aTokData );            break;
        case svExternalSingleRef:   ProcessExternalCellRef( aTokData );     break;
        case svExternalDoubleRef:   ProcessExternalRangeRef( aTokData );    break;
        case svExternalName:        ProcessExternalName( aTokData );        break;
        case svMatrix:              ProcessMatrix( aTokData );              break;
        case svExternal:            ProcessExternal( aTokData );            break;

        default: switch( aTokData.GetOpCode() )
        {
            case ocNone:        /* do nothing */                    break;
            case ocMissing:     ProcessMissing( aTokData );         break;
            case ocBad:         ProcessBad( aTokData );             break;
            case ocOpen:        ProcessParentheses( aTokData );     break;
            case ocName:        ProcessDefinedName( aTokData );     break;
            case ocDBArea:      ProcessDatabaseArea( aTokData );    break;
            case ocFalse:
            case ocTrue:        ProcessBoolean( aTokData );         break;
            case ocDde:         ProcessDdeLink( aTokData );         break;
            default:            ProcessFunction( aTokData );
        }
    }

    return GetNextToken();
}

// formula structure ----------------------------------------------------------

void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData )
{
    double fValue = rTokData.mpScToken->GetDouble();
    double fInt;
    double fFrac = modf( fValue, &fInt );
    if( (fFrac == 0.0) && (0.0 <= fInt) && (fInt <= 65535.0) )
        AppendIntToken( static_cast< sal_uInt16 >( fInt ), rTokData.mnSpaces );
    else
        AppendNumToken( fValue, rTokData.mnSpaces );
}

void XclExpFmlaCompImpl::ProcessString( const XclExpScToken& rTokData )
{
    AppendOperandTokenId( EXC_TOKID_STR, rTokData.mnSpaces );
    Append( rTokData.mpScToken->GetString() );
}

void XclExpFmlaCompImpl::ProcessError( const XclExpScToken& rTokData )
{
#if 0   // erAck
    AppendErrorToken( XclTools::GetXclErrorCode( rTokData.mpScToken->GetError() ), rTokData.mnSpaces );
#else
    (void)rTokData; // compiler warning
#endif
}

void XclExpFmlaCompImpl::ProcessMissing( const XclExpScToken& rTokData )
{
    AppendMissingToken( rTokData.mnSpaces );
}

void XclExpFmlaCompImpl::ProcessBad( const XclExpScToken& rTokData )
{
    AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
}

void XclExpFmlaCompImpl::ProcessParentheses( const XclExpScToken& rTokData )
{
    XclExpScToken aTokData = Expression( GetNextToken(), true, false );
    mxData->mbOk = aTokData.GetOpCode() == ocClose;
    AppendParenToken( rTokData.mnSpaces, aTokData.mnSpaces );
}

void XclExpFmlaCompImpl::ProcessBoolean( const XclExpScToken& rTokData )
{
    mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
    if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
    if( mxData->mbOk )
        AppendBoolToken( rTokData.GetOpCode() == ocTrue, rTokData.mnSpaces );
}

namespace {

inline bool lclGetTokenString( String& rString, const XclExpScToken& rTokData )
{
    bool bIsStr = (rTokData.GetType() == svString) && (rTokData.GetOpCode() == ocPush);
    if( bIsStr )
        rString = rTokData.mpScToken->GetString();
    return bIsStr;
}

} // namespace

void XclExpFmlaCompImpl::ProcessDdeLink( const XclExpScToken& rTokData )
{
    String aApplic, aTopic, aItem;

    mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
    if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aApplic, GetNextToken() );
    if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
    if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aTopic, GetNextToken() );
    if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
    if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aItem, GetNextToken() );
    if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
    if( mxData->mbOk ) mxData->mbOk = aApplic.Len() && aTopic.Len() && aItem.Len();
    if( mxData->mbOk )
    {
        sal_uInt16 nExtSheet, nExtName;
        if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertDde( nExtSheet, nExtName, aApplic, aTopic, aItem ) )
            AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
        else
            AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
    }
}

void XclExpFmlaCompImpl::ProcessExternal( const XclExpScToken& rTokData )
{
    /*  #i47228# Excel import generates svExternal/ocMacro tokens for invalid
        names and for external/invalid function calls. This function looks for
        the next token in the token array. If it is an opening parenthesis, the
        token is processed as external function call, otherwise as undefined name. */
    const FormulaToken* pNextScToken = PeekNextRawToken( true );
    if( !pNextScToken || (pNextScToken->GetOpCode() != ocOpen) )
        AppendMissingNameToken( rTokData.mpScToken->GetExternal(), rTokData.mnSpaces );
    else
        ProcessFunction( rTokData );
}

void XclExpFmlaCompImpl::ProcessMatrix( const XclExpScToken& rTokData )
{
    const ScMatrix* pMatrix = static_cast< const ScToken* >( rTokData.mpScToken )->GetMatrix();
    if( pMatrix && mxData->mrCfg.mbAllowArrays )
    {
        SCSIZE nScCols, nScRows;
        pMatrix->GetDimensions( nScCols, nScRows );
        DBG_ASSERT( (nScCols > 0) && (nScRows > 0), "XclExpFmlaCompImpl::ProcessMatrix - invalid matrix size" );
        sal_uInt16 nCols = ::limit_cast< sal_uInt16 >( nScCols, 0, 256 );
        sal_uInt16 nRows = ::limit_cast< sal_uInt16 >( nScRows, 0, 1024 );

        // create the tArray token
        AppendOperandTokenId( GetTokenId( EXC_TOKID_ARRAY, EXC_TOKCLASS_ARR ), rTokData.mnSpaces );
        Append( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
        Append( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
        Append( static_cast< sal_uInt32 >( 0 ) );

        // create the extended data containing the array values
        AppendExt( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
        AppendExt( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
        for( SCSIZE nScRow = 0; nScRow < nScRows; ++nScRow )
        {
            for( SCSIZE nScCol = 0; nScCol < nScCols; ++nScCol )
            {
                ScMatValType nType;
                const ScMatrixValue* pMatVal = pMatrix->Get( nScCol, nScRow, nType );
                DBG_ASSERT( pMatVal, "XclExpFmlaCompImpl::ProcessMatrix - missing matrix value" );
                if( ScMatrix::IsValueType( nType ) )    // value, boolean, or error
                {
                    if( ScMatrix::IsBooleanType( nType ) )
                    {
                        AppendExt( EXC_CACHEDVAL_BOOL );
                        AppendExt( static_cast< sal_uInt8 >( pMatVal->GetBoolean() ? 1 : 0 ) );
                        AppendExt( 0, 7 );
                    }
                    else if( sal_uInt16 nErr = pMatVal->GetError() )
                    {
                        AppendExt( EXC_CACHEDVAL_ERROR );
                        AppendExt( XclTools::GetXclErrorCode( nErr ) );
                        AppendExt( 0, 7 );
                    }
                    else
                    {
                        AppendExt( EXC_CACHEDVAL_DOUBLE );
                        AppendExt( pMatVal->fVal );
                    }
                }
                else    // string or empty
                {
                    const String& rStr = pMatVal->GetString();
                    if( rStr.Len() == 0 )
                    {
                        AppendExt( EXC_CACHEDVAL_EMPTY );
                        AppendExt( 0, 8 );
                    }
                    else
                    {
                        AppendExt( EXC_CACHEDVAL_STRING );
                        AppendExt( rStr );
                    }
                }
            }
        }
    }
    else
    {
        // array in places that do not allow it (cond fmts, data validation)
        AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
    }
}

void XclExpFmlaCompImpl::ProcessFunction( const XclExpScToken& rTokData )
{
    OpCode eOpCode = rTokData.GetOpCode();
    const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( eOpCode );

    XclExpExtFuncData aExtFuncData;

    // no exportable function found - try to create an external macro call
    if( !pFuncInfo && (eOpCode >= SC_OPCODE_START_NO_PAR) )
    {
        const String& rFuncName = ScCompiler::GetNativeSymbol( eOpCode );
        if( rFuncName.Len() )
        {
            aExtFuncData.Set( rFuncName, true, false );
            pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( ocMacro );
        }
    }

    mxData->mbOk = pFuncInfo != 0;
    if( !mxData->mbOk ) return;

    // functions simulated by a macro call in file format
    if( pFuncInfo->IsMacroFunc() )
        aExtFuncData.Set( pFuncInfo->GetMacroFuncName(), false, true );

    XclExpFuncData aFuncData( rTokData, *pFuncInfo, aExtFuncData );
    XclExpScToken aTokData;

    // preparations for special functions, before function processing starts
    PrepareFunction( aFuncData );

    enum { STATE_START, STATE_OPEN, STATE_PARAM, STATE_SEP, STATE_CLOSE, STATE_END }
        eState = STATE_START;
    while( eState != STATE_END ) switch( eState )
    {
        case STATE_START:
            mxData->mbOk = GetNextToken( aTokData ) && (aTokData.GetOpCode() == ocOpen);
            eState = mxData->mbOk ? STATE_OPEN : STATE_END;
        break;
        case STATE_OPEN:
            mxData->mbOk = GetNextToken( aTokData );
            eState = mxData->mbOk ? ((aTokData.GetOpCode() == ocClose) ? STATE_CLOSE : STATE_PARAM) : STATE_END;
        break;
        case STATE_PARAM:
            aTokData = ProcessParam( aTokData, aFuncData );
            switch( aTokData.GetOpCode() )
            {
                case ocSep:     eState = STATE_SEP;                 break;
                case ocClose:   eState = STATE_CLOSE;               break;
                default:        mxData->mbOk = false;
            }
            if( !mxData->mbOk ) eState = STATE_END;
        break;
        case STATE_SEP:
            mxData->mbOk = (aFuncData.GetParamCount() < EXC_FUNC_MAXPARAM) && GetNextToken( aTokData );
            eState = mxData->mbOk ? STATE_PARAM : STATE_END;
        break;
        case STATE_CLOSE:
            FinishFunction( aFuncData, aTokData.mnSpaces );
            eState = STATE_END;
        break;
        default:;
    }
}

void XclExpFmlaCompImpl::PrepareFunction( XclExpFuncData& rFuncData )
{
    switch( rFuncData.GetOpCode() )
    {
        case ocCosecant:                // simulate CSC(x) by (1/SIN(x))
        case ocSecant:                  // simulate SEC(x) by (1/COS(x))
        case ocCot:                     // simulate COT(x) by (1/TAN(x))
        case ocCosecantHyp:             // simulate CSCH(x) by (1/SINH(x))
        case ocSecantHyp:               // simulate SECH(x) by (1/COSH(x))
        case ocCotHyp:                  // simulate COTH(x) by (1/TANH(x))
            AppendIntToken( 1 );
        break;
        case ocArcCot:                  // simulate ACOT(x) by (PI/2-ATAN(x))
            AppendNumToken( F_PI2 );
        break;
        default:;
    }
}

void XclExpFmlaCompImpl::FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces )
{
    // append missing parameters required in Excel, may modify param count
    AppendTrailingParam( rFuncData );

    // check if parameter count fits into the limits of the function
    sal_uInt8 nParamCount = rFuncData.GetParamCount();
    if( (rFuncData.GetMinParamCount() <= nParamCount) && (nParamCount <= rFuncData.GetMaxParamCount()) )
    {
        // first put the tAttrSpace tokens, they must not be included in tAttrGoto handling
        AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_CLOSE, nCloseSpaces );
        AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, rFuncData.GetSpaces() );

        // add tAttrGoto tokens for IF or CHOOSE functions
        switch( rFuncData.GetOpCode() )
        {
            case ocIf:
            case ocChose:
                AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
            break;
            default:;
        }

        // put the tFunc or tFuncVar token (or another special token, e.g. tAttrSum)
        AppendFuncToken( rFuncData );

        // update volatile flag - is set if at least one used function is volatile
        mxData->mbVolatile |= rFuncData.IsVolatile();

        // update jump tokens for specific functions, add additional tokens
        switch( rFuncData.GetOpCode() )
        {
            case ocIf:
                FinishIfFunction( rFuncData );
            break;
            case ocChose:
                FinishChooseFunction( rFuncData );
            break;

            case ocCosecant:                // simulate CSC(x) by (1/SIN(x))
            case ocSecant:                  // simulate SEC(x) by (1/COS(x))
            case ocCot:                     // simulate COT(x) by (1/TAN(x))
            case ocCosecantHyp:             // simulate CSCH(x) by (1/SINH(x))
            case ocSecantHyp:               // simulate SECH(x) by (1/COSH(x))
            case ocCotHyp:                  // simulate COTH(x) by (1/TANH(x))
                AppendBinaryOperatorToken( EXC_TOKID_DIV, true );
                AppendParenToken();
            break;
            case ocArcCot:                  // simulate ACOT(x) by (PI/2-ATAN(x))
                AppendBinaryOperatorToken( EXC_TOKID_SUB, true );
                AppendParenToken();
            break;

            default:;
        }
    }
    else
        mxData->mbOk = false;
}

void XclExpFmlaCompImpl::FinishIfFunction( XclExpFuncData& rFuncData )
{
    sal_uInt16 nParamCount = rFuncData.GetParamCount();
    DBG_ASSERT( (nParamCount == 2) || (nParamCount == 3), "XclExpFmlaCompImpl::FinishIfFunction - wrong parameter count" );
    const ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
    DBG_ASSERT( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishIfFunction - wrong number of tAttr tokens" );
    // update tAttrIf token following the condition parameter
    Overwrite( rAttrPos[ 0 ] + 2, static_cast< sal_uInt16 >( rAttrPos[ 1 ] - rAttrPos[ 0 ] ) );
    // update the tAttrGoto tokens following true and false parameters
    UpdateAttrGoto( rAttrPos[ 1 ] );
    if( nParamCount == 3 )
        UpdateAttrGoto( rAttrPos[ 2 ] );
}

void XclExpFmlaCompImpl::FinishChooseFunction( XclExpFuncData& rFuncData )
{
    sal_uInt16 nParamCount = rFuncData.GetParamCount();
    ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
    DBG_ASSERT( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishChooseFunction - wrong number of tAttr tokens" );
    // number of choices is parameter count minus 1
    sal_uInt16 nChoices = nParamCount - 1;
    // tAttrChoose token contains number of choices
    Overwrite( rAttrPos[ 0 ] + 2, nChoices );
    // cache position of the jump table (follows number of choices in tAttrChoose token)
    sal_uInt16 nJumpArrPos = rAttrPos[ 0 ] + 4;
    // size of jump table: number of choices, plus 1 for error position
    sal_uInt16 nJumpArrSize = 2 * (nChoices + 1);
    // insert the jump table into the tAttrChoose token
    InsertZeros( nJumpArrPos, nJumpArrSize );
    // update positions of tAttrGoto tokens after jump table insertion
    sal_uInt16 nIdx;
    for( nIdx = 1; nIdx < nParamCount; ++nIdx )
        rAttrPos[ nIdx ] = rAttrPos[ nIdx ] + nJumpArrSize;
    // update the tAttrGoto tokens (they contain a value one-less to real distance)
    for( nIdx = 1; nIdx < nParamCount; ++nIdx )
        UpdateAttrGoto( rAttrPos[ nIdx ] );
    // update the distances in the jump table
    Overwrite( nJumpArrPos, nJumpArrSize );
    for( nIdx = 1; nIdx < nParamCount; ++nIdx )
        Overwrite( nJumpArrPos + 2 * nIdx, static_cast< sal_uInt16 >( rAttrPos[ nIdx ] + 4 - nJumpArrPos ) );
}

XclExpScToken XclExpFmlaCompImpl::ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData )
{
    if( rFuncData.IsCalcOnlyParam() )
    {
        // skip Calc-only parameter, stop at next ocClose or ocSep
        aTokData = SkipExpression( aTokData, true );
        rFuncData.IncParamInfoIdx();
    }
    else
    {
        // insert Excel-only parameters, modifies param count and class in rFuncData
        while( rFuncData.IsExcelOnlyParam() )
            AppendDefaultParam( rFuncData );

        // process the parameter, stop at next ocClose or ocSep
        PrepareParam( rFuncData );
        /*  #i37355# insert tMissArg token for missing parameters --
            Excel import filter adds ocMissing token (handled in Factor()),
            but Calc itself does not do this if a new formula is entered. */
        switch( aTokData.GetOpCode() )
        {
            case ocSep:
            case ocClose:   AppendMissingToken();   break;  // empty parameter
            default:        aTokData = Expression( aTokData, false, true );
        }
        // finalize the parameter and add special tokens, e.g. for IF or CHOOSE parameters
        if( mxData->mbOk ) FinishParam( rFuncData );
    }
    return aTokData;
}

void XclExpFmlaCompImpl::PrepareParam( XclExpFuncData& rFuncData )
{
    // index of this parameter is equal to number of already finished parameters
    sal_uInt8 nParamIdx = rFuncData.GetParamCount();

    switch( rFuncData.GetOpCode() )
    {
        case ocIf:
            switch( nParamIdx )
            {
                // add a tAttrIf token before true-parameter (second parameter)
                case 1:     AppendJumpToken( rFuncData, EXC_TOK_ATTR_IF );      break;
                // add a tAttrGoto token before false-parameter (third parameter)
                case 2:     AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );    break;
            }
        break;

        case ocChose:
            switch( nParamIdx )
            {
                // do nothing for first parameter
                case 0:                                                         break;
                // add a tAttrChoose token before first value parameter (second parameter)
                case 1:     AppendJumpToken( rFuncData, EXC_TOK_ATTR_CHOOSE );  break;
                // add a tAttrGoto token before other value parameters
                default:    AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
            }
        break;

        case ocArcCotHyp:               // simulate ACOTH(x) by ATANH(1/(x))
            if( nParamIdx == 0 )
                AppendIntToken( 1 );
        break;
        default:;
    }
}

void XclExpFmlaCompImpl::FinishParam( XclExpFuncData& rFuncData )
{
    // increase parameter count, update operand stack
    rFuncData.FinishParam( PopOperandPos() );

    // append more tokens for parameters of some special functions
    sal_uInt8 nParamIdx = rFuncData.GetParamCount() - 1;
    switch( rFuncData.GetOpCode() )
    {
        case ocArcCotHyp:               // simulate ACOTH(x) by ATANH(1/(x))
            if( nParamIdx == 0 )
            {
                AppendParenToken();
                AppendBinaryOperatorToken( EXC_TOKID_DIV, true );
            }
        break;
        default:;
    }
}

void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData )
{
    // prepare parameters of some special functions
    PrepareParam( rFuncData );

    switch( rFuncData.GetOpCode() )
    {
        case ocExternal:
            AppendAddInCallToken( rFuncData.GetExtFuncData() );
        break;
        case ocEuroConvert:
            AppendEuroToolCallToken( rFuncData.GetExtFuncData() );
        break;
        case ocMacro:
            AppendMacroCallToken( rFuncData.GetExtFuncData() );
        break;
        default:
        {
            DBG_ASSERT( rFuncData.IsMacroFunc(), "XclExpFmlaCompImpl::AppendDefaultParam - unknown opcode" );
            if( rFuncData.IsMacroFunc() )
                AppendMacroCallToken( rFuncData.GetExtFuncData() );
            else
                AppendMissingToken();   // to keep parameter count valid
        }
    }

    // update parameter count, add special parameter tokens
    FinishParam( rFuncData );
}

void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
{
    sal_uInt8 nParamCount = rFuncData.GetParamCount();
    switch( rFuncData.GetOpCode() )
    {
        case ocIf:
            if( nParamCount == 1 )
            {
                // #112262# Excel needs at least two parameters in IF function
                PrepareParam( rFuncData );
                AppendBoolToken( true );
                FinishParam( rFuncData );
            }
        break;

        case ocRound:
        case ocRoundUp:
        case ocRoundDown:
            if( nParamCount == 1 )
            {
                // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
                PrepareParam( rFuncData );
                AppendIntToken( 0 );
                FinishParam( rFuncData );
            }
        break;

        case ocIndex:
            if( nParamCount == 1 )
            {
                // INDEX function needs at least 2 parameters in Excel
                PrepareParam( rFuncData );
                AppendMissingToken();
                FinishParam( rFuncData );
            }
        break;

        case ocExternal:
        case ocMacro:
            // external or macro call without parameters needs the external name reference
            if( nParamCount == 0 )
                AppendDefaultParam( rFuncData );
        break;

        case ocGammaDist:
            if( nParamCount == 3 )
            {
                // GAMMADIST function needs 4 parameters in Excel
                PrepareParam( rFuncData );
                AppendIntToken( 1 );
                FinishParam( rFuncData );
            }
        break;

        case ocPoissonDist:
            if( nParamCount == 2 )
            {
                // POISSON function needs 3 parameters in Excel
                PrepareParam( rFuncData );
                AppendIntToken( 1 );
                FinishParam( rFuncData );
            }
        break;

        case ocNormDist:
            if( nParamCount == 3 )
            {
                // NORMDIST function needs 4 parameters in Excel
                PrepareParam( rFuncData );
                AppendBoolToken( true );
                FinishParam( rFuncData );
            }
        break;

        case ocLogNormDist:
            switch( nParamCount )
             {
                // LOGNORMDIST function needs 3 parameters in Excel
                case 1:
                    PrepareParam( rFuncData );
                    AppendIntToken( 0 );
                    FinishParam( rFuncData );
                 // do not break, add next default parameter
                case 2:
                    PrepareParam( rFuncData );
                    AppendIntToken( 1 );
                    FinishParam( rFuncData );
                    break;
                default:;
             }

        break;

        default:
            // #i108420# function without parameters stored as macro call needs the external name reference
            if( (nParamCount == 0) && rFuncData.IsMacroFunc() )
                AppendDefaultParam( rFuncData );

    }
}

// reference handling ---------------------------------------------------------

namespace {

inline bool lclIsRefRel2D( const ScSingleRefData& rRefData )
{
    return rRefData.IsColRel() || rRefData.IsRowRel();
}

inline bool lclIsRefDel2D( const ScSingleRefData& rRefData )
{
    return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
}

inline bool lclIsRefRel2D( const ScComplexRefData& rRefData )
{
    return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
}

inline bool lclIsRefDel2D( const ScComplexRefData& rRefData )
{
    return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
}

} // namespace

SCTAB XclExpFmlaCompImpl::GetScTab( const ScSingleRefData& rRefData ) const
{
    bool bInvTab = rRefData.IsTabDeleted() || (!mxData->mpScBasePos && IsInGlobals() && rRefData.IsTabRel());
    return bInvTab ? SCTAB_INVALID : static_cast< SCTAB >( rRefData.nTab );
}

bool XclExpFmlaCompImpl::IsRef2D( const ScSingleRefData& rRefData ) const
{
    /*  rRefData.IsFlag3D() determines if sheet name is always visible, even on
        the own sheet. If 3D references are allowed, the passed reference does
        not count as 2D reference. */
    return (!mxData->mpLinkMgr || !rRefData.IsFlag3D()) && !rRefData.IsTabDeleted() &&
        (rRefData.IsTabRel() ? (rRefData.nRelTab == 0) : (static_cast< SCTAB >( rRefData.nTab ) == GetCurrScTab()));
}

bool XclExpFmlaCompImpl::IsRef2D( const ScComplexRefData& rRefData ) const
{
    return IsRef2D( rRefData.Ref1 ) && IsRef2D( rRefData.Ref2 );
}

void XclExpFmlaCompImpl::ConvertRefData(
    ScSingleRefData& rRefData, XclAddress& rXclPos,
    bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const
{
    if( mxData->mpScBasePos )
    {
        // *** reference position exists (cell, matrix) - convert to absolute ***
        rRefData.CalcAbsIfRel( *mxData->mpScBasePos );

        // convert column index
        SCsCOL& rnScCol = rRefData.nCol;
        if( bTruncMaxCol && (rnScCol == mnMaxScCol) )
            rnScCol = mnMaxAbsCol;
        else if( (rnScCol < 0) || (rnScCol > mnMaxAbsCol) )
            rRefData.SetColDeleted( sal_True );
        rXclPos.mnCol = static_cast< sal_uInt16 >( rnScCol ) & mnMaxColMask;

        // convert row index
        SCsROW& rnScRow = rRefData.nRow;
        if( bTruncMaxRow && (rnScRow == mnMaxScRow) )
            rnScRow = mnMaxAbsRow;
        else if( (rnScRow < 0) || (rnScRow > mnMaxAbsRow) )
            rRefData.SetRowDeleted( sal_True );
        rXclPos.mnRow = static_cast< sal_uInt16 >( rnScRow ) & mnMaxRowMask;
    }
    else
    {
        // *** no reference position (shared, names, condfmt) - use relative values ***

        // convert column index (2-step-cast ScsCOL->sal_Int16->sal_uInt16 to get all bits correctly)
        sal_Int16 nXclRelCol = static_cast< sal_Int16 >( rRefData.IsColRel() ? rRefData.nRelCol : rRefData.nCol );
        rXclPos.mnCol = static_cast< sal_uInt16 >( nXclRelCol ) & mnMaxColMask;

        // convert row index (2-step-cast ScsROW->sal_Int16->sal_uInt16 to get all bits correctly)
        sal_Int16 nXclRelRow = static_cast< sal_Int16 >( rRefData.IsRowRel() ? rRefData.nRelRow : rRefData.nRow );
        rXclPos.mnRow = static_cast< sal_uInt16 >( nXclRelRow ) & mnMaxRowMask;

        // resolve relative tab index if possible
        if( rRefData.IsTabRel() && !IsInGlobals() && (GetCurrScTab() < GetDoc().GetTableCount()) )
            rRefData.nTab = static_cast< SCsTAB >( GetCurrScTab() + rRefData.nRelTab );
    }

    // flags for relative column and row
    if( bNatLangRef )
    {
        DBG_ASSERT( meBiff == EXC_BIFF8, "XclExpFmlaCompImpl::ConvertRefData - NLRs only for BIFF8" );
        // Calc does not support absolute reference mode in natural language references
        ::set_flag( rXclPos.mnCol, EXC_TOK_NLR_REL );
    }
    else
    {
        sal_uInt16& rnRelField = (meBiff <= EXC_BIFF5) ? rXclPos.mnRow : rXclPos.mnCol;
        ::set_flag( rnRelField, EXC_TOK_REF_COLREL, rRefData.IsColRel() );
        ::set_flag( rnRelField, EXC_TOK_REF_ROWREL, rRefData.IsRowRel() );
    }
}

void XclExpFmlaCompImpl::ConvertRefData(
        ScComplexRefData& rRefData, XclRange& rXclRange, bool bNatLangRef ) const
{
    // convert start and end of the range
    ConvertRefData( rRefData.Ref1, rXclRange.maFirst, bNatLangRef, false, false );
    bool bTruncMaxCol = !rRefData.Ref1.IsColDeleted() && (rRefData.Ref1.nCol == 0);
    bool bTruncMaxRow = !rRefData.Ref1.IsRowDeleted() && (rRefData.Ref1.nRow == 0);
    ConvertRefData( rRefData.Ref2, rXclRange.maLast, bNatLangRef, bTruncMaxCol, bTruncMaxRow );
}

XclExpRefLogEntry* XclExpFmlaCompImpl::GetNewRefLogEntry()
{
    if( mxData->mpRefLog )
    {
        mxData->mpRefLog->resize( mxData->mpRefLog->size() + 1 );
        return &mxData->mpRefLog->back();
    }
    return 0;
}

void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData )
{
    // get the Excel address components, adjust internal data in aRefData
    bool bNatLangRef = (meBiff == EXC_BIFF8) && mxData->mpScBasePos && (rTokData.GetOpCode() == ocColRowName);
    ScSingleRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetSingleRef();
    XclAddress aXclPos( ScAddress::UNINITIALIZED );
    ConvertRefData( aRefData, aXclPos, bNatLangRef, false, false );

    if( bNatLangRef )
    {
        DBG_ASSERT( aRefData.IsColRel() != aRefData.IsRowRel(),
            "XclExpFmlaCompImpl::ProcessCellRef - broken natural language reference" );
        // create tNlr token for natural language reference
        sal_uInt8 nSubId = aRefData.IsColRel() ? EXC_TOK_NLR_COLV : EXC_TOK_NLR_ROWV;
        AppendOperandTokenId( EXC_TOKID_NLR, rTokData.mnSpaces );
        Append( nSubId );
        AppendAddress( aXclPos );
    }
    else
    {
        // store external cell contents in CRN records
        if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
            mxData->mpLinkMgr->StoreCell( aRefData );

        // create the tRef, tRefErr, tRefN, tRef3d, or tRefErr3d token
        if( !mxData->mrCfg.mb3DRefOnly && IsRef2D( aRefData ) )
        {
            // 2D reference (not in defined names, but allowed in range lists)
            sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_REFN :
                (lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR : EXC_TOKID_REF);
            AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
            AppendAddress( aXclPos );
        }
        else if( mxData->mpLinkMgr )    // 3D reference
        {
            // 1-based EXTERNSHEET index and 0-based Excel sheet index
            sal_uInt16 nExtSheet, nXclTab;
            mxData->mpLinkMgr->FindExtSheet( nExtSheet, nXclTab, GetScTab( aRefData ), GetNewRefLogEntry() );
            // write the token
            sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
            AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
            Append( nExtSheet );
            if( meBiff <= EXC_BIFF5 )
            {
                Append( 0, 8 );
                Append( nXclTab );
                Append( nXclTab );
            }
            AppendAddress( aXclPos );
        }
        else
        {
            // 3D ref in cond. format, or 2D ref in name
            AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
        }
    }
}

void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpScToken& rTokData )
{
    // get the Excel address components, adjust internal data in aRefData
    ScComplexRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetDoubleRef();
    XclRange aXclRange( ScAddress::UNINITIALIZED );
    ConvertRefData( aRefData, aXclRange, false );

    // store external cell contents in CRN records
    if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
        mxData->mpLinkMgr->StoreCellRange( aRefData );

    // create the tArea, tAreaErr, tAreaN, tArea3d, or tAreaErr3d token
    if( !mxData->mrCfg.mb3DRefOnly && IsRef2D( aRefData ) )
    {
        // 2D reference (not in name formulas, but allowed in range lists)
        sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_AREAN :
             (lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR : EXC_TOKID_AREA);
        AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
        AppendRange( aXclRange );
    }
    else if( mxData->mpLinkMgr )    // 3D reference
    {
        // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
        sal_uInt16 nExtSheet, nFirstXclTab, nLastXclTab;
        mxData->mpLinkMgr->FindExtSheet( nExtSheet, nFirstXclTab, nLastXclTab,
            GetScTab( aRefData.Ref1 ), GetScTab( aRefData.Ref2 ), GetNewRefLogEntry() );
        // write the token
        sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
        AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
        Append( nExtSheet );
        if( meBiff <= EXC_BIFF5 )
        {
            Append( 0, 8 );
            Append( nFirstXclTab );
            Append( nLastXclTab );
        }
        AppendRange( aXclRange );
    }
    else
    {
        // 3D ref in cond. format, or 2D ref in name
        AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    }
}

void XclExpFmlaCompImpl::ProcessExternalCellRef( const XclExpScToken& rTokData )
{
    if( mxData->mpLinkMgr )
    {
        // get the Excel address components, adjust internal data in aRefData
        ScSingleRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetSingleRef();
        XclAddress aXclPos( ScAddress::UNINITIALIZED );
        ConvertRefData( aRefData, aXclPos, false, false, false );

        // store external cell contents in CRN records
        sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
        const String& rTabName = rTokData.mpScToken->GetString();
        if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
            mxData->mpLinkMgr->StoreCell( nFileId, rTabName, aRefData );

        // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
        sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
        mxData->mpLinkMgr->FindExtSheet( nFileId, rTabName, 1, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
        // write the token
        sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
        AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
        Append( nExtSheet );
        if( meBiff <= EXC_BIFF5 )
        {
            Append( 0, 8 );
            Append( nFirstSBTab );
            Append( nLastSBTab );
        }
        AppendAddress( aXclPos );
    }
    else
    {
        AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    }
}

void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData )
{
    if( mxData->mpLinkMgr )
    {
        // get the Excel address components, adjust internal data in aRefData
        ScComplexRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetDoubleRef();
        XclRange aXclRange( ScAddress::UNINITIALIZED );
        ConvertRefData( aRefData, aXclRange, false );

        // store external cell contents in CRN records
        sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
        const String& rTabName = rTokData.mpScToken->GetString();
        if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
            mxData->mpLinkMgr->StoreCellRange( nFileId, rTabName, aRefData );

        // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
        sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
        sal_uInt16 nTabSpan = static_cast< sal_uInt16 >( aRefData.Ref2.nTab - aRefData.Ref1.nTab + 1 );
        mxData->mpLinkMgr->FindExtSheet( nFileId, rTabName, nTabSpan, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
        // write the token
        sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
        AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
        Append( nExtSheet );
        if( meBiff <= EXC_BIFF5 )
        {
            Append( 0, 8 );
            Append( nFirstSBTab );
            Append( nLastSBTab );
        }
        AppendRange( aXclRange );
    }
    else
    {
        AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
    }
}

void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData )
{
    XclExpNameManager& rNameMgr = GetNameManager();
    sal_uInt16 nNameIdx = rNameMgr.InsertName( rTokData.mpScToken->GetIndex() );
    if( nNameIdx != 0 )
    {
        // global names always with tName token, local names dependent on config
        SCTAB nScTab = rNameMgr.GetScTab( nNameIdx );
        if( (nScTab == SCTAB_GLOBAL) || (!mxData->mrCfg.mb3DRefOnly && (nScTab == GetCurrScTab())) )
        {
            AppendNameToken( nNameIdx, rTokData.mnSpaces );
        }
        else if( mxData->mpLinkMgr )
        {
            // use the same special EXTERNNAME to refer to any local name
            sal_uInt16 nExtSheet = mxData->mpLinkMgr->FindExtSheet( EXC_EXTSH_OWNDOC );
            AppendNameXToken( nExtSheet, nNameIdx, rTokData.mnSpaces );
        }
        else
            AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
        // volatile names (containing volatile functions)
        mxData->mbVolatile |= rNameMgr.IsVolatile( nNameIdx );
    }
    else
        AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
}

void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData )
{
    if( mxData->mpLinkMgr )
    {
        ScExternalRefManager& rExtRefMgr = *GetDoc().GetExternalRefManager();
        sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
        const String& rName = rTokData.mpScToken->GetString();
        ScExternalRefCache::TokenArrayRef xArray = rExtRefMgr.getRangeNameTokens( nFileId, rName );
        if( xArray.get() )
        {
            // store external cell contents in CRN records
            if( mxData->mpScBasePos )
            {
                for( FormulaToken* pScToken = xArray->First(); pScToken; pScToken = xArray->Next() )
                {
                    if( pScToken->GetOpCode() == ocExternalRef )
                    {
                        switch( pScToken->GetType() )
                        {
                            case svExternalSingleRef:
                            {
                                ScSingleRefData aRefData = static_cast< ScToken* >( pScToken )->GetSingleRef();
                                aRefData.CalcAbsIfRel( *mxData->mpScBasePos );
                                mxData->mpLinkMgr->StoreCell( nFileId, pScToken->GetString(), aRefData );
                            }
                            break;
                            case svExternalDoubleRef:
                            {
                                ScComplexRefData aRefData = static_cast< ScToken* >( pScToken )->GetDoubleRef();
                                aRefData.CalcAbsIfRel( *mxData->mpScBasePos );
                                mxData->mpLinkMgr->StoreCellRange( nFileId, pScToken->GetString(), aRefData );
                            }
                            default:
                                ;   // nothing, avoid compiler warning
                        }
                    }
                }
            }

            // insert the new external name and create the tNameX token
            sal_uInt16 nExtSheet, nExtName;
            const String* pFile = rExtRefMgr.getExternalFileName( nFileId );
            if( pFile && mxData->mpLinkMgr->InsertExtName( nExtSheet, nExtName, *pFile, rName, xArray ) )
            {
                AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
                return;
            }
        }
    }

    // on any error: create a #NAME? error
    AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
}

void XclExpFmlaCompImpl::ProcessDatabaseArea( const XclExpScToken& rTokData )
{
    sal_uInt16 nNameIdx = GetNameManager().InsertDBRange( rTokData.mpScToken->GetIndex() );
    AppendNameToken( nNameIdx, rTokData.mnSpaces );
}

// token vector ---------------------------------------------------------------

void XclExpFmlaCompImpl::PushOperandPos( sal_uInt16 nTokPos )
{
    mxData->maOpPosStack.push_back( nTokPos );
}

void XclExpFmlaCompImpl::PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands )
{
    PushOperandPos( nTokPos );
    DBG_ASSERT( rxOperands.get(), "XclExpFmlaCompImpl::AppendOperatorTokenId - missing operand list" );
    if( mxData->maOpListVec.size() <= nTokPos )
        mxData->maOpListVec.resize( nTokPos + 1, XclExpOperandListRef() );
    mxData->maOpListVec[ nTokPos ] = rxOperands;
}

sal_uInt16 XclExpFmlaCompImpl::PopOperandPos()
{
    DBG_ASSERT( !mxData->mbOk || !mxData->maOpPosStack.empty(), "XclExpFmlaCompImpl::PopOperandPos - token stack broken" );
    mxData->mbOk &= !mxData->maOpPosStack.empty();
    if( mxData->mbOk )
    {
        sal_uInt16 nTokPos = mxData->maOpPosStack.back();
        mxData->maOpPosStack.pop_back();
        return nTokPos;
    }
    return 0;
}

namespace {

inline void lclAppend( ScfUInt8Vec& orVector, sal_uInt16 nData )
{
    orVector.resize( orVector.size() + 2 );
    ShortToSVBT16( nData, &*(orVector.end() - 2) );
}

inline void lclAppend( ScfUInt8Vec& orVector, sal_uInt32 nData )
{
    orVector.resize( orVector.size() + 4 );
    UInt32ToSVBT32( nData, &*(orVector.end() - 4) );
}

inline void lclAppend( ScfUInt8Vec& orVector, double fData )
{
    orVector.resize( orVector.size() + 8 );
    DoubleToSVBT64( fData, &*(orVector.end() - 8) );
}

inline void lclAppend( ScfUInt8Vec& orVector, const XclExpRoot& rRoot, const String& rString, XclStrFlags nStrFlags )
{
    XclExpStringRef xXclStr = XclExpStringHelper::CreateString( rRoot, rString, nStrFlags, EXC_TOK_STR_MAXLEN );
    size_t nSize = orVector.size();
    orVector.resize( nSize + xXclStr->GetSize() );
    xXclStr->WriteToMem( &orVector[ nSize ] );
}

} // namespace

void XclExpFmlaCompImpl::Append( sal_uInt8 nData )
{
    mxData->maTokVec.push_back( nData );
}

void XclExpFmlaCompImpl::Append( sal_uInt8 nData, size_t nCount )
{
    mxData->maTokVec.resize( mxData->maTokVec.size() + nCount, nData );
}

void XclExpFmlaCompImpl::Append( sal_uInt16 nData )
{
    lclAppend( mxData->maTokVec, nData );
}

void XclExpFmlaCompImpl::Append( sal_uInt32 nData )
{
    lclAppend( mxData->maTokVec, nData );
}

void XclExpFmlaCompImpl::Append( double fData )
{
    lclAppend( mxData->maTokVec, fData );
}

void XclExpFmlaCompImpl::Append( const String& rString )
{
    lclAppend( mxData->maTokVec, GetRoot(), rString, EXC_STR_8BITLENGTH );
}

void XclExpFmlaCompImpl::AppendAddress( const XclAddress& rXclPos )
{
    Append( rXclPos.mnRow );
    if( meBiff <= EXC_BIFF5 )
        Append( static_cast< sal_uInt8 >( rXclPos.mnCol ) );
    else
        Append( rXclPos.mnCol );
}

void XclExpFmlaCompImpl::AppendRange( const XclRange& rXclRange )
{
    Append( rXclRange.maFirst.mnRow );
    Append( rXclRange.maLast.mnRow );
    if( meBiff <= EXC_BIFF5 )
    {
        Append( static_cast< sal_uInt8 >( rXclRange.maFirst.mnCol ) );
        Append( static_cast< sal_uInt8 >( rXclRange.maLast.mnCol ) );
    }
    else
    {
        Append( rXclRange.maFirst.mnCol );
        Append( rXclRange.maLast.mnCol );
    }
}

void XclExpFmlaCompImpl::AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount )
{
    if( nCount > 0 )
    {
        Append( EXC_TOKID_ATTR );
        Append( EXC_TOK_ATTR_SPACE );
        Append( nType );
        Append( nCount );
    }
}

void XclExpFmlaCompImpl::AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces )
{
    AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, nSpaces );
    PushOperandPos( GetSize() );
    Append( nTokenId );
}

void XclExpFmlaCompImpl::AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces )
{
    AppendOperandTokenId( EXC_TOKID_INT, nSpaces );
    Append( nValue );
}

void XclExpFmlaCompImpl::AppendNumToken( double fValue, sal_uInt8 nSpaces )
{
    AppendOperandTokenId( EXC_TOKID_NUM, nSpaces );
    Append( fValue );
}

void XclExpFmlaCompImpl::AppendBoolToken( bool bValue, sal_uInt8 nSpaces )
{
    AppendOperandTokenId( EXC_TOKID_BOOL, nSpaces );
    Append( bValue ? EXC_TOK_BOOL_TRUE : EXC_TOK_BOOL_FALSE );
}

void XclExpFmlaCompImpl::AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces )
{
    AppendOperandTokenId( EXC_TOKID_ERR, nSpaces );
    Append( nErrCode );
}

void XclExpFmlaCompImpl::AppendMissingToken( sal_uInt8 nSpaces )
{
    AppendOperandTokenId( EXC_TOKID_MISSARG, nSpaces );
}

void XclExpFmlaCompImpl::AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces )
{
    if( nNameIdx > 0 )
    {
        AppendOperandTokenId( GetTokenId( EXC_TOKID_NAME, EXC_TOKCLASS_REF ), nSpaces );
        Append( nNameIdx );
        Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
    }
    else
        AppendErrorToken( EXC_ERR_NAME );
}

void XclExpFmlaCompImpl::AppendMissingNameToken( const String& rName, sal_uInt8 nSpaces )
{
    sal_uInt16 nNameIdx = GetNameManager().InsertRawName( rName );
    AppendNameToken( nNameIdx, nSpaces );
}

void XclExpFmlaCompImpl::AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces )
{
    AppendOperandTokenId( GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ), nSpaces );
    Append( nExtSheet );
    if( meBiff <= EXC_BIFF5 )
        Append( 0, 8 );
    Append( nExtName );
    Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
}

void XclExpFmlaCompImpl::AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
{
    sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rExtFuncData.maFuncName, rExtFuncData.mbVBasic, true, rExtFuncData.mbHidden );
    AppendNameToken( nNameIdx, nSpaces );
}

void XclExpFmlaCompImpl::AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
{
    String aXclFuncName;
    if( mxData->mpLinkMgr && ScGlobal::GetAddInCollection()->GetExcelName( rExtFuncData.maFuncName, GetUILanguage(), aXclFuncName ) )
    {
        sal_uInt16 nExtSheet, nExtName;
        if( mxData->mpLinkMgr->InsertAddIn( nExtSheet, nExtName, aXclFuncName ) )
        {
            AppendNameXToken( nExtSheet, nExtName, nSpaces );
            return;
        }
    }
    AppendMacroCallToken( rExtFuncData, nSpaces );
}

void XclExpFmlaCompImpl::AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
{
    sal_uInt16 nExtSheet, nExtName;
    if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) )
        AppendNameXToken( nExtSheet, nExtName, nSpaces );
    else
        AppendMacroCallToken( rExtFuncData, nSpaces );
}

void XclExpFmlaCompImpl::AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces )
{
    AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, nSpaces );
    PushOperatorPos( GetSize(), rxOperands );
    Append( nTokenId );
}

void XclExpFmlaCompImpl::AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces )
{
    XclExpOperandListRef xOperands( new XclExpOperandList );
    xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, true );
    AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
}

void XclExpFmlaCompImpl::AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces )
{
    XclExpOperandListRef xOperands( new XclExpOperandList );
    xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
    xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
    AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
}

void XclExpFmlaCompImpl::AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount )
{
    XclExpOperandListRef xOperands( new XclExpOperandList );
    for( sal_uInt8 nOpIdx = 0; nOpIdx < nOpCount; ++nOpIdx  )
        xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPX, false );
    AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, EXC_TOKCLASS_VAL ), xOperands );
    Append( nOpCount );
    Append( nXclFuncIdx );
}

void XclExpFmlaCompImpl::AppendFuncToken( const XclExpFuncData& rFuncData )
{
    sal_uInt16 nXclFuncIdx = rFuncData.GetXclFuncIdx();
    sal_uInt8 nParamCount = rFuncData.GetParamCount();
    sal_uInt8 nRetClass = rFuncData.GetReturnClass();

    if( (nXclFuncIdx == EXC_FUNCID_SUM) && (nParamCount == 1) )
    {
        // SUM with only one parameter
        AppendOperatorTokenId( EXC_TOKID_ATTR, rFuncData.GetOperandList() );
        Append( EXC_TOK_ATTR_SUM );
        Append( sal_uInt16( 0 ) );
    }
    else if( rFuncData.IsFixedParamCount() )
    {
        // fixed number of parameters
        AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNC, nRetClass ), rFuncData.GetOperandList() );
        Append( nXclFuncIdx );
    }
    else
    {
        // variable number of parameters
        AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, nRetClass ), rFuncData.GetOperandList() );
        Append( nParamCount );
        Append( nXclFuncIdx );
    }
}

void XclExpFmlaCompImpl::AppendParenToken( sal_uInt8 nOpenSpaces, sal_uInt8 nCloseSpaces )
{
    AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_OPEN, nOpenSpaces );
    AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_CLOSE, nCloseSpaces );
    Append( EXC_TOKID_PAREN );
}

void XclExpFmlaCompImpl::AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType )
{
    // store the start position of the token
    rFuncData.AppendAttrPos( GetSize() );
    // create the tAttr token
    Append( EXC_TOKID_ATTR );
    Append( nAttrType );
    Append( sal_uInt16( 0 ) );  // placeholder that will be updated later
}

void XclExpFmlaCompImpl::InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize )
{
    // insert zeros into the token array
    DBG_ASSERT( nInsertPos < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Insert - invalid position" );
    mxData->maTokVec.insert( mxData->maTokVec.begin() + nInsertPos, nInsertSize, 0 );

    // update positions of operands waiting for an operator
    for( ScfUInt16Vec::iterator aIt = mxData->maOpPosStack.begin(), aEnd = mxData->maOpPosStack.end(); aIt != aEnd; ++aIt )
        if( nInsertPos <= *aIt )
            *aIt = *aIt + nInsertSize;

    // update operand lists of all operator tokens
    if( nInsertPos < mxData->maOpListVec.size() )
        mxData->maOpListVec.insert( mxData->maOpListVec.begin() + nInsertPos, nInsertSize, XclExpOperandListRef() );
    for( XclExpOperandListVector::iterator aIt = mxData->maOpListVec.begin(), aEnd = mxData->maOpListVec.end(); aIt != aEnd; ++aIt )
        if( aIt->get() )
            for( XclExpOperandList::iterator aIt2 = (*aIt)->begin(), aEnd2 = (*aIt)->end(); aIt2 != aEnd2; ++aIt2 )
                if( nInsertPos <= aIt2->mnTokPos )
                    aIt2->mnTokPos = aIt2->mnTokPos + nInsertSize;
}

void XclExpFmlaCompImpl::Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset )
{
    DBG_ASSERT( static_cast< size_t >( nWriteToPos + 1 ) < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Overwrite - invalid position" );
    ShortToSVBT16( nOffset, &mxData->maTokVec[ nWriteToPos ] );
}

void XclExpFmlaCompImpl::UpdateAttrGoto( sal_uInt16 nAttrPos )
{
    /*  tAttrGoto contains distance from end of tAttr token to position behind
        the function token (for IF or CHOOSE function), which is currently at
        the end of the token array. Additionally this distance is decreased by
        one, for whatever reason. So we have to subtract 4 and 1 from the
        distance between the tAttr token start and the end of the token array. */
    Overwrite( nAttrPos + 2, static_cast< sal_uInt16 >( GetSize() - nAttrPos - 5 ) );
}

bool XclExpFmlaCompImpl::IsSpaceToken( sal_uInt16 nPos ) const
{
    return
        (static_cast< size_t >( nPos + 4 ) <= mxData->maTokVec.size()) &&
        (mxData->maTokVec[ nPos ] == EXC_TOKID_ATTR) &&
        (mxData->maTokVec[ nPos + 1 ] == EXC_TOK_ATTR_SPACE);
}

void XclExpFmlaCompImpl::RemoveTrailingParen()
{
    // remove trailing tParen token
    if( !mxData->maTokVec.empty() && (mxData->maTokVec.back() == EXC_TOKID_PAREN) )
        mxData->maTokVec.pop_back();
    // remove remaining tAttrSpace tokens
    while( (mxData->maTokVec.size() >= 4) && IsSpaceToken( GetSize() - 4 ) )
        mxData->maTokVec.erase( mxData->maTokVec.end() - 4, mxData->maTokVec.end() );
}

void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData )
{
    mxData->maExtDataVec.push_back( nData );
}

void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData, size_t nCount )
{
    mxData->maExtDataVec.resize( mxData->maExtDataVec.size() + nCount, nData );
}

void XclExpFmlaCompImpl::AppendExt( sal_uInt16 nData )
{
    lclAppend( mxData->maExtDataVec, nData );
}

void XclExpFmlaCompImpl::AppendExt( sal_uInt32 nData )
{
    lclAppend( mxData->maExtDataVec, nData );
}

void XclExpFmlaCompImpl::AppendExt( double fData )
{
    lclAppend( mxData->maExtDataVec, fData );
}

void XclExpFmlaCompImpl::AppendExt( const String& rString )
{
    lclAppend( mxData->maExtDataVec, GetRoot(), rString, (meBiff == EXC_BIFF8) ? EXC_STR_DEFAULT : EXC_STR_8BITLENGTH );
}

// ============================================================================

namespace {

void lclInitOwnTab( ScSingleRefData& rRef, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
{
    if( b3DRefOnly )
    {
        // no reduction to 2D reference, if global link manager is used
        rRef.SetFlag3D( sal_True );
    }
    else if( rScPos.Tab() == nCurrScTab )
    {
        rRef.SetTabRel( sal_True );
        rRef.nRelTab = 0;
    }
}

void lclPutCellToTokenArray( ScTokenArray& rScTokArr, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
{
    ScSingleRefData aRef;
    aRef.InitAddress( rScPos );
    lclInitOwnTab( aRef, rScPos, nCurrScTab, b3DRefOnly );
    rScTokArr.AddSingleReference( aRef );
}

void lclPutRangeToTokenArray( ScTokenArray& rScTokArr, const ScRange& rScRange, SCTAB nCurrScTab, bool b3DRefOnly )
{
    if( rScRange.aStart == rScRange.aEnd )
    {
        lclPutCellToTokenArray( rScTokArr, rScRange.aStart, nCurrScTab, b3DRefOnly );
    }
    else
    {
        ScComplexRefData aRef;
        aRef.InitRange( rScRange );
        lclInitOwnTab( aRef.Ref1, rScRange.aStart, nCurrScTab, b3DRefOnly );
        lclInitOwnTab( aRef.Ref2, rScRange.aEnd, nCurrScTab, b3DRefOnly );
        rScTokArr.AddDoubleReference( aRef );
    }
}

} // namespace

// ----------------------------------------------------------------------------

XclExpFormulaCompiler::XclExpFormulaCompiler( const XclExpRoot& rRoot ) :
    XclExpRoot( rRoot ),
    mxImpl( new XclExpFmlaCompImpl( rRoot ) )
{
}

XclExpFormulaCompiler::~XclExpFormulaCompiler()
{
}

XclTokenArrayRef XclExpFormulaCompiler::CreateFormula(
        XclFormulaType eType, const ScTokenArray& rScTokArr,
        const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
{
    return mxImpl->CreateFormula( eType, rScTokArr, pScBasePos, pRefLog );
}

XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScAddress& rScPos )
{
    ScTokenArray aScTokArr;
    lclPutCellToTokenArray( aScTokArr, rScPos, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
    return mxImpl->CreateFormula( eType, aScTokArr );
}

XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScRange& rScRange )
{
    ScTokenArray aScTokArr;
    lclPutRangeToTokenArray( aScTokArr, rScRange, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
    return mxImpl->CreateFormula( eType, aScTokArr );
}

XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScRangeList& rScRanges )
{
    sal_uLong nCount = rScRanges.Count();
    if( nCount == 0 )
        return XclTokenArrayRef();

    ScTokenArray aScTokArr;
    SCTAB nCurrScTab = GetCurrScTab();
    bool b3DRefOnly = mxImpl->Is3DRefOnly( eType );
    for( sal_uLong nIdx = 0; nIdx < nCount; ++nIdx )
    {
        if( nIdx > 0 )
            aScTokArr.AddOpCode( ocUnion );
        lclPutRangeToTokenArray( aScTokArr, *rScRanges.GetObject( nIdx ), nCurrScTab, b3DRefOnly );
    }
    return mxImpl->CreateFormula( eType, aScTokArr );
}

XclTokenArrayRef XclExpFormulaCompiler::CreateErrorFormula( sal_uInt8 nErrCode )
{
    return mxImpl->CreateErrorFormula( nErrCode );
}

XclTokenArrayRef XclExpFormulaCompiler::CreateSpecialRefFormula(
        sal_uInt8 nTokenId, const XclAddress& rXclPos )
{
    return mxImpl->CreateSpecialRefFormula( nTokenId, rXclPos );
}

XclTokenArrayRef XclExpFormulaCompiler::CreateNameXFormula(
        sal_uInt16 nExtSheet, sal_uInt16 nExtName )
{
    return mxImpl->CreateNameXFormula( nExtSheet, nExtName );
}

// ============================================================================

