Date: prev next · Thread: first prev next last
2019 Archives by date, by thread · List index


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.