21#include <rtl/math.hxx>
27#include <core_resource.hxx>
28#include <core_resource.hrc>
35#include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp>
36#include <com/sun/star/sheet/FormulaMapGroup.hpp>
37#include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
45 static const char*
pInternal[2] = {
"TTT",
"__DEBUG_VAR" };
49class FormulaCompilerRecursionGuard
54 explicit FormulaCompilerRecursionGuard(
short& rRec )
56 ~FormulaCompilerRecursionGuard() { --
rRecursion; }
88 return SvNumFormatType::LOGICAL;
92 return SvNumFormatType::DATE;
94 return SvNumFormatType::DATETIME;
96 return SvNumFormatType::TIME;
110 return SvNumFormatType::CURRENCY;
118 return SvNumFormatType::PERCENT;
120 return SvNumFormatType::NUMBER;
124void lclPushOpCodeMapEntry( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec,
125 const OUString* pTable, sal_uInt16 nOpCode )
127 sheet::FormulaOpCodeMapEntry aEntry;
128 aEntry.Token.OpCode = nOpCode;
129 aEntry.Name = pTable[nOpCode];
130 rVec.push_back( aEntry);
133void lclPushOpCodeMapEntries( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec,
134 const OUString* pTable, sal_uInt16 nOpCodeBeg, sal_uInt16 nOpCodeEnd )
136 for (sal_uInt16 nOpCode = nOpCodeBeg; nOpCode < nOpCodeEnd; ++nOpCode)
137 lclPushOpCodeMapEntry( rVec, pTable, nOpCode );
140void lclPushOpCodeMapEntries( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec,
141 const OUString* pTable,
const sal_uInt16* pnOpCodes,
size_t nCount )
143 for (
const sal_uInt16* pnEnd = pnOpCodes + nCount; pnOpCodes < pnEnd; ++pnOpCodes)
144 lclPushOpCodeMapEntry( rVec, pTable, *pnOpCodes );
147CharClass* createCharClassIfNonEnglishUI()
150 if (rLanguageTag.getLanguage() ==
"en")
152 return new CharClass( ::comphelper::getProcessComponentContext(), rLanguageTag);
165 bool getOpCodeString( OUString& rStr, sal_uInt16 nOp );
180 std::unique_ptr<CharClass> xCharClass( xMap->isEnglish() ?
nullptr : createCharClassIfNonEnglishUI());
181 const CharClass* pCharClass = xCharClass.get();
182 if (
meSepType == FormulaCompiler::SeparatorType::RESOURCE_BASE)
186 putDefaultOpCode( xMap,
i, pCharClass);
194 if ( getOpCodeString( aOpStr, i) )
195 xMap->putOpCode( aOpStr,
OpCode(i), pCharClass);
197 putDefaultOpCode( xMap, i, pCharClass);
202OpCodeList::OpCodeList(
const std::pair<TranslateId, int>* pSymbols,
const FormulaCompiler::NonConstOpCodeMapPtr& xMap,
203 FormulaCompiler::SeparatorType eSepType)
208 std::unique_ptr<CharClass> xCharClass( xMap->isEnglish() ?
nullptr : createCharClassIfNonEnglishUI());
209 const CharClass* pCharClass = xCharClass.get();
210 if (
meSepType == FormulaCompiler::SeparatorType::RESOURCE_BASE)
214 putDefaultOpCode( xMap, i, pCharClass);
222 if ( getOpCodeString( aOpStr, i) )
223 xMap->putOpCode( aOpStr,
OpCode(i), pCharClass);
225 putDefaultOpCode( xMap, i, pCharClass);
230bool OpCodeList::getOpCodeString( OUString& rStr, sal_uInt16 nOp )
236 if (
meSepType == FormulaCompiler::SeparatorType::SEMICOLON_BASE)
245 if (
meSepType == FormulaCompiler::SeparatorType::SEMICOLON_BASE)
254 if (
meSepType == FormulaCompiler::SeparatorType::SEMICOLON_BASE)
266void OpCodeList::putDefaultOpCode(
const FormulaCompiler::NonConstOpCodeMapPtr& xMap, sal_uInt16 nOp,
272 const char* pKey =
nullptr;
273 for (
const std::pair<const char*, int>* pSymbol =
mpSymbols1; pSymbol->first; ++pSymbol)
275 if (nOp == pSymbol->second)
277 pKey = pSymbol->first;
283 sKey = OUString::createFromAscii(pKey);
288 for (
const std::pair<TranslateId, int>* pSymbol =
mpSymbols2; pSymbol->first; ++pSymbol)
290 if (nOp == pSymbol->second)
292 pKey = pSymbol->first;
300 xMap->putOpCode(sKey,
OpCode(nOp), pCharClass);
324bool isPotentialRangeLeftOp(
OpCode eOp )
335bool isRangeResultFunction(
OpCode eOp )
347bool isRangeResultOpCode(
OpCode eOp )
371bool isPotentialRangeType( FormulaToken
const * pToken,
bool bRPN,
bool bRight )
373 switch (pToken->GetType())
377 return isRangeResultOpCode( pToken->GetOpCode());
379 return isRangeResultFunction( pToken->GetOpCode());
381 return isPotentialRangeLeftOp( pToken->GetOpCode());
393 return bRPN && !bRight && pToken->GetOpCode() ==
ocUnion;
397 return !bRPN && !bRight && isPotentialRangeLeftOp( pToken->GetOpCode());
401bool isIntersectable( FormulaToken** pCode1, FormulaToken** pCode2 )
403 FormulaToken* pToken1 = *pCode1;
404 FormulaToken* pToken2 = *pCode2;
405 if (pToken1 && pToken2)
406 return isPotentialRangeType( pToken1,
true,
false) && isPotentialRangeType( pToken2,
true,
true);
410bool isAdjacentRpnEnd( sal_uInt16 nPC,
411 FormulaToken
const *
const *
const pCode,
412 FormulaToken
const *
const *
const pCode1,
413 FormulaToken
const *
const *
const pCode2 )
415 return nPC >= 2 && pCode1 && pCode2 &&
416 (pCode2 - pCode1 == 1) && (pCode - pCode2 == 1) &&
417 (*pCode1 !=
nullptr) && (*pCode2 !=
nullptr);
420bool isAdjacentOrGapRpnEnd( sal_uInt16 nPC,
421 FormulaToken
const *
const *
const pCode,
422 FormulaToken
const *
const *
const pCode1,
423 FormulaToken
const *
const *
const pCode2 )
425 return nPC >= 2 && pCode1 && pCode2 &&
426 (pCode2 > pCode1) && (pCode - pCode2 == 1) &&
427 (*pCode1 !=
nullptr) && (*pCode2 !=
nullptr);
434void FormulaCompiler::OpCodeMap::putExternal(
const OUString & rSymbol,
const OUString & rAddIn )
440 bool bOk = maExternalHashMap.emplace(rSymbol, rAddIn).second;
441 SAL_WARN_IF( !bOk,
"formula.core",
"OpCodeMap::putExternal: symbol not inserted, " << rSymbol <<
" -> " << rAddIn);
444 bOk = maReverseExternalHashMap.emplace(rAddIn, rSymbol).second;
447 SAL_INFO_IF( !bOk,
"formula.core",
"OpCodeMap::putExternal: AddIn not inserted, " << rAddIn <<
" -> " << rSymbol);
451void FormulaCompiler::OpCodeMap::putExternalSoftly(
const OUString & rSymbol,
const OUString & rAddIn )
454 bool bOk = maExternalHashMap.emplace(rSymbol, rAddIn).second;
455 SAL_INFO(
"formula.core",
"OpCodeMap::putExternalSoftly: symbol " << (bOk ?
"" :
"not ") <<
"inserted, " << rSymbol <<
" -> " << rAddIn);
458 bOk = maReverseExternalHashMap.emplace(rAddIn, rSymbol).second;
459 SAL_INFO_IF( !bOk,
"formula.core",
"OpCodeMap::putExternalSoftly: AddIn not inserted, " << rAddIn <<
" -> " << rSymbol);
466 const sal_Int32 nLen = rNames.getLength();
468 sheet::FormulaToken* pToken = aTokens.getArray();
469 OUString
const *
pName = rNames.getConstArray();
470 OUString
const *
const pStop =
pName + nLen;
473 OpCodeHashMap::const_iterator iLook( maHashMap.find( *
pName));
474 if (iLook != maHashMap.end())
475 pToken->OpCode = (*iLook).second;
481 ExternalHashMap::const_iterator iExt( maExternalHashMap.find( *
pName));
482 if (iExt != maExternalHashMap.end())
483 aIntName = (*iExt).second;
487 if (aIntName.isEmpty())
489 if (aIntName.isEmpty())
490 pToken->OpCode = getOpCodeUnknown();
494 pToken->Data <<= aIntName;
504 using namespace sheet;
509 ::std::vector< FormulaOpCodeMapEntry > aVec;
511 if (nGroups == FormulaMapGroup::SPECIAL)
520 { FormulaMapGroupSpecialOffset::PUSH ,
ocPush } ,
521 { FormulaMapGroupSpecialOffset::CALL ,
ocCall } ,
522 { FormulaMapGroupSpecialOffset::STOP ,
ocStop } ,
523 { FormulaMapGroupSpecialOffset::EXTERNAL ,
ocExternal } ,
524 { FormulaMapGroupSpecialOffset::NAME ,
ocName } ,
525 { FormulaMapGroupSpecialOffset::NO_NAME ,
ocNoName } ,
526 { FormulaMapGroupSpecialOffset::MISSING ,
ocMissing } ,
527 { FormulaMapGroupSpecialOffset::BAD ,
ocBad } ,
528 { FormulaMapGroupSpecialOffset::SPACES ,
ocSpaces } ,
529 { FormulaMapGroupSpecialOffset::MAT_REF ,
ocMatRef } ,
530 { FormulaMapGroupSpecialOffset::DB_AREA ,
ocDBArea } ,
532 { FormulaMapGroupSpecialOffset::MACRO ,
ocMacro } ,
533 { FormulaMapGroupSpecialOffset::COL_ROW_NAME ,
ocColRowName } ,
534 { FormulaMapGroupSpecialOffset::WHITESPACE ,
ocWhitespace }
538 FormulaOpCodeMapEntry aEntry;
539 aEntry.Token.OpCode = getOpCodeUnknown();
540 aVec.resize(
nCount, aEntry);
544 size_t nIndex =
static_cast< size_t >(
i.nOff );
545 if (aVec.size() <=
nIndex)
551 aEntry.Token.OpCode = getOpCodeUnknown();
552 aVec.resize(
nIndex + 1, aEntry );
554 aEntry.Token.OpCode =
i.eOp;
565 if ((nGroups & FormulaMapGroup::SEPARATORS) != 0)
567 static const sal_uInt16 aOpCodes[] = {
572 lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes,
SAL_N_ELEMENTS(aOpCodes) );
574 if ((nGroups & FormulaMapGroup::ARRAY_SEPARATORS) != 0)
576 static const sal_uInt16 aOpCodes[] = {
582 lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes,
SAL_N_ELEMENTS(aOpCodes) );
584 if ((nGroups & FormulaMapGroup::UNARY_OPERATORS) != 0)
590 if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) == 0)
591 lclPushOpCodeMapEntry( aVec, mpTable.get(),
ocAdd );
595 lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp );
598 if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) != 0)
610 lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp );
614 if ((nGroups & FormulaMapGroup::FUNCTIONS) != 0)
623 static const sal_uInt16 aOpCodes[] = {
631 lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes,
SAL_N_ELEMENTS(aOpCodes) );
641 lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp );
647 for (
auto const& elem : maExternalHashMap)
649 FormulaOpCodeMapEntry aEntry;
650 aEntry.Name = elem.first;
651 aEntry.Token.Data <<= elem.second;
653 aVec.push_back( aEntry);
666void FormulaCompiler::OpCodeMap::putOpCode(
const OUString & rStr,
const OpCode eOp,
const CharClass* pCharClass )
668 if (0 < eOp && sal_uInt16(eOp) < mnSymbols)
670 bool bPutOp = mpTable[eOp].isEmpty();
671 bool bRemoveFromMap =
false;
680 bRemoveFromMap =
true;
687 bRemoveFromMap = (mpTable[
ocArrayRowSep] != mpTable[eOp] && mpTable[
ocSep] != mpTable[eOp]);
691 bRemoveFromMap = (mpTable[
ocArrayColSep] != mpTable[eOp] && mpTable[
ocSep] != mpTable[eOp]);
697 bRemoveFromMap = (mpTable[eOp] !=
";" &&
715 if (rStr == mpTable[eOp])
730 FormulaGrammar::extractFormulaLanguage( meGrammar) == FormulaGrammar::GRAM_EXTERNAL)
738 "OpCodeMap::putOpCode: reusing OpCode " <<
static_cast<sal_uInt16
>(eOp)
739 <<
", replacing '" << mpTable[eOp] <<
"' with '" << rStr <<
"' in "
740 << (mbEnglish ?
"" :
"non-") <<
"English map 0x" << ::std::hex << meGrammar);
747 OUString aUpper( pCharClass ? pCharClass->
uppercase( mpTable[eOp]) : rStr.toAsciiUpperCase());
749 OpCodeHashMap::const_iterator it( maHashMap.find( aUpper));
750 if (it != maHashMap.end() && (*it).second == eOp)
751 maHashMap.erase( it);
755 OUString aUpper( pCharClass ? pCharClass->
uppercase( rStr) : rStr.toAsciiUpperCase());
756 maHashMap.emplace(aUpper, eOp);
760 SAL_WARN(
"formula.core",
"OpCodeMap::putOpCode: OpCode out of range");
767 nCurrentFactorParam(0),
769 maArrIterator( rArr ),
777 bAutoCorrect( false ),
780 needsRPNTokenCheck( false ),
781 mbJumpCommandReorder(true),
783 mbComputeII(bComputeII),
784 mbMatrixFlag(bMatrixFlag)
792 nCurrentFactorParam(0),
794 maArrIterator( smDummyTokenArray ),
802 bAutoCorrect( false ),
805 needsRPNTokenCheck( false ),
806 mbJumpCommandReorder(true),
808 mbComputeII(bComputeII),
809 mbMatrixFlag(bMatrixFlag)
829 using namespace sheet;
832 case FormulaLanguage::ODFF :
837 case FormulaLanguage::ODF_11 :
842 case FormulaLanguage::ENGLISH :
847 case FormulaLanguage::NATIVE :
852 case FormulaLanguage::XL_ENGLISH:
857 case FormulaLanguage::OOXML:
862 case FormulaLanguage::API :
875 using namespace sheet;
878 case FormulaLanguage::ODFF :
881 case FormulaLanguage::ODF_11 :
884 case FormulaLanguage::ENGLISH :
887 case FormulaLanguage::NATIVE :
890 case FormulaLanguage::XL_ENGLISH:
893 case FormulaLanguage::OOXML:
896 case FormulaLanguage::API :
906 using namespace sheet;
909 case FormulaLanguage::ODFF :
911 case FormulaLanguage::ODF_11 :
913 case FormulaLanguage::ENGLISH :
915 case FormulaLanguage::NATIVE :
917 case FormulaLanguage::XL_ENGLISH:
919 case FormulaLanguage::OOXML:
921 case FormulaLanguage::API :
936 const sheet::FormulaOpCodeMapEntry > & rMapping,
939 using sheet::FormulaOpCodeMapEntry;
944 std::unique_ptr<CharClass> xCharClass( xMap->isEnglish() ?
nullptr : createCharClassIfNonEnglishUI());
945 const CharClass* pCharClass = xCharClass.get();
946 for (
auto const& rMapEntry : rMapping)
950 xMap->putOpCode( rMapEntry.Name, eOp, pCharClass);
953 OUString aExternalName;
954 if (rMapEntry.Token.Data >>= aExternalName)
955 xMap->putExternal( rMapEntry.Name, aExternalName);
958 SAL_WARN(
"formula.core",
"FormulaCompiler::CreateOpCodeMap: no Token.Data external name");
967 static OpCodeMapData aSymbolMap;
968 std::unique_lock aGuard(aSymbolMap.maMtx);
970 if (eWhat == FormulaCompiler::InitSymbols::ASK)
972 return bool(aSymbolMap.mxSymbolMap);
974 else if (eWhat == FormulaCompiler::InitSymbols::DESTROY)
976 aSymbolMap.mxSymbolMap.reset();
978 else if (!aSymbolMap.mxSymbolMap)
981 aSymbolMap.mxSymbolMap =
982 std::make_shared<FormulaCompiler::OpCodeMap>(
984 OpCodeList aOpCodeListSymbols(RID_STRLIST_FUNCTION_NAMES_SYMBOLS, aSymbolMap.mxSymbolMap);
985 OpCodeList aOpCodeListNative(RID_STRLIST_FUNCTION_NAMES, aSymbolMap.mxSymbolMap);
989 xMap = aSymbolMap.mxSymbolMap;
998 return xSymbolsNative->getSymbol( eOp );
1013 static OpCodeMapData
aMap;
1014 std::unique_lock aGuard(
aMap.maMtx);
1015 if (eWhat == InitSymbols::ASK)
1016 return bool(
aMap.mxSymbolMap);
1017 else if (eWhat == InitSymbols::DESTROY)
1018 aMap.mxSymbolMap.reset();
1019 else if (!
aMap.mxSymbolMap)
1027 static OpCodeMapData
aMap;
1028 std::unique_lock aGuard(
aMap.maMtx);
1029 if (eWhat == InitSymbols::ASK)
1030 return bool(
aMap.mxSymbolMap);
1031 else if (eWhat == InitSymbols::DESTROY)
1032 aMap.mxSymbolMap.reset();
1033 else if (!
aMap.mxSymbolMap)
1041 static OpCodeMapData
aMap;
1042 std::unique_lock aGuard(
aMap.maMtx);
1043 if (eWhat == InitSymbols::ASK)
1044 return bool(
aMap.mxSymbolMap);
1045 else if (eWhat == InitSymbols::DESTROY)
1046 aMap.mxSymbolMap.reset();
1047 else if (!
aMap.mxSymbolMap)
1055 static OpCodeMapData
aMap;
1056 std::unique_lock aGuard(
aMap.maMtx);
1057 if (eWhat == InitSymbols::ASK)
1058 return bool(
aMap.mxSymbolMap);
1059 else if (eWhat == InitSymbols::DESTROY)
1060 aMap.mxSymbolMap.reset();
1061 else if (!
aMap.mxSymbolMap)
1069 static OpCodeMapData
aMap;
1070 std::unique_lock aGuard(
aMap.maMtx);
1071 if (eWhat == InitSymbols::ASK)
1072 return bool(
aMap.mxSymbolMap);
1073 else if (eWhat == InitSymbols::DESTROY)
1074 aMap.mxSymbolMap.reset();
1075 else if (!
aMap.mxSymbolMap)
1078 if (eWhat != InitSymbols::INIT)
1093 static OpCodeMapData
aMap;
1094 std::unique_lock aGuard(
aMap.maMtx);
1095 if (eWhat == InitSymbols::ASK)
1096 return bool(
aMap.mxSymbolMap);
1097 else if (eWhat == InitSymbols::DESTROY)
1098 aMap.mxSymbolMap.reset();
1099 else if (!
aMap.mxSymbolMap)
1114 OpCodeList aOpCodeList(pSymbols, rxMap, eSepType);
1148 formula::OpCodeHashMap::const_iterator iLook( xMap->getHashMap().find( rName ) );
1149 bool bFound = (iLook != xMap->getHashMap().end());
1150 return bFound ? (*iLook).second :
ocNone;
1201 sal_Int32 nLen = rStr.getLength();
1202 if ( nLen > 1 && rStr[0] ==
'\'' && rStr[ nLen-1 ] ==
'\'' )
1204 rStr = rStr.copy( 1, nLen-2 );
1205 rStr = rStr.replaceAll(
"''",
"'" );
1212 ::std::vector< sheet::FormulaOpCodeMapEntry >& ,
1246 "OpCodeMap::putCopyOpCode: NOT replacing OpCode " <<
static_cast<sal_uInt16
>(eOp)
1247 <<
" '" <<
mpTable[eOp] <<
"' with empty name!");
1248 if (!
mpTable[eOp].isEmpty() && rSymbol.isEmpty())
1263 "OpCodeMap::copyFrom: unequal size, this: " << mnSymbols <<
" that: " <<
n);
1269 "OpCodeMap::copyFrom: OpCode 0 assigned, this: '"
1270 << mpTable[0] <<
"' that: '" << r.
mpTable[0] <<
"'");
1279 for (sal_uInt16
i = 1;
i <
n; ++
i)
1289 aSymbol =
"MULTIPLE.OPERATIONS";
1294 putCopyOpCode( aSymbol, eOp);
1299 for (sal_uInt16
i = 1;
i <
n; ++
i)
1302 const OUString& rSymbol = r.
mpTable[
i];
1303 putCopyOpCode( rSymbol, eOp);
1310 if (!hasExternals())
1333 OpCodeHashMap::const_iterator iLook(
mxSymbols->getHashMap().find( rName));
1334 if (iLook !=
mxSymbols->getHashMap().end())
1336 switch ((*iLook).second)
1370 if (rName.startsWithIgnoreAsciiCase(
"#ERR") && rName.getLength() <= 10 && rName[rName.getLength()-1] ==
'!')
1372 sal_uInt32 nErr =
o3tl::toUInt32(rName.subView( 4, rName.getLength() - 5));
1420 rBuffer.append(
"#ERR");
1421 rBuffer.append(
static_cast<sal_Int32
>(nError));
1422 rBuffer.append(
'!');
1426 rBuffer.append(
mxSymbols->getSymbol( eOp));
1433 FormulaCompilerRecursionGuard aRecursionGuard(
nRecursion );
1451 short nWasColRowName;
1465 if ( nWasColRowName )
1496 isPotentialRangeType(
mpLastToken.get(),
false,
false) &&
1497 isPotentialRangeType(
mpToken.get(),
false,
true))
1517 if (
mpToken->IsExternalRef() )
1609 if (
p && isPotentialRangeType(
p,
true,
false))
1612 if (
p && isPotentialRangeType(
p,
true,
true))
1639 if(
nNumFmt == SvNumFormatType::UNDEFINED )
1640 nNumFmt = lcl_GetRetFormat( eOp );
1663 if (
mpToken->GetExternal() ==
"com.sun.star.sheet.addin.Analysis.getRandbetween")
1715 bool bNoParam =
false;
1729 sal_uInt32 nSepCount = 0;
1748 pFacToken->
SetByte( nSepCount );
1770 pFacToken->
SetByte( nSepCount - 1 );
1786 if(
nNumFmt == SvNumFormatType::UNDEFINED && eOp ==
ocNot )
1787 nNumFmt = SvNumFormatType::LOGICAL;
1823 bool bNoParam =
false;
1824 bool bBadName =
false;
1836 else if (eMyLastOp ==
ocBad)
1845 sal_uInt32 nSepCount = 0;
1855 bDoIICompute =
false;
1861 pArgArray[nSepCount-1] =
pCode - 1;
1872 pArgArray[nSepCount - 1] =
pCode - 1;
1892 pFacToken->
SetByte( nSepCount );
1905 pFacToken->
GetJump()[ 0 ] = 3;
1912 pFacToken->
GetJump()[ 0 ] = 2;
1915 SAL_WARN(
"formula.core",
"Jump OpCode: " << +eOp);
1916 assert(!
"FormulaCompiler::Factor: someone forgot to add a jump count case");
1953 SAL_WARN(
"formula.core",
"Jump OpCode: " << +eFacOpCode);
1954 assert(!
"FormulaCompiler::Factor: someone forgot to add a jump max case");
1956 short nJumpCount = 0;
1960 if ( ++nJumpCount <= nJumpMax )
1961 pFacToken->
GetJump()[nJumpCount] =
pc-1;
1974 if ( ++nJumpCount <= nJumpMax )
1975 pFacToken->
GetJump()[ nJumpCount ] =
pc-1;
1981 bLimitOk = (nJumpCount <= 3);
1988 bLimitOk = (nJumpCount <= 2);
2000 SAL_WARN(
"formula.core",
"Jump OpCode: " << +eFacOpCode);
2001 assert(!
"FormulaCompiler::Factor: someone forgot to add a jump limit case");
2004 pFacToken->
GetJump()[ 0 ] = nJumpCount;
2018 else if ( eOp ==
ocSep )
2027 else if (
mpToken->IsExternalRef() )
2082 if (isAdjacentOrGapRpnEnd(
pc,
pCode, pCode1, pCode2) && isIntersectable( pCode1, pCode2))
2088 pArr->
ReplaceToken( nCodeIndex, pIntersect.get(), FormulaTokenArray::ReplaceMode::CODE_ONLY);
2115 else if (SC_OPCODE_START_UN_OP <= mpToken->GetOpCode() &&
2155 pArgArray[0] =
pCode - 1;
2160 pArgArray[1] =
pCode - 1;
2175 pArgArray[0] =
pCode - 1;
2180 pArgArray[1] =
pCode - 1;
2195 pArgArray[0] =
pCode - 1;
2200 pArgArray[1] =
pCode - 1;
2215 pArgArray[0] =
pCode - 1;
2220 pArgArray[1] =
pCode - 1;
2235 pArgArray[0] =
pCode - 1;
2240 pArgArray[1] =
pCode - 1;
2249 FormulaCompilerRecursionGuard aRecursionGuard(
nRecursion );
2262 pArgArray[0] =
pCode - 1;
2267 pArgArray[1] =
pCode - 1;
2287 if (!isAdjacentRpnEnd(
pc,
pCode, pCode1, pCode2))
2324 pDataArray[ 0 ] =
nullptr;
2366 if(
nNumFmt == SvNumFormatType::UNDEFINED )
2367 nNumFmt = SvNumFormatType::NUMBER;
2380 p->pArr->SetExclusiveRecalcModeAlways();
2385 p->pArr->SetHyperLink(
true );
2399 rFormula =
aBuffer.makeStringAndClear();
2404 rBuffer.setLength(0);
2434 rBuffer.ensureCapacity(
pArr->
GetLen() * 5 );
2437 rBuffer.append(
'=');
2442 if (pSaveArr !=
pArr)
2460 bool bAllowArrAdvance )
2463 bool bSpaces =
false;
2469 if ( bAllowArrAdvance )
2474 bSpaces = ( !
t ||
t->GetOpCode() !=
ocOpen );
2477 rBuffer.append(
' ');
2481 bool bWriteSpaces =
true;
2486 if (bIntersectionOp)
2491 if (bIntersectionOp)
2493 rBuffer.append(
"!!");
2494 bWriteSpaces =
false;
2510 if (
p &&
p->IsFunction())
2514 bWriteSpaces =
false;
2524 rBuffer.append(
t->GetChar());
2526 rBuffer.append(
' ');
2536 rBuffer.append(
' ');
2538 rBuffer.append(
mxSymbols->getSymbol( eOp));
2540 else if(
static_cast<sal_uInt16
>(eOp) <
mxSymbols->getSymbolCount())
2541 rBuffer.append(
mxSymbols->getSymbol( eOp));
2544 SAL_WARN(
"formula.core",
"unknown OpCode");
2549 if (
t->IsExternalRef())
2555 switch(
t->GetType() )
2563 rBuffer.append(
t->GetString().getString());
2596 switch (
t->GetOpCode())
2626 OUString aAddIn(
t->GetExternal() );
2628 if (!bMapped &&
mxSymbols->hasExternals())
2630 ExternalHashMap::const_iterator iLook =
mxSymbols->getReverseExternalHashMap().find( aAddIn);
2631 if (iLook !=
mxSymbols->getReverseExternalHashMap().end())
2633 aAddIn = (*iLook).second;
2637 if (!bMapped && !
mxSymbols->isEnglish())
2639 rBuffer.append( aAddIn);
2652 SAL_WARN(
"formula.core",
"FormulaCompiler::GetStringFromToken: unknown token type " <<
t->GetType());
2657 rBuffer.append(
' ');
2658 if ( bAllowArrAdvance )
2672 ::rtl::math::doubleToUStringBuffer( rBuffer, fVal,
2673 rtl_math_StringFormat_Automatic,
2674 rtl_math_DecimalPlaces_Max,
'.',
true );
2679 ::rtl::math::doubleToUStringBuffer( rBuffer, fVal,
2680 rtl_math_StringFormat_Automatic,
2681 rtl_math_DecimalPlaces_Max,
2694 rBuffer.append(
'"');
2695 if ( lcl_UnicodeStrChr( rStr.getStr(),
'"' ) ==
nullptr )
2696 rBuffer.append( rStr );
2699 OUString
aStr = rStr.replaceAll(
"\"",
"\"\"" );
2700 rBuffer.append(
aStr);
2702 rBuffer.append(
'"');
2715 const OUString& rSep,
const OUString& rArrayColSep,
const OUString& rArrayRowSep )
2719 xSymbolsNative->putOpCode( rSep,
ocSep,
nullptr);
2720 xSymbolsNative->putOpCode( rArrayColSep,
ocArrayColSep,
nullptr);
2721 xSymbolsNative->putOpCode( rArrayRowSep,
ocArrayRowSep,
nullptr);
2735 xSymbolsNative->copyFrom( *xMap );
2753 FormulaCompilerRecursionGuard aRecursionGuard(
nRecursion );
2838 if (pPrev && isPotentialRangeType( pPrev,
false,
false))
2841 if (pNext && isPotentialRangeType( pNext,
false,
true))
2861 SAL_WARN(
"formula.core",
"FormulaCompiler::PutCode - CodeOverflow with OpCode " << +
p->GetOpCode());
2938 const OpCode eOp = rCurr->GetOpCode();
3020 rCurr->SetInForceArray( eArrayReturn);
3028 rCurr->SetInForceArray( eArrayReturn);
3055 rCurr->SetInForceArray( eForceType);
3068 rCurr->SetInForceArray( eParamType);
3072 rCurr->SetInForceArray( eParamType);
static const AllSettings & GetSettings()
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
const OUString & getNumDecimalSep() const
const LocaleDataWrapper & GetLocaleData() const
#define SC_OPCODE_STOP_BIN_OP
#define SC_OPCODE_ARRAY_COL_SEP
#define SC_OPCODE_STOP_1_PAR
#define SC_OPCODE_START_2_PAR
#define SC_OPCODE_ARRAY_OPEN
#define SC_OPCODE_STOP_UN_OP
#define SC_OPCODE_ARRAY_CLOSE
#define SC_OPCODE_START_UN_OP
#define SC_OPCODE_STOP_2_PAR
#define SC_OPCODE_STOP_NO_PAR
#define SC_OPCODE_NO_NAME
#define SC_OPCODE_ARRAY_ROW_SEP
#define SC_OPCODE_START_1_PAR
#define SC_OPCODE_START_NO_PAR
#define SC_OPCODE_START_BIN_OP
#define SC_OPCODE_LAST_OPCODE_ID
#define SC_OPCODE_IF_ERROR
OUString ForResId(TranslateId aId)
bool isPublishedFormulaError(FormulaError nErr)
Error values that are accepted as detailed "#ERRxxx!" constants.
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
#define SAL_N_ELEMENTS(arr)
std::unique_ptr< sal_Int32[]> pData
sal_uInt32 toUInt32(std::u16string_view str, sal_Int16 radix=10)
HashMap_OWString_Interface aMap
std::unique_ptr< char[]> aBuffer