LCOV - code coverage report
Current view: top level - sc/source/filter/oox - formulabase.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 313 522 60.0 %
Date: 2012-08-25 Functions: 43 73 58.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 320 943 33.9 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "formulabase.hxx"
      30                 :            : 
      31                 :            : #include <map>
      32                 :            : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      33                 :            : #include <com/sun/star/table/XCellRange.hpp>
      34                 :            : #include <com/sun/star/sheet/AddressConvention.hpp>
      35                 :            : #include <com/sun/star/sheet/ReferenceFlags.hpp>
      36                 :            : #include <com/sun/star/sheet/SingleReference.hpp>
      37                 :            : #include <com/sun/star/sheet/ComplexReference.hpp>
      38                 :            : #include <com/sun/star/sheet/FormulaLanguage.hpp>
      39                 :            : #include <com/sun/star/sheet/FormulaMapGroup.hpp>
      40                 :            : #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
      41                 :            : #include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp>
      42                 :            : #include <com/sun/star/sheet/XFormulaParser.hpp>
      43                 :            : #include <rtl/strbuf.hxx>
      44                 :            : #include <rtl/ustrbuf.hxx>
      45                 :            : #include "oox/core/filterbase.hxx"
      46                 :            : #include "oox/helper/containerhelper.hxx"
      47                 :            : #include "oox/token/properties.hxx"
      48                 :            : #include "biffinputstream.hxx"
      49                 :            : 
      50                 :            : namespace oox {
      51                 :            : namespace xls {
      52                 :            : 
      53                 :            : // ============================================================================
      54                 :            : 
      55                 :            : using namespace ::com::sun::star::lang;
      56                 :            : using namespace ::com::sun::star::sheet;
      57                 :            : using namespace ::com::sun::star::table;
      58                 :            : using namespace ::com::sun::star::uno;
      59                 :            : 
      60                 :            : using ::rtl::OString;
      61                 :            : using ::rtl::OStringBuffer;
      62                 :            : using ::rtl::OStringToOUString;
      63                 :            : using ::rtl::OUString;
      64                 :            : using ::rtl::OUStringBuffer;
      65                 :            : using ::rtl::OUStringToOString;
      66                 :            : 
      67                 :            : // reference helpers ==========================================================
      68                 :            : 
      69                 :          0 : BinSingleRef2d::BinSingleRef2d() :
      70                 :            :     mnCol( 0 ),
      71                 :            :     mnRow( 0 ),
      72                 :            :     mbColRel( false ),
      73                 :          0 :     mbRowRel( false )
      74                 :            : {
      75                 :          0 : }
      76                 :            : 
      77                 :          0 : void BinSingleRef2d::setBiff12Data( sal_uInt16 nCol, sal_Int32 nRow, bool bRelativeAsOffset )
      78                 :            : {
      79                 :          0 :     mnCol = nCol & BIFF12_TOK_REF_COLMASK;
      80                 :          0 :     mnRow = nRow & BIFF12_TOK_REF_ROWMASK;
      81                 :          0 :     mbColRel = getFlag( nCol, BIFF12_TOK_REF_COLREL );
      82                 :          0 :     mbRowRel = getFlag( nCol, BIFF12_TOK_REF_ROWREL );
      83 [ #  # ][ #  # ]:          0 :     if( bRelativeAsOffset && mbColRel && (mnCol > (BIFF12_TOK_REF_COLMASK >> 1)) )
                 [ #  # ]
      84                 :          0 :         mnCol -= (BIFF12_TOK_REF_COLMASK + 1);
      85 [ #  # ][ #  # ]:          0 :     if( bRelativeAsOffset && mbRowRel && (mnRow > (BIFF12_TOK_REF_ROWMASK >> 1)) )
                 [ #  # ]
      86                 :          0 :         mnRow -= (BIFF12_TOK_REF_ROWMASK + 1);
      87                 :          0 : }
      88                 :            : 
      89                 :          0 : void BinSingleRef2d::setBiff2Data( sal_uInt8 nCol, sal_uInt16 nRow, bool bRelativeAsOffset )
      90                 :            : {
      91                 :          0 :     mnCol = nCol;
      92                 :          0 :     mnRow = nRow & BIFF_TOK_REF_ROWMASK;
      93                 :          0 :     mbColRel = getFlag( nRow, BIFF_TOK_REF_COLREL );
      94                 :          0 :     mbRowRel = getFlag( nRow, BIFF_TOK_REF_ROWREL );
      95 [ #  # ][ #  # ]:          0 :     if( bRelativeAsOffset && mbColRel && (mnCol >= 0x80) )
                 [ #  # ]
      96                 :          0 :         mnCol -= 0x100;
      97 [ #  # ][ #  # ]:          0 :     if( bRelativeAsOffset && mbRowRel && (mnRow > (BIFF_TOK_REF_ROWMASK >> 1)) )
                 [ #  # ]
      98                 :          0 :         mnRow -= (BIFF_TOK_REF_ROWMASK + 1);
      99                 :          0 : }
     100                 :            : 
     101                 :          0 : void BinSingleRef2d::setBiff8Data( sal_uInt16 nCol, sal_uInt16 nRow, bool bRelativeAsOffset )
     102                 :            : {
     103                 :          0 :     mnCol = nCol & BIFF_TOK_REF_COLMASK;
     104                 :          0 :     mnRow = nRow;
     105                 :          0 :     mbColRel = getFlag( nCol, BIFF_TOK_REF_COLREL );
     106                 :          0 :     mbRowRel = getFlag( nCol, BIFF_TOK_REF_ROWREL );
     107 [ #  # ][ #  # ]:          0 :     if( bRelativeAsOffset && mbColRel && (mnCol > (BIFF_TOK_REF_COLMASK >> 1)) )
                 [ #  # ]
     108                 :          0 :         mnCol -= (BIFF_TOK_REF_COLMASK + 1);
     109 [ #  # ][ #  # ]:          0 :     if( bRelativeAsOffset && mbRowRel && (mnRow >= 0x8000) )
                 [ #  # ]
     110                 :          0 :         mnRow -= 0x10000;
     111                 :          0 : }
     112                 :            : 
     113                 :          0 : void BinSingleRef2d::readBiff12Data( SequenceInputStream& rStrm, bool bRelativeAsOffset )
     114                 :            : {
     115                 :            :     sal_Int32 nRow;
     116                 :            :     sal_uInt16 nCol;
     117 [ #  # ][ #  # ]:          0 :     rStrm >> nRow >> nCol;
     118         [ #  # ]:          0 :     setBiff12Data( nCol, nRow, bRelativeAsOffset );
     119                 :          0 : }
     120                 :            : 
     121                 :          0 : void BinSingleRef2d::readBiff2Data( BiffInputStream& rStrm, bool bRelativeAsOffset )
     122                 :            : {
     123                 :            :     sal_uInt16 nRow;
     124                 :            :     sal_uInt8 nCol;
     125 [ #  # ][ #  # ]:          0 :     rStrm >> nRow >> nCol;
     126         [ #  # ]:          0 :     setBiff2Data( nCol, nRow, bRelativeAsOffset );
     127                 :          0 : }
     128                 :            : 
     129                 :          0 : void BinSingleRef2d::readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset )
     130                 :            : {
     131                 :            :     sal_uInt16 nRow, nCol;
     132 [ #  # ][ #  # ]:          0 :     rStrm >> nRow >> nCol;
     133         [ #  # ]:          0 :     setBiff8Data( nCol, nRow, bRelativeAsOffset );
     134                 :          0 : }
     135                 :            : 
     136                 :            : // ----------------------------------------------------------------------------
     137                 :            : 
     138                 :          0 : void BinComplexRef2d::readBiff12Data( SequenceInputStream& rStrm, bool bRelativeAsOffset )
     139                 :            : {
     140                 :            :     sal_Int32 nRow1, nRow2;
     141                 :            :     sal_uInt16 nCol1, nCol2;
     142 [ #  # ][ #  # ]:          0 :     rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2;
         [ #  # ][ #  # ]
     143         [ #  # ]:          0 :     maRef1.setBiff12Data( nCol1, nRow1, bRelativeAsOffset );
     144         [ #  # ]:          0 :     maRef2.setBiff12Data( nCol2, nRow2, bRelativeAsOffset );
     145                 :          0 : }
     146                 :            : 
     147                 :          0 : void BinComplexRef2d::readBiff2Data( BiffInputStream& rStrm, bool bRelativeAsOffset )
     148                 :            : {
     149                 :            :     sal_uInt16 nRow1, nRow2;
     150                 :            :     sal_uInt8 nCol1, nCol2;
     151 [ #  # ][ #  # ]:          0 :     rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2;
         [ #  # ][ #  # ]
     152         [ #  # ]:          0 :     maRef1.setBiff2Data( nCol1, nRow1, bRelativeAsOffset );
     153         [ #  # ]:          0 :     maRef2.setBiff2Data( nCol2, nRow2, bRelativeAsOffset );
     154                 :          0 : }
     155                 :            : 
     156                 :          0 : void BinComplexRef2d::readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset )
     157                 :            : {
     158                 :            :     sal_uInt16 nRow1, nRow2, nCol1, nCol2;
     159 [ #  # ][ #  # ]:          0 :     rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2;
         [ #  # ][ #  # ]
     160         [ #  # ]:          0 :     maRef1.setBiff8Data( nCol1, nRow1, bRelativeAsOffset );
     161         [ #  # ]:          0 :     maRef2.setBiff8Data( nCol2, nRow2, bRelativeAsOffset );
     162                 :          0 : }
     163                 :            : 
     164                 :            : // token vector, sequence =====================================================
     165                 :            : 
     166                 :         48 : ApiTokenVector::ApiTokenVector()
     167                 :            : {
     168                 :         48 : }
     169                 :            : 
     170                 :         81 : Any& ApiTokenVector::append( sal_Int32 nOpCode )
     171                 :            : {
     172                 :         81 :     resize( size() + 1 );
     173                 :         81 :     back().OpCode = nOpCode;
     174                 :         81 :     return back().Data;
     175                 :            : }
     176                 :            : 
     177                 :            : // token sequence iterator ====================================================
     178                 :            : 
     179                 :          3 : ApiTokenIterator::ApiTokenIterator( const ApiTokenSequence& rTokens, sal_Int32 nSpacesOpCode, bool bSkipSpaces ) :
     180                 :          3 :     mpToken( rTokens.getConstArray() ),
     181                 :          3 :     mpTokenEnd( rTokens.getConstArray() + rTokens.getLength() ),
     182                 :            :     mnSpacesOpCode( nSpacesOpCode ),
     183                 :          6 :     mbSkipSpaces( bSkipSpaces )
     184                 :            : {
     185                 :          3 :     skipSpaces();
     186                 :          3 : }
     187                 :            : 
     188                 :          3 : ApiTokenIterator& ApiTokenIterator::operator++()
     189                 :            : {
     190         [ +  - ]:          3 :     if( is() )
     191                 :            :     {
     192                 :          3 :         ++mpToken;
     193                 :          3 :         skipSpaces();
     194                 :            :     }
     195                 :          3 :     return *this;
     196                 :            : }
     197                 :            : 
     198                 :          6 : void ApiTokenIterator::skipSpaces()
     199                 :            : {
     200         [ +  - ]:          6 :     if( mbSkipSpaces )
     201 [ +  + ][ -  + ]:          6 :         while( is() && (mpToken->OpCode == mnSpacesOpCode) )
                 [ -  + ]
     202                 :          0 :             ++mpToken;
     203                 :          6 : }
     204                 :            : 
     205                 :            : // function data ==============================================================
     206                 :            : 
     207                 :            : namespace {
     208                 :            : 
     209                 :            : const size_t FUNCINFO_PARAMINFOCOUNT        = 5;        /// Number of parameter type entries.
     210                 :            : 
     211                 :            : const sal_uInt16 FUNCFLAG_VOLATILE          = 0x0001;   /// Result is volatile (e.g. NOW() function).
     212                 :            : const sal_uInt16 FUNCFLAG_IMPORTONLY        = 0x0002;   /// Only used in import filter.
     213                 :            : const sal_uInt16 FUNCFLAG_EXPORTONLY        = 0x0004;   /// Only used in export filter.
     214                 :            : const sal_uInt16 FUNCFLAG_MACROCALL         = 0x0008;   /// Function is stored as macro call in Excel (_xlfn. prefix). OOXML name MUST exist.
     215                 :            : const sal_uInt16 FUNCFLAG_MACROCALLODF      = 0x0010;   /// ODF-only function stored as macro call in Excel (_xlfnodf. prefix). ODF name MUST exist.
     216                 :            : const sal_uInt16 FUNCFLAG_EXTERNAL          = 0x0020;   /// Function is external in Calc.
     217                 :            : const sal_uInt16 FUNCFLAG_MACROFUNC         = 0x0040;   /// Function is a macro-sheet function.
     218                 :            : const sal_uInt16 FUNCFLAG_MACROCMD          = 0x0080;   /// Function is a macro-sheet command.
     219                 :            : const sal_uInt16 FUNCFLAG_ALWAYSVAR         = 0x0100;   /// Function is always represented by a tFuncVar token.
     220                 :            : const sal_uInt16 FUNCFLAG_PARAMPAIRS        = 0x0200;   /// Optional parameters are expected to appear in pairs.
     221                 :            : 
     222                 :            : /// Converts a function library index (value of enum FunctionLibraryType) to function flags.
     223                 :            : #define FUNCLIB_TO_FUNCFLAGS( funclib_index ) static_cast< sal_uInt16 >( static_cast< sal_uInt8 >( funclib_index ) << 12 )
     224                 :            : /// Extracts a function library index (value of enum FunctionLibraryType) from function flags.
     225                 :            : #define FUNCFLAGS_TO_FUNCLIB( func_flags ) extractValue< FunctionLibraryType >( func_flags, 12, 4 )
     226                 :            : 
     227                 :            : typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef;
     228                 :            : 
     229                 :            : struct FunctionData
     230                 :            : {
     231                 :            :     const sal_Char*     mpcOdfFuncName;     /// ODF function name.
     232                 :            :     const sal_Char*     mpcOoxFuncName;     /// OOXML function name.
     233                 :            :     sal_uInt16          mnBiff12FuncId;     /// BIFF12 function identifier.
     234                 :            :     sal_uInt16          mnBiffFuncId;       /// BIFF2-BIFF8 function identifier.
     235                 :            :     sal_uInt8           mnMinParamCount;    /// Minimum number of parameters.
     236                 :            :     sal_uInt8           mnMaxParamCount;    /// Maximum number of parameters.
     237                 :            :     sal_uInt8           mnRetClass;         /// BIFF token class of the return value.
     238                 :            :     FunctionParamInfo   mpParamInfos[ FUNCINFO_PARAMINFOCOUNT ]; /// Information about all parameters.
     239                 :            :     sal_uInt16          mnFlags;            /// Additional flags.
     240                 :            : 
     241                 :            :     inline bool         isSupported( bool bImportFilter ) const;
     242                 :            : };
     243                 :            : 
     244                 :      10536 : inline bool FunctionData::isSupported( bool bImportFilter ) const
     245                 :            : {
     246                 :            :     /*  For import filters: the FUNCFLAG_EXPORTONLY flag must not be set,
     247                 :            :         for export filters: the FUNCFLAG_IMPORTONLY flag must not be set. */
     248         [ +  - ]:      10536 :     return !getFlag( mnFlags, bImportFilter ? FUNCFLAG_EXPORTONLY : FUNCFLAG_IMPORTONLY );
     249                 :            : }
     250                 :            : 
     251                 :            : const sal_uInt16 NOID = SAL_MAX_UINT16;     /// No BIFF function identifier available.
     252                 :            : const sal_uInt8 MX    = SAL_MAX_UINT8;      /// Maximum parameter count.
     253                 :            : 
     254                 :            : // abbreviations for function return token class
     255                 :            : const sal_uInt8 R = BIFF_TOKCLASS_REF;
     256                 :            : const sal_uInt8 V = BIFF_TOKCLASS_VAL;
     257                 :            : const sal_uInt8 A = BIFF_TOKCLASS_ARR;
     258                 :            : 
     259                 :            : // abbreviations for parameter infos
     260                 :            : #define RO   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_ORG, false }
     261                 :            : #define RV   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_VAL, false }
     262                 :            : #define RA   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_ARR, false }
     263                 :            : #define RR   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_RPT, false }
     264                 :            : #define RX   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_RPX, false }
     265                 :            : #define VO   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_ORG, true  }
     266                 :            : #define VV   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_VAL, true  }
     267                 :            : #define VA   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_ARR, true  }
     268                 :            : #define VR   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_RPT, true  }
     269                 :            : #define VX   { FUNC_PARAM_REGULAR,   FUNC_PARAMCONV_RPX, true  }
     270                 :            : #define RO_E { FUNC_PARAM_EXCELONLY, FUNC_PARAMCONV_ORG, false }
     271                 :            : #define VR_E { FUNC_PARAM_EXCELONLY, FUNC_PARAMCONV_RPT, true  }
     272                 :            : #define C    { FUNC_PARAM_CALCONLY,  FUNC_PARAMCONV_ORG, false }
     273                 :            : 
     274                 :            : // Note: parameter types of all macro sheet functions (FUNCFLAG_MACROFUNC/FUNCFLAG_MACROCMD) untested!
     275                 :            : 
     276                 :            : /** Functions new in BIFF2. */
     277                 :            : static const FunctionData saFuncTableBiff2[] =
     278                 :            : {
     279                 :            :     { "COUNT",                  "COUNT",                0,      0,      0,  MX, V, { RX }, 0 },
     280                 :            :     { "IF",                     "IF",                   1,      1,      2,  3,  R, { VO, RO }, 0 },
     281                 :            :     { "ISNA",                   "ISNA",                 2,      2,      1,  1,  V, { VR }, 0 },
     282                 :            :     { "ISERROR",                "ISERROR",              3,      3,      1,  1,  V, { VR }, 0 },
     283                 :            :     { "SUM",                    "SUM",                  4,      4,      0,  MX, V, { RX }, 0 },
     284                 :            :     { "AVERAGE",                "AVERAGE",              5,      5,      1,  MX, V, { RX }, 0 },
     285                 :            :     { "MIN",                    "MIN",                  6,      6,      1,  MX, V, { RX }, 0 },
     286                 :            :     { "MAX",                    "MAX",                  7,      7,      1,  MX, V, { RX }, 0 },
     287                 :            :     { "ROW",                    "ROW",                  8,      8,      0,  1,  V, { RO }, 0 },
     288                 :            :     { "COLUMN",                 "COLUMN",               9,      9,      0,  1,  V, { RO }, 0 },
     289                 :            :     { "NA",                     "NA",                   10,     10,     0,  0,  V, {}, 0 },
     290                 :            :     { "NPV",                    "NPV",                  11,     11,     2,  MX, V, { VR, RX }, 0 },
     291                 :            :     { "STDEV",                  "STDEV",                12,     12,     1,  MX, V, { RX }, 0 },
     292                 :            :     { "DOLLAR",                 "DOLLAR",               13,     13,     1,  2,  V, { VR }, 0 },
     293                 :            :     { "FIXED",                  "FIXED",                14,     14,     1,  2,  V, { VR, VR, C }, 0 },
     294                 :            :     { "SIN",                    "SIN",                  15,     15,     1,  1,  V, { VR }, 0 },
     295                 :            :     { "CSC",                    "SIN",                  15,     15,     1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     296                 :            :     { "COS",                    "COS",                  16,     16,     1,  1,  V, { VR }, 0 },
     297                 :            :     { "SEC",                    "COS",                  16,     16,     1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     298                 :            :     { "TAN",                    "TAN",                  17,     17,     1,  1,  V, { VR }, 0 },
     299                 :            :     { "COT",                    "TAN",                  17,     17,     1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     300                 :            :     { "ATAN",                   "ATAN",                 18,     18,     1,  1,  V, { VR }, 0 },
     301                 :            :     { "ACOT",                   "ATAN",                 18,     18,     1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     302                 :            :     { "PI",                     "PI",                   19,     19,     0,  0,  V, {}, 0 },
     303                 :            :     { "SQRT",                   "SQRT",                 20,     20,     1,  1,  V, { VR }, 0 },
     304                 :            :     { "EXP",                    "EXP",                  21,     21,     1,  1,  V, { VR }, 0 },
     305                 :            :     { "LN",                     "LN",                   22,     22,     1,  1,  V, { VR }, 0 },
     306                 :            :     { "LOG10",                  "LOG10",                23,     23,     1,  1,  V, { VR }, 0 },
     307                 :            :     { "ABS",                    "ABS",                  24,     24,     1,  1,  V, { VR }, 0 },
     308                 :            :     { "INT",                    "INT",                  25,     25,     1,  1,  V, { VR }, 0 },
     309                 :            :     { "SIGN",                   "SIGN",                 26,     26,     1,  1,  V, { VR }, 0 },
     310                 :            :     { "ROUND",                  "ROUND",                27,     27,     2,  2,  V, { VR }, 0 },
     311                 :            :     { "LOOKUP",                 "LOOKUP",               28,     28,     2,  3,  V, { VR, RA }, 0 },
     312                 :            :     { "INDEX",                  "INDEX",                29,     29,     2,  4,  R, { RA, VV }, 0 },
     313                 :            :     { "REPT",                   "REPT",                 30,     30,     2,  2,  V, { VR }, 0 },
     314                 :            :     { "MID",                    "MID",                  31,     31,     3,  3,  V, { VR }, 0 },
     315                 :            :     { "LEN",                    "LEN",                  32,     32,     1,  1,  V, { VR }, 0 },
     316                 :            :     { "VALUE",                  "VALUE",                33,     33,     1,  1,  V, { VR }, 0 },
     317                 :            :     { "TRUE",                   "TRUE",                 34,     34,     0,  0,  V, {}, 0 },
     318                 :            :     { "FALSE",                  "FALSE",                35,     35,     0,  0,  V, {}, 0 },
     319                 :            :     { "AND",                    "AND",                  36,     36,     1,  MX, V, { RX }, 0 },
     320                 :            :     { "OR",                     "OR",                   37,     37,     1,  MX, V, { RX }, 0 },
     321                 :            :     { "NOT",                    "NOT",                  38,     38,     1,  1,  V, { VR }, 0 },
     322                 :            :     { "MOD",                    "MOD",                  39,     39,     2,  2,  V, { VR }, 0 },
     323                 :            :     { "DCOUNT",                 "DCOUNT",               40,     40,     3,  3,  V, { RO, RR }, 0 },
     324                 :            :     { "DSUM",                   "DSUM",                 41,     41,     3,  3,  V, { RO, RR }, 0 },
     325                 :            :     { "DAVERAGE",               "DAVERAGE",             42,     42,     3,  3,  V, { RO, RR }, 0 },
     326                 :            :     { "DMIN",                   "DMIN",                 43,     43,     3,  3,  V, { RO, RR }, 0 },
     327                 :            :     { "DMAX",                   "DMAX",                 44,     44,     3,  3,  V, { RO, RR }, 0 },
     328                 :            :     { "DSTDEV",                 "DSTDEV",               45,     45,     3,  3,  V, { RO, RR }, 0 },
     329                 :            :     { "VAR",                    "VAR",                  46,     46,     1,  MX, V, { RX }, 0 },
     330                 :            :     { "DVAR",                   "DVAR",                 47,     47,     3,  3,  V, { RO, RR }, 0 },
     331                 :            :     { "TEXT",                   "TEXT",                 48,     48,     2,  2,  V, { VR }, 0 },
     332                 :            :     { "LINEST",                 "LINEST",               49,     49,     1,  2,  A, { RA, RA, C, C }, 0 },
     333                 :            :     { "TREND",                  "TREND",                50,     50,     1,  3,  A, { RA, RA, RA, C }, 0 },
     334                 :            :     { "LOGEST",                 "LOGEST",               51,     51,     1,  2,  A, { RA, RA, C, C }, 0 },
     335                 :            :     { "GROWTH",                 "GROWTH",               52,     52,     1,  3,  A, { RA, RA, RA, C }, 0 },
     336                 :            :     { "PV",                     "PV",                   56,     56,     3,  5,  V, { VR }, 0 },
     337                 :            :     { "FV",                     "FV",                   57,     57,     3,  5,  V, { VR }, 0 },
     338                 :            :     { "NPER",                   "NPER",                 58,     58,     3,  5,  V, { VR }, 0 },
     339                 :            :     { "PMT",                    "PMT",                  59,     59,     3,  5,  V, { VR }, 0 },
     340                 :            :     { "RATE",                   "RATE",                 60,     60,     3,  6,  V, { VR }, 0 },
     341                 :            :     { "MIRR",                   "MIRR",                 61,     61,     3,  3,  V, { RA, VR }, 0 },
     342                 :            :     { "IRR",                    "IRR",                  62,     62,     1,  2,  V, { RA, VR }, 0 },
     343                 :            :     { "RAND",                   "RAND",                 63,     63,     0,  0,  V, {}, FUNCFLAG_VOLATILE },
     344                 :            :     { "MATCH",                  "MATCH",                64,     64,     2,  3,  V, { VR, RX, RR }, 0 },
     345                 :            :     { "DATE",                   "DATE",                 65,     65,     3,  3,  V, { VR }, 0 },
     346                 :            :     { "TIME",                   "TIME",                 66,     66,     3,  3,  V, { VR }, 0 },
     347                 :            :     { "DAY",                    "DAY",                  67,     67,     1,  1,  V, { VR }, 0 },
     348                 :            :     { "MONTH",                  "MONTH",                68,     68,     1,  1,  V, { VR }, 0 },
     349                 :            :     { "YEAR",                   "YEAR",                 69,     69,     1,  1,  V, { VR }, 0 },
     350                 :            :     { "WEEKDAY",                "WEEKDAY",              70,     70,     1,  1,  V, { VR, C }, 0 },
     351                 :            :     { "HOUR",                   "HOUR",                 71,     71,     1,  1,  V, { VR }, 0 },
     352                 :            :     { "MINUTE",                 "MINUTE",               72,     72,     1,  1,  V, { VR }, 0 },
     353                 :            :     { "SECOND",                 "SECOND",               73,     73,     1,  1,  V, { VR }, 0 },
     354                 :            :     { "NOW",                    "NOW",                  74,     74,     0,  0,  V, {}, FUNCFLAG_VOLATILE },
     355                 :            :     { "AREAS",                  "AREAS",                75,     75,     1,  1,  V, { RO }, 0 },
     356                 :            :     { "ROWS",                   "ROWS",                 76,     76,     1,  1,  V, { RO }, 0 },
     357                 :            :     { "COLUMNS",                "COLUMNS",              77,     77,     1,  1,  V, { RO }, 0 },
     358                 :            :     { "OFFSET",                 "OFFSET",               78,     78,     3,  5,  R, { RO, VR }, FUNCFLAG_VOLATILE },
     359                 :            :     { "SEARCH",                 "SEARCH",               82,     82,     2,  3,  V, { VR }, 0 },
     360                 :            :     { "TRANSPOSE",              "TRANSPOSE",            83,     83,     1,  1,  A, { VO }, 0 },
     361                 :            :     { "TYPE",                   "TYPE",                 86,     86,     1,  1,  V, { VX }, 0 },
     362                 :            :     { "ATAN2",                  "ATAN2",                97,     97,     2,  2,  V, { VR }, 0 },
     363                 :            :     { "ASIN",                   "ASIN",                 98,     98,     1,  1,  V, { VR }, 0 },
     364                 :            :     { "ACOS",                   "ACOS",                 99,     99,     1,  1,  V, { VR }, 0 },
     365                 :            :     { "CHOOSE",                 "CHOOSE",               100,    100,    2,  MX, R, { VO, RO }, 0 },
     366                 :            :     { "HLOOKUP",                "HLOOKUP",              101,    101,    3,  3,  V, { VV, RO, RO, C }, 0 },
     367                 :            :     { "VLOOKUP",                "VLOOKUP",              102,    102,    3,  3,  V, { VV, RO, RO, C }, 0 },
     368                 :            :     { "ISREF",                  "ISREF",                105,    105,    1,  1,  V, { RX }, 0 },
     369                 :            :     { "LOG",                    "LOG",                  109,    109,    1,  2,  V, { VR }, 0 },
     370                 :            :     { "CHAR",                   "CHAR",                 111,    111,    1,  1,  V, { VR }, 0 },
     371                 :            :     { "LOWER",                  "LOWER",                112,    112,    1,  1,  V, { VR }, 0 },
     372                 :            :     { "UPPER",                  "UPPER",                113,    113,    1,  1,  V, { VR }, 0 },
     373                 :            :     { "PROPER",                 "PROPER",               114,    114,    1,  1,  V, { VR }, 0 },
     374                 :            :     { "LEFT",                   "LEFT",                 115,    115,    1,  2,  V, { VR }, 0 },
     375                 :            :     { "RIGHT",                  "RIGHT",                116,    116,    1,  2,  V, { VR }, 0 },
     376                 :            :     { "EXACT",                  "EXACT",                117,    117,    2,  2,  V, { VR }, 0 },
     377                 :            :     { "TRIM",                   "TRIM",                 118,    118,    1,  1,  V, { VR }, 0 },
     378                 :            :     { "REPLACE",                "REPLACE",              119,    119,    4,  4,  V, { VR }, 0 },
     379                 :            :     { "SUBSTITUTE",             "SUBSTITUTE",           120,    120,    3,  4,  V, { VR }, 0 },
     380                 :            :     { "CODE",                   "CODE",                 121,    121,    1,  1,  V, { VR }, 0 },
     381                 :            :     { "FIND",                   "FIND",                 124,    124,    2,  3,  V, { VR }, 0 },
     382                 :            :     { "CELL",                   "CELL",                 125,    125,    1,  2,  V, { VV, RO }, FUNCFLAG_VOLATILE },
     383                 :            :     { "ISERR",                  "ISERR",                126,    126,    1,  1,  V, { VR }, 0 },
     384                 :            :     { "ISTEXT",                 "ISTEXT",               127,    127,    1,  1,  V, { VR }, 0 },
     385                 :            :     { "ISNUMBER",               "ISNUMBER",             128,    128,    1,  1,  V, { VR }, 0 },
     386                 :            :     { "ISBLANK",                "ISBLANK",              129,    129,    1,  1,  V, { VR }, 0 },
     387                 :            :     { "T",                      "T",                    130,    130,    1,  1,  V, { RO }, 0 },
     388                 :            :     { "N",                      "N",                    131,    131,    1,  1,  V, { RO }, 0 },
     389                 :            :     { "DATEVALUE",              "DATEVALUE",            140,    140,    1,  1,  V, { VR }, 0 },
     390                 :            :     { "TIMEVALUE",              "TIMEVALUE",            141,    141,    1,  1,  V, { VR }, 0 },
     391                 :            :     { "SLN",                    "SLN",                  142,    142,    3,  3,  V, { VR }, 0 },
     392                 :            :     { "SYD",                    "SYD",                  143,    143,    4,  4,  V, { VR }, 0 },
     393                 :            :     { "DDB",                    "DDB",                  144,    144,    4,  5,  V, { VR }, 0 },
     394                 :            :     { "INDIRECT",               "INDIRECT",             148,    148,    1,  2,  R, { VR }, FUNCFLAG_VOLATILE },
     395                 :            :     { "CLEAN",                  "CLEAN",                162,    162,    1,  1,  V, { VR }, 0 },
     396                 :            :     { "MDETERM",                "MDETERM",              163,    163,    1,  1,  V, { VA }, 0 },
     397                 :            :     { "MINVERSE",               "MINVERSE",             164,    164,    1,  1,  A, { VA }, 0 },
     398                 :            :     { "MMULT",                  "MMULT",                165,    165,    2,  2,  A, { VA }, 0 },
     399                 :            :     { "IPMT",                   "IPMT",                 167,    167,    4,  6,  V, { VR }, 0 },
     400                 :            :     { "PPMT",                   "PPMT",                 168,    168,    4,  6,  V, { VR }, 0 },
     401                 :            :     { "COUNTA",                 "COUNTA",               169,    169,    0,  MX, V, { RX }, 0 },
     402                 :            :     { "PRODUCT",                "PRODUCT",              183,    183,    0,  MX, V, { RX }, 0 },
     403                 :            :     { "FACT",                   "FACT",                 184,    184,    1,  1,  V, { VR }, 0 },
     404                 :            :     { "DPRODUCT",               "DPRODUCT",             189,    189,    3,  3,  V, { RO, RR }, 0 },
     405                 :            :     { "ISNONTEXT",              "ISNONTEXT",            190,    190,    1,  1,  V, { VR }, 0 },
     406                 :            :     { "STDEVP",                 "STDEVP",               193,    193,    1,  MX, V, { RX }, 0 },
     407                 :            :     { "VARP",                   "VARP",                 194,    194,    1,  MX, V, { RX }, 0 },
     408                 :            :     { "DSTDEVP",                "DSTDEVP",              195,    195,    3,  3,  V, { RO, RR }, 0 },
     409                 :            :     { "DVARP",                  "DVARP",                196,    196,    3,  3,  V, { RO, RR }, 0 },
     410                 :            :     { "TRUNC",                  "TRUNC",                197,    197,    1,  1,  V, { VR, C }, 0 },
     411                 :            :     { "ISLOGICAL",              "ISLOGICAL",            198,    198,    1,  1,  V, { VR }, 0 },
     412                 :            :     { "DCOUNTA",                "DCOUNTA",              199,    199,    3,  3,  V, { RO, RR }, 0 },
     413                 :            :     { 0,                        "EXTERN.CALL",          255,    255,    1,  MX, R, { RO_E, RO }, FUNCFLAG_IMPORTONLY },
     414                 :            : 
     415                 :            :     // *** macro sheet commands ***
     416                 :            : 
     417                 :            :     { 0,                        "A1.R1C1",              30,     30,     0,  1,  V, { VR }, FUNCFLAG_MACROCMD },
     418                 :            :     { 0,                        "RETURN",               55,     55,     0,  1,  R, { RO }, FUNCFLAG_MACROFUNC },
     419                 :            :     { 0,                        "ABSREF",               79,     79,     2,  2,  R, { VR, RO }, FUNCFLAG_MACROFUNC },
     420                 :            :     { 0,                        "ADD.ARROW",            81,     81,     0,  0,  V, {}, FUNCFLAG_MACROCMD },
     421                 :            :     { 0,                        "ACTIVE.CELL",          94,     94,     0,  0,  R, {}, FUNCFLAG_MACROFUNC },
     422                 :            :     { 0,                        "ACTIVATE",             103,    103,    0,  2,  V, { VR }, FUNCFLAG_MACROCMD },
     423                 :            :     { 0,                        "ACTIVATE.NEXT",        104,    104,    0,  0,  V, {}, FUNCFLAG_MACROCMD },
     424                 :            :     { 0,                        "ACTIVATE.PREV",        105,    105,    0,  0,  V, {}, FUNCFLAG_MACROCMD },
     425                 :            :     { 0,                        "ADD.BAR",              151,    151,    0,  0,  V, {}, FUNCFLAG_MACROFUNC | FUNCFLAG_ALWAYSVAR },
     426                 :            :     { 0,                        "ADD.MENU",             152,    152,    2,  2,  V, { VR, RO }, FUNCFLAG_MACROFUNC | FUNCFLAG_ALWAYSVAR },
     427                 :            :     { 0,                        "ADD.COMMAND",          153,    153,    3,  3,  V, { VR, RO }, FUNCFLAG_MACROFUNC | FUNCFLAG_ALWAYSVAR }
     428                 :            : };
     429                 :            : 
     430                 :            : /** Functions new in BIFF3. */
     431                 :            : static const FunctionData saFuncTableBiff3[] =
     432                 :            : {
     433                 :            :     { "LINEST",                 "LINEST",               49,     49,     1,  4,  A, { RA, RA, VV }, 0 },             // BIFF2: 1-2, BIFF3: 1-4
     434                 :            :     { "TREND",                  "TREND",                50,     50,     1,  4,  A, { RA, RA, RA, VV }, 0 },             // BIFF2: 1-3, BIFF3: 1-4
     435                 :            :     { "LOGEST",                 "LOGEST",               51,     51,     1,  4,  A, { RA, RA, VV }, 0 },             // BIFF2: 1-2, BIFF3: 1-4
     436                 :            :     { "GROWTH",                 "GROWTH",               52,     52,     1,  4,  A, { RA, RA, RA, VV }, 0 },             // BIFF2: 1-3, BIFF3: 1-4
     437                 :            :     { "TRUNC",                  "TRUNC",                197,    197,    1,  2,  V, { VR }, 0 },                      // BIFF2: 1,   BIFF3: 1-2
     438                 :            :     { "DOLLAR",                 "USDOLLAR",             204,    204,    1,  2,  V, { VR }, FUNCFLAG_IMPORTONLY },
     439                 :            :     { 0/*"FIND"*/,              "FINDB",                205,    205,    2,  3,  V, { VR }, 0 },
     440                 :            :     { 0/*"SEARCH"*/,            "SEARCHB",              206,    206,    2,  3,  V, { VR }, 0 },
     441                 :            :     { 0/*"REPLACE"*/,           "REPLACEB",             207,    207,    4,  4,  V, { VR }, 0 },
     442                 :            :     { 0/*"LEFT"*/,              "LEFTB",                208,    208,    1,  2,  V, { VR }, 0 },
     443                 :            :     { 0/*"RIGHT"*/,             "RIGHTB",               209,    209,    1,  2,  V, { VR }, 0 },
     444                 :            :     { 0/*"MID"*/,               "MIDB",                 210,    210,    3,  3,  V, { VR }, 0 },
     445                 :            :     { 0/*"LEN"*/,               "LENB",                 211,    211,    1,  1,  V, { VR }, 0 },
     446                 :            :     { "ROUNDUP",                "ROUNDUP",              212,    212,    2,  2,  V, { VR }, 0 },
     447                 :            :     { "ROUNDDOWN",              "ROUNDDOWN",            213,    213,    2,  2,  V, { VR }, 0 },
     448                 :            :     { "ASC",                    "ASC",                  214,    214,    1,  1,  V, { VR }, 0 },
     449                 :            :     { "JIS",                    "DBCS",                 215,    215,    1,  1,  V, { VR }, 0 },
     450                 :            :     { "ADDRESS",                "ADDRESS",              219,    219,    2,  5,  V, { VR }, 0 },
     451                 :            :     { "DAYS360",                "DAYS360",              220,    220,    2,  2,  V, { VR, VR, C }, 0 },
     452                 :            :     { "TODAY",                  "TODAY",                221,    221,    0,  0,  V, {}, FUNCFLAG_VOLATILE },
     453                 :            :     { "VDB",                    "VDB",                  222,    222,    5,  7,  V, { VR }, 0 },
     454                 :            :     { "MEDIAN",                 "MEDIAN",               227,    227,    1,  MX, V, { RX }, 0 },
     455                 :            :     { "SUMPRODUCT",             "SUMPRODUCT",           228,    228,    1,  MX, V, { VA }, 0 },
     456                 :            :     { "SINH",                   "SINH",                 229,    229,    1,  1,  V, { VR }, 0 },
     457                 :            :     { "CSCH",                   "SINH",                 229,    229,    1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     458                 :            :     { "COSH",                   "COSH",                 230,    230,    1,  1,  V, { VR }, 0 },
     459                 :            :     { "SECH",                   "COSH",                 230,    230,    1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     460                 :            :     { "TANH",                   "TANH",                 231,    231,    1,  1,  V, { VR }, 0 },
     461                 :            :     { "COTH",                   "TANH",                 231,    231,    1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     462                 :            :     { "ASINH",                  "ASINH",                232,    232,    1,  1,  V, { VR }, 0 },
     463                 :            :     { "ACOSH",                  "ACOSH",                233,    233,    1,  1,  V, { VR }, 0 },
     464                 :            :     { "ATANH",                  "ATANH",                234,    234,    1,  1,  V, { VR }, 0 },
     465                 :            :     { "ACOTH",                  "ATANH",                234,    234,    1,  1,  V, { VR }, FUNCFLAG_EXPORTONLY },
     466                 :            :     { "DGET",                   "DGET",                 235,    235,    3,  3,  V, { RO, RR }, 0 },
     467                 :            :     { "INFO",                   "INFO",                 244,    244,    1,  1,  V, { VR }, FUNCFLAG_VOLATILE },
     468                 :            : 
     469                 :            :     // *** macro sheet commands ***
     470                 :            : 
     471                 :            :     { 0,                        "ADD.BAR",              151,    151,    0,  1,  V, { VR }, FUNCFLAG_MACROFUNC },    // BIFF2: 0,   BIFF3: 0-1
     472                 :            :     { 0,                        "ADD.MENU",             152,    152,    2,  3,  V, { VR, RO }, FUNCFLAG_MACROFUNC },  // BIFF2: 2,   BIFF3: 2-3
     473                 :            :     { 0,                        "ADD.COMMAND",          153,    153,    3,  4,  V, { VR, RO }, FUNCFLAG_MACROFUNC }   // BIFF2: 3,   BIFF3: 3-4
     474                 :            : };
     475                 :            : 
     476                 :            : /** Functions new in BIFF4. */
     477                 :            : static const FunctionData saFuncTableBiff4[] =
     478                 :            : {
     479                 :            :     { "FIXED",                  "FIXED",                14,     14,     1,  3,  V, { VR }, 0 },       // BIFF2-3: 1-2, BIFF4: 1-3
     480                 :            :     { "RANK",                   "RANK",                 216,    216,    2,  3,  V, { VR, RO, VR }, 0 },
     481                 :            :     { "DB",                     "DB",                   247,    247,    4,  5,  V, { VR }, 0 },
     482                 :            :     { "FREQUENCY",              "FREQUENCY",            252,    252,    2,  2,  A, { RA }, 0 },
     483                 :            :     { "ORG.OPENOFFICE.ERRORTYPE","ERROR.TYPE",          261,    261,    1,  1,  V, { VR }, 0 },
     484                 :            :     { "AVEDEV",                 "AVEDEV",               269,    269,    1,  MX, V, { RX }, 0 },
     485                 :            :     { "BETADIST",               "BETADIST",             270,    270,    3,  5,  V, { VR }, 0 },
     486                 :            :     { "GAMMALN",                "GAMMALN",              271,    271,    1,  1,  V, { VR }, 0 },
     487                 :            :     { "BETAINV",                "BETAINV",              272,    272,    3,  5,  V, { VR }, 0 },
     488                 :            :     { "BINOMDIST",              "BINOMDIST",            273,    273,    4,  4,  V, { VR }, 0 },
     489                 :            :     { "LEGACY.CHIDIST",         "CHIDIST",              274,    274,    2,  2,  V, { VR }, 0 },
     490                 :            :     { "LEGACY.CHIINV",          "CHIINV",               275,    275,    2,  2,  V, { VR }, 0 },
     491                 :            :     { "COMBIN",                 "COMBIN",               276,    276,    2,  2,  V, { VR }, 0 },
     492                 :            :     { "CONFIDENCE",             "CONFIDENCE",           277,    277,    3,  3,  V, { VR }, 0 },
     493                 :            :     { "CRITBINOM",              "CRITBINOM",            278,    278,    3,  3,  V, { VR }, 0 },
     494                 :            :     { "EVEN",                   "EVEN",                 279,    279,    1,  1,  V, { VR }, 0 },
     495                 :            :     { "EXPONDIST",              "EXPONDIST",            280,    280,    3,  3,  V, { VR }, 0 },
     496                 :            :     { "LEGACY.FDIST",           "FDIST",                281,    281,    3,  3,  V, { VR }, 0 },
     497                 :            :     { "LEGACY.FINV",            "FINV",                 282,    282,    3,  3,  V, { VR }, 0 },
     498                 :            :     { "FISHER",                 "FISHER",               283,    283,    1,  1,  V, { VR }, 0 },
     499                 :            :     { "FISHERINV",              "FISHERINV",            284,    284,    1,  1,  V, { VR }, 0 },
     500                 :            :     { "FLOOR",                  "FLOOR",                285,    285,    2,  2,  V, { VR, VR, C }, 0 },
     501                 :            :     { "GAMMADIST",              "GAMMADIST",            286,    286,    4,  4,  V, { VR }, 0 },
     502                 :            :     { "GAMMAINV",               "GAMMAINV",             287,    287,    3,  3,  V, { VR }, 0 },
     503                 :            :     { "CEILING",                "CEILING",              288,    288,    2,  2,  V, { VR, VR, C }, 0 },
     504                 :            :     { "HYPGEOMDIST",            "HYPGEOMDIST",          289,    289,    4,  4,  V, { VR }, 0 },
     505                 :            :     { "LOGNORMDIST",            "LOGNORMDIST",          290,    290,    3,  3,  V, { VR }, 0 },
     506                 :            :     { "LOGINV",                 "LOGINV",               291,    291,    3,  3,  V, { VR }, 0 },
     507                 :            :     { "NEGBINOMDIST",           "NEGBINOMDIST",         292,    292,    3,  3,  V, { VR }, 0 },
     508                 :            :     { "NORMDIST",               "NORMDIST",             293,    293,    4,  4,  V, { VR }, 0 },
     509                 :            :     { "LEGACY.NORMSDIST",       "NORMSDIST",            294,    294,    1,  1,  V, { VR }, 0 },
     510                 :            :     { "NORMINV",                "NORMINV",              295,    295,    3,  3,  V, { VR }, 0 },
     511                 :            :     { "LEGACY.NORMSINV",        "NORMSINV",             296,    296,    1,  1,  V, { VR }, 0 },
     512                 :            :     { "STANDARDIZE",            "STANDARDIZE",          297,    297,    3,  3,  V, { VR }, 0 },
     513                 :            :     { "ODD",                    "ODD",                  298,    298,    1,  1,  V, { VR }, 0 },
     514                 :            :     { "PERMUT",                 "PERMUT",               299,    299,    2,  2,  V, { VR }, 0 },
     515                 :            :     { "POISSON",                "POISSON",              300,    300,    3,  3,  V, { VR }, 0 },
     516                 :            :     { "TDIST",                  "TDIST",                301,    301,    3,  3,  V, { VR }, 0 },
     517                 :            :     { "WEIBULL",                "WEIBULL",              302,    302,    4,  4,  V, { VR }, 0 },
     518                 :            :     { "SUMXMY2",                "SUMXMY2",              303,    303,    2,  2,  V, { VA }, 0 },
     519                 :            :     { "SUMX2MY2",               "SUMX2MY2",             304,    304,    2,  2,  V, { VA }, 0 },
     520                 :            :     { "SUMX2PY2",               "SUMX2PY2",             305,    305,    2,  2,  V, { VA }, 0 },
     521                 :            :     { "LEGACY.CHITEST",         "CHITEST",              306,    306,    2,  2,  V, { VA }, 0 },
     522                 :            :     { "CORREL",                 "CORREL",               307,    307,    2,  2,  V, { VA }, 0 },
     523                 :            :     { "COVAR",                  "COVAR",                308,    308,    2,  2,  V, { VA }, 0 },
     524                 :            :     { "FORECAST",               "FORECAST",             309,    309,    3,  3,  V, { VR, VA }, 0 },
     525                 :            :     { "FTEST",                  "FTEST",                310,    310,    2,  2,  V, { VA }, 0 },
     526                 :            :     { "INTERCEPT",              "INTERCEPT",            311,    311,    2,  2,  V, { VA }, 0 },
     527                 :            :     { "PEARSON",                "PEARSON",              312,    312,    2,  2,  V, { VA }, 0 },
     528                 :            :     { "RSQ",                    "RSQ",                  313,    313,    2,  2,  V, { VA }, 0 },
     529                 :            :     { "STEYX",                  "STEYX",                314,    314,    2,  2,  V, { VA }, 0 },
     530                 :            :     { "SLOPE",                  "SLOPE",                315,    315,    2,  2,  V, { VA }, 0 },
     531                 :            :     { "TTEST",                  "TTEST",                316,    316,    4,  4,  V, { VA, VA, VR }, 0 },
     532                 :            :     { "PROB",                   "PROB",                 317,    317,    3,  4,  V, { VA, VA, VR }, 0 },
     533                 :            :     { "DEVSQ",                  "DEVSQ",                318,    318,    1,  MX, V, { RX }, 0 },
     534                 :            :     { "GEOMEAN",                "GEOMEAN",              319,    319,    1,  MX, V, { RX }, 0 },
     535                 :            :     { "HARMEAN",                "HARMEAN",              320,    320,    1,  MX, V, { RX }, 0 },
     536                 :            :     { "SUMSQ",                  "SUMSQ",                321,    321,    0,  MX, V, { RX }, 0 },
     537                 :            :     { "KURT",                   "KURT",                 322,    322,    1,  MX, V, { RX }, 0 },
     538                 :            :     { "SKEW",                   "SKEW",                 323,    323,    1,  MX, V, { RX }, 0 },
     539                 :            :     { "ZTEST",                  "ZTEST",                324,    324,    2,  3,  V, { RX, VR }, 0 },
     540                 :            :     { "LARGE",                  "LARGE",                325,    325,    2,  2,  V, { RX, VR }, 0 },
     541                 :            :     { "SMALL",                  "SMALL",                326,    326,    2,  2,  V, { RX, VR }, 0 },
     542                 :            :     { "QUARTILE",               "QUARTILE",             327,    327,    2,  2,  V, { RX, VR }, 0 },
     543                 :            :     { "PERCENTILE",             "PERCENTILE",           328,    328,    2,  2,  V, { RX, VR }, 0 },
     544                 :            :     { "PERCENTRANK",            "PERCENTRANK",          329,    329,    2,  3,  V, { RX, VR, VR_E }, 0 },
     545                 :            :     { "MODE",                   "MODE",                 330,    330,    1,  MX, V, { VA }, 0 },
     546                 :            :     { "TRIMMEAN",               "TRIMMEAN",             331,    331,    2,  2,  V, { RX, VR }, 0 },
     547                 :            :     { "TINV",                   "TINV",                 332,    332,    2,  2,  V, { VR }, 0 },
     548                 :            : 
     549                 :            :     // *** Analysis add-in ***
     550                 :            : 
     551                 :            :     { "HEX2BIN",                "HEX2BIN",              384,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     552                 :            :     { "HEX2DEC",                "HEX2DEC",              385,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     553                 :            :     { "HEX2OCT",                "HEX2OCT",              386,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     554                 :            :     { "DEC2BIN",                "DEC2BIN",              387,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     555                 :            :     { "DEC2HEX",                "DEC2HEX",              388,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     556                 :            :     { "DEC2OCT",                "DEC2OCT",              389,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     557                 :            :     { "OCT2BIN",                "OCT2BIN",              390,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     558                 :            :     { "OCT2HEX",                "OCT2HEX",              391,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     559                 :            :     { "OCT2DEC",                "OCT2DEC",              392,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     560                 :            :     { "BIN2DEC",                "BIN2DEC",              393,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     561                 :            :     { "BIN2OCT",                "BIN2OCT",              394,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     562                 :            :     { "BIN2HEX",                "BIN2HEX",              395,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     563                 :            :     { "IMSUB",                  "IMSUB",                396,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     564                 :            :     { "IMDIV",                  "IMDIV",                397,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     565                 :            :     { "IMPOWER",                "IMPOWER",              398,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     566                 :            :     { "IMABS",                  "IMABS",                399,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     567                 :            :     { "IMSQRT",                 "IMSQRT",               400,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     568                 :            :     { "IMLN",                   "IMLN",                 401,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     569                 :            :     { "IMLOG2",                 "IMLOG2",               402,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     570                 :            :     { "IMLOG10",                "IMLOG10",              403,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     571                 :            :     { "IMSIN",                  "IMSIN",                404,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     572                 :            :     { "IMCOS",                  "IMCOS",                405,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     573                 :            :     { "IMEXP",                  "IMEXP",                406,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     574                 :            :     { "IMARGUMENT",             "IMARGUMENT",           407,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     575                 :            :     { "IMCONJUGATE",            "IMCONJUGATE",          408,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     576                 :            :     { "IMAGINARY",              "IMAGINARY",            409,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     577                 :            :     { "IMREAL",                 "IMREAL",               410,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     578                 :            :     { "COMPLEX",                "COMPLEX",              411,    NOID,   2,  3,  V, { RR }, FUNCFLAG_EXTERNAL },
     579                 :            :     { "IMSUM",                  "IMSUM",                412,    NOID,   1,  MX, V, { RX }, FUNCFLAG_EXTERNAL },
     580                 :            :     { "IMPRODUCT",              "IMPRODUCT",            413,    NOID,   1,  MX, V, { RX }, FUNCFLAG_EXTERNAL },
     581                 :            :     { "SERIESSUM",              "SERIESSUM",            414,    NOID,   4,  4,  V, { RR, RR, RR, RX }, FUNCFLAG_EXTERNAL },
     582                 :            :     { "FACTDOUBLE",             "FACTDOUBLE",           415,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     583                 :            :     { "SQRTPI",                 "SQRTPI",               416,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     584                 :            :     { "QUOTIENT",               "QUOTIENT",             417,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     585                 :            :     { "DELTA",                  "DELTA",                418,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     586                 :            :     { "GESTEP",                 "GESTEP",               419,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     587                 :            :     { "ISEVEN",                 "ISEVEN",               420,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     588                 :            :     { "ISODD",                  "ISODD",                421,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     589                 :            :     { "MROUND",                 "MROUND",               422,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     590                 :            :     { "ERF",                    "ERF",                  423,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     591                 :            :     { "ERFC",                   "ERFC",                 424,    NOID,   1,  1,  V, { RR }, FUNCFLAG_EXTERNAL },
     592                 :            :     { "BESSELJ",                "BESSELJ",              425,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     593                 :            :     { "BESSELK",                "BESSELK",              426,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     594                 :            :     { "BESSELY",                "BESSELY",              427,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     595                 :            :     { "BESSELI",                "BESSELI",              428,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     596                 :            :     { "XIRR",                   "XIRR",                 429,    NOID,   2,  3,  V, { RX, RX, RR }, FUNCFLAG_EXTERNAL },
     597                 :            :     { "XNPV",                   "XNPV",                 430,    NOID,   3,  3,  V, { RR, RX, RX }, FUNCFLAG_EXTERNAL },
     598                 :            :     { "PRICEMAT",               "PRICEMAT",             431,    NOID,   5,  6,  V, { RR }, FUNCFLAG_EXTERNAL },
     599                 :            :     { "YIELDMAT",               "YIELDMAT",             432,    NOID,   5,  6,  V, { RR }, FUNCFLAG_EXTERNAL },
     600                 :            :     { "INTRATE",                "INTRATE",              433,    NOID,   4,  5,  V, { RR }, FUNCFLAG_EXTERNAL },
     601                 :            :     { "RECEIVED",               "RECEIVED",             434,    NOID,   4,  5,  V, { RR }, FUNCFLAG_EXTERNAL },
     602                 :            :     { "DISC",                   "DISC",                 435,    NOID,   4,  5,  V, { RR }, FUNCFLAG_EXTERNAL },
     603                 :            :     { "PRICEDISC",              "PRICEDISC",            436,    NOID,   4,  5,  V, { RR }, FUNCFLAG_EXTERNAL },
     604                 :            :     { "YIELDDISC",              "YIELDDISC",            437,    NOID,   4,  5,  V, { RR }, FUNCFLAG_EXTERNAL },
     605                 :            :     { "TBILLEQ",                "TBILLEQ",              438,    NOID,   3,  3,  V, { RR }, FUNCFLAG_EXTERNAL },
     606                 :            :     { "TBILLPRICE",             "TBILLPRICE",           439,    NOID,   3,  3,  V, { RR }, FUNCFLAG_EXTERNAL },
     607                 :            :     { "TBILLYIELD",             "TBILLYIELD",           440,    NOID,   3,  3,  V, { RR }, FUNCFLAG_EXTERNAL },
     608                 :            :     { "PRICE",                  "PRICE",                441,    NOID,   6,  7,  V, { RR }, FUNCFLAG_EXTERNAL },
     609                 :            :     { "YIELD",                  "YIELD",                442,    NOID,   6,  7,  V, { RR }, FUNCFLAG_EXTERNAL },
     610                 :            :     { "DOLLARDE",               "DOLLARDE",             443,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     611                 :            :     { "DOLLARFR",               "DOLLARFR",             444,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     612                 :            :     { "NOMINAL",                "NOMINAL",              445,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     613                 :            :     { "EFFECT",                 "EFFECT",               446,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     614                 :            :     { "CUMPRINC",               "CUMPRINC",             447,    NOID,   6,  6,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     615                 :            :     { "CUMIPMT",                "CUMIPMT",              448,    NOID,   6,  6,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     616                 :            :     { "EDATE",                  "EDATE",                449,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     617                 :            :     { "EOMONTH",                "EOMONTH",              450,    NOID,   2,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     618                 :            :     { "YEARFRAC",               "YEARFRAC",             451,    NOID,   2,  3,  V, { RR }, FUNCFLAG_EXTERNAL },
     619                 :            :     { "COUPDAYBS",              "COUPDAYBS",            452,    NOID,   3,  4,  V, { RR }, FUNCFLAG_EXTERNAL },
     620                 :            :     { "COUPDAYS",               "COUPDAYS",             453,    NOID,   3,  4,  V, { RR }, FUNCFLAG_EXTERNAL },
     621                 :            :     { "COUPDAYSNC",             "COUPDAYSNC",           454,    NOID,   3,  4,  V, { RR }, FUNCFLAG_EXTERNAL },
     622                 :            :     { "COUPNCD",                "COUPNCD",              455,    NOID,   3,  4,  V, { RR }, FUNCFLAG_EXTERNAL },
     623                 :            :     { "COUPNUM",                "COUPNUM",              456,    NOID,   3,  4,  V, { RR }, FUNCFLAG_EXTERNAL },
     624                 :            :     { "COUPPCD",                "COUPPCD",              457,    NOID,   3,  4,  V, { RR }, FUNCFLAG_EXTERNAL },
     625                 :            :     { "DURATION",               "DURATION",             458,    NOID,   5,  6,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     626                 :            :     { "MDURATION",              "MDURATION",            459,    NOID,   5,  6,  V, { RR }, FUNCFLAG_EXTERNAL },
     627                 :            :     { "ODDLPRICE",              "ODDLPRICE",            460,    NOID,   7,  8,  V, { RR }, FUNCFLAG_EXTERNAL },
     628                 :            :     { "ODDLYIELD",              "ODDLYIELD",            461,    NOID,   8,  9,  V, { RR }, FUNCFLAG_EXTERNAL },
     629                 :            :     { "ODDFPRICE",              "ODDFPRICE",            462,    NOID,   8,  9,  V, { RR }, FUNCFLAG_EXTERNAL },
     630                 :            :     { "ODDFYIELD",              "ODDFYIELD",            463,    NOID,   8,  9,  V, { RR }, FUNCFLAG_EXTERNAL },
     631                 :            :     { "RANDBETWEEN",            "RANDBETWEEN",          464,    NOID,   2,  2,  V, { RR }, FUNCFLAG_VOLATILE | FUNCFLAG_EXTERNAL },
     632                 :            :     { "WEEKNUM",                "WEEKNUM",              465,    NOID,   1,  2,  V, { RR }, FUNCFLAG_EXTERNAL },
     633                 :            :     { "AMORDEGRC",              "AMORDEGRC",            466,    NOID,   6,  7,  V, { RR }, FUNCFLAG_EXTERNAL },
     634                 :            :     { "AMORLINC",               "AMORLINC",             467,    NOID,   6,  7,  V, { RR }, FUNCFLAG_EXTERNAL },
     635                 :            :     { "CONVERT",                "CONVERT",              468,    NOID,   3,  3,  V, { RR }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     636                 :            :     { "ACCRINT",                "ACCRINT",              469,    NOID,   6,  7,  V, { RR }, FUNCFLAG_EXTERNAL },
     637                 :            :     { "ACCRINTM",               "ACCRINTM",             470,    NOID,   4,  5,  V, { RR }, FUNCFLAG_EXTERNAL },
     638                 :            :     { "WORKDAY",                "WORKDAY",              471,    NOID,   2,  3,  V, { RR, RR, RX, C }, FUNCFLAG_EXTERNAL },
     639                 :            :     { "NETWORKDAYS",            "NETWORKDAYS",          472,    NOID,   2,  3,  V, { RR, RR, RX, C }, FUNCFLAG_EXTERNAL },
     640                 :            :     { "GCD",                    "GCD",                  473,    NOID,   1,  MX, V, { RX }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     641                 :            :     { "MULTINOMIAL",            "MULTINOMIAL",          474,    NOID,   1,  MX, V, { RX }, FUNCFLAG_EXTERNAL },
     642                 :            :     { "LCM",                    "LCM",                  475,    NOID,   1,  MX, V, { RX }, FUNCFLAG_EXTERNAL },       // Calc: builtin and add-in
     643                 :            :     { "FVSCHEDULE",             "FVSCHEDULE",           476,    NOID,   2,  2,  V, { RR, RX }, FUNCFLAG_EXTERNAL },
     644                 :            : 
     645                 :            :     // *** macro sheet commands ***
     646                 :            : 
     647                 :            :     { 0,                        "ACTIVATE.NEXT",        104,    104,    0,  1,  V, { VR }, FUNCFLAG_MACROCMD },      // BIFF2-3: 0, BIFF4: 0-1
     648                 :            :     { 0,                        "ACTIVATE.PREV",        105,    105,    0,  1,  V, { VR }, FUNCFLAG_MACROCMD }       // BIFF2-3: 0, BIFF4: 0-1
     649                 :            : };
     650                 :            : 
     651                 :            : /** Functions new in BIFF5/BIFF7. */
     652                 :            : static const FunctionData saFuncTableBiff5[] =
     653                 :            : {
     654                 :            :     { "WEEKDAY",                "WEEKDAY",              70,     70,     1,  2,  V, { VR }, 0 },                              // BIFF2-4: 1,   BIFF5: 1-2
     655                 :            :     { "HLOOKUP",                "HLOOKUP",              101,    101,    3,  4,  V, { VV, RO, RO, VV }, 0 },                     // BIFF2-4: 3,   BIFF5: 3-4
     656                 :            :     { "VLOOKUP",                "VLOOKUP",              102,    102,    3,  4,  V, { VV, RO, RO, VV }, 0 },                     // BIFF2-4: 3,   BIFF5: 3-4
     657                 :            :     { "DAYS360",                "DAYS360",              220,    220,    2,  3,  V, { VR }, 0 },                              // BIFF3-4: 2,   BIFF5: 2-3
     658                 :            :     { 0,                        "EXTERN.CALL",          255,    255,    1,  MX, R, { RO_E, RO }, FUNCFLAG_EXPORTONLY },        // MACRO or EXTERNAL
     659                 :            :     { "CONCATENATE",            "CONCATENATE",          336,    336,    0,  MX, V, { VR }, 0 },
     660                 :            :     { "POWER",                  "POWER",                337,    337,    2,  2,  V, { VR }, 0 },
     661                 :            :     { "RADIANS",                "RADIANS",              342,    342,    1,  1,  V, { VR }, 0 },
     662                 :            :     { "DEGREES",                "DEGREES",              343,    343,    1,  1,  V, { VR }, 0 },
     663                 :            :     { "SUBTOTAL",               "SUBTOTAL",             344,    344,    2,  MX, V, { VR, RO }, 0 },
     664                 :            :     { "SUMIF",                  "SUMIF",                345,    345,    2,  3,  V, { RO, VR, RO }, 0 },
     665                 :            :     { "COUNTIF",                "COUNTIF",              346,    346,    2,  2,  V, { RO, VR }, 0 },
     666                 :            :     { "COUNTBLANK",             "COUNTBLANK",           347,    347,    1,  1,  V, { RO }, 0 },
     667                 :            :     { "ISPMT",                  "ISPMT",                350,    350,    4,  4,  V, { VR }, 0 },
     668                 :            :     { "DATEDIF",                "DATEDIF",              351,    351,    3,  3,  V, { VR }, 0 },
     669                 :            :     { 0,                        "DATESTRING",           352,    352,    1,  1,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     670                 :            :     { 0,                        "NUMBERSTRING",         353,    353,    2,  2,  V, { VR }, FUNCFLAG_IMPORTONLY },   // not supported in Calc, missing in OOXML spec
     671                 :            :     { "ROMAN",                  "ROMAN",                354,    354,    1,  2,  V, { VR }, 0 },
     672                 :            : 
     673                 :            :     // *** EuroTool add-in ***
     674                 :            : 
     675                 :            :     { "EUROCONVERT",            "EUROCONVERT",          NOID,   NOID,   3,  5,  V, { VR }, FUNCLIB_TO_FUNCFLAGS( FUNCLIB_EUROTOOL ) },
     676                 :            : 
     677                 :            :     // *** macro sheet commands ***
     678                 :            : 
     679                 :            :     { 0,                        "ADD.MENU",             152,    152,    2,  4,  V, { VR, RO, RO, VR }, FUNCFLAG_MACROFUNC },    // BIFF3-4: 2-3, BIFF5: 2-4
     680                 :            :     { 0,                        "ADD.COMMAND",          153,    153,    3,  5,  V, { VR, RO, RO, RO, VR }, FUNCFLAG_MACROFUNC }, // BIFF3-4: 3-4, BIFF5: 3-5
     681                 :            :     { 0,                        "ADD.CHART.AUTOFORMAT", 390,    390,    0,  2,  V, { VR }, FUNCFLAG_MACROCMD },
     682                 :            :     { 0,                        "ADD.LIST.ITEM",        451,    451,    0,  2,  V, { VR }, FUNCFLAG_MACROCMD },
     683                 :            :     { 0,                        "ACTIVE.CELL.FONT",     476,    476,    0,  14, V, { VR }, FUNCFLAG_MACROCMD }
     684                 :            : };
     685                 :            : 
     686                 :            : /** Functions new in BIFF8. */
     687                 :            : static const FunctionData saFuncTableBiff8[] =
     688                 :            : {
     689                 :            :     { "GETPIVOTDATA",           "GETPIVOTDATA",         358,    358,    2,  MX, V, { RR, RR, VR, VR }, FUNCFLAG_IMPORTONLY | FUNCFLAG_PARAMPAIRS },
     690                 :            :     { "HYPERLINK",              "HYPERLINK",            359,    359,    1,  2,  V, { VV, VO }, 0 },
     691                 :            :     { 0,                        "PHONETIC",             360,    360,    1,  1,  V, { RO }, FUNCFLAG_IMPORTONLY },
     692                 :            :     { "AVERAGEA",               "AVERAGEA",             361,    361,    1,  MX, V, { RX }, 0 },
     693                 :            :     { "MAXA",                   "MAXA",                 362,    362,    1,  MX, V, { RX }, 0 },
     694                 :            :     { "MINA",                   "MINA",                 363,    363,    1,  MX, V, { RX }, 0 },
     695                 :            :     { "STDEVPA",                "STDEVPA",              364,    364,    1,  MX, V, { RX }, 0 },
     696                 :            :     { "VARPA",                  "VARPA",                365,    365,    1,  MX, V, { RX }, 0 },
     697                 :            :     { "STDEVA",                 "STDEVA",               366,    366,    1,  MX, V, { RX }, 0 },
     698                 :            :     { "VARA",                   "VARA",                 367,    367,    1,  MX, V, { RX }, 0 },
     699                 :            :     { "COM.MICROSOFT.BAHTTEXT", "BAHTTEXT",             368,    368,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     700                 :            :     { 0,                        "THAIDAYOFWEEK",        369,    369,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     701                 :            :     { 0,                        "THAIDIGIT",            370,    370,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     702                 :            :     { 0,                        "THAIMONTHOFYEAR",      371,    371,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     703                 :            :     { 0,                        "THAINUMSOUND",         372,    372,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     704                 :            :     { 0,                        "THAINUMSTRING",        373,    373,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     705                 :            :     { 0,                        "THAISTRINGLENGTH",     374,    374,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     706                 :            :     { 0,                        "ISTHAIDIGIT",          375,    375,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     707                 :            :     { 0,                        "ROUNDBAHTDOWN",        376,    376,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     708                 :            :     { 0,                        "ROUNDBAHTUP",          377,    377,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     709                 :            :     { 0,                        "THAIYEAR",             378,    378,    1,  1,  V, { VR }, FUNCFLAG_MACROCALL },
     710                 :            :     { 0,                        "RTD",                  379,    379,    3,  3,  A, { VR, VR, RO }, 0 }
     711                 :            : };
     712                 :            : 
     713                 :            : /** Functions new in OOXML. */
     714                 :            : static const FunctionData saFuncTableOox[] =
     715                 :            : {
     716                 :            :     { 0,                        "CUBEVALUE",            380,    NOID,   1,  MX, V, { VR, RX }, 0 },
     717                 :            :     { 0,                        "CUBEMEMBER",           381,    NOID,   2,  3,  V, { VR, RX, VR }, 0 },
     718                 :            :     { 0,                        "CUBEMEMBERPROPERTY",   382,    NOID,   3,  3,  V, { VR }, 0 },
     719                 :            :     { 0,                        "CUBERANKEDMEMBER",     383,    NOID,   3,  4,  V, { VR }, 0 },
     720                 :            :     { 0,                        "CUBEKPIMEMBER",        477,    NOID,   3,  4,  V, { VR }, 0 },
     721                 :            :     { 0,                        "CUBESET",              478,    NOID,   2,  5,  V, { VR, RX, VR }, 0 },
     722                 :            :     { 0,                        "CUBESETCOUNT",         479,    NOID,   1,  1,  V, { VR }, 0 },
     723                 :            :     { 0,                        "IFERROR",              480,    NOID,   2,  2,  V, { VO, RO }, 0 },
     724                 :            :     { 0,                        "COUNTIFS",             481,    NOID,   2,  MX, V, { RO, VR }, FUNCFLAG_PARAMPAIRS },
     725                 :            :     { 0,                        "SUMIFS",               482,    NOID,   3,  MX, V, { RO, RO, VR }, FUNCFLAG_PARAMPAIRS },
     726                 :            :     { 0,                        "AVERAGEIF",            483,    NOID,   2,  3,  V, { RO, VR, RO }, 0 },
     727                 :            :     { 0,                        "AVERAGEIFS",           484,    NOID,   3,  MX, V, { RO, RO, VR }, 0 }
     728                 :            : };
     729                 :            : 
     730                 :            : /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */
     731                 :            : static const FunctionData saFuncTableOdf[] =
     732                 :            : {
     733                 :            :     { "ARABIC",                 0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     734                 :            :     { "B",                      0,                      NOID,   NOID,   3,  4,  V, { VR }, FUNCFLAG_MACROCALLODF },
     735                 :            :     { "BASE",                   0,                      NOID,   NOID,   2,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
     736                 :            :     { "BITAND",                 0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     737                 :            :     { "BITLSHIFT",              0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     738                 :            :     { "BITOR",                  0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     739                 :            :     { "BITRSHIFT",              0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     740                 :            :     { "BITXOR",                 0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     741                 :            :     { "CHISQDIST",              0,                      NOID,   NOID,   2,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
     742                 :            :     { "CHISQINV",               0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     743                 :            :     { "COMBINA",                0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     744                 :            :     { "DAYS",                   0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     745                 :            :     { "DECIMAL",                0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     746                 :            :     { "FDIST",                  0,                      NOID,   NOID,   3,  4,  V, { VR }, FUNCFLAG_MACROCALLODF },
     747                 :            :     { "FINV",                   0,                      NOID,   NOID,   3,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
     748                 :            :     { "FORMULA",                0,                      NOID,   NOID,   1,  1,  V, { RO }, FUNCFLAG_MACROCALLODF },
     749                 :            :     { "GAMMA",                  0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     750                 :            :     { "GAUSS",                  0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     751                 :            :     { "IFNA",                   0,                      NOID,   NOID,   2,  2,  V, { VR, RO }, FUNCFLAG_MACROCALLODF },
     752                 :            :     { "ISFORMULA",              0,                      NOID,   NOID,   1,  1,  V, { RO }, FUNCFLAG_MACROCALLODF },
     753                 :            :     { "ISOWEEKNUM",             0,                      NOID,   NOID,   1,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     754                 :            :     { "MUNIT",                  0,                      NOID,   NOID,   1,  1,  A, { VR }, FUNCFLAG_MACROCALLODF },
     755                 :            :     { "NUMBERVALUE",            0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     756                 :            :     { "PDURATION",              0,                      NOID,   NOID,   3,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
     757                 :            :     { "PERMUTATIONA",           0,                      NOID,   NOID,   2,  2,  V, { VR }, FUNCFLAG_MACROCALLODF },
     758                 :            :     { "PHI",                    0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     759                 :            :     { "RRI",                    0,                      NOID,   NOID,   3,  3,  V, { VR }, FUNCFLAG_MACROCALLODF },
     760                 :            :     { "SHEET",                  0,                      NOID,   NOID,   0,  1,  V, { RO }, FUNCFLAG_MACROCALLODF },
     761                 :            :     { "SHEETS",                 0,                      NOID,   NOID,   0,  1,  V, { RO }, FUNCFLAG_MACROCALLODF },
     762                 :            :     { "SKEWP",                  0,                      NOID,   NOID,   1,  MX, V, { RX }, FUNCFLAG_MACROCALLODF },
     763                 :            :     { "UNICHAR",                0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     764                 :            :     { "UNICODE",                0,                      NOID,   NOID,   1,  1,  V, { VR }, FUNCFLAG_MACROCALLODF },
     765                 :            :     { "XOR",                    0,                      NOID,   NOID,   1,  MX, V, { RX }, FUNCFLAG_MACROCALLODF }
     766                 :            : };
     767                 :            : 
     768                 :            : // ----------------------------------------------------------------------------
     769                 :            : 
     770                 :            : const sal_Unicode API_TOKEN_OPEN            = '(';
     771                 :            : const sal_Unicode API_TOKEN_CLOSE           = ')';
     772                 :            : const sal_Unicode API_TOKEN_SEP             = ';';
     773                 :            : 
     774                 :            : const sal_Unicode API_TOKEN_ARRAY_OPEN      = '{';
     775                 :            : const sal_Unicode API_TOKEN_ARRAY_CLOSE     = '}';
     776                 :            : const sal_Unicode API_TOKEN_ARRAY_ROWSEP    = '|';
     777                 :            : const sal_Unicode API_TOKEN_ARRAY_COLSEP    = ';';
     778                 :            : 
     779                 :            : } // namespace
     780                 :            : 
     781                 :            : // function info parameter class iterator =====================================
     782                 :            : 
     783                 :         15 : FunctionParamInfoIterator::FunctionParamInfoIterator( const FunctionInfo& rFuncInfo ) :
     784                 :            :     mpParamInfo( rFuncInfo.mpParamInfos ),
     785                 :         15 :     mpParamInfoEnd( rFuncInfo.mpParamInfos + FUNCINFO_PARAMINFOCOUNT ),
     786                 :         30 :     mbParamPairs( rFuncInfo.mbParamPairs )
     787                 :            : {
     788                 :            :     OSL_ENSURE( !mbParamPairs || (mpParamInfo + 1 < mpParamInfoEnd),
     789                 :            :         "FunctionParamInfoIterator::FunctionParamInfoIterator - expecting at least 2 infos for paired parameters" );
     790                 :         15 : }
     791                 :            : 
     792                 :         81 : bool FunctionParamInfoIterator::isCalcOnlyParam() const
     793                 :            : {
     794 [ +  - ][ -  + ]:         81 :     return mpParamInfo && (mpParamInfo->meValid == FUNC_PARAM_CALCONLY);
     795                 :            : }
     796                 :            : 
     797                 :         66 : bool FunctionParamInfoIterator::isExcelOnlyParam() const
     798                 :            : {
     799 [ +  - ][ -  + ]:         66 :     return mpParamInfo && (mpParamInfo->meValid == FUNC_PARAM_EXCELONLY);
     800                 :            : }
     801                 :            : 
     802                 :         39 : FunctionParamInfoIterator& FunctionParamInfoIterator::operator++()
     803                 :            : {
     804         [ +  - ]:         39 :     if( mpParamInfo )
     805                 :            :     {
     806                 :            :         // move pointer to next entry, if something explicit follows
     807 [ +  - ][ +  + ]:         39 :         if( (mpParamInfo + 1 < mpParamInfoEnd) && (mpParamInfo[ 1 ].meValid != FUNC_PARAM_NONE) )
     808                 :         12 :             ++mpParamInfo;
     809                 :            :         // points to last info, but parameter pairs expected, move to previous info
     810         [ -  + ]:         27 :         else if( mbParamPairs )
     811                 :          0 :             --mpParamInfo;
     812                 :            :         // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
     813 [ +  - ][ -  + ]:         27 :         else if( isExcelOnlyParam() || isCalcOnlyParam() )
                 [ -  + ]
     814                 :         39 :             mpParamInfo = 0;
     815                 :            :         // otherwise: repeat last parameter class
     816                 :            :     }
     817                 :         39 :     return *this;
     818                 :            : }
     819                 :            : 
     820                 :            : // function provider ==========================================================
     821                 :            : 
     822                 :         24 : struct FunctionProviderImpl
     823                 :            : {
     824                 :            :     typedef RefMap< OUString, FunctionInfo >    FuncNameMap;
     825                 :            :     typedef RefMap< sal_uInt16, FunctionInfo >  FuncIdMap;
     826                 :            : 
     827                 :            :     FunctionInfoVector  maFuncs;            /// All function infos in one list.
     828                 :            :     FuncNameMap         maOoxFuncs;         /// Maps OOXML function names to function data.
     829                 :            :     FuncIdMap           maBiff12Funcs;      /// Maps BIFF12 function indexes to function data.
     830                 :            :     FuncIdMap           maBiffFuncs;        /// Maps BIFF2-BIFF8 function indexes to function data.
     831                 :            :     FuncNameMap         maMacroFuncs;       /// Maps macro function names to function data.
     832                 :            : 
     833                 :            :     explicit            FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter );
     834                 :            : 
     835                 :            : private:
     836                 :            :     /** Creates and inserts a function info struct from the passed function data. */
     837                 :            :     void                initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam );
     838                 :            : 
     839                 :            :     /** Initializes the members from the passed function data list. */
     840                 :            :     void                initFuncs(
     841                 :            :                             const FunctionData* pBeg, const FunctionData* pEnd,
     842                 :            :                             sal_uInt8 nMaxParam, bool bImportFilter );
     843                 :            : };
     844                 :            : 
     845                 :            : // ----------------------------------------------------------------------------
     846                 :            : 
     847 [ +  - ][ +  - ]:         24 : FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter )
         [ +  - ][ +  - ]
     848                 :            : {
     849                 :            :     OSL_ENSURE( bImportFilter, "FunctionProviderImpl::FunctionProviderImpl - need special handling for macro call functions" );
     850                 :         24 :     sal_uInt8 nMaxParam = 0;
     851   [ +  -  -  - ]:         24 :     switch( eFilter )
     852                 :            :     {
     853                 :            :         case FILTER_OOXML:
     854                 :         24 :             nMaxParam = OOX_MAX_PARAMCOUNT;
     855                 :         24 :             eBiff = BIFF8;  // insert all BIFF function tables, then the OOXML table
     856                 :         24 :         break;
     857                 :            :         case FILTER_BIFF:
     858                 :          0 :             nMaxParam = BIFF_MAX_PARAMCOUNT;
     859                 :          0 :         break;
     860                 :            :         case FILTER_UNKNOWN:
     861                 :            :             OSL_FAIL( "FunctionProviderImpl::FunctionProviderImpl - invalid filter type" );
     862                 :          0 :         break;
     863                 :            :     }
     864                 :            :     OSL_ENSURE( eBiff != BIFF_UNKNOWN, "FunctionProviderImpl::FunctionProviderImpl - invalid BIFF type" );
     865                 :            : 
     866                 :            :     /*  Add functions supported in the current BIFF version only. Function
     867                 :            :         tables from later BIFF versions may overwrite single functions from
     868                 :            :         earlier tables. */
     869         [ +  - ]:         24 :     if( eBiff >= BIFF2 )
     870         [ +  - ]:         24 :         initFuncs( saFuncTableBiff2, STATIC_ARRAY_END( saFuncTableBiff2 ), nMaxParam, bImportFilter );
     871         [ +  - ]:         24 :     if( eBiff >= BIFF3 )
     872         [ +  - ]:         24 :         initFuncs( saFuncTableBiff3, STATIC_ARRAY_END( saFuncTableBiff3 ), nMaxParam, bImportFilter );
     873         [ +  - ]:         24 :     if( eBiff >= BIFF4 )
     874         [ +  - ]:         24 :         initFuncs( saFuncTableBiff4, STATIC_ARRAY_END( saFuncTableBiff4 ), nMaxParam, bImportFilter );
     875         [ +  - ]:         24 :     if( eBiff >= BIFF5 )
     876         [ +  - ]:         24 :         initFuncs( saFuncTableBiff5, STATIC_ARRAY_END( saFuncTableBiff5 ), nMaxParam, bImportFilter );
     877         [ +  - ]:         24 :     if( eBiff >= BIFF8 )
     878         [ +  - ]:         24 :         initFuncs( saFuncTableBiff8, STATIC_ARRAY_END( saFuncTableBiff8 ), nMaxParam, bImportFilter );
     879         [ +  - ]:         24 :     if( eFilter == FILTER_OOXML )
     880         [ +  - ]:         24 :         initFuncs( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ), nMaxParam, bImportFilter );
     881         [ +  - ]:         24 :     initFuncs( saFuncTableOdf, STATIC_ARRAY_END( saFuncTableOdf ), nMaxParam, bImportFilter );
     882                 :         24 : }
     883                 :            : 
     884                 :      10320 : void FunctionProviderImpl::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxParam )
     885                 :            : {
     886                 :            :     // create a function info object
     887 [ +  - ][ +  - ]:      10320 :     FunctionInfoRef xFuncInfo( new FunctionInfo );
     888         [ +  + ]:      10320 :     if( rFuncData.mpcOdfFuncName )
     889                 :       9000 :         xFuncInfo->maOdfFuncName = OUString::createFromAscii( rFuncData.mpcOdfFuncName );
     890         [ +  + ]:      10320 :     if( rFuncData.mpcOoxFuncName )
     891                 :       9528 :         xFuncInfo->maOoxFuncName = OUString::createFromAscii( rFuncData.mpcOoxFuncName );
     892                 :            : 
     893         [ +  + ]:      10320 :     if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALL ) )
     894                 :            :     {
     895                 :            :         OSL_ENSURE( !xFuncInfo->maOoxFuncName.isEmpty(), "FunctionProviderImpl::initFunc - missing OOXML function name" );
     896                 :            :         OSL_ENSURE( !getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALLODF ), "FunctionProviderImpl::initFunc - unexpected flag FUNCFLAG_MACROCALLODF" );
     897         [ +  - ]:        264 :         xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfn." ) + xFuncInfo->maOoxFuncName;
     898                 :            :     }
     899         [ +  + ]:      10056 :     else if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALLODF ) )
     900                 :            :     {
     901                 :            :         OSL_ENSURE( !xFuncInfo->maOdfFuncName.isEmpty(), "FunctionProviderImpl::initFunc - missing ODF function name" );
     902         [ +  - ]:        792 :         xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfnodf." ) + xFuncInfo->maOdfFuncName;
     903                 :            :     }
     904                 :            : 
     905                 :      10320 :     xFuncInfo->meFuncLibType = FUNCFLAGS_TO_FUNCLIB( rFuncData.mnFlags );
     906                 :      10320 :     xFuncInfo->mnApiOpCode = -1;
     907                 :      10320 :     xFuncInfo->mnBiff12FuncId = rFuncData.mnBiff12FuncId;
     908                 :      10320 :     xFuncInfo->mnBiffFuncId = rFuncData.mnBiffFuncId;
     909                 :      10320 :     xFuncInfo->mnMinParamCount = rFuncData.mnMinParamCount;
     910         [ +  + ]:      10320 :     xFuncInfo->mnMaxParamCount = (rFuncData.mnMaxParamCount == MX) ? nMaxParam : rFuncData.mnMaxParamCount;
     911                 :      10320 :     xFuncInfo->mnRetClass = rFuncData.mnRetClass;
     912                 :      10320 :     xFuncInfo->mpParamInfos = rFuncData.mpParamInfos;
     913                 :      10320 :     xFuncInfo->mbParamPairs = getFlag( rFuncData.mnFlags, FUNCFLAG_PARAMPAIRS );
     914                 :      10320 :     xFuncInfo->mbVolatile = getFlag( rFuncData.mnFlags, FUNCFLAG_VOLATILE );
     915                 :      10320 :     xFuncInfo->mbExternal = getFlag( rFuncData.mnFlags, FUNCFLAG_EXTERNAL );
     916                 :      10320 :     bool bMacroCmd = getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCMD );
     917 [ +  + ][ +  + ]:      10320 :     xFuncInfo->mbMacroFunc = bMacroCmd || getFlag( rFuncData.mnFlags, FUNCFLAG_MACROFUNC );
     918 [ +  + ][ +  + ]:      10320 :     xFuncInfo->mbVarParam = bMacroCmd || (rFuncData.mnMinParamCount != rFuncData.mnMaxParamCount) || getFlag( rFuncData.mnFlags, FUNCFLAG_ALWAYSVAR );
                 [ +  + ]
     919                 :            : 
     920                 :      10320 :     setFlag( xFuncInfo->mnBiff12FuncId, BIFF_TOK_FUNCVAR_CMD, bMacroCmd );
     921                 :      10320 :     setFlag( xFuncInfo->mnBiffFuncId, BIFF_TOK_FUNCVAR_CMD, bMacroCmd );
     922                 :            : 
     923                 :            :     // insert the function info into the member maps
     924         [ +  - ]:      10320 :     maFuncs.push_back( xFuncInfo );
     925         [ +  + ]:      10320 :     if( !xFuncInfo->maOoxFuncName.isEmpty() )
     926 [ +  - ][ +  - ]:       9528 :         maOoxFuncs[ xFuncInfo->maOoxFuncName ] = xFuncInfo;
     927         [ +  - ]:      10320 :     if( xFuncInfo->mnBiff12FuncId != NOID )
     928 [ +  - ][ +  - ]:      10320 :         maBiff12Funcs[ xFuncInfo->mnBiff12FuncId ] = xFuncInfo;
     929         [ +  - ]:      10320 :     if( xFuncInfo->mnBiffFuncId != NOID )
     930 [ +  - ][ +  - ]:      10320 :         maBiffFuncs[ xFuncInfo->mnBiffFuncId ] = xFuncInfo;
     931         [ +  + ]:      10320 :     if( !xFuncInfo->maBiffMacroName.isEmpty() )
     932 [ +  - ][ +  - ]:      10320 :         maMacroFuncs[ xFuncInfo->maBiffMacroName ] = xFuncInfo;
                 [ +  - ]
     933                 :      10320 : }
     934                 :            : 
     935                 :        168 : void FunctionProviderImpl::initFuncs( const FunctionData* pBeg, const FunctionData* pEnd, sal_uInt8 nMaxParam, bool bImportFilter )
     936                 :            : {
     937         [ +  + ]:      10704 :     for( const FunctionData* pIt = pBeg; pIt != pEnd; ++pIt )
     938         [ +  + ]:      10536 :         if( pIt->isSupported( bImportFilter ) )
     939                 :      10320 :             initFunc( *pIt, nMaxParam );
     940                 :        168 : }
     941                 :            : 
     942                 :            : // ----------------------------------------------------------------------------
     943                 :            : 
     944                 :         24 : FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter ) :
     945         [ +  - ]:         24 :     mxFuncImpl( new FunctionProviderImpl( eFilter, eBiff, bImportFilter ) )
     946                 :            : {
     947                 :         24 : }
     948                 :            : 
     949                 :         72 : FunctionProvider::~FunctionProvider()
     950                 :            : {
     951         [ -  + ]:         72 : }
     952                 :            : 
     953                 :         12 : const FunctionInfo* FunctionProvider::getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const
     954                 :            : {
     955 [ +  - ][ +  - ]:         12 :     return mxFuncImpl->maOoxFuncs.get( rFuncName ).get();
     956                 :            : }
     957                 :            : 
     958                 :          0 : const FunctionInfo* FunctionProvider::getFuncInfoFromBiff12FuncId( sal_uInt16 nFuncId ) const
     959                 :            : {
     960                 :          0 :     return mxFuncImpl->maBiff12Funcs.get( nFuncId ).get();
     961                 :            : }
     962                 :            : 
     963                 :          0 : const FunctionInfo* FunctionProvider::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const
     964                 :            : {
     965                 :          0 :     return mxFuncImpl->maBiffFuncs.get( nFuncId ).get();
     966                 :            : }
     967                 :            : 
     968                 :          0 : const FunctionInfo* FunctionProvider::getFuncInfoFromMacroName( const OUString& rFuncName ) const
     969                 :            : {
     970 [ #  # ][ #  # ]:          0 :     return mxFuncImpl->maMacroFuncs.get( rFuncName ).get();
     971                 :            : }
     972                 :            : 
     973                 :          0 : FunctionLibraryType FunctionProvider::getFuncLibTypeFromLibraryName( const OUString& rLibraryName ) const
     974                 :            : {
     975                 :            : #define OOX_XLS_IS_LIBNAME( libname, basename ) (libname.equalsIgnoreAsciiCaseAscii( basename ".XLA" ) || libname.equalsIgnoreAsciiCaseAscii( basename ".XLAM" ))
     976                 :            : 
     977                 :            :     // the EUROTOOL add-in containing the EUROCONVERT function
     978 [ #  # ][ #  # ]:          0 :     if( OOX_XLS_IS_LIBNAME( rLibraryName, "EUROTOOL" ) )
                 [ #  # ]
     979                 :          0 :         return FUNCLIB_EUROTOOL;
     980                 :            : 
     981                 :            : #undef OOX_XLS_IS_LIBNAME
     982                 :            : 
     983                 :            :     // default: unknown library
     984                 :          0 :     return FUNCLIB_UNKNOWN;
     985                 :            : }
     986                 :            : 
     987                 :         24 : const FunctionInfoVector& FunctionProvider::getFuncs() const
     988                 :            : {
     989                 :         24 :     return mxFuncImpl->maFuncs;
     990                 :            : }
     991                 :            : 
     992                 :            : // op-code and function provider ==============================================
     993                 :            : 
     994                 :         24 : struct OpCodeProviderImpl : public ApiOpCodes
     995                 :            : {
     996                 :            :     typedef RefMap< sal_Int32, FunctionInfo >       OpCodeFuncMap;
     997                 :            :     typedef RefMap< OUString, FunctionInfo >        FuncNameMap;
     998                 :            :     typedef ::std::vector< FormulaOpCodeMapEntry >  OpCodeEntryVector;
     999                 :            : 
    1000                 :            :     OpCodeFuncMap       maOpCodeFuncs;      /// Maps API function op-codes to function data.
    1001                 :            :     FuncNameMap         maExtProgFuncs;     /// Maps programmatical API function names to function data.
    1002                 :            :     OpCodeEntryVector   maParserMap;        /// OOXML token mapping for formula parser service.
    1003                 :            : 
    1004                 :            :     explicit            OpCodeProviderImpl(
    1005                 :            :                             const FunctionInfoVector& rFuncInfos,
    1006                 :            :                             const Reference< XMultiServiceFactory >& rxModelFactory );
    1007                 :            : 
    1008                 :            : private:
    1009                 :            :     typedef ::std::map< OUString, ApiToken >    ApiTokenMap;
    1010                 :            :     typedef Sequence< FormulaOpCodeMapEntry >   OpCodeEntrySequence;
    1011                 :            : 
    1012                 :            :     static bool         fillEntrySeq( OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup );
    1013                 :            :     static bool         fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup );
    1014                 :            :     bool                fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const;
    1015                 :            : 
    1016                 :            :     static bool         initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId );
    1017                 :            :     bool                initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName );
    1018                 :            :     bool                initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName );
    1019                 :            :     bool                initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName );
    1020                 :            : 
    1021                 :            :     bool                initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap );
    1022                 :            :     bool                initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos );
    1023                 :            : };
    1024                 :            : 
    1025                 :            : // ----------------------------------------------------------------------------
    1026                 :            : 
    1027                 :         24 : OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos,
    1028 [ +  - ][ +  - ]:         24 :         const Reference< XMultiServiceFactory >& rxModelFactory )
    1029                 :            : {
    1030         [ +  - ]:         24 :     if( rxModelFactory.is() ) try
    1031                 :            :     {
    1032         [ +  - ]:         24 :         Reference< XFormulaOpCodeMapper > xMapper( rxModelFactory->createInstance(
    1033 [ +  - ][ +  - ]:         24 :             CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW );
                 [ +  - ]
    1034                 :            : 
    1035                 :            :         // op-codes provided as attributes
    1036 [ +  - ][ +  - ]:         24 :         OPCODE_UNKNOWN = xMapper->getOpCodeUnknown();
    1037 [ +  - ][ +  - ]:         24 :         OPCODE_EXTERNAL = xMapper->getOpCodeExternal();
    1038                 :            : 
    1039                 :            :         using namespace ::com::sun::star::sheet::FormulaMapGroup;
    1040                 :            :         using namespace ::com::sun::star::sheet::FormulaMapGroupSpecialOffset;
    1041                 :            : 
    1042         [ +  - ]:         24 :         OpCodeEntrySequence aEntrySeq;
    1043 [ +  - ][ +  - ]:         24 :         ApiTokenMap aTokenMap, aExtFuncTokenMap;
    1044                 :            :         bool bIsValid =
    1045                 :            :             // special
    1046         [ +  - ]:         24 :             fillEntrySeq( aEntrySeq, xMapper, SPECIAL ) &&
    1047         [ +  - ]:         24 :             initOpCode( OPCODE_PUSH,          aEntrySeq, PUSH ) &&
    1048         [ +  - ]:         24 :             initOpCode( OPCODE_MISSING,       aEntrySeq, MISSING ) &&
    1049         [ +  - ]:         24 :             initOpCode( OPCODE_SPACES,        aEntrySeq, SPACES ) &&
    1050         [ +  - ]:         24 :             initOpCode( OPCODE_NAME,          aEntrySeq, NAME ) &&
    1051         [ +  - ]:         24 :             initOpCode( OPCODE_DBAREA,        aEntrySeq, DB_AREA ) &&
    1052         [ +  - ]:         24 :             initOpCode( OPCODE_NLR,           aEntrySeq, COL_ROW_NAME ) &&
    1053         [ +  - ]:         24 :             initOpCode( OPCODE_MACRO,         aEntrySeq, MACRO ) &&
    1054         [ +  - ]:         24 :             initOpCode( OPCODE_BAD,           aEntrySeq, BAD ) &&
    1055         [ +  - ]:         24 :             initOpCode( OPCODE_NONAME,        aEntrySeq, NO_NAME ) &&
    1056                 :            :             // separators
    1057         [ +  - ]:         24 :             fillTokenMap( aTokenMap, aEntrySeq, xMapper, SEPARATORS ) &&
    1058         [ +  - ]:         24 :             initOpCode( OPCODE_OPEN,          aTokenMap, API_TOKEN_OPEN,  '('  ) &&
    1059         [ +  - ]:         24 :             initOpCode( OPCODE_CLOSE,         aTokenMap, API_TOKEN_CLOSE, ')'  ) &&
    1060         [ +  - ]:         24 :             initOpCode( OPCODE_SEP,           aTokenMap, API_TOKEN_SEP,   ','  ) &&
    1061                 :            :             // array separators
    1062         [ +  - ]:         24 :             fillTokenMap( aTokenMap, aEntrySeq, xMapper, ARRAY_SEPARATORS ) &&
    1063         [ +  - ]:         24 :             initOpCode( OPCODE_ARRAY_OPEN,    aTokenMap, API_TOKEN_ARRAY_OPEN,   '{'  ) &&
    1064         [ +  - ]:         24 :             initOpCode( OPCODE_ARRAY_CLOSE,   aTokenMap, API_TOKEN_ARRAY_CLOSE,  '}'  ) &&
    1065         [ +  - ]:         24 :             initOpCode( OPCODE_ARRAY_ROWSEP,  aTokenMap, API_TOKEN_ARRAY_ROWSEP, ';'  ) &&
    1066         [ +  - ]:         24 :             initOpCode( OPCODE_ARRAY_COLSEP,  aTokenMap, API_TOKEN_ARRAY_COLSEP, ','  ) &&
    1067                 :            :             // unary operators
    1068         [ +  - ]:         24 :             fillTokenMap( aTokenMap, aEntrySeq, xMapper, UNARY_OPERATORS ) &&
    1069         [ +  - ]:         24 :             initOpCode( OPCODE_PLUS_SIGN,     aTokenMap, '+',  '\0' ) && // same op-code as OPCODE_ADD
    1070         [ +  - ]:         24 :             initOpCode( OPCODE_MINUS_SIGN,    aTokenMap, '-',  '-'  ) &&
    1071         [ +  - ]:         24 :             initOpCode( OPCODE_PERCENT,       aTokenMap, '%',  '%'  ) &&
    1072                 :            :             // binary operators
    1073         [ +  - ]:         24 :             fillTokenMap( aTokenMap, aEntrySeq, xMapper, BINARY_OPERATORS ) &&
    1074         [ +  - ]:         24 :             initOpCode( OPCODE_ADD,           aTokenMap, '+',  '+'  ) &&
    1075         [ +  - ]:         24 :             initOpCode( OPCODE_SUB,           aTokenMap, '-',  '-'  ) &&
    1076         [ +  - ]:         24 :             initOpCode( OPCODE_MULT,          aTokenMap, '*',  '*'  ) &&
    1077         [ +  - ]:         24 :             initOpCode( OPCODE_DIV,           aTokenMap, '/',  '/'  ) &&
    1078         [ +  - ]:         24 :             initOpCode( OPCODE_POWER,         aTokenMap, '^',  '^'  ) &&
    1079         [ +  - ]:         24 :             initOpCode( OPCODE_CONCAT,        aTokenMap, '&',  '&'  ) &&
    1080         [ +  - ]:         24 :             initOpCode( OPCODE_EQUAL,         aTokenMap, '=',  '='  ) &&
    1081         [ +  - ]:         24 :             initOpCode( OPCODE_NOT_EQUAL,     aTokenMap, "<>", "<>" ) &&
    1082         [ +  - ]:         24 :             initOpCode( OPCODE_LESS,          aTokenMap, '<',  '<'  ) &&
    1083         [ +  - ]:         24 :             initOpCode( OPCODE_LESS_EQUAL,    aTokenMap, "<=", "<=" ) &&
    1084         [ +  - ]:         24 :             initOpCode( OPCODE_GREATER,       aTokenMap, '>',  '>'  ) &&
    1085         [ +  - ]:         24 :             initOpCode( OPCODE_GREATER_EQUAL, aTokenMap, ">=", ">=" ) &&
    1086         [ +  - ]:         24 :             initOpCode( OPCODE_INTERSECT,     aTokenMap, '!',  ' '  ) &&
    1087         [ +  - ]:         24 :             initOpCode( OPCODE_LIST,          aTokenMap, '~',  ','  ) &&
    1088         [ +  - ]:         24 :             initOpCode( OPCODE_RANGE,         aTokenMap, ':',  ':'  ) &&
    1089                 :            :             // functions
    1090         [ +  - ]:         24 :             fillFuncTokenMaps( aTokenMap, aExtFuncTokenMap, aEntrySeq, xMapper ) &&
    1091         [ +  - ]:         24 :             initFuncOpCodes( aTokenMap, aExtFuncTokenMap, rFuncInfos ) &&
    1092 [ +  - ][ +  - ]:        984 :             initOpCode( OPCODE_DDE,           aTokenMap, "DDE", 0 );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
                 [ #  # ]
    1093                 :            : 
    1094                 :            :         OSL_ENSURE( bIsValid, "OpCodeProviderImpl::OpCodeProviderImpl - opcodes not initialized" );
    1095                 :            :         (void)bIsValid;
    1096                 :            : 
    1097                 :            :         // OPCODE_PLUS_SIGN and OPCODE_ADD should be equal, otherwise "+" has to be passed above
    1098 [ +  - ][ #  # ]:         24 :         OSL_ENSURE( OPCODE_PLUS_SIGN == OPCODE_ADD, "OpCodeProviderImpl::OpCodeProviderImpl - need opcode mapping for OPCODE_PLUS_SIGN" );
    1099                 :            :     }
    1100         [ #  # ]:          0 :     catch( Exception& )
    1101                 :            :     {
    1102                 :            :         OSL_FAIL( "OpCodeProviderImpl::OpCodeProviderImpl - cannot receive formula opcode mapper" );
    1103                 :            :     }
    1104                 :         24 : }
    1105                 :            : 
    1106                 :        144 : bool OpCodeProviderImpl::fillEntrySeq( OpCodeEntrySequence& orEntrySeq,
    1107                 :            :         const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup )
    1108                 :            : {
    1109                 :            :     try
    1110                 :            :     {
    1111 [ +  - ][ +  - ]:        144 :         orEntrySeq = rxMapper->getAvailableMappings( ::com::sun::star::sheet::FormulaLanguage::ODFF, nMapGroup );
                 [ +  - ]
           [ +  -  #  # ]
    1112                 :        144 :         return orEntrySeq.hasElements();
    1113                 :            :     }
    1114                 :          0 :     catch( Exception& )
    1115                 :            :     {
    1116                 :            :     }
    1117                 :          0 :     return false;
    1118                 :            : }
    1119                 :            : 
    1120                 :         96 : bool OpCodeProviderImpl::fillTokenMap( ApiTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq,
    1121                 :            :         const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup )
    1122                 :            : {
    1123                 :         96 :     orTokenMap.clear();
    1124         [ +  - ]:         96 :     if( fillEntrySeq( orEntrySeq, rxMapper, nMapGroup ) )
    1125                 :            :     {
    1126                 :         96 :         const FormulaOpCodeMapEntry* pEntry = orEntrySeq.getConstArray();
    1127                 :         96 :         const FormulaOpCodeMapEntry* pEntryEnd = pEntry + orEntrySeq.getLength();
    1128         [ +  + ]:        696 :         for( ; pEntry != pEntryEnd; ++pEntry )
    1129                 :        600 :             orTokenMap[ pEntry->Name ] = pEntry->Token;
    1130                 :            :     }
    1131                 :         96 :     return orEntrySeq.hasElements();
    1132                 :            : }
    1133                 :            : 
    1134                 :         24 : bool OpCodeProviderImpl::fillFuncTokenMaps( ApiTokenMap& orIntFuncTokenMap, ApiTokenMap& orExtFuncTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper ) const
    1135                 :            : {
    1136                 :         24 :     orIntFuncTokenMap.clear();
    1137                 :         24 :     orExtFuncTokenMap.clear();
    1138         [ +  - ]:         24 :     if( fillEntrySeq( orEntrySeq, rxMapper, ::com::sun::star::sheet::FormulaMapGroup::FUNCTIONS ) )
    1139                 :            :     {
    1140                 :         24 :         const FormulaOpCodeMapEntry* pEntry = orEntrySeq.getConstArray();
    1141                 :         24 :         const FormulaOpCodeMapEntry* pEntryEnd = pEntry + orEntrySeq.getLength();
    1142         [ +  + ]:       9744 :         for( ; pEntry != pEntryEnd; ++pEntry )
    1143         [ +  + ]:       9720 :             ((pEntry->Token.OpCode == OPCODE_EXTERNAL) ? orExtFuncTokenMap : orIntFuncTokenMap)[ pEntry->Name ] = pEntry->Token;
    1144                 :            :     }
    1145                 :         24 :     return orEntrySeq.hasElements();
    1146                 :            : }
    1147                 :            : 
    1148                 :        216 : bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId )
    1149                 :            : {
    1150 [ +  - ][ +  - ]:        216 :     if( (0 <= nSpecialId) && (nSpecialId < rEntrySeq.getLength()) )
                 [ +  - ]
    1151                 :            :     {
    1152                 :        216 :         ornOpCode = rEntrySeq[ nSpecialId ].Token.OpCode;
    1153                 :        216 :         return true;
    1154                 :            :     }
    1155                 :            :     OSL_FAIL( OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for special offset " ).
    1156                 :            :         append( nSpecialId ).append( " not found" ).getStr() );
    1157                 :        216 :     return false;
    1158                 :            : }
    1159                 :            : 
    1160                 :        600 : bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const OUString& rOdfName, const OUString& rOoxName )
    1161                 :            : {
    1162         [ +  - ]:        600 :     ApiTokenMap::const_iterator aIt = rTokenMap.find( rOdfName );
    1163         [ +  - ]:        600 :     if( aIt != rTokenMap.end() )
    1164                 :            :     {
    1165                 :        600 :         ornOpCode = aIt->second.OpCode;
    1166         [ +  + ]:        600 :         if( !rOoxName.isEmpty() )
    1167                 :            :         {
    1168                 :        576 :             FormulaOpCodeMapEntry aEntry;
    1169                 :        576 :             aEntry.Name = rOoxName;
    1170                 :        576 :             aEntry.Token.OpCode = ornOpCode;
    1171         [ +  - ]:        576 :             maParserMap.push_back( aEntry );
    1172                 :            :         }
    1173                 :        600 :         return true;
    1174                 :            :     }
    1175                 :            :     OSL_FAIL( OStringBuffer( "OpCodeProviderImpl::initOpCode - opcode for \"" ).
    1176                 :            :         append( OUStringToOString( rOdfName, RTL_TEXTENCODING_ASCII_US ) ).
    1177                 :            :         append( "\" not found" ).getStr() );
    1178                 :        600 :     return false;
    1179                 :            : }
    1180                 :            : 
    1181                 :         72 : bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName )
    1182                 :            : {
    1183                 :         72 :     OUString aOoxName;
    1184         [ +  - ]:         72 :     if( pcOoxName ) aOoxName = OUString::createFromAscii( pcOoxName );
    1185         [ +  - ]:         72 :     return initOpCode( ornOpCode, rTokenMap, OUString::createFromAscii( pcOdfName ), aOoxName );
    1186                 :            : }
    1187                 :            : 
    1188                 :        528 : bool OpCodeProviderImpl::initOpCode( sal_Int32& ornOpCode, const ApiTokenMap& rTokenMap, sal_Unicode cOdfName, sal_Unicode cOoxName )
    1189                 :            : {
    1190                 :        528 :     OUString aOoxName;
    1191         [ +  + ]:        528 :     if( cOoxName ) aOoxName = OUString( cOoxName );
    1192         [ +  - ]:        528 :     return initOpCode( ornOpCode, rTokenMap, OUString( cOdfName ), aOoxName );
    1193                 :            : }
    1194                 :            : 
    1195                 :      10320 : bool OpCodeProviderImpl::initFuncOpCode( FunctionInfo& orFuncInfo, const ApiTokenMap& rFuncTokenMap )
    1196                 :            : {
    1197                 :      10320 :     bool bIsValid = false;
    1198         [ +  + ]:      10320 :     if( !orFuncInfo.maOdfFuncName.isEmpty() )
    1199                 :            :     {
    1200         [ +  - ]:       9000 :         ApiTokenMap::const_iterator aIt = rFuncTokenMap.find( orFuncInfo.maOdfFuncName );
    1201         [ +  + ]:       9000 :         if( aIt != rFuncTokenMap.end() )
    1202                 :            :         {
    1203                 :       8832 :             orFuncInfo.mnApiOpCode = aIt->second.OpCode;
    1204                 :            :             bIsValid =
    1205                 :            :                 (orFuncInfo.mnApiOpCode >= 0) &&
    1206                 :            :                 (orFuncInfo.mnApiOpCode != OPCODE_UNKNOWN) &&
    1207 [ +  - ][ +  - ]:       8832 :                 (orFuncInfo.mnApiOpCode != OPCODE_NONAME);
                 [ +  - ]
    1208                 :            :             OSL_ENSURE( bIsValid,
    1209                 :            :                 OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no valid opcode for ODF function \"" ).
    1210                 :            :                 append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ).
    1211                 :            :                 append( '"' ).getStr() );
    1212                 :            : 
    1213 [ +  - ][ +  + ]:       8832 :             if( bIsValid && (orFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) )
    1214                 :            :             {
    1215 [ +  - ][ +  - ]:       2232 :                 bIsValid = (aIt->second.Data >>= orFuncInfo.maExtProgName) && !orFuncInfo.maExtProgName.isEmpty();
    1216                 :            :                 OSL_ENSURE( bIsValid,
    1217                 :            :                     OStringBuffer( "OpCodeProviderImpl::initFuncOpCode - no programmatical name for external function \"" ).
    1218                 :            :                     append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ).
    1219                 :            :                     append( '"' ).getStr() );
    1220                 :            :             }
    1221                 :            : 
    1222                 :            :             // add to parser map, if OOXML function name exists
    1223 [ +  - ][ +  + ]:       8832 :             if( bIsValid && !orFuncInfo.maOoxFuncName.isEmpty() )
                 [ +  + ]
    1224                 :            :             {
    1225                 :            :                 // create the parser map entry
    1226                 :       8184 :                 FormulaOpCodeMapEntry aEntry;
    1227                 :       8184 :                 aEntry.Name = orFuncInfo.maOoxFuncName;
    1228                 :       8184 :                 aEntry.Token = aIt->second;
    1229         [ +  - ]:       8184 :                 maParserMap.push_back( aEntry );
    1230                 :            :             }
    1231                 :            :         }
    1232                 :            :         else
    1233                 :            :         {
    1234                 :            :             // ignore entries for functions unknown by Calc *and* by Excel
    1235                 :       9000 :             bIsValid = orFuncInfo.maOoxFuncName.isEmpty();
    1236                 :            :         }
    1237                 :            :     }
    1238         [ +  + ]:       1320 :     else if( orFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL )
    1239                 :            :     {
    1240                 :         24 :         orFuncInfo.mnApiOpCode = OPCODE_EXTERNAL;
    1241                 :         24 :         bIsValid = true;
    1242                 :            :     }
    1243         [ +  - ]:       1296 :     else if( !orFuncInfo.maOoxFuncName.isEmpty() )
    1244                 :            :     {
    1245                 :       1296 :         orFuncInfo.mnApiOpCode = OPCODE_BAD;
    1246                 :       1296 :         bIsValid = true;
    1247                 :            :     }
    1248                 :            : 
    1249 [ +  + ][ +  + ]:      10320 :     if( !bIsValid || (orFuncInfo.mnApiOpCode == OPCODE_UNKNOWN) || (orFuncInfo.mnApiOpCode < 0) )
                 [ -  + ]
    1250                 :        168 :         orFuncInfo.mnApiOpCode = OPCODE_NONAME;
    1251                 :      10320 :     return bIsValid;
    1252                 :            : }
    1253                 :            : 
    1254                 :         24 : bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, const ApiTokenMap& rExtFuncTokenMap, const FunctionInfoVector& rFuncInfos )
    1255                 :            : {
    1256                 :         24 :     bool bIsValid = true;
    1257 [ +  - ][ +  + ]:      10344 :     for( FunctionInfoVector::const_iterator aIt = rFuncInfos.begin(), aEnd = rFuncInfos.end(); aIt != aEnd; ++aIt )
    1258                 :            :     {
    1259         [ +  - ]:      10320 :         FunctionInfoRef xFuncInfo = *aIt;
    1260                 :            :         // set API opcode from ODF function name
    1261 [ +  + ][ +  - ]:      10320 :         bIsValid &= initFuncOpCode( *xFuncInfo, xFuncInfo->mbExternal ? rExtFuncTokenMap : rIntFuncTokenMap );
    1262                 :            :         // insert the function info into the maps
    1263         [ +  + ]:      10320 :         if( xFuncInfo->mnApiOpCode != OPCODE_NONAME )
    1264                 :            :         {
    1265 [ +  + ][ +  + ]:      10152 :             if( (xFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && !xFuncInfo->maExtProgName.isEmpty() )
                 [ +  + ]
    1266 [ +  - ][ +  - ]:       2232 :                 maExtProgFuncs[ xFuncInfo->maExtProgName ] = xFuncInfo;
    1267                 :            :             else
    1268 [ +  - ][ +  - ]:       7920 :                 maOpCodeFuncs[ xFuncInfo->mnApiOpCode ] = xFuncInfo;
    1269                 :            :         }
    1270         [ +  - ]:      10320 :     }
    1271                 :         24 :     return bIsValid;
    1272                 :            : }
    1273                 :            : 
    1274                 :            : // ----------------------------------------------------------------------------
    1275                 :            : 
    1276                 :         24 : OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxModelFactory,
    1277                 :            :         FilterType eFilter, BiffType eBiff, bool bImportFilter ) :
    1278                 :            :     FunctionProvider( eFilter, eBiff, bImportFilter ),
    1279 [ +  - ][ +  - ]:         24 :     mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxModelFactory ) )
         [ +  - ][ +  - ]
    1280                 :            : {
    1281                 :         24 : }
    1282                 :            : 
    1283         [ +  - ]:         72 : OpCodeProvider::~OpCodeProvider()
    1284                 :            : {
    1285         [ -  + ]:         72 : }
    1286                 :            : 
    1287                 :         48 : const ApiOpCodes& OpCodeProvider::getOpCodes() const
    1288                 :            : {
    1289                 :         48 :     return *mxOpCodeImpl;
    1290                 :            : }
    1291                 :            : 
    1292                 :        207 : const FunctionInfo* OpCodeProvider::getFuncInfoFromApiToken( const ApiToken& rToken ) const
    1293                 :            : {
    1294                 :        207 :     const FunctionInfo* pFuncInfo = 0;
    1295 [ -  + ][ #  # ]:        207 :     if( (rToken.OpCode == mxOpCodeImpl->OPCODE_EXTERNAL) && rToken.Data.has< OUString >() )
                 [ -  + ]
    1296 [ #  # ][ #  # ]:          0 :         pFuncInfo = mxOpCodeImpl->maExtProgFuncs.get( rToken.Data.get< OUString >() ).get();
    1297 [ -  + ][ #  # ]:        207 :     else if( (rToken.OpCode == mxOpCodeImpl->OPCODE_MACRO) && rToken.Data.has< OUString >() )
                 [ -  + ]
    1298         [ #  # ]:          0 :         pFuncInfo = getFuncInfoFromMacroName( rToken.Data.get< OUString >() );
    1299 [ +  + ][ +  - ]:        207 :     else if( (rToken.OpCode == mxOpCodeImpl->OPCODE_BAD) && rToken.Data.has< OUString >() )
                 [ +  + ]
    1300         [ +  - ]:         12 :         pFuncInfo = getFuncInfoFromOoxFuncName( rToken.Data.get< OUString >() );
    1301                 :            :     else
    1302                 :        195 :         pFuncInfo = mxOpCodeImpl->maOpCodeFuncs.get( rToken.OpCode ).get();
    1303                 :        207 :     return pFuncInfo;
    1304                 :            : }
    1305                 :            : 
    1306                 :         24 : Sequence< FormulaOpCodeMapEntry > OpCodeProvider::getOoxParserMap() const
    1307                 :            : {
    1308                 :         24 :     return ContainerHelper::vectorToSequence( mxOpCodeImpl->maParserMap );
    1309                 :            : }
    1310                 :            : 
    1311                 :            : // API formula parser wrapper =================================================
    1312                 :            : 
    1313                 :         24 : ApiParserWrapper::ApiParserWrapper(
    1314                 :            :         const Reference< XMultiServiceFactory >& rxModelFactory, const OpCodeProvider& rOpCodeProv ) :
    1315         [ +  - ]:         24 :     OpCodeProvider( rOpCodeProv )
    1316                 :            : {
    1317         [ +  - ]:         24 :     if( rxModelFactory.is() ) try
    1318                 :            :     {
    1319 [ +  - ][ +  - ]:         24 :         mxParser.set( rxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW );
         [ +  - ][ +  - ]
                 [ #  # ]
    1320                 :            :     }
    1321         [ #  # ]:          0 :     catch( Exception& )
    1322                 :            :     {
    1323                 :            :     }
    1324                 :            :     OSL_ENSURE( mxParser.is(), "ApiParserWrapper::ApiParserWrapper - cannot create API formula parser object" );
    1325         [ +  - ]:         24 :     maParserProps.set( mxParser );
    1326         [ +  - ]:         24 :     maParserProps.setProperty( PROP_CompileEnglish, true );
    1327         [ +  - ]:         24 :     maParserProps.setProperty( PROP_FormulaConvention, ::com::sun::star::sheet::AddressConvention::XL_OOX );
    1328         [ +  - ]:         24 :     maParserProps.setProperty( PROP_IgnoreLeadingSpaces, false );
    1329 [ +  - ][ +  - ]:         24 :     maParserProps.setProperty( PROP_OpCodeMap, getOoxParserMap() );
                 [ +  - ]
    1330                 :         24 : }
    1331                 :            : 
    1332                 :        117 : ApiTokenSequence ApiParserWrapper::parseFormula( const OUString& rFormula, const CellAddress& rRefPos )
    1333                 :            : {
    1334                 :        117 :     ApiTokenSequence aTokenSeq;
    1335         [ +  - ]:        117 :     if( mxParser.is() ) try
    1336                 :            :     {
    1337 [ +  - ][ +  - ]:        117 :         aTokenSeq = mxParser->parseFormula( rFormula, rRefPos );
         [ +  - ][ +  - ]
                 [ #  # ]
    1338                 :            :     }
    1339         [ #  # ]:          0 :     catch( Exception& )
    1340                 :            :     {
    1341                 :            :     }
    1342                 :        117 :     return aTokenSeq;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : // formula parser/printer base class for filters ==============================
    1346                 :            : 
    1347                 :            : namespace {
    1348                 :            : 
    1349                 :          0 : bool lclConvertToCellAddress( CellAddress& orAddress, const SingleReference& rSingleRef, sal_Int32 nForbiddenFlags, sal_Int32 nFilterBySheet )
    1350                 :            : {
    1351                 :            :     orAddress = CellAddress( static_cast< sal_Int16 >( rSingleRef.Sheet ),
    1352                 :          0 :         rSingleRef.Column, rSingleRef.Row );
    1353                 :            :     return
    1354                 :          0 :         !getFlag( rSingleRef.Flags, nForbiddenFlags ) &&
    1355 [ #  # ][ #  # ]:          0 :         ((nFilterBySheet < 0) || (nFilterBySheet == rSingleRef.Sheet));
                 [ #  # ]
    1356                 :            : }
    1357                 :            : 
    1358                 :          3 : bool lclConvertToCellRange( CellRangeAddress& orRange, const ComplexReference& rComplexRef, sal_Int32 nForbiddenFlags, sal_Int32 nFilterBySheet )
    1359                 :            : {
    1360                 :            :     orRange = CellRangeAddress( static_cast< sal_Int16 >( rComplexRef.Reference1.Sheet ),
    1361                 :            :         rComplexRef.Reference1.Column, rComplexRef.Reference1.Row,
    1362                 :          3 :         rComplexRef.Reference2.Column, rComplexRef.Reference2.Row );
    1363                 :            :     return
    1364                 :          3 :         !getFlag( rComplexRef.Reference1.Flags, nForbiddenFlags ) &&
    1365                 :          3 :         !getFlag( rComplexRef.Reference2.Flags, nForbiddenFlags ) &&
    1366                 :            :         (rComplexRef.Reference1.Sheet == rComplexRef.Reference2.Sheet) &&
    1367 [ +  - ][ -  + ]:          6 :         ((nFilterBySheet < 0) || (nFilterBySheet == rComplexRef.Reference1.Sheet));
                 [ #  # ]
           [ +  -  +  - ]
    1368                 :            : }
    1369                 :            : 
    1370                 :            : enum TokenToRangeListState { STATE_REF, STATE_SEP, STATE_OPEN, STATE_CLOSE, STATE_ERROR };
    1371                 :            : 
    1372                 :          3 : TokenToRangeListState lclProcessRef( ApiCellRangeList& orRanges, const Any& rData, bool bAllowRelative, sal_Int32 nFilterBySheet )
    1373                 :            : {
    1374                 :            :     using namespace ::com::sun::star::sheet::ReferenceFlags;
    1375                 :          3 :     const sal_Int32 FORBIDDEN_FLAGS_DEL = COLUMN_DELETED | ROW_DELETED | SHEET_DELETED;
    1376                 :          3 :     const sal_Int32 FORBIDDEN_FLAGS_REL = FORBIDDEN_FLAGS_DEL | COLUMN_RELATIVE | ROW_RELATIVE | SHEET_RELATIVE | RELATIVE_NAME;
    1377                 :            : 
    1378         [ -  + ]:          3 :     sal_Int32 nForbiddenFlags = bAllowRelative ? FORBIDDEN_FLAGS_DEL : FORBIDDEN_FLAGS_REL;
    1379                 :          3 :     SingleReference aSingleRef;
    1380 [ -  + ][ +  - ]:          3 :     if( rData >>= aSingleRef )
    1381                 :            :     {
    1382                 :          0 :         CellAddress aAddress;
    1383                 :            :         // ignore invalid addresses (with #REF! errors), but do not stop parsing
    1384 [ #  # ][ #  # ]:          0 :         if( lclConvertToCellAddress( aAddress, aSingleRef, nForbiddenFlags, nFilterBySheet ) )
    1385         [ #  # ]:          0 :             orRanges.push_back( CellRangeAddress( aAddress.Sheet, aAddress.Column, aAddress.Row, aAddress.Column, aAddress.Row ) );
    1386                 :          0 :         return STATE_REF;
    1387                 :            :     }
    1388                 :          3 :     ComplexReference aComplexRef;
    1389 [ +  - ][ +  - ]:          3 :     if( rData >>= aComplexRef )
    1390                 :            :     {
    1391                 :          3 :         CellRangeAddress aRange;
    1392                 :            :         // ignore invalid ranges (with #REF! errors), but do not stop parsing
    1393 [ +  - ][ +  - ]:          3 :         if( lclConvertToCellRange( aRange, aComplexRef, nForbiddenFlags, nFilterBySheet ) )
    1394         [ +  - ]:          3 :             orRanges.push_back( aRange );
    1395                 :          3 :         return STATE_REF;
    1396                 :            :     }
    1397                 :          3 :     return STATE_ERROR;
    1398                 :            : }
    1399                 :            : 
    1400                 :          0 : TokenToRangeListState lclProcessOpen( sal_Int32& ornParenLevel )
    1401                 :            : {
    1402                 :          0 :     ++ornParenLevel;
    1403                 :          0 :     return STATE_OPEN;
    1404                 :            : }
    1405                 :            : 
    1406                 :          0 : TokenToRangeListState lclProcessClose( sal_Int32& ornParenLevel )
    1407                 :            : {
    1408                 :          0 :     --ornParenLevel;
    1409         [ #  # ]:          0 :     return (ornParenLevel >= 0) ? STATE_CLOSE : STATE_ERROR;
    1410                 :            : }
    1411                 :            : 
    1412                 :            : } // namespace
    1413                 :            : 
    1414                 :            : // ----------------------------------------------------------------------------
    1415                 :            : 
    1416                 :         24 : FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper& rHelper ) :
    1417                 :         48 :     OpCodeProvider( rHelper.getBaseFilter().getModelFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ),
    1418         [ +  - ]:         24 :     ApiOpCodes( getOpCodes() ),
    1419                 :         72 :     WorkbookHelper( rHelper )
    1420                 :            : {
    1421                 :         24 : }
    1422                 :            : 
    1423                 :            : // ----------------------------------------------------------------------------
    1424                 :            : 
    1425                 :          0 : OUString FormulaProcessorBase::generateAddress2dString( const CellAddress& rAddress, bool bAbsolute )
    1426                 :            : {
    1427         [ #  # ]:          0 :     return generateAddress2dString( BinAddress( rAddress ), bAbsolute );
    1428                 :            : }
    1429                 :            : 
    1430                 :          0 : OUString FormulaProcessorBase::generateAddress2dString( const BinAddress& rAddress, bool bAbsolute )
    1431                 :            : {
    1432                 :          0 :     OUStringBuffer aBuffer;
    1433                 :            :     // column
    1434         [ #  # ]:          0 :     for( sal_Int32 nTemp = rAddress.mnCol; nTemp >= 0; (nTemp /= 26) -= 1 )
    1435         [ #  # ]:          0 :         aBuffer.insert( 0, sal_Unicode( 'A' + (nTemp % 26) ) );
    1436         [ #  # ]:          0 :     if( bAbsolute )
    1437         [ #  # ]:          0 :         aBuffer.insert( 0, sal_Unicode( '$' ) );
    1438                 :            :     // row
    1439         [ #  # ]:          0 :     if( bAbsolute )
    1440         [ #  # ]:          0 :         aBuffer.append( sal_Unicode( '$' ) );
    1441         [ #  # ]:          0 :     aBuffer.append( static_cast< sal_Int32 >( rAddress.mnRow + 1 ) );
    1442         [ #  # ]:          0 :     return aBuffer.makeStringAndClear();
    1443                 :            : }
    1444                 :            : 
    1445                 :          0 : OUString FormulaProcessorBase::generateRange2dString( const CellRangeAddress& rRange, bool bAbsolute )
    1446                 :            : {
    1447         [ #  # ]:          0 :     return generateRange2dString( BinRange( rRange ), bAbsolute );
    1448                 :            : }
    1449                 :            : 
    1450                 :          0 : OUString FormulaProcessorBase::generateRange2dString( const BinRange& rRange, bool bAbsolute )
    1451                 :            : {
    1452 [ #  # ][ #  # ]:          0 :     OUStringBuffer aBuffer( generateAddress2dString( rRange.maFirst, bAbsolute ) );
    1453 [ #  # ][ #  # ]:          0 :     if( (rRange.getColCount() > 1) || (rRange.getRowCount() > 1) )
                 [ #  # ]
    1454 [ #  # ][ #  # ]:          0 :         aBuffer.append( sal_Unicode( ':' ) ).append( generateAddress2dString( rRange.maLast, bAbsolute ) );
                 [ #  # ]
    1455         [ #  # ]:          0 :     return aBuffer.makeStringAndClear();
    1456                 :            : }
    1457                 :            : 
    1458                 :          0 : OUString FormulaProcessorBase::generateRangeList2dString( const ApiCellRangeList& rRanges,
    1459                 :            :         bool bAbsolute, sal_Unicode cSeparator, bool bEncloseMultiple )
    1460                 :            : {
    1461                 :          0 :     OUStringBuffer aBuffer;
    1462 [ #  # ][ #  # ]:          0 :     for( ApiCellRangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt )
    1463                 :            :     {
    1464         [ #  # ]:          0 :         if( aBuffer.getLength() > 0 )
    1465         [ #  # ]:          0 :             aBuffer.append( cSeparator );
    1466 [ #  # ][ #  # ]:          0 :         aBuffer.append( generateRange2dString( *aIt, bAbsolute ) );
    1467                 :            :     }
    1468 [ #  # ][ #  # ]:          0 :     if( bEncloseMultiple && (rRanges.size() > 1) )
                 [ #  # ]
    1469 [ #  # ][ #  # ]:          0 :         aBuffer.insert( 0, sal_Unicode( '(' ) ).append( sal_Unicode( ')' ) );
    1470         [ #  # ]:          0 :     return aBuffer.makeStringAndClear();
    1471                 :            : }
    1472                 :            : 
    1473                 :            : // ----------------------------------------------------------------------------
    1474                 :            : 
    1475                 :          0 : OUString FormulaProcessorBase::generateApiString( const OUString& rString )
    1476                 :            : {
    1477                 :          0 :     OUString aRetString = rString;
    1478                 :          0 :     sal_Int32 nQuotePos = aRetString.getLength();
    1479         [ #  # ]:          0 :     while( (nQuotePos = aRetString.lastIndexOf( '"', nQuotePos )) >= 0 )
    1480         [ #  # ]:          0 :         aRetString = aRetString.replaceAt( nQuotePos, 1, CREATE_OUSTRING( "\"\"" ) );
    1481 [ #  # ][ #  # ]:          0 :     return OUStringBuffer().append( sal_Unicode( '"' ) ).append( aRetString ).append( sal_Unicode( '"' ) ).makeStringAndClear();
         [ #  # ][ #  # ]
    1482                 :            : }
    1483                 :            : 
    1484                 :          0 : OUString FormulaProcessorBase::generateApiArray( const Matrix< Any >& rMatrix )
    1485                 :            : {
    1486                 :            :     OSL_ENSURE( !rMatrix.empty(), "FormulaProcessorBase::generateApiArray - missing matrix values" );
    1487                 :          0 :     OUStringBuffer aBuffer;
    1488         [ #  # ]:          0 :     aBuffer.append( API_TOKEN_ARRAY_OPEN );
    1489 [ #  # ][ #  # ]:          0 :     for( size_t nRow = 0, nHeight = rMatrix.height(); nRow < nHeight; ++nRow )
    1490                 :            :     {
    1491         [ #  # ]:          0 :         if( nRow > 0 )
    1492         [ #  # ]:          0 :             aBuffer.append( API_TOKEN_ARRAY_ROWSEP );
    1493 [ #  # ][ #  # ]:          0 :         for( Matrix< Any >::const_iterator aBeg = rMatrix.row_begin( nRow ), aIt = aBeg, aEnd = rMatrix.row_end( nRow ); aIt != aEnd; ++aIt )
         [ #  # ][ #  # ]
    1494                 :            :         {
    1495                 :          0 :             double fValue = 0.0;
    1496                 :          0 :             OUString aString;
    1497 [ #  # ][ #  # ]:          0 :             if( aIt != aBeg )
    1498         [ #  # ]:          0 :                 aBuffer.append( API_TOKEN_ARRAY_COLSEP );
    1499         [ #  # ]:          0 :             if( *aIt >>= fValue )
    1500         [ #  # ]:          0 :                 aBuffer.append( fValue );
    1501         [ #  # ]:          0 :             else if( *aIt >>= aString )
    1502 [ #  # ][ #  # ]:          0 :                 aBuffer.append( generateApiString( aString ) );
    1503                 :            :             else
    1504         [ #  # ]:          0 :                 aBuffer.appendAscii( "\"\"" );
    1505                 :          0 :         }
    1506                 :            :     }
    1507         [ #  # ]:          0 :     aBuffer.append( API_TOKEN_ARRAY_CLOSE );
    1508         [ #  # ]:          0 :     return aBuffer.makeStringAndClear();
    1509                 :            : }
    1510                 :            : 
    1511                 :            : // ----------------------------------------------------------------------------
    1512                 :            : 
    1513                 :          3 : Any FormulaProcessorBase::extractReference( const ApiTokenSequence& rTokens ) const
    1514                 :            : {
    1515         [ +  - ]:          3 :     ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true );
    1516 [ +  - ][ +  - ]:          3 :     if( aTokenIt.is() && (aTokenIt->OpCode == OPCODE_PUSH) )
                 [ +  - ]
    1517                 :            :     {
    1518                 :          3 :         Any aRefAny = aTokenIt->Data;
    1519 [ +  - ][ +  - ]:          3 :         if( !(++aTokenIt).is() && (aRefAny.has< SingleReference >() || aRefAny.has< ComplexReference >()) )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1520         [ -  + ]:          3 :             return aRefAny;
    1521                 :            :     }
    1522                 :          3 :     return Any();
    1523                 :            : }
    1524                 :            : 
    1525                 :          3 : bool FormulaProcessorBase::extractCellRange( CellRangeAddress& orRange,
    1526                 :            :         const ApiTokenSequence& rTokens, bool bAllowRelative ) const
    1527                 :            : {
    1528         [ +  - ]:          3 :     ApiCellRangeList aRanges;
    1529 [ +  - ][ +  - ]:          3 :     lclProcessRef( aRanges, extractReference( rTokens ), bAllowRelative, -1 );
    1530         [ +  - ]:          3 :     if( !aRanges.empty() )
    1531                 :            :     {
    1532         [ +  - ]:          3 :         orRange = aRanges.front();
    1533                 :          3 :         return true;
    1534                 :            :     }
    1535                 :          3 :     return false;
    1536                 :            : }
    1537                 :            : 
    1538                 :          0 : void FormulaProcessorBase::extractCellRangeList( ApiCellRangeList& orRanges,
    1539                 :            :         const ApiTokenSequence& rTokens, bool bAllowRelative, sal_Int32 nFilterBySheet ) const
    1540                 :            : {
    1541                 :          0 :     orRanges.clear();
    1542                 :          0 :     TokenToRangeListState eState = STATE_OPEN;
    1543                 :          0 :     sal_Int32 nParenLevel = 0;
    1544 [ #  # ][ #  # ]:          0 :     for( ApiTokenIterator aIt( rTokens, OPCODE_SPACES, true ); aIt.is() && (eState != STATE_ERROR); ++aIt )
         [ #  # ][ #  # ]
                 [ #  # ]
    1545                 :            :     {
    1546                 :          0 :         sal_Int32 nOpCode = aIt->OpCode;
    1547   [ #  #  #  #  :          0 :         switch( eState )
                      # ]
    1548                 :            :         {
    1549                 :            :             // #i107275# accept OPCODE_SEP and OPCODE_LIST as separator token
    1550                 :            :             case STATE_REF:
    1551         [ #  # ]:          0 :                      if( nOpCode == OPCODE_SEP )   eState = STATE_SEP;
    1552         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_LIST )  eState = STATE_SEP;
    1553         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel );
    1554                 :          0 :                 else                               eState = STATE_ERROR;
    1555                 :          0 :             break;
    1556                 :            :             case STATE_SEP:
    1557 [ #  # ][ #  # ]:          0 :                      if( nOpCode == OPCODE_PUSH )  eState = lclProcessRef( orRanges, aIt->Data, bAllowRelative, nFilterBySheet );
    1558         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_SEP )   eState = STATE_SEP;
    1559         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_LIST )  eState = STATE_SEP;
    1560         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_OPEN )  eState = lclProcessOpen( nParenLevel );
    1561         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel );
    1562                 :          0 :                 else                               eState = STATE_ERROR;
    1563                 :          0 :             break;
    1564                 :            :             case STATE_OPEN:
    1565 [ #  # ][ #  # ]:          0 :                      if( nOpCode == OPCODE_PUSH )  eState = lclProcessRef( orRanges, aIt->Data, bAllowRelative, nFilterBySheet );
    1566         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_SEP )   eState = STATE_SEP;
    1567         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_LIST )  eState = STATE_SEP;
    1568         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_OPEN )  eState = lclProcessOpen( nParenLevel );
    1569         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel );
    1570                 :          0 :                 else                               eState = STATE_ERROR;
    1571                 :          0 :             break;
    1572                 :            :             case STATE_CLOSE:
    1573         [ #  # ]:          0 :                      if( nOpCode == OPCODE_SEP )   eState = STATE_SEP;
    1574         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_LIST )  eState = STATE_SEP;
    1575         [ #  # ]:          0 :                 else if( nOpCode == OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel );
    1576                 :          0 :                 else                               eState = STATE_ERROR;
    1577                 :          0 :             break;
    1578                 :            :             default:;
    1579                 :            :         }
    1580                 :            :     }
    1581                 :            : 
    1582         [ #  # ]:          0 :     if( eState == STATE_ERROR )
    1583                 :          0 :         orRanges.clear();
    1584                 :            :     else
    1585 [ #  # ][ #  # ]:          0 :         getAddressConverter().validateCellRangeList( orRanges, false );
    1586                 :          0 : }
    1587                 :            : 
    1588                 :          0 : bool FormulaProcessorBase::extractString( OUString& orString, const ApiTokenSequence& rTokens ) const
    1589                 :            : {
    1590         [ #  # ]:          0 :     ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true );
    1591 [ #  # ][ #  # ]:          0 :     return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_PUSH) && (aTokenIt->Data >>= orString) && !(++aTokenIt).is();
         [ #  # ][ #  # ]
                 [ #  # ]
    1592                 :            : }
    1593                 :            : 
    1594                 :          0 : bool FormulaProcessorBase::extractSpecialTokenInfo( ApiSpecialTokenInfo& orTokenInfo, const ApiTokenSequence& rTokens ) const
    1595                 :            : {
    1596         [ #  # ]:          0 :     ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true );
    1597 [ #  # ][ #  # ]:          0 :     return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_BAD) && (aTokenIt->Data >>= orTokenInfo);
         [ #  # ][ #  # ]
    1598                 :            : }
    1599                 :            : 
    1600                 :          0 : void FormulaProcessorBase::convertStringToStringList(
    1601                 :            :         ApiTokenSequence& orTokens, sal_Unicode cStringSep, bool bTrimLeadingSpaces ) const
    1602                 :            : {
    1603                 :          0 :     OUString aString;
    1604 [ #  # ][ #  # ]:          0 :     if( extractString( aString, orTokens ) && !aString.isEmpty() )
         [ #  # ][ #  # ]
    1605                 :            :     {
    1606         [ #  # ]:          0 :         ::std::vector< ApiToken > aNewTokens;
    1607                 :          0 :         sal_Int32 nPos = 0;
    1608                 :          0 :         sal_Int32 nLen = aString.getLength();
    1609 [ #  # ][ #  # ]:          0 :         while( (0 <= nPos) && (nPos < nLen) )
                 [ #  # ]
    1610                 :            :         {
    1611                 :          0 :             OUString aEntry = aString.getToken( 0, cStringSep, nPos );
    1612         [ #  # ]:          0 :             if( bTrimLeadingSpaces )
    1613                 :            :             {
    1614                 :          0 :                 sal_Int32 nStart = 0;
    1615 [ #  # ][ #  # ]:          0 :                 while( (nStart < aEntry.getLength()) && (aEntry[ nStart ] == ' ') ) ++nStart;
                 [ #  # ]
    1616                 :          0 :                 aEntry = aEntry.copy( nStart );
    1617                 :            :             }
    1618         [ #  # ]:          0 :             if( !aNewTokens.empty() )
    1619         [ #  # ]:          0 :                 aNewTokens.push_back( ApiToken( OPCODE_SEP, Any() ) );
    1620 [ #  # ][ #  # ]:          0 :             aNewTokens.push_back( ApiToken( OPCODE_PUSH, Any( aEntry ) ) );
    1621                 :          0 :         }
    1622 [ #  # ][ #  # ]:          0 :         orTokens = ContainerHelper::vectorToSequence( aNewTokens );
                 [ #  # ]
    1623                 :          0 :     }
    1624                 :          0 : }
    1625                 :            : 
    1626                 :            : // ============================================================================
    1627                 :            : 
    1628                 :            : } // namespace xls
    1629 [ +  - ][ +  - ]:         24 : } // namespace oox
    1630                 :            : 
    1631                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10