Kaydet (Commit) f551477a authored tarafından Eike Rathke's avatar Eike Rathke

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
89c4a691

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
üst c9221611
......@@ -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));
}
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment