formula/source/core/api/FormulaCompiler.cxx |   91 +++++++++++++++++++++++++---
 sc/source/core/tool/compiler.cxx            |   18 +++++
 2 files changed, 102 insertions(+), 7 deletions(-)

New commits:
commit f551477ab32ad2671d85a3070a0a436715ea7505
Author: Eike Rathke <er...@redhat.com>
Date:   Fri Aug 26 16:31:33 2016 +0200

    handle overwriting of symbols/opcodes in symbol map for known cases
    
    This silences the SAL_WARN_IF like
    warn:formula.core:6944:1:formula/source/core/api/FormulaCompiler.cxx:625:
    OpCodeMap::putOpCode: reusing OpCode 161,
    replacing '_xlfn.ORG.OPENOFFICE.ERRORTYPE' with 'ERRORTYPE'
    in English map 0x1018000
    
    that occurred during the first load of OOXML .xlsx documents since the
    old bad entries were added with commit
    89c4a69103b6e15e7f52401c51110b926c3ccf36
    
    In fact the direction opcode -> string was replaced, which it should had
    not. That specific mapping is only used though when loading msoxl
    namespace formulas from ODF.
    
    Also, the replacement of parameter separator and array column and row
    separator worked merely by chance, depending on in which order the
    entries where inserted to the hash map. Fixed along as it popped up with
    the new handling.
    
    Change-Id: I88017a8b38ccc30874c3dca7d78f0fa47a77a36f

diff --git a/formula/source/core/api/FormulaCompiler.cxx 
b/formula/source/core/api/FormulaCompiler.cxx
index 7354cfc..be19fcf 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -617,14 +617,91 @@ void FormulaCompiler::OpCodeMap::putOpCode( const 
OUString & rStr, const OpCode
 {
     if (0 < eOp && sal_uInt16(eOp) < mnSymbols)
     {
-        SAL_WARN_IF( !(mpTable[eOp].isEmpty() || (mpTable[eOp] == rStr) ||
-                    (eOp == ocCurrency) || (eOp == ocSep) || (eOp == 
ocArrayColSep) ||
-                    (eOp == ocArrayRowSep)), "formula.core",
-                "OpCodeMap::putOpCode: reusing OpCode " << 
static_cast<sal_uInt16>(eOp)
-                << ", replacing '" << mpTable[eOp] << "' with '" << rStr << "' 
in "
-                << (mbEnglish ? "" : "non-") << "English map 0x" << ::std::hex 
<< meGrammar);
+        bool bPutOp = mpTable[eOp].isEmpty();
+        bool bRemoveFromMap = false;
+        if (!bPutOp)
+        {
+            switch (eOp)
+            {
+                // These OpCodes are meant to overwrite and also remove an
+                // existing mapping.
+                case ocCurrency:
+                    bPutOp = true;
+                    bRemoveFromMap = true;
+                break;
+                // These separator OpCodes are meant to overwrite and also
+                // remove an existing mapping if it is not used for one of the
+                // other separators.
+                case ocArrayColSep:
+                    bPutOp = true;
+                    bRemoveFromMap = (mpTable[ocArrayRowSep] != mpTable[eOp] 
&& mpTable[ocSep] != mpTable[eOp]);
+                break;
+                case ocArrayRowSep:
+                    bPutOp = true;
+                    bRemoveFromMap = (mpTable[ocArrayColSep] != mpTable[eOp] 
&& mpTable[ocSep] != mpTable[eOp]);
+                break;
+                // For ocSep keep the ";" in map but remove any other if it is
+                // not used for ocArrayColSep or ocArrayRowSep.
+                case ocSep:
+                    bPutOp = true;
+                    bRemoveFromMap = (mpTable[eOp] != ";" &&
+                            mpTable[ocArrayColSep] != mpTable[eOp] &&
+                            mpTable[ocArrayColSep] != mpTable[eOp]);
+                break;
+                // These OpCodes are known to be duplicates in the Excel
+                // external API mapping because of different parameter counts
+                // in different BIFF versions. Names are identical and entries
+                // are ignored.
+                case ocLinest:
+                case ocTrend:
+                case ocLogest:
+                case ocGrowth:
+                case ocTrunc:
+                case ocFixed:
+                case ocGetDayOfWeek:
+                case ocHLookup:
+                case ocVLookup:
+                case ocGetDiffDate360:
+                    if (rStr == mpTable[eOp])
+                        return;
+                    SAL_FALLTHROUGH;
+                // These OpCodes are known to be added to an existing mapping,
+                // but only for the OOXML external API mapping. This is *not*
+                // FormulaLanguage::OOXML. Keep the first
+                // (correct) definition for the OpCode, all following are
+                // additional alias entries in the map.
+                case ocErrorType:
+                case ocMultiArea:
+                case ocBackSolver:
+                case ocEasterSunday:
+                case ocCurrent:
+                case ocStyle:
+                    if (mbEnglish &&
+                            FormulaGrammar::extractFormulaLanguage( meGrammar) 
== FormulaGrammar::GRAM_EXTERNAL)
+                    {
+                        // Both bPutOp and bRemoveFromMap stay false.
+                        break;
+                    }
+                    SAL_FALLTHROUGH;
+                default:
+                    SAL_WARN("formula.core",
+                            "OpCodeMap::putOpCode: reusing OpCode " << 
static_cast<sal_uInt16>(eOp)
+                            << ", replacing '" << mpTable[eOp] << "' with '" 
<< rStr << "' in "
+                            << (mbEnglish ? "" : "non-") << "English map 0x" 
<< ::std::hex << meGrammar);
+            }
+        }
+
         // Case preserving opcode -> string, upper string -> opcode
-        mpTable[eOp] = rStr;
+        if (bRemoveFromMap)
+        {
+            OUString aUpper( pCharClass ? pCharClass->uppercase( mpTable[eOp]) 
: rStr.toAsciiUpperCase());
+            // Ensure we remove a mapping only for the requested OpCode.
+            OpCodeHashMap::const_iterator it( mpHashMap->find( aUpper));
+            if (it != mpHashMap->end() && (*it).second == eOp)
+                mpHashMap->erase( it);
+        }
+        if (bPutOp)
+            mpTable[eOp] = rStr;
         OUString aUpper( pCharClass ? pCharClass->uppercase( rStr) : 
rStr.toAsciiUpperCase());
         mpHashMap->insert( OpCodeHashMap::value_type( aUpper, eOp));
     }
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 0767e2c..7c38ca4 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -2691,6 +2691,24 @@ bool ScCompiler::IsOpCode( const OUString& rName, bool 
bInArray )
             else if (rName.equals(mxSymbols->getSymbol(ocArrayRowSep)))
                 eOp = ocArrayRowSep;
         }
+        else if (eOp == ocArrayColSep || eOp == ocArrayRowSep)
+        {
+            if (rName.equals(mxSymbols->getSymbol(ocSep)))
+                eOp = ocSep;
+            else if (rName == ";")
+            {
+                switch (FormulaGrammar::extractFormulaLanguage( meGrammar))
+                {
+                    // Only for languages/grammars that actually use ';'
+                    // parameter separator.
+                    case css::sheet::FormulaLanguage::NATIVE:
+                    case css::sheet::FormulaLanguage::ENGLISH:
+                    case css::sheet::FormulaLanguage::ODFF:
+                    case css::sheet::FormulaLanguage::ODF_11:
+                        eOp = ocSep;
+                }
+            }
+        }
         else if (eOp == ocCeil && mxSymbols->isOOXML())
         {
             // Ensure that _xlfn.CEILING.MATH maps to ocCeil_Math. ocCeil is
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to