Hi Winfried, *,
On Fri, Apr 26, 2019 at 9:04 AM Winfried Donkers
<Winfried.Donkers@dekimo.com> wrote:
I am working on tdf#124710, which means that I need to convert functions IFS and SWITCH to 'jump
functions'. I tried this before, but abandoned my work, which was in gerrit #26348.
Somehow I cannot retrieve that 'commit'.
Is there any way to retrieve it (so that I can read the comments and changes), or does it really
no longer exist?
Not on gerrit anymore, but is available on jenkins mirror...
Attached is the change v1 - if there was a second revision, then that is lost.
ciao
Christian
commit 44ae1f7586d0a038d6f41b5a0c01fc1275009c24
Author: Winfried Donkers <winfrieddonkers@libreoffice.org>
Date: Thu Jun 16 09:00:58 2016 +0200
Convert ScInterpreter::ScIfs_MS() and ScSwitch_MS() to jump functions.
Current situation:
All seems to work well, except when any argument (other than the first)
contains a function or expression. See comment above ScSwitch_MS() in
interpr1.cxx. The 'test code' in ScSwitch_MS() was used to get the results
in the comment.
How do I recognise that an argument is an expression? I think I need to
know that first to be able to handle that argument correctly.
I left the trace code in, but renamed SAL_DEBUG to SAL__DEBUG to get the
code accepted by git.
Change-Id: I879a211dc525502f4730d67215b324e30ed54955
diff --git a/formula/source/core/api/FormulaCompiler.cxx
b/formula/source/core/api/FormulaCompiler.cxx
index 675da4bb422a..d84d2c5409a0 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -930,6 +930,8 @@ bool FormulaCompiler::IsOpCodeJumpCommand( OpCode eOp )
case ocIfError:
case ocIfNA:
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
return true;
default:
;
@@ -1540,6 +1542,8 @@ void FormulaCompiler::Factor()
pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
break;
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
pFacToken->GetJump()[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
break;
case ocIfError:
@@ -1572,6 +1576,8 @@ void FormulaCompiler::Factor()
nJumpMax = 3;
break;
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
nJumpMax = FORMULA_MAXJUMPCOUNT;
break;
case ocIfError:
@@ -1611,6 +1617,8 @@ void FormulaCompiler::Factor()
bLimitOk = (nJumpCount <= 3);
break;
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
bLimitOk = (nJumpCount < FORMULA_MAXJUMPCOUNT);
break;
case ocIfError:
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 9c16870ea6fa..d49dd01b590a 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -85,7 +85,8 @@ bool FormulaToken::IsFunction() const
eOp != ocTableRef &&
(GetByte() != 0 // x parameters
|| (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) // no parameter
- || (ocIf == eOp || ocIfError == eOp || ocIfNA == eOp || ocChoose == eOp ) // @ jump
commands
+ || (ocIf == eOp || ocIfError == eOp || ocIfNA == eOp ||
+ ocChoose == eOp || ocIfs_MS == eOp || ocSwitch_MS == eOp ) // @ jump commands
|| (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) // one parameter
|| (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) // x parameters
(cByte==0 in
// FuncAutoPilot)
@@ -101,10 +102,11 @@ sal_uInt8 FormulaToken::GetParamCount() const
{
if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
eOp != ocIf && eOp != ocIfError && eOp != ocIfNA && eOp != ocChoose &&
- eOp != ocPercentSign )
+ eOp != ocIfs_MS && eOp != ocSwitch_MS && eOp != ocPercentSign )
return 0; // parameters and specials
- // ocIf, ocIfError, ocIfNA and ocChoose not for FAP, have cByte then
-//2do: bool parameter whether FAP or not?
+ // ocIf, ocIfError, ocIfNA, ocChoose, ocIfs_MS and ocSwitch_MS not for FAP,
+ // have cByte then
+// todo : bool parameter whether FAP or not?
else if ( GetByte() )
return GetByte(); // all functions, also ocExternal and ocMacro
else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
@@ -116,7 +118,8 @@ sal_uInt8 FormulaToken::GetParamCount() const
return 0; // no parameter
else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
return 1; // one parameter
- else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChoose )
+ else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA ||
+ eOp == ocChoose || eOp == ocIfs_MS || eOp == ocSwitch_MS )
return 1; // only the condition counts as parameter
else
return 0; // all the rest, no Parameter, or
@@ -976,7 +979,8 @@ bool FormulaTokenArray::HasMatrixDoubleRefOps()
}
if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() ) )
pStack[sp++] = t;
- else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChoose )
+ else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA ||
+ eOp == ocChoose || eOp == ocIfs_MS || eOp == ocSwitch_MS )
{ // ignore Jumps, pop previous Result (Condition)
if ( sp )
--sp;
@@ -1529,11 +1533,13 @@ FormulaToken* FormulaTokenArray::AddOpCode( OpCode eOp )
case ocIfError:
case ocIfNA:
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
{
short nJump[FORMULA_MAXJUMPCOUNT + 1];
if ( eOp == ocIf )
nJump[ 0 ] = 3;
- else if ( eOp == ocChoose )
+ else if ( eOp == ocChoose || eOp == ocIfs_MS || eOp == ocSwitch_MS )
nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
else
nJump[ 0 ] = 2;
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index fc912fcc9bc3..bfc8f4b0d9d5 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -35,7 +35,7 @@
#include <memory>
#include <unordered_map>
-#define FORMULA_MAXJUMPCOUNT 32 /* maximum number of jumps (ocChoose) */
+#define FORMULA_MAXJUMPCOUNT 255 /* maximum number of jumps (ocChoose, ocIfs_MS, ocSwitch_MS) */
#define FORMULA_MAXTOKENS 8192 /* maximum number of tokens in formula */
diff --git a/include/formula/compiler.hrc b/include/formula/compiler.hrc
index 7a7bfe74ab94..9aad8cdddd71 100644
--- a/include/formula/compiler.hrc
+++ b/include/formula/compiler.hrc
@@ -33,33 +33,35 @@
#define SC_OPCODE_IF_ERROR 7
#define SC_OPCODE_IF_NA 8
#define SC_OPCODE_CHOOSE 9
-#define SC_OPCODE_OPEN 10 /* parentheses and separators */
-#define SC_OPCODE_CLOSE 11
-#define SC_OPCODE_SEP 12
-#define SC_OPCODE_MISSING 13 /* special OpCodes */
-#define SC_OPCODE_BAD 14
-#define SC_OPCODE_STRINGXML 15
-#define SC_OPCODE_SPACES 16
-#define SC_OPCODE_MAT_REF 17
-#define SC_OPCODE_DB_AREA 18 /* additional access operators */
-#define SC_OPCODE_TABLE_REF 19
-#define SC_OPCODE_MACRO 20
-#define SC_OPCODE_COL_ROW_NAME 21
-#define SC_OPCODE_COL_ROW_NAME_AUTO 22
-#define SC_OPCODE_PERCENT_SIGN 23 /* operator _follows_ value */
-#define SC_OPCODE_ARRAY_OPEN 24
-#define SC_OPCODE_ARRAY_CLOSE 25
-#define SC_OPCODE_ARRAY_ROW_SEP 26
-#define SC_OPCODE_ARRAY_COL_SEP 27 /* some convs use sep != col_sep */
-#define SC_OPCODE_TABLE_REF_OPEN 28
-#define SC_OPCODE_TABLE_REF_CLOSE 29
-#define SC_OPCODE_TABLE_REF_ITEM_ALL 30
-#define SC_OPCODE_TABLE_REF_ITEM_HEADERS 31
-#define SC_OPCODE_TABLE_REF_ITEM_DATA 32
-#define SC_OPCODE_TABLE_REF_ITEM_TOTALS 33
-#define SC_OPCODE_TABLE_REF_ITEM_THIS_ROW 34
-#define SC_OPCODE_STOP_DIV 35
-#define SC_OPCODE_SKIP 36 /* used to skip raw tokens during string compilation */
+#define SC_OPCODE_IFS_MS 10
+#define SC_OPCODE_SWITCH_MS 11
+#define SC_OPCODE_OPEN 12 /* parentheses and separators */
+#define SC_OPCODE_CLOSE 13
+#define SC_OPCODE_SEP 14
+#define SC_OPCODE_MISSING 15 /* special OpCodes */
+#define SC_OPCODE_BAD 16
+#define SC_OPCODE_STRINGXML 17
+#define SC_OPCODE_SPACES 18
+#define SC_OPCODE_MAT_REF 19
+#define SC_OPCODE_DB_AREA 20 /* additional access operators */
+#define SC_OPCODE_TABLE_REF 21
+#define SC_OPCODE_MACRO 22
+#define SC_OPCODE_COL_ROW_NAME 23
+#define SC_OPCODE_COL_ROW_NAME_AUTO 24
+#define SC_OPCODE_PERCENT_SIGN 25 /* operator _follows_ value */
+#define SC_OPCODE_ARRAY_OPEN 26
+#define SC_OPCODE_ARRAY_CLOSE 27
+#define SC_OPCODE_ARRAY_ROW_SEP 28
+#define SC_OPCODE_ARRAY_COL_SEP 29 /* some convs use sep != col_sep */
+#define SC_OPCODE_TABLE_REF_OPEN 30
+#define SC_OPCODE_TABLE_REF_CLOSE 31
+#define SC_OPCODE_TABLE_REF_ITEM_ALL 32
+#define SC_OPCODE_TABLE_REF_ITEM_HEADERS 33
+#define SC_OPCODE_TABLE_REF_ITEM_DATA 34
+#define SC_OPCODE_TABLE_REF_ITEM_TOTALS 35
+#define SC_OPCODE_TABLE_REF_ITEM_THIS_ROW 36
+#define SC_OPCODE_STOP_DIV 37
+#define SC_OPCODE_SKIP 38 /* used to skip raw tokens during string compilation */
/*** error constants #... ***/
#define SC_OPCODE_START_ERRORS 40
@@ -497,11 +499,9 @@
#define SC_OPCODE_FORECAST_LIN 486
#define SC_OPCODE_CONCAT_MS 487
#define SC_OPCODE_TEXTJOIN_MS 488
-#define SC_OPCODE_IFS_MS 489
-#define SC_OPCODE_SWITCH_MS 490
-#define SC_OPCODE_MINIFS_MS 491
-#define SC_OPCODE_MAXIFS_MS 492
-#define SC_OPCODE_STOP_2_PAR 493 /* last function with two or more parameters' OpCode +
1 */
+#define SC_OPCODE_MINIFS_MS 489
+#define SC_OPCODE_MAXIFS_MS 490
+#define SC_OPCODE_STOP_2_PAR 491 /* last function with two or more parameters' OpCode +
1 */
#define SC_OPCODE_STOP_FUNCTION SC_OPCODE_STOP_2_PAR /* last function's OpCode + 1
*/
#define SC_OPCODE_LAST_OPCODE_ID (SC_OPCODE_STOP_FUNCTION - 1) /* last OpCode */
diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx
index 30dc94ff578c..81163165295b 100644
--- a/include/formula/opcode.hxx
+++ b/include/formula/opcode.hxx
@@ -37,6 +37,8 @@ enum OpCode : sal_uInt16
ocIfError = SC_OPCODE_IF_ERROR,
ocIfNA = SC_OPCODE_IF_NA,
ocChoose = SC_OPCODE_CHOOSE,
+ ocIfs_MS = SC_OPCODE_IFS_MS,
+ ocSwitch_MS = SC_OPCODE_SWITCH_MS,
// Parentheses and separators
ocOpen = SC_OPCODE_OPEN,
ocClose = SC_OPCODE_CLOSE,
@@ -282,8 +284,6 @@ enum OpCode : sal_uInt16
ocNominal = SC_OPCODE_NOMINAL,
ocSubTotal = SC_OPCODE_SUB_TOTAL,
ocRawSubtract = SC_OPCODE_RAWSUBTRACT,
- ocIfs_MS = SC_OPCODE_IFS_MS,
- ocSwitch_MS = SC_OPCODE_SWITCH_MS,
ocMinIfs_MS = SC_OPCODE_MINIFS_MS,
ocMaxIfs_MS = SC_OPCODE_MAXIFS_MS,
// Database functions
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index 81b85586f274..27e40a010b08 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -357,8 +357,8 @@ public:
@param nStop
Stop before reaching code at position nStop. If not specified the
default is to either run the entire code, or to stop if an ocSep or
- ocClose is encountered, which are only present in ocIf or ocChoose
- jumps.
+ ocClose is encountered, which are only present in ocIf, ocChoose,
+ ocIfs_MS or ocSwitch_MS jumps.
*/
void Jump( short nStart, short nNext, short nStop = SHRT_MAX );
void Push( const FormulaTokenArray* );
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 6e78b880c0c3..16d6de3fb83c 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -503,6 +503,190 @@ void ScInterpreter::ScChooseJump()
aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
}
+// TODO : when argument is function or expression, problems arise (see ScSwitch_MS)
+void ScInterpreter::ScIfs_MS()
+{
+ const short* pJump = pCur->GetJump();
+ short nJumpCount = pJump[ 0 ];
+ MatrixDoubleRefToMatrix();
+ bool bFinished = false;
+ short nJumpIndex = 0;
+ // SAL__DEBUG( "ScIfs_MS(), nJumpIndex = " << nJumpIndex << "(before loop), nJumpCount = " <<
nJumpCount );
+ while ( !bFinished )
+ {
+ if ( GetBool() )
+ { // TRUE
+ // SAL__DEBUG( "ScIfs_MS(), expression is true, nJumpIndex = " << nJumpIndex <<
+ // "(before+1), nJumpCount = " << nJumpCount );
+ if( ++nJumpIndex < nJumpCount )
+ { // THEN path
+ // SAL__DEBUG( "ScIfs_MS(), expression is true, jumping to " << nJumpIndex );
+ aCode.Jump( pJump[ nJumpIndex ], pJump[ nJumpCount ] );
+ }
+ else
+ { // no parameter given for THEN
+ PushNA();
+ aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
+ }
+ bFinished = true;
+ }
+ else
+ { // FALSE
+ // SAL__DEBUG( "ScIfs_MS(), expression is false, nJumpIndex = " << nJumpIndex <<
+ // "(before+2), nJumpCount = " << nJumpCount );
+ nJumpIndex += 2;
+ if( nJumpIndex < nJumpCount - 1 )
+ { // ELSE path
+ // SAL__DEBUG( "ScIfs_MS(), expression is false, jumping to " << nJumpIndex );
+ aCode.Jump( pJump[ nJumpIndex ], pJump[ nJumpCount ] );
+ pCur = aCode.Next();
+ if ( pCur != nullptr )
+ PushWithoutError( (FormulaToken&) *pCur );
+ else
+ {
+ PushError( errUnknownState );
+ bFinished = true;
+ }
+ }
+ else
+ { // no parameter given for ELSE
+ PushNA();
+ aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
+ bFinished = true;
+ }
+ }
+ }
+}
+
+// TODO : when argument is function or expression, problems arise:
+// SWITCH(1;2/3;4;IF(5>6;7;8);9;10) produces stack values after jump to
+// 0 (no jump) 1 ok
+// 1 2 wrong
+// 2 4 ok
+// 3 5 wrong
+// 4 9 ok
+// 5 10 ok
+void ScInterpreter::ScSwitch_MS()
+{
+ const short* pJump = pCur->GetJump();
+ short nJumpCount = pJump[ 0 ];
+ MatrixDoubleRefToMatrix();
+ bool bIsValue = false;
+ double fRefVal = 0;
+ svl::SharedString aRefStr;
+ OUString aStackType;
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ aStackType = "svDouble";
+ bIsValue = true;
+ fRefVal = GetDouble();
+ break;
+ case svString:
+ aStackType = "svString";
+ bIsValue = false;
+ aRefStr = GetString();
+ break;
+ case svSingleRef :
+ case svDoubleRef :
+ aStackType = "svSingle of DoubleRef";
+ {
+ ScAddress aAdr;
+ if (!PopDoubleRefOrSingleRef( aAdr ))
+ break;
+ ScRefCellValue aCell( *pDok, aAdr );
+ bIsValue = !( aCell.hasString() || aCell.hasEmptyValue() || aCell.isEmpty() );
+ if ( bIsValue )
+ fRefVal = GetCellValue( aAdr, aCell);
+ else
+ GetCellString( aRefStr, aCell);
+ }
+ break;
+ case svExternalSingleRef:
+ case svExternalDoubleRef:
+ case svMatrix:
+ {
+ aStackType = "svExternalSingle of DoubleRef of svMatrix";
+ bIsValue = ScMatrix::IsValueType( GetDoubleOrStringFromMatrix( fRefVal, aRefStr )
);
+ }
+ break;
+ default :
+ aStackType = "other";
+ PushIllegalArgument();
+ return;
+ }
+ // SAL__DEBUG( "ScSwitch_MS(), argument " << 0 << " : stacktype=" << aStackType <<
+ // ", bIsValue=" << bIsValue << ", fRefVal=" << fRefVal << ", aRefStr=" <<
+ // aRefStr.getString() << ", nGlobalError=" << nGlobalError );
+ bool bFinished = false;
+ short nJumpIndex = 1;
+ while ( !bFinished )
+ {
+ aCode.Jump( pJump[ nJumpIndex ], pJump[ nJumpCount ] );
+ pCur = aCode.Next();
+ if ( pCur != nullptr )
+ {
+ PushWithoutError( (FormulaToken&) *pCur );
+ double fVal = 0;
+ svl::SharedString aStr;
+ if ( bIsValue )
+ fVal = GetDouble();
+ else
+ aStr = GetString();
+ // SAL__DEBUG( "ScSwitch_MS(), argument " << nJumpIndex << " : fVal=" << fVal <<
+ // ", aStr=" << aStr.getString() << ", nGlobalError=" << nGlobalError <<
+ // ", nJumpCount=" << nJumpCount );
+/*
+// start test code
+ if ( ++nJumpIndex >= nJumpCount )
+ {
+ bFinished = true;
+ PushNA();
+ }
+ // SAL__DEBUG( "ScSwitch_MS(), argument " << nJumpIndex << ", nJumpCount=" <<
nJumpCount <<
+ // ", finished=" << bFinished);
+// end test code
+*/
+// * start original code
+ if ( nGlobalError || (( bIsValue && rtl::math::approxEqual( fRefVal, fVal ) ) ||
+ ( !bIsValue && ( aRefStr == aStr ) ) ) )
+ {
+ bFinished = true;
+ nJumpIndex++;
+ }
+ else
+ {
+ nJumpIndex += 2;
+ // SAL__DEBUG( "ScSwitch_MS(), argument " << nJumpIndex << ", nJumpCount=" <<
nJumpCount );
+ if ( nJumpIndex >= nJumpCount )
+ {
+ // no match found
+ // SAL__DEBUG( "ScSwitch_MS(), no match found, return N/A" );
+ bFinished = true;
+ PushNA();
+ }
+ else
+ {
+ if ( nJumpIndex == nJumpCount - 1 )
+ {
+ // no more evaluations, jump to default value
+ // SAL__DEBUG( "ScSwitch_MS(), no match found, return default value" );
+ bFinished = true;
+ }
+ }
+ }
+// end original code */
+ if ( !nGlobalError )
+ aCode.Jump( pJump[ nJumpIndex ], pJump[ nJumpCount ] );
+ }
+ else
+ {
+ PushError( errUnknownState );
+ bFinished = true;
+ }
+ }
+}
+
static void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, SCSIZE nParmCols, SCSIZE nParmRows )
{
SCSIZE nJumpCols, nJumpRows;
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index eff287105e86..eb0a0b72ead7 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -3695,8 +3695,6 @@ bool IsErrFunc(OpCode oc)
case ocIfError :
case ocIfNA :
case ocErrorType_ODF :
- case ocIfs_MS:
- case ocSwitch_MS:
return true;
default:
return false;
@@ -3743,7 +3741,8 @@ StackVar ScInterpreter::Interpret()
PushWithoutError( (FormulaToken&) *pCur );
}
else if (pTokenMatrixMap &&
- !(eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChoose) &&
+ !(eOp == ocIf || eOp == ocIfError || eOp == ocIfNA ||
+ eOp == ocChoose || eOp == ocIfs_MS || eOp == ocSwitch_MS ) &&
((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
pTokenMatrixMap->end()) &&
(*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
@@ -3764,7 +3763,8 @@ StackVar ScInterpreter::Interpret()
nFuncFmtType = css::util::NumberFormat::NUMBER;
nFuncFmtIndex = 0;
- if ( eOp == ocIf || eOp == ocChoose || eOp == ocIfError || eOp == ocIfNA )
+ if ( eOp == ocIf || eOp == ocChoose || eOp == ocIfError ||
+ eOp == ocChoose || eOp == ocIfs_MS || eOp == ocSwitch_MS )
nStackBase = sp; // don't mess around with the jumps
else
{
@@ -3794,6 +3794,8 @@ StackVar ScInterpreter::Interpret()
case ocIfError : ScIfError( false ); break;
case ocIfNA : ScIfError( true ); break;
case ocChoose : ScChooseJump(); break;
+ case ocIfs_MS : ScIfs_MS(); break;
+ case ocSwitch_MS : ScSwitch_MS(); break;
case ocAdd : ScAdd(); break;
case ocSub : ScSub(); break;
case ocMul : ScMul(); break;
@@ -4036,8 +4038,6 @@ StackVar ScInterpreter::Interpret()
case ocConcat : ScConcat(); break;
case ocConcat_MS : ScConcat_MS(); break;
case ocTextJoin_MS : ScTextJoin_MS(); break;
- case ocIfs_MS : ScIfs_MS(); break;
- case ocSwitch_MS : ScSwitch_MS(); break;
case ocMinIfs_MS : ScMinIfs_MS(); break;
case ocMaxIfs_MS : ScMaxIfs_MS(); break;
case ocMatValue : ScMatValue(); break;
diff --git a/sc/source/core/tool/interpr8.cxx b/sc/source/core/tool/interpr8.cxx
index a94cd032ed02..02af2e9e2d8b 100644
--- a/sc/source/core/tool/interpr8.cxx
+++ b/sc/source/core/tool/interpr8.cxx
@@ -1873,166 +1873,4 @@ void ScInterpreter::ScTextJoin_MS()
}
}
-
-void ScInterpreter::ScIfs_MS()
-{
- short nParamCount = GetByte();
-
- ReverseStack( nParamCount );
-
- nGlobalError = 0; // propagate only for condition or active result path
- bool bFinished = false;
- while ( nParamCount > 0 && !bFinished && !nGlobalError )
- {
- bool bVal = GetBool();
- nParamCount--;
- if ( bVal )
- {
- // TRUE
- if ( nParamCount < 1 )
- {
- // no parameter given for THEN
- PushParameterExpected();
- return;
- }
- bFinished = true;
- }
- else
- {
- // FALSE
- if ( nParamCount >= 3 )
- {
- // ELSEIF path
- Pop();
- nParamCount--;
- }
- else
- {
- // no parameter given for ELSE
- PushNA();
- return;
- }
- }
- }
-
- if ( nGlobalError || !bFinished )
- {
- if ( !bFinished )
- PushNA(); // no true expression found
- if ( nGlobalError )
- PushNoValue(); // expression returned something other than true or false
- return;
- }
-
- //push result :
- FormulaTokenRef xToken( PopToken() );
- if ( xToken )
- PushTempToken( xToken.get() );
- else
- PushError( errUnknownStackVariable );
-}
-
-
-void ScInterpreter::ScSwitch_MS()
-{
- short nParamCount = GetByte();
-
- if (!MustHaveParamCountMin( nParamCount, 3))
- return;
-
- ReverseStack( nParamCount );
-
- nGlobalError = 0; // propagate only for match or active result path
- bool isValue = false;
- double fRefVal = 0;
- svl::SharedString aRefStr;
- switch ( GetStackType() )
- {
- case svDouble:
- isValue = true;
- fRefVal = GetDouble();
- break;
- case svString:
- isValue = false;
- aRefStr = GetString();
- break;
- case svSingleRef :
- case svDoubleRef :
- {
- ScAddress aAdr;
- if (!PopDoubleRefOrSingleRef( aAdr ))
- break;
- ScRefCellValue aCell( *pDok, aAdr );
- isValue = !( aCell.hasString() || aCell.hasEmptyValue() || aCell.isEmpty() );
- if ( isValue )
- fRefVal = GetCellValue( aAdr, aCell);
- else
- GetCellString( aRefStr, aCell);
- }
- break;
- case svExternalSingleRef:
- case svExternalDoubleRef:
- case svMatrix:
- isValue = ScMatrix::IsValueType( GetDoubleOrStringFromMatrix( fRefVal, aRefStr ) );
- break;
- default :
- PopError();
- PushIllegalArgument();
- return;
- }
- nParamCount--;
- bool bFinished = false;
- while ( nParamCount > 1 && !bFinished && !nGlobalError )
- {
- double fVal = 0;
- svl::SharedString aStr;
- if ( isValue )
- fVal = GetDouble();
- else
- aStr = GetString();
- nParamCount--;
- if ( nGlobalError || (( isValue && rtl::math::approxEqual( fRefVal, fVal ) ) ||
- ( !isValue && aRefStr.getDataIgnoreCase() == aStr.getDataIgnoreCase() )) )
- {
- // TRUE
- bFinished = true;
- }
- else
- {
- // FALSE
- if ( nParamCount >= 2 )
- {
- // ELSEIF path
- Pop();
- nParamCount--;
- // if nParamCount equals 1: default value to be returned
- bFinished = ( nParamCount == 1 );
- }
- else
- {
- // no parameter given for ELSE
- PushNA();
- return;
- }
- nGlobalError = 0;
- }
- }
-
- if ( nGlobalError || !bFinished )
- {
- if ( !bFinished )
- PushNA(); // no true expression found
- else
- PushError( nGlobalError );
- return;
- }
-
- // push result
- FormulaTokenRef xToken( PopToken() );
- if ( xToken )
- PushTempToken( xToken.get() );
- else
- PushError( errUnknownStackVariable );
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx
index bd8ca5544a8d..f7a7abf59c58 100644
--- a/sc/source/core/tool/parclass.cxx
+++ b/sc/source/core/tool/parclass.cxx
@@ -517,6 +517,8 @@ void ScParameterClassification::GenerateDocumentation()
case ocIfError:
case ocIfNA:
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
aToken.SetByte(2);
break;
case ocPercentSign:
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index c7f03f2b6f56..5bc35fef85d8 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -237,6 +237,8 @@ void ScRawToken::SetOpCode( OpCode e )
nJump[ 0 ] = 2; // If, Behind
break;
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
eType = svJump;
nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
break;
@@ -1347,6 +1349,8 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
case ocIfError:
case ocIfNA:
case ocChoose:
+ case ocIfs_MS:
+ case ocSwitch_MS:
// Jump commands are now supported.
break;
case ocAverage:
diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx
index fab7c26e8350..08dba32dc1e0 100644
--- a/sc/source/ui/unoobj/tokenuno.cxx
+++ b/sc/source/ui/unoobj/tokenuno.cxx
@@ -478,7 +478,7 @@ bool ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc,
OSL_TRACE( "ScTokenConversion::ConvertToTokenSequence: unhandled token type
SvStackVar %d", rToken.GetType());
SAL_FALLTHROUGH;
case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray*
- case svJump: // occurs with ocIf, ocChoose
+ case svJump: // occurs with ocIf, ocChoose, ocError, ocNA, ocIfs_MS and
ocSwitch_MS
case svMissing: // occurs with ocMissing
rAPI.Data.clear(); // no data
}
Context
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.