diff options
author | Eike Rathke <erack@redhat.com> | 2016-08-26 16:31:33 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-08-26 16:46:12 +0200 |
commit | f551477ab32ad2671d85a3070a0a436715ea7505 (patch) | |
tree | d46cbd8446ef7caae59d703e6c121c1d62b83c94 /formula | |
parent | c922161117dcaf33d6c61b0c5ffe860231e32e3c (diff) |
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
Diffstat (limited to 'formula')
-rw-r--r-- | formula/source/core/api/FormulaCompiler.cxx | 91 |
1 files changed, 84 insertions, 7 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index 7354cfc59484..be19fcf87883 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)); } |