summaryrefslogtreecommitdiff
path: root/formula
diff options
context:
space:
mode:
Diffstat (limited to 'formula')
-rw-r--r--formula/source/core/api/FormulaCompiler.cxx26
-rw-r--r--formula/source/core/api/token.cxx57
2 files changed, 82 insertions, 1 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index c4ca443ffef9..457beeefb4b1 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1271,6 +1271,7 @@ void FormulaCompiler::Factor()
else
SetError( errPairExpected);
sal_uInt8 nSepCount = 0;
+ const sal_uInt16 nSepPos = pArr->nIndex - 1; // separator position, if any
if( !bNoParam )
{
nSepCount++;
@@ -1289,7 +1290,30 @@ void FormulaCompiler::Factor()
pFacToken->SetByte( nSepCount );
if (nSepCount == 2)
{
- pFacToken->NewOpCode( ocWeek, FormulaToken::PrivateAccess());
+ // An old mode!=1 indicates ISO week, remove argument if
+ // literal double value and keep function. Anything else
+ // can not be resolved, there exists no "like ISO but week
+ // starts on Sunday" mode in WEEKNUM and for an expression
+ // we can't determine, so let ISOWEEKNUM generate an error
+ // for two arguments in these cases.
+ if (pc >= 2 && pArr->nIndex == nSepPos + 3 &&
+ pArr->pCode[nSepPos+1]->GetType() == svDouble &&
+ pArr->pCode[nSepPos+1]->GetDouble() != 1.0 &&
+ pArr->RemoveToken( nSepPos, 2) == 2)
+ {
+ // Remove the ocPush/svDouble just removed also from
+ // the compiler local RPN array.
+ --pCode, --pc;
+ (*pCode)->DecRef(); // may be dead now
+ pFacToken->SetByte( nSepCount - 1 );
+ }
+ else
+ {
+ /* FIXME: introduce (hidden?) compatibility function? */
+#if 0
+ pFacToken->NewOpCode( ocWeeknumCompat, FormulaToken::PrivateAccess());
+#endif
+ }
}
PutCode( pFacToken );
}
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 339e927742fa..65211f362561 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -900,6 +900,63 @@ FormulaToken* FormulaTokenArray::ReplaceToken( sal_uInt16 nOffset, FormulaToken*
}
}
+sal_uInt16 FormulaTokenArray::RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount )
+{
+ if (nOffset < nLen)
+ {
+ SAL_WARN_IF( nOffset + nCount > nLen, "formula.core",
+ "FormulaTokenArray::RemoveToken - nOffset " << nOffset << " + nCount " << nCount << " > nLen " << nLen);
+ const sal_uInt16 nStop = ::std::min( static_cast<sal_uInt16>(nOffset + nCount), nLen);
+ nCount = nStop - nOffset;
+ for (sal_uInt16 j = nOffset; j < nStop; ++j)
+ {
+ FormulaToken* p = pCode[j];
+ if (p->GetRef() > 1)
+ {
+ for (sal_uInt16 i=0; i < nRPN; ++i)
+ {
+ if (pRPN[i] == p)
+ {
+ // Shift remaining tokens in pRPN down.
+ for (sal_uInt16 x=i+1; x < nRPN; ++x)
+ {
+ pRPN[x-1] = pRPN[x];
+ }
+ --nRPN;
+
+ p->DecRef();
+ if (p->GetRef() == 1)
+ break; // for
+ }
+ }
+ }
+ p->DecRef(); // may be dead now
+ }
+
+ // Shift remaining tokens in pCode down.
+ for (sal_uInt16 x = nStop; x < nLen; ++x)
+ {
+ pCode[x-nCount] = pCode[x];
+ }
+ nLen -= nCount;
+
+ if (nIndex >= nOffset)
+ {
+ if (nIndex < nStop)
+ nIndex = nOffset + 1;
+ else
+ nIndex -= nStop - nOffset;
+ }
+
+ return nCount;
+ }
+ else
+ {
+ SAL_WARN("formula.core","FormulaTokenArray::RemoveToken - nOffset " << nOffset << " >= nLen " << nLen);
+ return 0;
+ }
+}
+
FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
{
if( !pCode )