Hi Winfried, *,

On Fri, Apr 26, 2019 at 9:04 AM Winfried Donkers
<winfried.donk...@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 <winfrieddonk...@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
             }
_______________________________________________
LibreOffice mailing list
LibreOffice@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to