summaryrefslogtreecommitdiff
path: root/formula
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2016-08-26 16:31:33 +0200
committerEike Rathke <erack@redhat.com>2016-08-26 16:46:12 +0200
commitf551477ab32ad2671d85a3070a0a436715ea7505 (patch)
treed46cbd8446ef7caae59d703e6c121c1d62b83c94 /formula
parentc922161117dcaf33d6c61b0c5ffe860231e32e3c (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.cxx91
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));
}