summaryrefslogtreecommitdiff
path: root/formula
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2013-01-11 16:50:48 +0100
committerEike Rathke <erack@redhat.com>2013-01-11 17:01:44 +0100
commit3914d00c32c4226d3a73ffdd8985c887016887e0 (patch)
tree214d06dd8f9a28e8196ba7d26275d4bd16179ae2 /formula
parent5fd9feafa5d73121636af9397d42e046cc394719 (diff)
fdo#56124 changes to "add functions IFERROR and IFNA"
* reimplemented actual ScIfError() function for matrix cases and simpler pop/push of non-error values * various smaller adaptions, see also inline comments of https://gerrit.libreoffice.org/1522 Change-Id: I80a8235a2cbb548c0ef993862e76741af46e30d2
Diffstat (limited to 'formula')
-rw-r--r--formula/inc/formula/errorcodes.hxx3
-rw-r--r--formula/source/core/api/FormulaCompiler.cxx69
2 files changed, 57 insertions, 15 deletions
diff --git a/formula/inc/formula/errorcodes.hxx b/formula/inc/formula/errorcodes.hxx
index a99dc7b9d4e0..1e145e04132b 100644
--- a/formula/inc/formula/errorcodes.hxx
+++ b/formula/inc/formula/errorcodes.hxx
@@ -72,6 +72,9 @@ const sal_uInt16 errNestedArray = 533;
// be used to distinguish that condition from all other (inherited) errors. Do
// not use for anything else! Never push or inherit the error otherwise!
const sal_uInt16 errNotNumericString = 534;
+// ScInterpreter internal: jump matrix already has a result at this position,
+// do not overwrite in case of empty code path.
+const sal_uInt16 errJumpMatHasResult = 535;
// Interpreter: NA() not available condition, not a real error
const sal_uInt16 NOTAVAILABLE = 0x7fff;
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index e91912368a5c..d4d69ddbd84b 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1179,12 +1179,21 @@ void FormulaCompiler::Factor()
{
// the PC counters are -1
pFacToken = mpToken;
- if ( eOp == ocIf )
- pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
- else if ( eOp == ocChose )
- pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
- else
- pFacToken->GetJump()[ 0 ] = 2; // if, else
+ switch (eOp)
+ {
+ case ocIf:
+ pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
+ break;
+ case ocChose:
+ pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
+ break;
+ case ocIfError:
+ case ocIfNA:
+ pFacToken->GetJump()[ 0 ] = 2; // if, behind
+ break;
+ default:
+ SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump count case?");
+ }
eOp = NextToken();
if (eOp == ocOpen)
{
@@ -1193,15 +1202,30 @@ void FormulaCompiler::Factor()
}
else
SetError(errPairExpected);
- short nJumpCount = 0;
PutCode( pFacToken );
- // during AutoCorrect (since pArr->GetCodeError() is
+ // During AutoCorrect (since pArr->GetCodeError() is
// ignored) an unlimited ocIf would crash because
// ScRawToken::Clone() allocates the JumpBuffer according to
// nJump[0]*2+2, which is 3*2+2 on ocIf and 2*2+2 ocIfError and ocIfNA.
+ short nJumpMax;
OpCode eFacOpCode = pFacToken->GetOpCode();
- const short nJumpMax = ( eFacOpCode == ocIf ? 3 :
- ( eFacOpCode == ocChose ? MAXJUMPCOUNT : 2 ) );
+ switch (eFacOpCode)
+ {
+ case ocIf:
+ nJumpMax = 3;
+ break;
+ case ocChose:
+ nJumpMax = MAXJUMPCOUNT;
+ break;
+ case ocIfError:
+ case ocIfNA:
+ nJumpMax = 2;
+ break;
+ default:
+ nJumpMax = 0;
+ SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump max case?");
+ }
+ short nJumpCount = 0;
while ( (nJumpCount < (MAXJUMPCOUNT - 1)) && (eOp == ocSep)
&& (!pArr->GetCodeError() || bIgnoreErrors) )
{
@@ -1221,12 +1245,27 @@ void FormulaCompiler::Factor()
if ( ++nJumpCount <= nJumpMax )
pFacToken->GetJump()[ nJumpCount ] = pc-1;
eFacOpCode = pFacToken->GetOpCode();
- if ( ( eFacOpCode == ocIf && nJumpCount > 3) ||
- ( ( eFacOpCode == ocIfError || eFacOpCode == ocIfNA ) && nJumpCount > 2 ) ||
- ( nJumpCount >= MAXJUMPCOUNT ) )
- SetError(errIllegalParameter);
- else
+ bool bLimitOk;
+ switch (eFacOpCode)
+ {
+ case ocIf:
+ bLimitOk = (nJumpCount <= 3);
+ break;
+ case ocChose:
+ bLimitOk = (nJumpCount < MAXJUMPCOUNT); /* TODO: check, really <, not <=? */
+ break;
+ case ocIfError:
+ case ocIfNA:
+ bLimitOk = (nJumpCount <= 2);
+ break;
+ default:
+ bLimitOk = false;
+ SAL_WARN( "formula.core", "FormulaCompiler::Factor: forgot to add a jump limit case?");
+ }
+ if (bLimitOk)
pFacToken->GetJump()[ 0 ] = nJumpCount;
+ else
+ SetError(errIllegalParameter);
}
}
else if ( eOp == ocMissing )