xref: /core/sc/source/core/tool/interpr4.cxx (revision 6873e0a9)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <config_features.h>
21 
22 #include <interpre.hxx>
23 
24 #include <rangelst.hxx>
25 #include <rtl/math.hxx>
26 #include <sfx2/app.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/docfilt.hxx>
30 #include <basic/sbmeth.hxx>
31 #include <basic/sbmod.hxx>
32 #include <basic/sbstar.hxx>
33 #include <basic/sbx.hxx>
34 #include <basic/sbxobj.hxx>
35 #include <basic/sbuno.hxx>
36 #include <svl/zforlist.hxx>
37 #include <svl/sharedstringpool.hxx>
38 #include <unotools/charclass.hxx>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <signal.h>
42 
43 #include <com/sun/star/table/XCellRange.hpp>
44 #include <com/sun/star/sheet/XSheetCellRange.hpp>
45 
46 #include <global.hxx>
47 #include <dbdata.hxx>
48 #include <formulacell.hxx>
49 #include <callform.hxx>
50 #include <addincol.hxx>
51 #include <document.hxx>
52 #include <dociter.hxx>
53 #include <docoptio.hxx>
54 #include <scmatrix.hxx>
55 #include <adiasync.hxx>
56 #include <sc.hrc>
57 #include <cellsuno.hxx>
58 #include <optuno.hxx>
59 #include <rangeseq.hxx>
60 #include <addinlis.hxx>
61 #include <jumpmatrix.hxx>
62 #include <parclass.hxx>
63 #include <externalrefmgr.hxx>
64 #include <formula/FormulaCompiler.hxx>
65 #include <macromgr.hxx>
66 #include <doubleref.hxx>
67 #include <queryparam.hxx>
68 #include <tokenarray.hxx>
69 #include <compiler.hxx>
70 
71 #include <math.h>
72 #include <float.h>
73 #include <map>
74 #include <algorithm>
75 #include <basic/basmgr.hxx>
76 #include <vbahelper/vbaaccesshelper.hxx>
77 #include <memory>
78 #include <stack>
79 
80 using namespace com::sun::star;
81 using namespace formula;
82 using ::std::unique_ptr;
83 
84 #define ADDIN_MAXSTRLEN 256
85 
86 thread_local std::unique_ptr<ScTokenStack> ScInterpreter::pGlobalStack;
87 thread_local bool ScInterpreter::bGlobalStackInUse = false;
88 
89 // document access functions
90 
91 void ScInterpreter::ReplaceCell( ScAddress& rPos )
92 {
93     size_t ListSize = pDok->m_TableOpList.size();
94     for ( size_t i = 0; i < ListSize; ++i )
95     {
96         ScInterpreterTableOpParams *const pTOp = pDok->m_TableOpList[ i ];
97         if ( rPos == pTOp->aOld1 )
98         {
99             rPos = pTOp->aNew1;
100             return ;
101         }
102         else if ( rPos == pTOp->aOld2 )
103         {
104             rPos = pTOp->aNew2;
105             return ;
106         }
107     }
108 }
109 
110 bool ScInterpreter::IsTableOpInRange( const ScRange& rRange )
111 {
112     if ( rRange.aStart == rRange.aEnd )
113         return false;   // not considered to be a range in TableOp sense
114 
115     // we can't replace a single cell in a range
116     size_t ListSize = pDok->m_TableOpList.size();
117     for ( size_t i = 0; i < ListSize; ++i )
118     {
119         ScInterpreterTableOpParams *const pTOp = pDok->m_TableOpList[ i ];
120         if ( rRange.In( pTOp->aOld1 ) )
121             return true;
122         if ( rRange.In( pTOp->aOld2 ) )
123             return true;
124     }
125     return false;
126 }
127 
128 sal_uInt32 ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, ScRefCellValue& rCell )
129 {
130     sal_uInt32 nFormat;
131     FormulaError nErr;
132     if (rCell.isEmpty())
133     {
134         nFormat = pDok->GetNumberFormat( mrContext, rPos );
135         nErr = FormulaError::NONE;
136     }
137     else
138     {
139         if (rCell.meType == CELLTYPE_FORMULA)
140             nErr = rCell.mpFormula->GetErrCode();
141         else
142             nErr = FormulaError::NONE;
143         nFormat = pDok->GetNumberFormat( mrContext, rPos );
144     }
145 
146     SetError(nErr);
147     return nFormat;
148 }
149 
150 /// Only ValueCell, formula cells already store the result rounded.
151 double ScInterpreter::GetValueCellValue( const ScAddress& rPos, double fOrig )
152 {
153     if ( bCalcAsShown && fOrig != 0.0 )
154     {
155         sal_uInt32 nFormat = pDok->GetNumberFormat( mrContext, rPos );
156         fOrig = pDok->RoundValueAsShown( fOrig, nFormat, &mrContext );
157     }
158     return fOrig;
159 }
160 
161 FormulaError ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell )
162 {
163     return rCell.meType == CELLTYPE_FORMULA ? rCell.mpFormula->GetErrCode() : FormulaError::NONE;
164 }
165 
166 double ScInterpreter::ConvertStringToValue( const OUString& rStr )
167 {
168     FormulaError nError = FormulaError::NONE;
169     double fValue = ScGlobal::ConvertStringToValue( rStr, maCalcConfig, nError, mnStringNoValueError,
170             pFormatter, nCurFmtType);
171     if (nError != FormulaError::NONE)
172         SetError(nError);
173     return fValue;
174 }
175 
176 double ScInterpreter::ConvertStringToValue( const OUString& rStr, FormulaError& rError, SvNumFormatType& rCurFmtType )
177 {
178     return ScGlobal::ConvertStringToValue( rStr, maCalcConfig, rError, mnStringNoValueError, pFormatter, rCurFmtType);
179 }
180 
181 double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& rCell )
182 {
183     FormulaError nErr = nGlobalError;
184     nGlobalError = FormulaError::NONE;
185     double nVal = GetCellValueOrZero(rPos, rCell);
186     if ( nGlobalError == FormulaError::NONE || nGlobalError == FormulaError::CellNoValue )
187         nGlobalError = nErr;
188     return nVal;
189 }
190 
191 double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& rCell )
192 {
193     double fValue = 0.0;
194 
195     CellType eType = rCell.meType;
196     switch (eType)
197     {
198         case CELLTYPE_FORMULA:
199         {
200             ScFormulaCell* pFCell = rCell.mpFormula;
201             FormulaError nErr = pFCell->GetErrCode();
202             if( nErr == FormulaError::NONE )
203             {
204                 if (pFCell->IsValue())
205                 {
206                     fValue = pFCell->GetValue();
207                     pDok->GetNumberFormatInfo( mrContext, nCurFmtType, nCurFmtIndex,
208                         rPos );
209                 }
210                 else
211                 {
212                     fValue = ConvertStringToValue(pFCell->GetString().getString());
213                 }
214             }
215             else
216             {
217                 fValue = 0.0;
218                 SetError(nErr);
219             }
220         }
221         break;
222         case CELLTYPE_VALUE:
223         {
224             fValue = rCell.mfValue;
225             nCurFmtIndex = pDok->GetNumberFormat( mrContext, rPos );
226             nCurFmtType = mrContext.GetNumberFormatType( nCurFmtIndex );
227             if ( bCalcAsShown && fValue != 0.0 )
228                 fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex, &mrContext );
229         }
230         break;
231         case  CELLTYPE_STRING:
232         case  CELLTYPE_EDIT:
233         {
234             // SUM(A1:A2) differs from A1+A2. No good. But people insist on
235             // it ... #i5658#
236             OUString aStr = rCell.getString(pDok);
237             fValue = ConvertStringToValue( aStr );
238         }
239         break;
240         case CELLTYPE_NONE:
241             fValue = 0.0;       // empty or broadcaster cell
242         break;
243     }
244 
245     return fValue;
246 }
247 
248 void ScInterpreter::GetCellString( svl::SharedString& rStr, ScRefCellValue& rCell )
249 {
250     FormulaError nErr = FormulaError::NONE;
251 
252     switch (rCell.meType)
253     {
254         case CELLTYPE_STRING:
255         case CELLTYPE_EDIT:
256             rStr = mrStrPool.intern(rCell.getString(pDok));
257         break;
258         case CELLTYPE_FORMULA:
259         {
260             ScFormulaCell* pFCell = rCell.mpFormula;
261             nErr = pFCell->GetErrCode();
262             if (pFCell->IsValue())
263             {
264                 rStr = GetStringFromDouble( pFCell->GetValue() );
265             }
266             else
267                 rStr = pFCell->GetString();
268         }
269         break;
270         case CELLTYPE_VALUE:
271         {
272             rStr = GetStringFromDouble( rCell.mfValue );
273         }
274         break;
275         default:
276             rStr = svl::SharedString::getEmptyString();
277         break;
278     }
279 
280     SetError(nErr);
281 }
282 
283 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
284                             SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr)
285 {
286 
287     // Old Add-Ins are hard limited to sal_uInt16 values.
288     static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns > SAL_MAX_UINT16!");
289     if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
290         return false;
291 
292     sal_uInt16 nCount = 0;
293     sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
294     *p++ = static_cast<sal_uInt16>(nCol1);
295     *p++ = static_cast<sal_uInt16>(nRow1);
296     *p++ = static_cast<sal_uInt16>(nTab1);
297     *p++ = static_cast<sal_uInt16>(nCol2);
298     *p++ = static_cast<sal_uInt16>(nRow2);
299     *p++ = static_cast<sal_uInt16>(nTab2);
300     sal_uInt16* pCount = p;
301     *p++ = 0;
302     sal_uInt16 nPos = 14;
303     SCTAB nTab = nTab1;
304     ScAddress aAdr;
305     while (nTab <= nTab2)
306     {
307         aAdr.SetTab( nTab );
308         SCROW nRow = nRow1;
309         while (nRow <= nRow2)
310         {
311             aAdr.SetRow( nRow );
312             SCCOL nCol = nCol1;
313             while (nCol <= nCol2)
314             {
315                 aAdr.SetCol( nCol );
316 
317                 ScRefCellValue aCell(*pDok, aAdr);
318                 if (!aCell.isEmpty())
319                 {
320                     FormulaError  nErr = FormulaError::NONE;
321                     double  nVal = 0.0;
322                     bool    bOk = true;
323                     switch (aCell.meType)
324                     {
325                         case CELLTYPE_VALUE :
326                             nVal = GetValueCellValue(aAdr, aCell.mfValue);
327                             break;
328                         case CELLTYPE_FORMULA :
329                             if (aCell.mpFormula->IsValue())
330                             {
331                                 nErr = aCell.mpFormula->GetErrCode();
332                                 nVal = aCell.mpFormula->GetValue();
333                             }
334                             else
335                                 bOk = false;
336                             break;
337                         default :
338                             bOk = false;
339                             break;
340                     }
341                     if (bOk)
342                     {
343                         if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
344                             return false;
345                         *p++ = static_cast<sal_uInt16>(nCol);
346                         *p++ = static_cast<sal_uInt16>(nRow);
347                         *p++ = static_cast<sal_uInt16>(nTab);
348                         *p++ = static_cast<sal_uInt16>(nErr);
349                         memcpy( p, &nVal, sizeof(double));
350                         nPos += 8 + sizeof(double);
351                         p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
352                         nCount++;
353                     }
354                 }
355                 nCol++;
356             }
357             nRow++;
358         }
359         nTab++;
360     }
361     *pCount = nCount;
362     return true;
363 }
364 
365 bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
366                                     SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
367                                     sal_uInt8* pCellArr)
368 {
369 
370     // Old Add-Ins are hard limited to sal_uInt16 values.
371     static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns > SAL_MAX_UINT16!");
372     if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
373         return false;
374 
375     sal_uInt16 nCount = 0;
376     sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
377     *p++ = static_cast<sal_uInt16>(nCol1);
378     *p++ = static_cast<sal_uInt16>(nRow1);
379     *p++ = static_cast<sal_uInt16>(nTab1);
380     *p++ = static_cast<sal_uInt16>(nCol2);
381     *p++ = static_cast<sal_uInt16>(nRow2);
382     *p++ = static_cast<sal_uInt16>(nTab2);
383     sal_uInt16* pCount = p;
384     *p++ = 0;
385     sal_uInt16 nPos = 14;
386     SCTAB nTab = nTab1;
387     while (nTab <= nTab2)
388     {
389         SCROW nRow = nRow1;
390         while (nRow <= nRow2)
391         {
392             SCCOL nCol = nCol1;
393             while (nCol <= nCol2)
394             {
395                 ScRefCellValue aCell(*pDok, ScAddress(nCol, nRow, nTab));
396                 if (!aCell.isEmpty())
397                 {
398                     OUString  aStr;
399                     FormulaError  nErr = FormulaError::NONE;
400                     bool    bOk = true;
401                     switch (aCell.meType)
402                     {
403                         case CELLTYPE_STRING:
404                         case CELLTYPE_EDIT:
405                             aStr = aCell.getString(pDok);
406                             break;
407                         case CELLTYPE_FORMULA:
408                             if (!aCell.mpFormula->IsValue())
409                             {
410                                 nErr = aCell.mpFormula->GetErrCode();
411                                 aStr = aCell.mpFormula->GetString().getString();
412                             }
413                             else
414                                 bOk = false;
415                             break;
416                         default :
417                             bOk = false;
418                             break;
419                     }
420                     if (bOk)
421                     {
422                         OString aTmp(OUStringToOString(aStr,
423                             osl_getThreadTextEncoding()));
424                         // Old Add-Ins are limited to sal_uInt16 string
425                         // lengths, and room for pad byte check.
426                         if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
427                             return false;
428                         // Append a 0-pad-byte if string length is odd
429                         // MUST be sal_uInt16
430                         sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength());
431                         sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
432 
433                         if ((static_cast<sal_uLong>(nPos) + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
434                             return false;
435                         *p++ = static_cast<sal_uInt16>(nCol);
436                         *p++ = static_cast<sal_uInt16>(nRow);
437                         *p++ = static_cast<sal_uInt16>(nTab);
438                         *p++ = static_cast<sal_uInt16>(nErr);
439                         *p++ = nLen;
440                         memcpy( p, aTmp.getStr(), nStrLen + 1);
441                         nPos += 10 + nStrLen + 1;
442                         sal_uInt8* q = pCellArr + nPos;
443                         if( (nStrLen & 1) == 0 )
444                         {
445                             *q++ = 0;
446                             nPos++;
447                         }
448                         p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
449                         nCount++;
450                     }
451                 }
452                 nCol++;
453             }
454             nRow++;
455         }
456         nTab++;
457     }
458     *pCount = nCount;
459     return true;
460 }
461 
462 bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
463                                   SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
464                                   sal_uInt8* pCellArr)
465 {
466 
467     // Old Add-Ins are hard limited to sal_uInt16 values.
468     static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16, "Add check for columns > SAL_MAX_UINT16!");
469     if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
470         return false;
471 
472     sal_uInt16 nCount = 0;
473     sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
474     *p++ = static_cast<sal_uInt16>(nCol1);
475     *p++ = static_cast<sal_uInt16>(nRow1);
476     *p++ = static_cast<sal_uInt16>(nTab1);
477     *p++ = static_cast<sal_uInt16>(nCol2);
478     *p++ = static_cast<sal_uInt16>(nRow2);
479     *p++ = static_cast<sal_uInt16>(nTab2);
480     sal_uInt16* pCount = p;
481     *p++ = 0;
482     sal_uInt16 nPos = 14;
483     SCTAB nTab = nTab1;
484     ScAddress aAdr;
485     while (nTab <= nTab2)
486     {
487         aAdr.SetTab( nTab );
488         SCROW nRow = nRow1;
489         while (nRow <= nRow2)
490         {
491             aAdr.SetRow( nRow );
492             SCCOL nCol = nCol1;
493             while (nCol <= nCol2)
494             {
495                 aAdr.SetCol( nCol );
496                 ScRefCellValue aCell(*pDok, aAdr);
497                 if (!aCell.isEmpty())
498                 {
499                     FormulaError  nErr = FormulaError::NONE;
500                     sal_uInt16  nType = 0; // 0 = number; 1 = string
501                     double  nVal = 0.0;
502                     OUString  aStr;
503                     bool    bOk = true;
504                     switch (aCell.meType)
505                     {
506                         case CELLTYPE_STRING :
507                         case CELLTYPE_EDIT :
508                             aStr = aCell.getString(pDok);
509                             nType = 1;
510                             break;
511                         case CELLTYPE_VALUE :
512                             nVal = GetValueCellValue(aAdr, aCell.mfValue);
513                             break;
514                         case CELLTYPE_FORMULA :
515                             nErr = aCell.mpFormula->GetErrCode();
516                             if (aCell.mpFormula->IsValue())
517                                 nVal = aCell.mpFormula->GetValue();
518                             else
519                                 aStr = aCell.mpFormula->GetString().getString();
520                             break;
521                         default :
522                             bOk = false;
523                             break;
524                     }
525                     if (bOk)
526                     {
527                         if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
528                             return false;
529                         *p++ = static_cast<sal_uInt16>(nCol);
530                         *p++ = static_cast<sal_uInt16>(nRow);
531                         *p++ = static_cast<sal_uInt16>(nTab);
532                         *p++ = static_cast<sal_uInt16>(nErr);
533                         *p++ = nType;
534                         nPos += 10;
535                         if (nType == 0)
536                         {
537                             if ((nPos + sizeof(double)) > MAXARRSIZE)
538                                 return false;
539                             memcpy( p, &nVal, sizeof(double));
540                             nPos += sizeof(double);
541                         }
542                         else
543                         {
544                             OString aTmp(OUStringToOString(aStr,
545                                 osl_getThreadTextEncoding()));
546                             // Old Add-Ins are limited to sal_uInt16 string
547                             // lengths, and room for pad byte check.
548                             if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
549                                 return false;
550                             // Append a 0-pad-byte if string length is odd
551                             // MUST be sal_uInt16
552                             sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength());
553                             sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
554                             if ( (static_cast<sal_uLong>(nPos) + 2 + nLen) > MAXARRSIZE)
555                                 return false;
556                             *p++ = nLen;
557                             memcpy( p, aTmp.getStr(), nStrLen + 1);
558                             nPos += 2 + nStrLen + 1;
559                             sal_uInt8* q = pCellArr + nPos;
560                             if( (nStrLen & 1) == 0 )
561                             {
562                                 *q++ = 0;
563                                 nPos++;
564                             }
565                         }
566                         nCount++;
567                         p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
568                     }
569                 }
570                 nCol++;
571             }
572             nRow++;
573         }
574         nTab++;
575     }
576     *pCount = nCount;
577     return true;
578 }
579 
580 // Stack operations
581 
582 // Also releases a TempToken if appropriate.
583 
584 void ScInterpreter::PushWithoutError( const FormulaToken& r )
585 {
586     if ( sp >= MAXSTACK )
587         SetError( FormulaError::StackOverflow );
588     else
589     {
590         r.IncRef();
591         if( sp >= maxsp )
592             maxsp = sp + 1;
593         else
594             pStack[ sp ]->DecRef();
595         pStack[ sp ] = &r;
596         ++sp;
597     }
598 }
599 
600 void ScInterpreter::Push( const FormulaToken& r )
601 {
602     if ( sp >= MAXSTACK )
603         SetError( FormulaError::StackOverflow );
604     else
605     {
606         if (nGlobalError != FormulaError::NONE)
607         {
608             if (r.GetType() == svError)
609                 PushWithoutError( r);
610             else
611                 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
612         }
613         else
614             PushWithoutError( r);
615     }
616 }
617 
618 void ScInterpreter::PushTempToken( FormulaToken* p )
619 {
620     if ( sp >= MAXSTACK )
621     {
622         SetError( FormulaError::StackOverflow );
623         // p may be a dangling pointer hereafter!
624         p->DeleteIfZeroRef();
625     }
626     else
627     {
628         if (nGlobalError != FormulaError::NONE)
629         {
630             if (p->GetType() == svError)
631             {
632                 p->SetError( nGlobalError);
633                 PushTempTokenWithoutError( p);
634             }
635             else
636             {
637                 // p may be a dangling pointer hereafter!
638                 p->DeleteIfZeroRef();
639                 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
640             }
641         }
642         else
643             PushTempTokenWithoutError( p);
644     }
645 }
646 
647 void ScInterpreter::PushTempTokenWithoutError( const FormulaToken* p )
648 {
649     p->IncRef();
650     if ( sp >= MAXSTACK )
651     {
652         SetError( FormulaError::StackOverflow );
653         // p may be a dangling pointer hereafter!
654         p->DecRef();
655     }
656     else
657     {
658         if( sp >= maxsp )
659             maxsp = sp + 1;
660         else
661             pStack[ sp ]->DecRef();
662         pStack[ sp ] = p;
663         ++sp;
664     }
665 }
666 
667 void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef& x )
668 {
669     if ( sp >= MAXSTACK )
670     {
671         SetError( FormulaError::StackOverflow );
672     }
673     else
674     {
675         if (nGlobalError != FormulaError::NONE)
676         {
677             if (x->GetType() == svError && x->GetError() == nGlobalError)
678                 PushTempTokenWithoutError( x.get());
679             else
680                 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
681         }
682         else
683             PushTempTokenWithoutError( x.get());
684     }
685 }
686 
687 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
688         const ScAddress & rAddress, SvNumFormatType * pRetTypeExpr, sal_uInt32 * pRetIndexExpr, bool bFinalResult )
689 {
690     ScRefCellValue aCell(*pDok, rAddress);
691     if (aCell.hasEmptyValue())
692     {
693         bool bInherited = (aCell.meType == CELLTYPE_FORMULA);
694         if (pRetTypeExpr && pRetIndexExpr)
695             pDok->GetNumberFormatInfo(mrContext, *pRetTypeExpr, *pRetIndexExpr, rAddress);
696         PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
697         return;
698     }
699 
700     FormulaError nErr = FormulaError::NONE;
701     if (aCell.meType == CELLTYPE_FORMULA)
702         nErr = aCell.mpFormula->GetErrCode();
703 
704     if (nErr != FormulaError::NONE)
705     {
706         PushError( nErr);
707         if (pRetTypeExpr)
708             *pRetTypeExpr = SvNumFormatType::UNDEFINED;
709         if (pRetIndexExpr)
710             *pRetIndexExpr = 0;
711     }
712     else if (aCell.hasString())
713     {
714         svl::SharedString aRes;
715         GetCellString( aRes, aCell);
716         PushString( aRes);
717         if (pRetTypeExpr)
718             *pRetTypeExpr = SvNumFormatType::TEXT;
719         if (pRetIndexExpr)
720             *pRetIndexExpr = 0;
721     }
722     else
723     {
724         double fVal = GetCellValue(rAddress, aCell);
725         if (bFinalResult)
726         {
727             TreatDoubleError( fVal);
728             if (!IfErrorPushError())
729                 PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal));
730         }
731         else
732         {
733             PushDouble( fVal);
734         }
735         if (pRetTypeExpr)
736             *pRetTypeExpr = nCurFmtType;
737         if (pRetIndexExpr)
738             *pRetIndexExpr = nCurFmtIndex;
739     }
740 }
741 
742 // Simply throw away TOS.
743 
744 void ScInterpreter::Pop()
745 {
746     if( sp )
747         sp--;
748     else
749         SetError(FormulaError::UnknownStackVariable);
750 }
751 
752 // Simply throw away TOS and set error code, used with ocIsError et al.
753 
754 void ScInterpreter::PopError()
755 {
756     if( sp )
757     {
758         sp--;
759         if (pStack[sp]->GetType() == svError)
760             nGlobalError = pStack[sp]->GetError();
761     }
762     else
763         SetError(FormulaError::UnknownStackVariable);
764 }
765 
766 FormulaConstTokenRef ScInterpreter::PopToken()
767 {
768     if (sp)
769     {
770         sp--;
771         const FormulaToken* p = pStack[ sp ];
772         if (p->GetType() == svError)
773             nGlobalError = p->GetError();
774         return p;
775     }
776     else
777         SetError(FormulaError::UnknownStackVariable);
778     return nullptr;
779 }
780 
781 double ScInterpreter::PopDouble()
782 {
783     nCurFmtType = SvNumFormatType::NUMBER;
784     nCurFmtIndex = 0;
785     if( sp )
786     {
787         --sp;
788         const FormulaToken* p = pStack[ sp ];
789         switch (p->GetType())
790         {
791             case svError:
792                 nGlobalError = p->GetError();
793                 break;
794             case svDouble:
795                 {
796                     SvNumFormatType nType = static_cast<SvNumFormatType>(p->GetDoubleType());
797                     if (nType != SvNumFormatType::ALL && nType != SvNumFormatType::UNDEFINED)
798                         nCurFmtType = nType;
799                     return p->GetDouble();
800                 }
801             case svEmptyCell:
802             case svMissing:
803                 return 0.0;
804             default:
805                 SetError( FormulaError::IllegalArgument);
806         }
807     }
808     else
809         SetError( FormulaError::UnknownStackVariable);
810     return 0.0;
811 }
812 
813 svl::SharedString ScInterpreter::PopString()
814 {
815     nCurFmtType = SvNumFormatType::TEXT;
816     nCurFmtIndex = 0;
817     if( sp )
818     {
819         --sp;
820         const FormulaToken* p = pStack[ sp ];
821         switch (p->GetType())
822         {
823             case svError:
824                 nGlobalError = p->GetError();
825                 break;
826             case svString:
827                 return p->GetString();
828             case svEmptyCell:
829             case svMissing:
830                 return svl::SharedString::getEmptyString();
831             default:
832                 SetError( FormulaError::IllegalArgument);
833         }
834     }
835     else
836         SetError( FormulaError::UnknownStackVariable);
837 
838     return svl::SharedString::getEmptyString();
839 }
840 
841 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
842 {
843     SCCOL nCol;
844     SCROW nRow;
845     SCTAB nTab;
846     SingleRefToVars( rRef, nCol, nRow, nTab);
847 }
848 
849 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
850 {
851     ValidateRef( rRef.Ref1);
852     ValidateRef( rRef.Ref2);
853 }
854 
855 void ScInterpreter::ValidateRef( const ScRefList & rRefList )
856 {
857     for (const auto& rRef : rRefList)
858     {
859         ValidateRef( rRef);
860     }
861 }
862 
863 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
864         SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
865 {
866     if ( rRef.IsColRel() )
867         rCol = aPos.Col() + rRef.Col();
868     else
869         rCol = rRef.Col();
870 
871     if ( rRef.IsRowRel() )
872         rRow = aPos.Row() + rRef.Row();
873     else
874         rRow = rRef.Row();
875 
876     if ( rRef.IsTabRel() )
877         rTab = aPos.Tab() + rRef.Tab();
878     else
879         rTab = rRef.Tab();
880 
881     if( !pDok->ValidCol( rCol) || rRef.IsColDeleted() )
882     {
883         SetError( FormulaError::NoRef );
884         rCol = 0;
885     }
886     if( !pDok->ValidRow( rRow) || rRef.IsRowDeleted() )
887     {
888         SetError( FormulaError::NoRef );
889         rRow = 0;
890     }
891     if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() )
892     {
893         SetError( FormulaError::NoRef );
894         rTab = 0;
895     }
896 }
897 
898 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
899 {
900     ScAddress aAddr(rCol, rRow, rTab);
901     PopSingleRef(aAddr);
902     rCol = aAddr.Col();
903     rRow = aAddr.Row();
904     rTab = aAddr.Tab();
905 }
906 
907 void ScInterpreter::PopSingleRef( ScAddress& rAdr )
908 {
909     if( sp )
910     {
911         --sp;
912         const FormulaToken* p = pStack[ sp ];
913         switch (p->GetType())
914         {
915             case svError:
916                 nGlobalError = p->GetError();
917                 break;
918             case svSingleRef:
919                 {
920                     const ScSingleRefData* pRefData = p->GetSingleRef();
921                     if (pRefData->IsDeleted())
922                     {
923                         SetError( FormulaError::NoRef);
924                         break;
925                     }
926 
927                     SCCOL nCol;
928                     SCROW nRow;
929                     SCTAB nTab;
930                     SingleRefToVars( *pRefData, nCol, nRow, nTab);
931                     rAdr.Set( nCol, nRow, nTab );
932                     if (!pDok->m_TableOpList.empty())
933                         ReplaceCell( rAdr );
934                 }
935                 break;
936             default:
937                 SetError( FormulaError::IllegalParameter);
938         }
939     }
940     else
941         SetError( FormulaError::UnknownStackVariable);
942 }
943 
944 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken* p,
945         SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
946         SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 )
947 {
948     const ScComplexRefData& rCRef = *p->GetDoubleRef();
949     SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
950     SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
951     if (rCol2 < rCol1)
952         std::swap( rCol2, rCol1);
953     if (rRow2 < rRow1)
954         std::swap( rRow2, rRow1);
955     if (rTab2 < rTab1)
956         std::swap( rTab2, rTab1);
957     if (!pDok->m_TableOpList.empty())
958     {
959         ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
960         if ( IsTableOpInRange( aRange ) )
961             SetError( FormulaError::IllegalParameter );
962     }
963 }
964 
965 ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
966 {
967     StackVar eType = GetStackType();
968     switch (eType)
969     {
970         case svUnknown:
971             SetError(FormulaError::UnknownStackVariable);
972         break;
973         case svError:
974             PopError();
975         break;
976         case svDoubleRef:
977         {
978             SCCOL nCol1, nCol2;
979             SCROW nRow1, nRow2;
980             SCTAB nTab1, nTab2;
981             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
982             if (nGlobalError != FormulaError::NONE)
983                 break;
984             return new ScDBInternalRange(pDok,
985                 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
986         }
987         case svMatrix:
988         case svExternalDoubleRef:
989         {
990             ScMatrixRef pMat;
991             if (eType == svMatrix)
992                 pMat = PopMatrix();
993             else
994                 PopExternalDoubleRef(pMat);
995             if (nGlobalError != FormulaError::NONE)
996                 break;
997             return new ScDBExternalRange(pDok, pMat);
998         }
999         default:
1000             SetError( FormulaError::IllegalParameter);
1001     }
1002 
1003     return nullptr;
1004 }
1005 
1006 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1007                                  SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2)
1008 {
1009     if( sp )
1010     {
1011         --sp;
1012         const FormulaToken* p = pStack[ sp ];
1013         switch (p->GetType())
1014         {
1015             case svError:
1016                 nGlobalError = p->GetError();
1017                 break;
1018             case svDoubleRef:
1019                 DoubleRefToVars( p, rCol1, rRow1, rTab1, rCol2, rRow2, rTab2);
1020                 break;
1021             default:
1022                 SetError( FormulaError::IllegalParameter);
1023         }
1024     }
1025     else
1026         SetError( FormulaError::UnknownStackVariable);
1027 }
1028 
1029 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1030         ScRange & rRange, bool bDontCheckForTableOp )
1031 {
1032     SCCOL nCol;
1033     SCROW nRow;
1034     SCTAB nTab;
1035     SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1036     rRange.aStart.Set( nCol, nRow, nTab );
1037     SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1038     rRange.aEnd.Set( nCol, nRow, nTab );
1039     rRange.PutInOrder();
1040     if (!pDok->m_TableOpList.empty() && !bDontCheckForTableOp)
1041     {
1042         if ( IsTableOpInRange( rRange ) )
1043             SetError( FormulaError::IllegalParameter );
1044     }
1045 }
1046 
1047 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1048 {
1049     if (sp)
1050     {
1051         const formula::FormulaToken* pToken = pStack[ sp-1 ];
1052         switch (pToken->GetType())
1053         {
1054             case svError:
1055                 nGlobalError = pToken->GetError();
1056                 break;
1057             case svDoubleRef:
1058             {
1059                 --sp;
1060                 const ScComplexRefData* pRefData = pToken->GetDoubleRef();
1061                 if (pRefData->IsDeleted())
1062                 {
1063                     SetError( FormulaError::NoRef);
1064                     break;
1065                 }
1066                 DoubleRefToRange( *pRefData, rRange);
1067                 break;
1068             }
1069             case svRefList:
1070                 {
1071                     const ScRefList* pList = pToken->GetRefList();
1072                     if (rRefInList < pList->size())
1073                     {
1074                         DoubleRefToRange( (*pList)[rRefInList], rRange);
1075                         if (++rRefInList < pList->size())
1076                             ++rParam;
1077                         else
1078                         {
1079                             --sp;
1080                             rRefInList = 0;
1081                         }
1082                     }
1083                     else
1084                     {
1085                         --sp;
1086                         rRefInList = 0;
1087                         SetError( FormulaError::IllegalParameter);
1088                     }
1089                 }
1090                 break;
1091             default:
1092                 SetError( FormulaError::IllegalParameter);
1093         }
1094     }
1095     else
1096         SetError( FormulaError::UnknownStackVariable);
1097 }
1098 
1099 void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1100 {
1101     if( sp )
1102     {
1103         --sp;
1104         const FormulaToken* p = pStack[ sp ];
1105         switch (p->GetType())
1106         {
1107             case svError:
1108                 nGlobalError = p->GetError();
1109                 break;
1110             case svDoubleRef:
1111                 DoubleRefToRange( *p->GetDoubleRef(), rRange, bDontCheckForTableOp);
1112                 break;
1113             default:
1114                 SetError( FormulaError::IllegalParameter);
1115         }
1116     }
1117     else
1118         SetError( FormulaError::UnknownStackVariable);
1119 }
1120 
1121 void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef)
1122 {
1123     if (!sp)
1124     {
1125         SetError(FormulaError::UnknownStackVariable);
1126         return;
1127     }
1128 
1129     --sp;
1130     const FormulaToken* p = pStack[sp];
1131     StackVar eType = p->GetType();
1132 
1133     if (eType == svError)
1134     {
1135         nGlobalError = p->GetError();
1136         return;
1137     }
1138 
1139     if (eType != svExternalSingleRef)
1140     {
1141         SetError( FormulaError::IllegalParameter);
1142         return;
1143     }
1144 
1145     rFileId = p->GetIndex();
1146     rTabName = p->GetString().getString();
1147     rRef = *p->GetSingleRef();
1148 }
1149 
1150 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1151 {
1152     sal_uInt16 nFileId;
1153     OUString aTabName;
1154     ScSingleRefData aData;
1155     PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1156 }
1157 
1158 void ScInterpreter::PopExternalSingleRef(
1159     sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
1160     ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1161 {
1162     PopExternalSingleRef(rFileId, rTabName, rRef);
1163     if (nGlobalError != FormulaError::NONE)
1164         return;
1165 
1166     ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1167     const OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1168     if (!pFile)
1169     {
1170         SetError(FormulaError::NoName);
1171         return;
1172     }
1173 
1174     if (rRef.IsTabRel())
1175     {
1176         OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1177         SetError(FormulaError::NoRef);
1178         return;
1179     }
1180 
1181     ScAddress aAddr = rRef.toAbs(pDok, aPos);
1182     ScExternalRefCache::CellFormat aFmt;
1183     ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1184         rFileId, rTabName, aAddr, &aPos, nullptr, &aFmt);
1185 
1186     if (!xNew)
1187     {
1188         SetError(FormulaError::NoRef);
1189         return;
1190     }
1191 
1192     if (xNew->GetType() == svError)
1193         SetError( xNew->GetError());
1194 
1195     rToken = xNew;
1196     if (pFmt)
1197         *pFmt = aFmt;
1198 }
1199 
1200 void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef)
1201 {
1202     if (!sp)
1203     {
1204         SetError(FormulaError::UnknownStackVariable);
1205         return;
1206     }
1207 
1208     --sp;
1209     const FormulaToken* p = pStack[sp];
1210     StackVar eType = p->GetType();
1211 
1212     if (eType == svError)
1213     {
1214         nGlobalError = p->GetError();
1215         return;
1216     }
1217 
1218     if (eType != svExternalDoubleRef)
1219     {
1220         SetError( FormulaError::IllegalParameter);
1221         return;
1222     }
1223 
1224     rFileId = p->GetIndex();
1225     rTabName = p->GetString().getString();
1226     rRef = *p->GetDoubleRef();
1227 }
1228 
1229 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1230 {
1231     sal_uInt16 nFileId;
1232     OUString aTabName;
1233     ScComplexRefData aData;
1234     PopExternalDoubleRef(nFileId, aTabName, aData);
1235     if (nGlobalError != FormulaError::NONE)
1236         return;
1237 
1238     GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1239     if (nGlobalError != FormulaError::NONE)
1240         return;
1241 }
1242 
1243 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1244 {
1245     ScExternalRefCache::TokenArrayRef pArray;
1246     PopExternalDoubleRef(pArray);
1247     if (nGlobalError != FormulaError::NONE)
1248         return;
1249 
1250     // For now, we only support single range data for external
1251     // references, which means the array should only contain a
1252     // single matrix token.
1253     formula::FormulaToken* p = pArray->FirstToken();
1254     if (!p || p->GetType() != svMatrix)
1255         SetError( FormulaError::IllegalParameter);
1256     else
1257     {
1258         rMat = p->GetMatrix();
1259         if (!rMat)
1260             SetError( FormulaError::UnknownVariable);
1261     }
1262 }
1263 
1264 void ScInterpreter::GetExternalDoubleRef(
1265     sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1266 {
1267     ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1268     const OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1269     if (!pFile)
1270     {
1271         SetError(FormulaError::NoName);
1272         return;
1273     }
1274     if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
1275     {
1276         OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1277         SetError(FormulaError::NoRef);
1278         return;
1279     }
1280 
1281     ScComplexRefData aData(rData);
1282     ScRange aRange = aData.toAbs(pDok, aPos);
1283     if (!pDok->ValidColRow(aRange.aStart.Col(), aRange.aStart.Row()) || !pDok->ValidColRow(aRange.aEnd.Col(), aRange.aEnd.Row()))
1284     {
1285         SetError(FormulaError::NoRef);
1286         return;
1287     }
1288 
1289     ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1290         nFileId, rTabName, aRange, &aPos);
1291 
1292     if (!pArray)
1293     {
1294         SetError(FormulaError::IllegalArgument);
1295         return;
1296     }
1297 
1298     formula::FormulaTokenArrayPlainIterator aIter(*pArray);
1299     formula::FormulaToken* pToken = aIter.First();
1300     assert(pToken);
1301     if (pToken->GetType() == svError)
1302     {
1303         SetError( pToken->GetError());
1304         return;
1305     }
1306     if (pToken->GetType() != svMatrix)
1307     {
1308         SetError(FormulaError::IllegalArgument);
1309         return;
1310     }
1311 
1312     if (aIter.Next())
1313     {
1314         // Can't handle more than one matrix per parameter.
1315         SetError( FormulaError::IllegalArgument);
1316         return;
1317     }
1318 
1319     rArray = pArray;
1320 }
1321 
1322 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1323 {
1324     switch ( GetStackType() )
1325     {
1326         case svDoubleRef :
1327         {
1328             ScRange aRange;
1329             PopDoubleRef( aRange, true );
1330             return DoubleRefToPosSingleRef( aRange, rAdr );
1331         }
1332         case svSingleRef :
1333         {
1334             PopSingleRef( rAdr );
1335             return true;
1336         }
1337         default:
1338             PopError();
1339             SetError( FormulaError::NoRef );
1340     }
1341     return false;
1342 }
1343 
1344 void ScInterpreter::PopDoubleRefPushMatrix()
1345 {
1346     if ( GetStackType() == svDoubleRef )
1347     {
1348         ScMatrixRef pMat = GetMatrix();
1349         if ( pMat )
1350             PushMatrix( pMat );
1351         else
1352             PushIllegalParameter();
1353     }
1354     else
1355         SetError( FormulaError::NoRef );
1356 }
1357 
1358 void ScInterpreter::PopRefListPushMatrixOrRef()
1359 {
1360     if ( GetStackType() == svRefList )
1361     {
1362         FormulaConstTokenRef xTok = pStack[sp-1];
1363         const std::vector<ScComplexRefData>* pv = xTok->GetRefList();
1364         if (pv)
1365         {
1366             const size_t nEntries = pv->size();
1367             if (nEntries == 1)
1368             {
1369                 --sp;
1370                 PushTempTokenWithoutError( new ScDoubleRefToken( pDok->GetSheetLimits(), (*pv)[0] ));
1371             }
1372             else if (bMatrixFormula)
1373             {
1374                 // Only single cells can be stuffed into a column vector.
1375                 // XXX NOTE: Excel doesn't do this but returns #VALUE! instead.
1376                 // Though there's no compelling reason not to...
1377                 for (const auto & rRef : *pv)
1378                 {
1379                     if (rRef.Ref1 != rRef.Ref2)
1380                         return;
1381                 }
1382                 ScMatrixRef xMat = GetNewMat( 1, nEntries, true);   // init empty
1383                 if (!xMat)
1384                     return;
1385                 for (size_t i=0; i < nEntries; ++i)
1386                 {
1387                     SCCOL nCol; SCROW nRow; SCTAB nTab;
1388                     SingleRefToVars( (*pv)[i].Ref1, nCol, nRow, nTab);
1389                     if (nGlobalError == FormulaError::NONE)
1390                     {
1391                         ScAddress aAdr( nCol, nRow, nTab);
1392                         ScRefCellValue aCell( *pDok, aAdr);
1393                         if (aCell.hasError())
1394                             xMat->PutError( aCell.mpFormula->GetErrCode(), 0, i);
1395                         else if (aCell.hasEmptyValue())
1396                             xMat->PutEmpty( 0, i);
1397                         else if (aCell.hasString())
1398                             xMat->PutString( mrStrPool.intern( aCell.getString( pDok)), 0, i);
1399                         else
1400                             xMat->PutDouble( aCell.getValue(), 0, i);
1401                     }
1402                     else
1403                     {
1404                         xMat->PutError( nGlobalError, 0, i);
1405                         nGlobalError = FormulaError::NONE;
1406                     }
1407                 }
1408                 --sp;
1409                 PushMatrix( xMat);
1410             }
1411         }
1412         // else: keep token on stack, something will handle the error
1413     }
1414     else
1415         SetError( FormulaError::NoRef );
1416 }
1417 
1418 void ScInterpreter::ConvertMatrixJumpConditionToMatrix()
1419 {
1420     StackVar eStackType = GetStackType();
1421     if (eStackType == svUnknown)
1422         return;     // can't do anything, some caller will catch that
1423     if (eStackType == svMatrix)
1424         return;     // already matrix, nothing to do
1425 
1426     if (eStackType != svDoubleRef && GetStackType(2) != svJumpMatrix)
1427         return;     // always convert svDoubleRef, others only in JumpMatrix context
1428 
1429     GetTokenMatrixMap();    // make sure it exists, create if not.
1430     ScMatrixRef pMat = GetMatrix();
1431     if ( pMat )
1432         PushMatrix( pMat );
1433     else
1434         PushIllegalParameter();
1435 }
1436 
1437 std::unique_ptr<ScTokenMatrixMap> ScInterpreter::CreateTokenMatrixMap()
1438 {
1439     return std::make_unique<ScTokenMatrixMap>();
1440 }
1441 
1442 bool ScInterpreter::ConvertMatrixParameters()
1443 {
1444     sal_uInt16 nParams = pCur->GetParamCount();
1445     OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch");
1446     SCSIZE nJumpCols = 0, nJumpRows = 0;
1447     for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
1448     {
1449         const FormulaToken* p = pStack[ sp - i ];
1450         if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
1451         {
1452             OSL_FAIL( "ConvertMatrixParameters: not a push");
1453         }
1454         else
1455         {
1456             switch ( p->GetType() )
1457             {
1458                 case svDouble:
1459                 case svString:
1460                 case svSingleRef:
1461                 case svExternalSingleRef:
1462                 case svMissing:
1463                 case svError:
1464                 case svEmptyCell:
1465                     // nothing to do
1466                 break;
1467                 case svMatrix:
1468                 {
1469                     if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1470                             == formula::ParamClass::Value )
1471                     {   // only if single value expected
1472                         ScConstMatrixRef pMat = p->GetMatrix();
1473                         if ( !pMat )
1474                             SetError( FormulaError::UnknownVariable);
1475                         else
1476                         {
1477                             SCSIZE nCols, nRows;
1478                             pMat->GetDimensions( nCols, nRows);
1479                             if ( nJumpCols < nCols )
1480                                 nJumpCols = nCols;
1481                             if ( nJumpRows < nRows )
1482                                 nJumpRows = nRows;
1483                         }
1484                     }
1485                 }
1486                 break;
1487                 case svDoubleRef:
1488                 {
1489                     formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1490                     if ( eType != formula::ParamClass::Reference &&
1491                             eType != formula::ParamClass::ReferenceOrRefArray &&
1492                             eType != formula::ParamClass::ReferenceOrForceArray &&
1493                             // For scalar Value: convert to Array/JumpMatrix
1494                             // only if in array formula context, else (function
1495                             // has ForceArray or ReferenceOrForceArray
1496                             // parameter *somewhere else*) pick a normal
1497                             // position dependent implicit intersection later.
1498                             (eType != formula::ParamClass::Value || IsInArrayContext()))
1499                     {
1500                         SCCOL nCol1, nCol2;
1501                         SCROW nRow1, nRow2;
1502                         SCTAB nTab1, nTab2;
1503                         DoubleRefToVars( p, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1504                         // Make sure the map exists, created if not.
1505                         GetTokenMatrixMap();
1506                         ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1507                                 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1508                         if (pMat)
1509                         {
1510                             if ( eType == formula::ParamClass::Value )
1511                             {   // only if single value expected
1512                                 if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) )
1513                                     nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1514                                 if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) )
1515                                     nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1516                             }
1517                             formula::FormulaToken* pNew = new ScMatrixToken( pMat);
1518                             pNew->IncRef();
1519                             pStack[ sp - i ] = pNew;
1520                             p->DecRef();    // p may be dead now!
1521                         }
1522                     }
1523                 }
1524                 break;
1525                 case svExternalDoubleRef:
1526                 {
1527                     formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1528                     if (eType == formula::ParamClass::Value || eType == formula::ParamClass::Array)
1529                     {
1530                         sal_uInt16 nFileId = p->GetIndex();
1531                         OUString aTabName = p->GetString().getString();
1532                         const ScComplexRefData& rRef = *p->GetDoubleRef();
1533                         ScExternalRefCache::TokenArrayRef pArray;
1534                         GetExternalDoubleRef(nFileId, aTabName, rRef, pArray);
1535                         if (nGlobalError != FormulaError::NONE || !pArray)
1536                             break;
1537                         formula::FormulaToken* pTemp = pArray->FirstToken();
1538                         if (!pTemp)
1539                             break;
1540 
1541                         ScMatrixRef pMat = pTemp->GetMatrix();
1542                         if (pMat)
1543                         {
1544                             if (eType == formula::ParamClass::Value)
1545                             {   // only if single value expected
1546                                 SCSIZE nC, nR;
1547                                 pMat->GetDimensions( nC, nR);
1548                                 if (nJumpCols < nC)
1549                                     nJumpCols = nC;
1550                                 if (nJumpRows < nR)
1551                                     nJumpRows = nR;
1552                             }
1553                             formula::FormulaToken* pNew = new ScMatrixToken( pMat);
1554                             pNew->IncRef();
1555                             pStack[ sp - i ] = pNew;
1556                             p->DecRef();    // p may be dead now!
1557                         }
1558                     }
1559                 }
1560                 break;
1561                 case svRefList:
1562                 {
1563                     formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1564                     if ( eType != formula::ParamClass::Reference &&
1565                             eType != formula::ParamClass::ReferenceOrRefArray &&
1566                             eType != formula::ParamClass::ReferenceOrForceArray &&
1567                             eType != formula::ParamClass::ForceArray)
1568                     {
1569                         // can't convert to matrix
1570                         SetError( FormulaError::NoValue);
1571                     }
1572                     // else: the consuming function has to decide if and how to
1573                     // handle a reference list argument in array context.
1574                 }
1575                 break;
1576                 default:
1577                     OSL_FAIL( "ConvertMatrixParameters: unknown parameter type");
1578             }
1579         }
1580     }
1581     if( nJumpCols && nJumpRows )
1582     {
1583         short nPC = aCode.GetPC();
1584         short nStart = nPC - 1;     // restart on current code (-1)
1585         short nNext = nPC;          // next instruction after subroutine
1586         short nStop = nPC + 1;      // stop subroutine before reaching that
1587         FormulaConstTokenRef xNew;
1588         ScTokenMatrixMap::const_iterator aMapIter;
1589         if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end()))
1590             xNew = (*aMapIter).second;
1591         else
1592         {
1593             std::unique_ptr<ScJumpMatrix> pJumpMat( new ScJumpMatrix( pCur->GetOpCode(), nJumpCols, nJumpRows));
1594             pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1595             // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1596             ScTokenVec aParams(nParams);
1597             for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
1598             {
1599                 const FormulaToken* p = pStack[ --sp ];
1600                 p->IncRef();
1601                 // store in reverse order such that a push may simply iterate
1602                 aParams[ nParams - i ] = p;
1603             }
1604             pJumpMat->SetJumpParameters( std::move(aParams) );
1605             xNew = new ScJumpMatrixToken( std::move(pJumpMat) );
1606             GetTokenMatrixMap().emplace(pCur, xNew);
1607         }
1608         PushTempTokenWithoutError( xNew.get());
1609         // set continuation point of path for main code line
1610         aCode.Jump( nNext, nNext);
1611         return true;
1612     }
1613     return false;
1614 }
1615 
1616 ScMatrixRef ScInterpreter::PopMatrix()
1617 {
1618     if( sp )
1619     {
1620         --sp;
1621         const FormulaToken* p = pStack[ sp ];
1622         switch (p->GetType())
1623         {
1624             case svError:
1625                 nGlobalError = p->GetError();
1626                 break;
1627             case svMatrix:
1628                 {
1629                     // ScMatrix itself maintains an im/mutable flag that should
1630                     // be obeyed where necessary... so we can return ScMatrixRef
1631                     // here instead of ScConstMatrixRef.
1632                     ScMatrix* pMat = const_cast<FormulaToken*>(p)->GetMatrix();
1633                     if ( pMat )
1634                         pMat->SetErrorInterpreter( this);
1635                     else
1636                         SetError( FormulaError::UnknownVariable);
1637                     return pMat;
1638                 }
1639             default:
1640                 SetError( FormulaError::IllegalParameter);
1641         }
1642     }
1643     else
1644         SetError( FormulaError::UnknownStackVariable);
1645     return nullptr;
1646 }
1647 
1648 sc::RangeMatrix ScInterpreter::PopRangeMatrix()
1649 {
1650     sc::RangeMatrix aRet;
1651     if (sp)
1652     {
1653         switch (pStack[sp-1]->GetType())
1654         {
1655             case svMatrix:
1656             {
1657                 --sp;
1658                 const FormulaToken* p = pStack[sp];
1659                 aRet.mpMat = const_cast<FormulaToken*>(p)->GetMatrix();
1660                 if (aRet.mpMat)
1661                 {
1662                     aRet.mpMat->SetErrorInterpreter(this);
1663                     if (p->GetByte() == MATRIX_TOKEN_HAS_RANGE)
1664                     {
1665                         const ScComplexRefData& rRef = *p->GetDoubleRef();
1666                         if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
1667                         {
1668                             aRet.mnCol1 = rRef.Ref1.Col();
1669                             aRet.mnRow1 = rRef.Ref1.Row();
1670                             aRet.mnTab1 = rRef.Ref1.Tab();
1671                             aRet.mnCol2 = rRef.Ref2.Col();
1672                             aRet.mnRow2 = rRef.Ref2.Row();
1673                             aRet.mnTab2 = rRef.Ref2.Tab();
1674                         }
1675                     }
1676                 }
1677                 else
1678                     SetError( FormulaError::UnknownVariable);
1679             }
1680             break;
1681             default:
1682                 aRet.mpMat = PopMatrix();
1683         }
1684     }
1685     return aRet;
1686 }
1687 
1688 void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, SvNumFormatType& rRetTypeExpr, sal_uInt32& rRetIndexExpr)
1689 {
1690     if (xMat)
1691     {
1692         SCSIZE nCols, nRows;
1693         xMat->GetDimensions(nCols, nRows);
1694         ScMatrixValue nMatVal = xMat->Get(0, 0);
1695         ScMatValType nMatValType = nMatVal.nType;
1696         if (ScMatrix::IsNonValueType( nMatValType))
1697         {
1698             if ( xMat->IsEmptyPath( 0, 0))
1699             {   // result of empty FALSE jump path
1700                 FormulaTokenRef xRes = CreateFormulaDoubleToken( 0.0);
1701                 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1702                 rRetTypeExpr = SvNumFormatType::LOGICAL;
1703             }
1704             else if ( xMat->IsEmptyResult( 0, 0))
1705             {   // empty formula result
1706                 FormulaTokenRef xRes = new ScEmptyCellToken( true, true);   // inherited, display empty
1707                 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1708             }
1709             else if ( xMat->IsEmpty( 0, 0))
1710             {   // empty or empty cell
1711                 FormulaTokenRef xRes = new ScEmptyCellToken( false, true);  // not inherited, display empty
1712                 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1713             }
1714             else
1715             {
1716                 FormulaTokenRef xRes = new FormulaStringToken( nMatVal.GetString() );
1717                 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1718                 rRetTypeExpr = SvNumFormatType::TEXT;
1719             }
1720         }
1721         else
1722         {
1723             FormulaError nErr = GetDoubleErrorValue( nMatVal.fVal);
1724             FormulaTokenRef xRes;
1725             if (nErr != FormulaError::NONE)
1726                 xRes = new FormulaErrorToken( nErr);
1727             else
1728                 xRes = CreateFormulaDoubleToken( nMatVal.fVal);
1729             PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1730             if ( rRetTypeExpr != SvNumFormatType::LOGICAL )
1731                 rRetTypeExpr = SvNumFormatType::NUMBER;
1732         }
1733         rRetIndexExpr = 0;
1734         xMat->SetErrorInterpreter( nullptr);
1735     }
1736     else
1737         SetError( FormulaError::UnknownStackVariable);
1738 }
1739 
1740 formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, SvNumFormatType nFmt )
1741 {
1742     assert( mrContext.maTokens.size() == TOKEN_CACHE_SIZE );
1743 
1744     // Find a spare token
1745     for ( auto p : mrContext.maTokens )
1746     {
1747         if (p && p->GetRef() == 1)
1748         {
1749             p->GetDoubleAsReference() = fVal;
1750             p->SetDoubleType( static_cast<sal_Int16>(nFmt) );
1751             return p;
1752         }
1753     }
1754 
1755     // Allocate a new token
1756     auto p = new FormulaTypedDoubleToken( fVal, static_cast<sal_Int16>(nFmt) );
1757     if ( mrContext.maTokens[mrContext.mnTokenCachePos] )
1758         mrContext.maTokens[mrContext.mnTokenCachePos]->DecRef();
1759     mrContext.maTokens[mrContext.mnTokenCachePos] = p;
1760     p->IncRef();
1761     mrContext.mnTokenCachePos = (mrContext.mnTokenCachePos + 1) % TOKEN_CACHE_SIZE;
1762     return p;
1763 }
1764 
1765 formula::FormulaToken* ScInterpreter::CreateDoubleOrTypedToken( double fVal )
1766 {
1767     // NumberFormat::NUMBER is the default untyped double.
1768     if (nFuncFmtType != SvNumFormatType::ALL && nFuncFmtType != SvNumFormatType::NUMBER &&
1769             nFuncFmtType != SvNumFormatType::UNDEFINED)
1770         return CreateFormulaDoubleToken( fVal, nFuncFmtType);
1771     else
1772         return CreateFormulaDoubleToken( fVal);
1773 }
1774 
1775 void ScInterpreter::PushDouble(double nVal)
1776 {
1777     TreatDoubleError( nVal );
1778     if (!IfErrorPushError())
1779         PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal));
1780 }
1781 
1782 void ScInterpreter::PushInt(int nVal)
1783 {
1784     if (!IfErrorPushError())
1785         PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal));
1786 }
1787 
1788 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1789 {
1790     if ( pString )
1791     {
1792         svl::SharedString aSS = pDok->GetSharedStringPool().intern(OUString(pString));
1793         PushString(aSS);
1794     }
1795     else
1796         PushString(svl::SharedString::getEmptyString());
1797 }
1798 
1799 void ScInterpreter::PushString( const OUString& rStr )
1800 {
1801     PushString(pDok->GetSharedStringPool().intern(rStr));
1802 }
1803 
1804 void ScInterpreter::PushString( const svl::SharedString& rString )
1805 {
1806     if (!IfErrorPushError())
1807         PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1808 }
1809 
1810 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1811 {
1812     if (!IfErrorPushError())
1813     {
1814         ScSingleRefData aRef;
1815         aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1816         PushTempTokenWithoutError( new ScSingleRefToken( pDok->GetSheetLimits(), aRef ) );
1817     }
1818 }
1819 
1820 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1821                                   SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1822 {
1823     if (!IfErrorPushError())
1824     {
1825         ScComplexRefData aRef;
1826         aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1827         PushTempTokenWithoutError( new ScDoubleRefToken( pDok->GetSheetLimits(), aRef ) );
1828     }
1829 }
1830 
1831 void ScInterpreter::PushExternalSingleRef(
1832     sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1833 {
1834     if (!IfErrorPushError())
1835     {
1836         ScSingleRefData aRef;
1837         aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1838         PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId,
1839                     pDok->GetSharedStringPool().intern( rTabName), aRef)) ;
1840     }
1841 }
1842 
1843 void ScInterpreter::PushExternalDoubleRef(
1844     sal_uInt16 nFileId, const OUString& rTabName,
1845     SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1846 {
1847     if (!IfErrorPushError())
1848     {
1849         ScComplexRefData aRef;
1850         aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1851         PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId,
1852                     pDok->GetSharedStringPool().intern( rTabName), aRef) );
1853     }
1854 }
1855 
1856 void ScInterpreter::PushSingleRef( const ScRefAddress& rRef )
1857 {
1858     if (!IfErrorPushError())
1859     {
1860         ScSingleRefData aRef;
1861         aRef.InitFromRefAddress( pDok, rRef, aPos);
1862         PushTempTokenWithoutError( new ScSingleRefToken( pDok->GetSheetLimits(), aRef ) );
1863     }
1864 }
1865 
1866 void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 )
1867 {
1868     if (!IfErrorPushError())
1869     {
1870         ScComplexRefData aRef;
1871         aRef.InitFromRefAddresses( pDok, rRef1, rRef2, aPos);
1872         PushTempTokenWithoutError( new ScDoubleRefToken( pDok->GetSheetLimits(), aRef ) );
1873     }
1874 }
1875 
1876 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
1877 {
1878     if (!rMat.isRangeValid())
1879     {
1880         // Just push the matrix part only.
1881         PushMatrix(rMat.mpMat);
1882         return;
1883     }
1884 
1885     rMat.mpMat->SetErrorInterpreter(nullptr);
1886     nGlobalError = FormulaError::NONE;
1887     PushTempTokenWithoutError(new ScMatrixRangeToken(rMat));
1888 }
1889 
1890 void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
1891 {
1892     pMat->SetErrorInterpreter( nullptr);
1893     // No   if (!IfErrorPushError())   because ScMatrix stores errors itself,
1894     // but with notifying ScInterpreter via nGlobalError, substituting it would
1895     // mean to inherit the error on all array elements in all following
1896     // operations.
1897     nGlobalError = FormulaError::NONE;
1898     PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
1899 }
1900 
1901 void ScInterpreter::PushError( FormulaError nError )
1902 {
1903     SetError( nError );     // only sets error if not already set
1904     PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
1905 }
1906 
1907 void ScInterpreter::PushParameterExpected()
1908 {
1909     PushError( FormulaError::ParameterExpected);
1910 }
1911 
1912 void ScInterpreter::PushIllegalParameter()
1913 {
1914     PushError( FormulaError::IllegalParameter);
1915 }
1916 
1917 void ScInterpreter::PushIllegalArgument()
1918 {
1919     PushError( FormulaError::IllegalArgument);
1920 }
1921 
1922 void ScInterpreter::PushNA()
1923 {
1924     PushError( FormulaError::NotAvailable);
1925 }
1926 
1927 void ScInterpreter::PushNoValue()
1928 {
1929     PushError( FormulaError::NoValue);
1930 }
1931 
1932 bool ScInterpreter::IsMissing() const
1933 {
1934     return sp && pStack[sp - 1]->GetType() == svMissing;
1935 }
1936 
1937 StackVar ScInterpreter::GetRawStackType()
1938 {
1939     StackVar eRes;
1940     if( sp )
1941     {
1942         eRes = pStack[sp - 1]->GetType();
1943     }
1944     else
1945     {
1946         SetError(FormulaError::UnknownStackVariable);
1947         eRes = svUnknown;
1948     }
1949     return eRes;
1950 }
1951 
1952 StackVar ScInterpreter::GetStackType()
1953 {
1954     StackVar eRes;
1955     if( sp )
1956     {
1957         eRes = pStack[sp - 1]->GetType();
1958         if( eRes == svMissing || eRes == svEmptyCell )
1959             eRes = svDouble;    // default!
1960     }
1961     else
1962     {
1963         SetError(FormulaError::UnknownStackVariable);
1964         eRes = svUnknown;
1965     }
1966     return eRes;
1967 }
1968 
1969 StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
1970 {
1971     StackVar eRes;
1972     if( sp > nParam-1 )
1973     {
1974         eRes = pStack[sp - nParam]->GetType();
1975         if( eRes == svMissing || eRes == svEmptyCell )
1976             eRes = svDouble;    // default!
1977     }
1978     else
1979         eRes = svUnknown;
1980     return eRes;
1981 }
1982 
1983 void ScInterpreter::ReverseStack( sal_uInt8 nParamCount )
1984 {
1985     //reverse order of parameter stack
1986     assert( sp >= nParamCount && " less stack elements than parameters");
1987     sal_uInt16 nStackParams = std::min<sal_uInt16>( sp, nParamCount);
1988     std::reverse( pStack+(sp-nStackParams), pStack+sp );
1989 }
1990 
1991 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
1992 {
1993     // Check for a singleton first - no implicit intersection for them.
1994     if( rRange.aStart == rRange.aEnd )
1995     {
1996         rAdr = rRange.aStart;
1997         return true;
1998     }
1999 
2000     bool bOk = false;
2001 
2002     if ( pJumpMatrix )
2003     {
2004         bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
2005         if ( !bOk )
2006             SetError( FormulaError::IllegalArgument);
2007         else
2008         {
2009             SCSIZE nC, nR;
2010             pJumpMatrix->GetPos( nC, nR);
2011             rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
2012             rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
2013             rAdr.SetTab( rRange.aStart.Tab());
2014             bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
2015                 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
2016                 rAdr.Row() <= rRange.aEnd.Row();
2017             if ( !bOk )
2018                 SetError( FormulaError::NoValue);
2019         }
2020         return bOk;
2021     }
2022 
2023     bOk = ScCompiler::DoubleRefToPosSingleRefScalarCase(rRange, rAdr, aPos);
2024 
2025     if ( !bOk )
2026         SetError( FormulaError::NoValue );
2027     return bOk;
2028 }
2029 
2030 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
2031 {
2032     if (!pMat)
2033         return 0.0;
2034 
2035     if ( !pJumpMatrix )
2036     {
2037         double fVal = pMat->GetDoubleWithStringConversion( 0, 0);
2038         FormulaError nErr = GetDoubleErrorValue( fVal);
2039         if (nErr != FormulaError::NONE)
2040         {
2041             // Do not propagate the coded double error, but set nGlobalError in
2042             // case the matrix did not have an error interpreter set.
2043             SetError( nErr);
2044             fVal = 0.0;
2045         }
2046         return fVal;
2047     }
2048 
2049     SCSIZE nCols, nRows, nC, nR;
2050     pMat->GetDimensions( nCols, nRows);
2051     pJumpMatrix->GetPos( nC, nR);
2052     // Use vector replication for single row/column arrays.
2053     if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2054     {
2055         double fVal = pMat->GetDoubleWithStringConversion( nC, nR);
2056         FormulaError nErr = GetDoubleErrorValue( fVal);
2057         if (nErr != FormulaError::NONE)
2058         {
2059             // Do not propagate the coded double error, but set nGlobalError in
2060             // case the matrix did not have an error interpreter set.
2061             SetError( nErr);
2062             fVal = 0.0;
2063         }
2064         return fVal;
2065     }
2066 
2067     SetError( FormulaError::NoValue);
2068     return 0.0;
2069 }
2070 
2071 double ScInterpreter::GetDouble()
2072 {
2073     double nVal(0.0);
2074     switch( GetRawStackType() )
2075     {
2076         case svDouble:
2077             nVal = PopDouble();
2078         break;
2079         case svString:
2080             nVal = ConvertStringToValue( PopString().getString());
2081         break;
2082         case svSingleRef:
2083         {
2084             ScAddress aAdr;
2085             PopSingleRef( aAdr );
2086             ScRefCellValue aCell(*pDok, aAdr);
2087             nVal = GetCellValue(aAdr, aCell);
2088         }
2089         break;
2090         case svDoubleRef:
2091         {   // generate position dependent SingleRef
2092             ScRange aRange;
2093             PopDoubleRef( aRange );
2094             ScAddress aAdr;
2095             if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) )
2096             {
2097                 ScRefCellValue aCell(*pDok, aAdr);
2098                 nVal = GetCellValue(aAdr, aCell);
2099             }
2100             else
2101                 nVal = 0.0;
2102         }
2103         break;
2104         case svExternalSingleRef:
2105         {
2106             ScExternalRefCache::TokenRef pToken;
2107             PopExternalSingleRef(pToken);
2108             if (nGlobalError == FormulaError::NONE)
2109             {
2110                 if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell)
2111                     nVal = pToken->GetDouble();
2112                 else
2113                     nVal = ConvertStringToValue( pToken->GetString().getString());
2114             }
2115         }
2116         break;
2117         case svExternalDoubleRef:
2118         {
2119             ScMatrixRef pMat;
2120             PopExternalDoubleRef(pMat);
2121             if (nGlobalError != FormulaError::NONE)
2122                 break;
2123 
2124             nVal = GetDoubleFromMatrix(pMat);
2125         }
2126         break;
2127         case svMatrix:
2128         {
2129             ScMatrixRef pMat = PopMatrix();
2130             nVal = GetDoubleFromMatrix(pMat);
2131         }
2132         break;
2133         case svError:
2134             PopError();
2135             nVal = 0.0;
2136         break;
2137         case svEmptyCell:
2138         case svMissing:
2139             Pop();
2140             nVal = 0.0;
2141         break;
2142         default:
2143             PopError();
2144             SetError( FormulaError::IllegalParameter);
2145             nVal = 0.0;
2146     }
2147     if ( nFuncFmtType == nCurFmtType )
2148         nFuncFmtIndex = nCurFmtIndex;
2149     return nVal;
2150 }
2151 
2152 double ScInterpreter::GetDoubleWithDefault(double nDefault)
2153 {
2154     bool bMissing = IsMissing();
2155     double nResultVal = GetDouble();
2156     if ( bMissing )
2157         nResultVal = nDefault;
2158     return nResultVal;
2159 }
2160 
2161 sal_Int32 ScInterpreter::double_to_int32(double fVal)
2162 {
2163     if (!rtl::math::isFinite(fVal))
2164     {
2165         SetError( GetDoubleErrorValue( fVal));
2166         return SAL_MAX_INT32;
2167     }
2168     if (fVal > 0.0)
2169     {
2170         fVal = rtl::math::approxFloor( fVal);
2171         if (fVal > SAL_MAX_INT32)
2172         {
2173             SetError( FormulaError::IllegalArgument);
2174             return SAL_MAX_INT32;
2175         }
2176     }
2177     else if (fVal < 0.0)
2178     {
2179         fVal = rtl::math::approxCeil( fVal);
2180         if (fVal < SAL_MIN_INT32)
2181         {
2182             SetError( FormulaError::IllegalArgument);
2183             return SAL_MAX_INT32;
2184         }
2185     }
2186     return static_cast<sal_Int32>(fVal);
2187 }
2188 
2189 sal_Int32 ScInterpreter::GetInt32()
2190 {
2191     return double_to_int32(GetDouble());
2192 }
2193 
2194 sal_Int32 ScInterpreter::GetInt32WithDefault( sal_Int32 nDefault )
2195 {
2196     bool bMissing = IsMissing();
2197     double fVal = GetDouble();
2198     if ( bMissing )
2199         return nDefault;
2200     return double_to_int32(fVal);
2201 }
2202 
2203 sal_Int16 ScInterpreter::GetInt16()
2204 {
2205     double fVal = GetDouble();
2206     if (!rtl::math::isFinite(fVal))
2207     {
2208         SetError( GetDoubleErrorValue( fVal));
2209         return SAL_MAX_INT16;
2210     }
2211     if (fVal > 0.0)
2212     {
2213         fVal = rtl::math::approxFloor( fVal);
2214         if (fVal > SAL_MAX_INT16)
2215         {
2216             SetError( FormulaError::IllegalArgument);
2217             return SAL_MAX_INT16;
2218         }
2219     }
2220     else if (fVal < 0.0)
2221     {
2222         fVal = rtl::math::approxCeil( fVal);
2223         if (fVal < SAL_MIN_INT16)
2224         {
2225             SetError( FormulaError::IllegalArgument);
2226             return SAL_MAX_INT16;
2227         }
2228     }
2229     return static_cast<sal_Int16>(fVal);
2230 }
2231 
2232 sal_uInt32 ScInterpreter::GetUInt32()
2233 {
2234     double fVal = rtl::math::approxFloor( GetDouble());
2235     if (!rtl::math::isFinite(fVal))
2236     {
2237         SetError( GetDoubleErrorValue( fVal));
2238         return SAL_MAX_UINT32;
2239     }
2240     if (fVal < 0.0 || fVal > SAL_MAX_UINT32)
2241     {
2242         SetError( FormulaError::IllegalArgument);
2243         return SAL_MAX_UINT32;
2244     }
2245     return static_cast<sal_uInt32>(fVal);
2246 }
2247 
2248 bool ScInterpreter::GetDoubleOrString( double& rDouble, svl::SharedString& rString )
2249 {
2250     bool bDouble = true;
2251     switch( GetRawStackType() )
2252     {
2253         case svDouble:
2254             rDouble = PopDouble();
2255         break;
2256         case svString:
2257             rString = PopString();
2258             bDouble = false;
2259         break;
2260         case svDoubleRef :
2261         case svSingleRef :
2262         {
2263             ScAddress aAdr;
2264             if (!PopDoubleRefOrSingleRef( aAdr))
2265             {
2266                 rDouble = 0.0;
2267                 return true;    // caller needs to check nGlobalError
2268             }
2269             ScRefCellValue aCell( *pDok, aAdr);
2270             if (aCell.hasNumeric())
2271             {
2272                 rDouble = GetCellValue( aAdr, aCell);
2273             }
2274             else
2275             {
2276                 GetCellString( rString, aCell);
2277                 bDouble = false;
2278             }
2279         }
2280         break;
2281         case svExternalSingleRef:
2282         case svExternalDoubleRef:
2283         case svMatrix:
2284         {
2285             ScMatValType nType = GetDoubleOrStringFromMatrix( rDouble, rString);
2286             bDouble = ScMatrix::IsValueType( nType);
2287         }
2288         break;
2289         case svError:
2290             PopError();
2291             rDouble = 0.0;
2292         break;
2293         case svEmptyCell:
2294         case svMissing:
2295             Pop();
2296             rDouble = 0.0;
2297         break;
2298         default:
2299             PopError();
2300             SetError( FormulaError::IllegalParameter);
2301             rDouble = 0.0;
2302     }
2303     if ( nFuncFmtType == nCurFmtType )
2304         nFuncFmtIndex = nCurFmtIndex;
2305     return bDouble;
2306 }
2307 
2308 svl::SharedString ScInterpreter::GetString()
2309 {
2310     switch (GetRawStackType())
2311     {
2312         case svError:
2313             PopError();
2314             return svl::SharedString::getEmptyString();
2315         case svMissing:
2316         case svEmptyCell:
2317             Pop();
2318             return svl::SharedString::getEmptyString();
2319         case svDouble:
2320         {
2321             return GetStringFromDouble( PopDouble() );
2322         }
2323         case svString:
2324             return PopString();
2325         case svSingleRef:
2326         {
2327             ScAddress aAdr;
2328             PopSingleRef( aAdr );
2329             if (nGlobalError == FormulaError::NONE)
2330             {
2331                 ScRefCellValue aCell(*pDok, aAdr);
2332                 svl::SharedString aSS;
2333                 GetCellString(aSS, aCell);
2334                 return aSS;
2335             }
2336             else
2337                 return svl::SharedString::getEmptyString();
2338         }
2339         case svDoubleRef:
2340         {   // generate position dependent SingleRef
2341             ScRange aRange;
2342             PopDoubleRef( aRange );
2343             ScAddress aAdr;
2344             if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) )
2345             {
2346                 ScRefCellValue aCell(*pDok, aAdr);
2347                 svl::SharedString aSS;
2348                 GetCellString(aSS, aCell);
2349                 return aSS;
2350             }
2351             else
2352                 return svl::SharedString::getEmptyString();
2353         }
2354         case svExternalSingleRef:
2355         {
2356             ScExternalRefCache::TokenRef pToken;
2357             PopExternalSingleRef(pToken);
2358             if (nGlobalError != FormulaError::NONE)
2359                 return svl::SharedString::getEmptyString();
2360 
2361             if (pToken->GetType() == svDouble)
2362             {
2363                 return GetStringFromDouble( pToken->GetDouble() );
2364             }
2365             else // svString or svEmpty
2366                 return pToken->GetString();
2367         }
2368         case svExternalDoubleRef:
2369         {
2370             ScMatrixRef pMat;
2371             PopExternalDoubleRef(pMat);
2372             return GetStringFromMatrix(pMat);
2373         }
2374         case svMatrix:
2375         {
2376             ScMatrixRef pMat = PopMatrix();
2377             return GetStringFromMatrix(pMat);
2378         }
2379         break;
2380         default:
2381             PopError();
2382             SetError( FormulaError::IllegalArgument);
2383     }
2384     return svl::SharedString::getEmptyString();
2385 }
2386 
2387 svl::SharedString ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2388 {
2389     if ( !pMat )
2390         ;   // nothing
2391     else if ( !pJumpMatrix )
2392     {
2393         return pMat->GetString( *pFormatter, 0, 0);
2394     }
2395     else
2396     {
2397         SCSIZE nCols, nRows, nC, nR;
2398         pMat->GetDimensions( nCols, nRows);
2399         pJumpMatrix->GetPos( nC, nR);
2400         // Use vector replication for single row/column arrays.
2401         if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2402             return pMat->GetString( *pFormatter, nC, nR);
2403 
2404         SetError( FormulaError::NoValue);
2405     }
2406     return svl::SharedString::getEmptyString();
2407 }
2408 
2409 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix(
2410     double& rDouble, svl::SharedString& rString )
2411 {
2412 
2413     rDouble = 0.0;
2414     rString = svl::SharedString::getEmptyString();
2415     ScMatValType nMatValType = ScMatValType::Empty;
2416 
2417     ScMatrixRef pMat;
2418     StackVar eType = GetStackType();
2419     if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
2420     {
2421         pMat = GetMatrix();
2422     }
2423     else
2424     {
2425         PopError();
2426         SetError( FormulaError::IllegalParameter);
2427         return nMatValType;
2428     }
2429 
2430     ScMatrixValue nMatVal;
2431     if (!pMat)
2432     {
2433         // nothing
2434     }
2435     else if (!pJumpMatrix)
2436     {
2437         nMatVal = pMat->Get(0, 0);
2438         nMatValType = nMatVal.nType;
2439     }
2440     else
2441     {
2442         SCSIZE nCols, nRows, nC, nR;
2443         pMat->GetDimensions( nCols, nRows);
2444         pJumpMatrix->GetPos( nC, nR);
2445         // Use vector replication for single row/column arrays.
2446         if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2447         {
2448             nMatVal = pMat->Get( nC, nR);
2449             nMatValType = nMatVal.nType;
2450         }
2451         else
2452             SetError( FormulaError::NoValue);
2453     }
2454 
2455     if (ScMatrix::IsValueType( nMatValType))
2456     {
2457         rDouble = nMatVal.fVal;
2458         FormulaError nError = nMatVal.GetError();
2459         if (nError != FormulaError::NONE)
2460             SetError( nError);
2461     }
2462     else
2463     {
2464         rString = nMatVal.GetString();
2465     }
2466 
2467     return nMatValType;
2468 }
2469 
2470 svl::SharedString ScInterpreter::GetStringFromDouble( double fVal )
2471 {
2472     sal_uLong nIndex = pFormatter->GetStandardFormat(
2473                         SvNumFormatType::NUMBER,
2474                         ScGlobal::eLnge);
2475     OUString aStr;
2476     pFormatter->GetInputLineString(fVal, nIndex, aStr);
2477     return mrStrPool.intern(aStr);
2478 }
2479 
2480 void ScInterpreter::ScDBGet()
2481 {
2482     bool bMissingField = false;
2483     unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2484     if (!pQueryParam)
2485     {
2486         // Failed to create query param.
2487         PushIllegalParameter();
2488         return;
2489     }
2490 
2491     pQueryParam->mbSkipString = false;
2492     ScDBQueryDataIterator aValIter(pDok, mrContext, std::move(pQueryParam));
2493     ScDBQueryDataIterator::Value aValue;
2494     if (!aValIter.GetFirst(aValue) || aValue.mnError != FormulaError::NONE)
2495     {
2496         // No match found.
2497         PushNoValue();
2498         return;
2499     }
2500 
2501     ScDBQueryDataIterator::Value aValNext;
2502     if (aValIter.GetNext(aValNext) && aValNext.mnError == FormulaError::NONE)
2503     {
2504         // There should be only one unique match.
2505         PushIllegalArgument();
2506         return;
2507     }
2508 
2509     if (aValue.mbIsNumber)
2510         PushDouble(aValue.mfValue);
2511     else
2512         PushString(aValue.maString);
2513 }
2514 
2515 void ScInterpreter::ScExternal()
2516 {
2517     sal_uInt8 nParamCount = GetByte();
2518     OUString aUnoName;
2519     OUString aFuncName( ScGlobal::pCharClass->uppercase( pCur->GetExternal() ) );
2520     LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName);
2521     if (pLegacyFuncData)
2522     {
2523         // Old binary non-UNO add-in function.
2524         // NOTE: parameter count is 1-based with the 0th "parameter" being the
2525         // return value, included in pLegacyFuncDatat->GetParamCount()
2526         if (nParamCount < MAXFUNCPARAM && nParamCount == pLegacyFuncData->GetParamCount() - 1)
2527         {
2528             ParamType   eParamType[MAXFUNCPARAM];
2529             void*       ppParam[MAXFUNCPARAM];
2530             double      nVal[MAXFUNCPARAM];
2531             char*       pStr[MAXFUNCPARAM];
2532             sal_uInt8*  pCellArr[MAXFUNCPARAM];
2533             short       i;
2534 
2535             for (i = 0; i < MAXFUNCPARAM; i++)
2536             {
2537                 eParamType[i] = pLegacyFuncData->GetParamType(i);
2538                 ppParam[i] = nullptr;
2539                 nVal[i] = 0.0;
2540                 pStr[i] = nullptr;
2541                 pCellArr[i] = nullptr;
2542             }
2543 
2544             for (i = nParamCount; (i > 0) && (nGlobalError == FormulaError::NONE); i--)
2545             {
2546                 if (IsMissing())
2547                 {
2548                     // Old binary Add-In can't distinguish between missing
2549                     // omitted argument and 0 (or any other value). Force
2550                     // error.
2551                     SetError( FormulaError::ParameterExpected);
2552                     break;  // for
2553                 }
2554                 switch (eParamType[i])
2555                 {
2556                     case ParamType::PTR_DOUBLE :
2557                         {
2558                             nVal[i-1] = GetDouble();
2559                             ppParam[i] = &nVal[i-1];
2560                         }
2561                         break;
2562                     case ParamType::PTR_STRING :
2563                         {
2564                             OString aStr(OUStringToOString(GetString().getString(),
2565                                 osl_getThreadTextEncoding()));
2566                             if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2567                                 SetError( FormulaError::StringOverflow );
2568                             else
2569                             {
2570                                 pStr[i-1] = new char[ADDIN_MAXSTRLEN];
2571                                 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2572                                 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2573                                 ppParam[i] = pStr[i-1];
2574                             }
2575                         }
2576                         break;
2577                     case ParamType::PTR_DOUBLE_ARR :
2578                         {
2579                             SCCOL nCol1;
2580                             SCROW nRow1;
2581                             SCTAB nTab1;
2582                             SCCOL nCol2;
2583                             SCROW nRow2;
2584                             SCTAB nTab2;
2585                             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2586                             pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2587                             if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2588                                 SetError(FormulaError::CodeOverflow);
2589                             else
2590                                 ppParam[i] = pCellArr[i-1];
2591                         }
2592                         break;
2593                     case ParamType::PTR_STRING_ARR :
2594                         {
2595                             SCCOL nCol1;
2596                             SCROW nRow1;
2597                             SCTAB nTab1;
2598                             SCCOL nCol2;
2599                             SCROW nRow2;
2600                             SCTAB nTab2;
2601                             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2602                             pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2603                             if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2604                                 SetError(FormulaError::CodeOverflow);
2605                             else
2606                                 ppParam[i] = pCellArr[i-1];
2607                         }
2608                         break;
2609                     case ParamType::PTR_CELL_ARR :
2610                         {
2611                             SCCOL nCol1;
2612                             SCROW nRow1;
2613                             SCTAB nTab1;
2614                             SCCOL nCol2;
2615                             SCROW nRow2;
2616                             SCTAB nTab2;
2617                             PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2618                             pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2619                             if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2620                                 SetError(FormulaError::CodeOverflow);
2621                             else
2622                                 ppParam[i] = pCellArr[i-1];
2623                         }
2624                         break;
2625                     default :
2626                         SetError(FormulaError::IllegalParameter);
2627                         break;
2628                 }
2629             }
2630             while ( i-- )
2631                 Pop();      // In case of error (otherwise i==0) pop all parameters
2632 
2633             if (nGlobalError == FormulaError::NONE)
2634             {
2635                 if ( pLegacyFuncData->GetAsyncType() == ParamType::NONE )
2636                 {
2637                     switch ( eParamType[0] )
2638                     {
2639                         case ParamType::PTR_DOUBLE :
2640                         {
2641                             double nErg = 0.0;
2642                             ppParam[0] = &nErg;
2643                             pLegacyFuncData->Call(ppParam);
2644                             PushDouble(nErg);
2645                         }
2646                         break;
2647                         case ParamType::PTR_STRING :
2648                         {
2649                             std::unique_ptr<char[]> pcErg(new char[ADDIN_MAXSTRLEN]);
2650                             ppParam[0] = pcErg.get();
2651                             pLegacyFuncData->Call(ppParam);
2652                             OUString aUni( pcErg.get(), strlen(pcErg.get()), osl_getThreadTextEncoding() );
2653                             PushString( aUni );
2654                         }
2655                         break;
2656                         default:
2657                             PushError( FormulaError::UnknownState );
2658                     }
2659                 }
2660                 else
2661                 {
2662                     // enable asyncs after loading
2663                     pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
2664                     // assure identical handler with identical call?
2665                     double nErg = 0.0;
2666                     ppParam[0] = &nErg;
2667                     pLegacyFuncData->Call(ppParam);
2668                     sal_uLong nHandle = sal_uLong( nErg );
2669                     if ( nHandle >= 65536 )
2670                     {
2671                         ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2672                         if ( !pAs )
2673                         {
2674                             pAs = new ScAddInAsync(nHandle, pLegacyFuncData, pDok);
2675                             pMyFormulaCell->StartListening( *pAs );
2676                         }
2677                         else
2678                         {
2679                             pMyFormulaCell->StartListening( *pAs );
2680                             if ( !pAs->HasDocument( pDok ) )
2681                                 pAs->AddDocument( pDok );
2682                         }
2683                         if ( pAs->IsValid() )
2684                         {
2685                             switch ( pAs->GetType() )
2686                             {
2687                                 case ParamType::PTR_DOUBLE :
2688                                     PushDouble( pAs->GetValue() );
2689                                     break;
2690                                 case ParamType::PTR_STRING :
2691                                     PushString( pAs->GetString() );
2692                                     break;
2693                                 default:
2694                                     PushError( FormulaError::UnknownState );
2695                             }
2696                         }
2697                         else
2698                             PushNA();
2699                     }
2700                     else
2701                         PushNoValue();
2702                 }
2703             }
2704 
2705             for (i = 0; i < MAXFUNCPARAM; i++)
2706             {
2707                 delete[] pStr[i];
2708                 delete[] pCellArr[i];
2709             }
2710         }
2711         else
2712         {
2713             while( nParamCount-- > 0)
2714                 Pop();
2715             PushIllegalParameter();
2716         }
2717     }
2718     else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty()  )
2719     {
2720         //  bLocalFirst=false in FindFunction, cFunc should be the stored
2721         //  internal name
2722 
2723         ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2724 
2725         if ( !aCall.ValidParamCount() )
2726             SetError( FormulaError::IllegalParameter );
2727 
2728         if ( aCall.NeedsCaller() && GetError() == FormulaError::NONE )
2729         {
2730             SfxObjectShell* pShell = pDok->GetDocumentShell();
2731             if (pShell)
2732                 aCall.SetCallerFromObjectShell( pShell );
2733             else
2734             {
2735                 // use temporary model object (without document) to supply options
2736                 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2737                                     new ScDocOptionsObj( pDok->GetDocOptions() ) ) );
2738             }
2739         }
2740 
2741         short nPar = nParamCount;
2742         while ( nPar > 0 && GetError() == FormulaError::NONE )
2743         {
2744             --nPar;     // 0 .. (nParamCount-1)
2745 
2746             uno::Any aParam;
2747             if (IsMissing())
2748             {
2749                 // Add-In has to explicitly handle an omitted empty missing
2750                 // argument, do not default to anything like GetDouble() would
2751                 // do (e.g. 0).
2752                 Pop();
2753                 aCall.SetParam( nPar, aParam );
2754                 continue;   // while
2755             }
2756 
2757             StackVar nStackType = GetStackType();
2758             ScAddInArgumentType eType = aCall.GetArgType( nPar );
2759             switch (eType)
2760             {
2761                 case SC_ADDINARG_INTEGER:
2762                     {
2763                         sal_Int32 nVal = GetInt32();
2764                         if (nGlobalError == FormulaError::NONE)
2765                             aParam <<= nVal;
2766                     }
2767                     break;
2768 
2769                 case SC_ADDINARG_DOUBLE:
2770                     aParam <<= GetDouble();
2771                     break;
2772 
2773                 case SC_ADDINARG_STRING:
2774                     aParam <<= GetString().getString();
2775                     break;
2776 
2777                 case SC_ADDINARG_INTEGER_ARRAY:
2778                     switch( nStackType )
2779                     {
2780                         case svDouble:
2781                         case svString:
2782                         case svSingleRef:
2783                             {
2784                                 sal_Int32 nVal = GetInt32();
2785                                 if (nGlobalError == FormulaError::NONE)
2786                                 {
2787                                     uno::Sequence<sal_Int32> aInner( &nVal, 1 );
2788                                     uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2789                                     aParam <<= aOuter;
2790                                 }
2791                             }
2792                             break;
2793                         case svDoubleRef:
2794                             {
2795                                 ScRange aRange;
2796                                 PopDoubleRef( aRange );
2797                                 if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
2798                                     SetError(FormulaError::IllegalParameter);
2799                             }
2800                             break;
2801                         case svMatrix:
2802                             if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2803                                 SetError(FormulaError::IllegalParameter);
2804                             break;
2805                         default:
2806                             PopError();
2807                             SetError(FormulaError::IllegalParameter);
2808                     }
2809                     break;
2810 
2811                 case SC_ADDINARG_DOUBLE_ARRAY:
2812                     switch( nStackType )
2813                     {
2814                         case svDouble:
2815                         case svString:
2816                         case svSingleRef:
2817                             {
2818                                 double fVal = GetDouble();
2819                                 uno::Sequence<double> aInner( &fVal, 1 );
2820                                 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2821                                 aParam <<= aOuter;
2822                             }
2823                             break;
2824                         case svDoubleRef:
2825                             {
2826                                 ScRange aRange;
2827                                 PopDoubleRef( aRange );
2828                                 if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
2829                                     SetError(FormulaError::IllegalParameter);
2830                             }
2831                             break;
2832                         case svMatrix:
2833                             if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2834                                 SetError(FormulaError::IllegalParameter);
2835                             break;
2836                         default:
2837                             PopError();
2838                             SetError(FormulaError::IllegalParameter);
2839                     }
2840                     break;
2841 
2842                 case SC_ADDINARG_STRING_ARRAY:
2843                     switch( nStackType )
2844                     {
2845                         case svDouble:
2846                         case svString:
2847                         case svSingleRef:
2848                             {
2849                                 OUString aString = GetString().getString();
2850                                 uno::Sequence<OUString> aInner( &aString, 1 );
2851                                 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 );
2852                                 aParam <<= aOuter;
2853                             }
2854                             break;
2855                         case svDoubleRef:
2856                             {
2857                                 ScRange aRange;
2858                                 PopDoubleRef( aRange );
2859                                 if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
2860                                     SetError(FormulaError::IllegalParameter);
2861                             }
2862                             break;
2863                         case svMatrix:
2864                             if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter ))
2865                                 SetError(FormulaError::IllegalParameter);
2866                             break;
2867                         default:
2868                             PopError();
2869                             SetError(FormulaError::IllegalParameter);
2870                     }
2871                     break;
2872 
2873                 case SC_ADDINARG_MIXED_ARRAY:
2874                     switch( nStackType )
2875                     {
2876                         case svDouble:
2877                         case svString:
2878                         case svSingleRef:
2879                             {
2880                                 uno::Any aElem;
2881                                 if ( nStackType == svDouble )
2882                                     aElem <<= GetDouble();
2883                                 else if ( nStackType == svString )
2884                                     aElem <<= GetString().getString();
2885                                 else
2886                                 {
2887                                     ScAddress aAdr;
2888                                     if ( PopDoubleRefOrSingleRef( aAdr ) )
2889                                     {
2890                                         ScRefCellValue aCell(*pDok, aAdr);
2891                                         if (aCell.hasString())
2892                                         {
2893                                             svl::SharedString aStr;
2894                                             GetCellString(aStr, aCell);
2895                                             aElem <<= aStr.getString();
2896                                         }
2897                                         else
2898                                             aElem <<= GetCellValue(aAdr, aCell);
2899                                     }
2900                                 }
2901                                 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2902                                 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2903                                 aParam <<= aOuter;
2904                             }
2905                             break;
2906                         case svDoubleRef:
2907                             {
2908                                 ScRange aRange;
2909                                 PopDoubleRef( aRange );
2910                                 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2911                                     SetError(FormulaError::IllegalParameter);
2912                             }
2913                             break;
2914                         case svMatrix:
2915                             if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2916                                 SetError(FormulaError::IllegalParameter);
2917                             break;
2918                         default:
2919                             PopError();
2920                             SetError(FormulaError::IllegalParameter);
2921                     }
2922                     break;
2923 
2924                 case SC_ADDINARG_VALUE_OR_ARRAY:
2925                     switch( nStackType )
2926                     {
2927                         case svDouble:
2928                             aParam <<= GetDouble();
2929                             break;
2930                         case svString:
2931                             aParam <<= GetString().getString();
2932                             break;
2933                         case svSingleRef:
2934                             {
2935                                 ScAddress aAdr;
2936                                 if ( PopDoubleRefOrSingleRef( aAdr ) )
2937                                 {
2938                                     ScRefCellValue aCell(*pDok, aAdr);
2939                                     if (aCell.hasString())
2940                                     {
2941                                         svl::SharedString aStr;
2942                                         GetCellString(aStr, aCell);
2943                                         aParam <<= aStr.getString();
2944                                     }
2945                                     else
2946                                         aParam <<= GetCellValue(aAdr, aCell);
2947                                 }
2948                             }
2949                             break;
2950                         case svDoubleRef:
2951                             {
2952                                 ScRange aRange;
2953                                 PopDoubleRef( aRange );
2954                                 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2955                                     SetError(FormulaError::IllegalParameter);
2956                             }
2957                             break;
2958                         case svMatrix:
2959                             if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2960                                 SetError(FormulaError::IllegalParameter);
2961                             break;
2962                         default:
2963                             PopError();
2964                             SetError(FormulaError::IllegalParameter);
2965                     }
2966                     break;
2967 
2968                 case SC_ADDINARG_CELLRANGE:
2969                     switch( nStackType )
2970                     {
2971                         case svSingleRef:
2972                             {
2973                                 ScAddress aAdr;
2974                                 PopSingleRef( aAdr );
2975                                 ScRange aRange( aAdr );
2976                                 uno::Reference<table::XCellRange> xObj =
2977                                         ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2978                                 if (xObj.is())
2979                                     aParam <<= xObj;
2980                                 else
2981                                     SetError(FormulaError::IllegalParameter);
2982                             }
2983                             break;
2984                         case svDoubleRef:
2985                             {
2986                                 ScRange aRange;
2987                                 PopDoubleRef( aRange );
2988                                 uno::Reference<table::XCellRange> xObj =
2989                                         ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2990                                 if (xObj.is())
2991                                 {
2992                                     aParam <<= xObj;
2993                                 }
2994                                 else
2995                                 {
2996                                     SetError(FormulaError::IllegalParameter);
2997                                 }
2998                             }
2999                             break;
3000                         default:
3001                             PopError();
3002                             SetError(FormulaError::IllegalParameter);
3003                     }
3004                     break;
3005 
3006                 default:
3007                     PopError();
3008                     SetError(FormulaError::IllegalParameter);
3009             }
3010             aCall.SetParam( nPar, aParam );
3011         }
3012 
3013         while (nPar-- > 0)
3014         {
3015             Pop();                  // in case of error, remove remaining args
3016         }
3017         if ( GetError() == FormulaError::NONE )
3018         {
3019             aCall.ExecuteCall();
3020 
3021             if ( aCall.HasVarRes() )                        // handle async functions
3022             {
3023                 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
3024                 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3025                 ScAddInListener* pLis = ScAddInListener::Get( xRes );
3026                 // In case there is no pMyFormulaCell, i.e. while interpreting
3027                 // temporarily from within the Function Wizard, try to obtain a
3028                 // valid result from an existing listener for that volatile, or
3029                 // create a new and hope for an immediate result. If none
3030                 // available that should lead to a void result and thus #N/A.
3031                 bool bTemporaryListener = false;
3032                 if ( !pLis )
3033                 {
3034                     pLis = ScAddInListener::CreateListener( xRes, pDok );
3035                     if (pMyFormulaCell)
3036                         pMyFormulaCell->StartListening( *pLis );
3037                     else
3038                         bTemporaryListener = true;
3039                 }
3040                 else if (pMyFormulaCell)
3041                 {
3042                     pMyFormulaCell->StartListening( *pLis );
3043                     if ( !pLis->HasDocument( pDok ) )
3044                     {
3045                         pLis->AddDocument( pDok );
3046                     }
3047                 }
3048 
3049                 aCall.SetResult( pLis->GetResult() );       // use result from async
3050 
3051                 if (bTemporaryListener)
3052                 {
3053                     try
3054                     {
3055                         // EventObject can be any, not evaluated by
3056                         // ScAddInListener::disposing()
3057                         css::lang::EventObject aEvent;
3058                         pLis->disposing(aEvent);    // pLis is dead hereafter
3059                     }
3060                     catch (const uno::Exception&)
3061                     {
3062                     }
3063                 }
3064             }
3065 
3066             if ( aCall.GetErrCode() != FormulaError::NONE )
3067             {
3068                 PushError( aCall.GetErrCode() );
3069             }
3070             else if ( aCall.HasMatrix() )
3071             {
3072                 PushMatrix( aCall.GetMatrix() );
3073             }
3074             else if ( aCall.HasString() )
3075             {
3076                 PushString( aCall.GetString() );
3077             }
3078             else
3079             {
3080                 PushDouble( aCall.GetValue() );
3081             }
3082         }
3083         else                // error...
3084             PushError( GetError());
3085     }
3086     else
3087     {
3088         while( nParamCount-- > 0)
3089         {
3090             Pop();
3091         }
3092         PushError( FormulaError::NoAddin );
3093     }
3094 }
3095 
3096 void ScInterpreter::ScMissing()
3097 {
3098     if ( aCode.IsEndOfPath() )
3099         PushTempToken( new ScEmptyCellToken( false, false ) );
3100     else
3101         PushTempToken( new FormulaMissingToken );
3102 }
3103 
3104 #if HAVE_FEATURE_SCRIPTING
3105 
3106 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, const ScDocument* pDok )
3107 {
3108     uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3109     uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
3110     OUString sCodeName;
3111     xProps->getPropertyValue("CodeName") >>= sCodeName;
3112     // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3113     // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3114     // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3115     // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3116     // create the special document module objects if they don't exist.
3117     BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3118 
3119     uno::Reference< uno::XInterface > xIf;
3120     if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
3121     {
3122         OUString sProj( "Standard" );
3123         if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3124         {
3125             sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
3126         }
3127         StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3128         if ( pBasic )
3129         {
3130             SbModule* pMod = pBasic->FindModule( sCodeName );
3131             if ( pMod )
3132             {
3133                 xIf = pMod->GetUnoModule();
3134             }
3135         }
3136     }
3137     return uno::makeAny( xIf );
3138 }
3139 
3140 static bool lcl_setVBARange( const ScRange& aRange, const ScDocument* pDok, SbxVariable* pPar )
3141 {
3142     bool bOk = false;
3143     try
3144     {
3145         uno::Reference< uno::XInterface > xVBARange;
3146         uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
3147         uno::Sequence< uno::Any > aArgs(2);
3148         aArgs[0] = lcl_getSheetModule( xCellRange, pDok );
3149         aArgs[1] <<= xCellRange;
3150         xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
3151         if ( xVBARange.is() )
3152         {
3153             SbxObjectRef aObj = GetSbUnoObject( "A-Range", uno::Any( xVBARange ) );
3154             SetSbUnoObjectDfltPropName( aObj.get() );
3155             bOk = pPar->PutObject( aObj.get() );
3156         }
3157     }
3158     catch( uno::Exception& )
3159     {
3160     }
3161     return bOk;
3162 }
3163 
3164 static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar )
3165 {
3166     switch (pVar->GetType())
3167     {
3168         case SbxINTEGER:
3169         case SbxLONG:
3170         case SbxSINGLE:
3171         case SbxDOUBLE:
3172         case SbxCURRENCY:
3173         case SbxDATE:
3174         case SbxUSHORT:
3175         case SbxULONG:
3176         case SbxINT:
3177         case SbxUINT:
3178         case SbxSALINT64:
3179         case SbxSALUINT64:
3180         case SbxDECIMAL:
3181             fVal = pVar->GetDouble();
3182             return true;
3183         case SbxBOOL:
3184             fVal = (pVar->GetBool() ? 1.0 : 0.0);
3185             return true;
3186         default:
3187             ;   // nothing
3188     }
3189     return false;
3190 }
3191 
3192 #endif
3193 
3194 void ScInterpreter::ScMacro()
3195 {
3196 
3197 #if !HAVE_FEATURE_SCRIPTING
3198     PushNoValue();      // without DocShell no CallBasic
3199     return;
3200 #else
3201     SbxBase::ResetError();
3202 
3203     sal_uInt8 nParamCount = GetByte();
3204     OUString aMacro( pCur->GetExternal() );
3205 
3206     SfxObjectShell* pDocSh = pDok->GetDocumentShell();
3207     if ( !pDocSh )
3208     {
3209         PushNoValue();      // without DocShell no CallBasic
3210         return;
3211     }
3212 
3213     //  no security queue beforehand (just CheckMacroWarn), moved to  CallBasic
3214 
3215     //  If the  Dok was loaded during a Basic-Calls,
3216     //  is the  Sbx-object created(?)
3217 //  pDocSh->GetSbxObject();
3218 
3219     //  search function with the name,
3220     //  then assemble  SfxObjectShell::CallBasic from aBasicStr, aMacroStr
3221 
3222     StarBASIC* pRoot;
3223 
3224     try
3225     {
3226         pRoot = pDocSh->GetBasic();
3227     }
3228     catch (...)
3229     {
3230         pRoot = nullptr;
3231     }
3232 
3233     SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr;
3234     if( !pVar || pVar->GetType() == SbxVOID || dynamic_cast<const SbMethod*>( pVar) ==  nullptr )
3235     {
3236         PushError( FormulaError::NoMacro );
3237         return;
3238     }
3239 
3240     bool bVolatileMacro = false;
3241     SbMethod* pMethod = static_cast<SbMethod*>(pVar);
3242 
3243     SbModule* pModule = pMethod->GetModule();
3244     bool bUseVBAObjects = pModule->IsVBACompat();
3245     SbxObject* pObject = pModule->GetParent();
3246     OSL_ENSURE(dynamic_cast<const StarBASIC *>(pObject) != nullptr, "No Basic found!");
3247     OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName();
3248     OUString aBasicStr;
3249     if (pRoot && bUseVBAObjects)
3250     {
3251         // just here to make sure the VBA objects when we run the macro during ODF import
3252         pRoot->getVBAGlobals();
3253     }
3254     if (pObject->GetParent())
3255     {
3256         aBasicStr = pObject->GetParent()->GetName();    // document BASIC
3257     }
3258     else
3259     {
3260         aBasicStr = SfxGetpApp()->GetName();            // application BASIC
3261     }
3262     //  assemble a parameter array
3263 
3264     SbxArrayRef refPar = new SbxArray;
3265     bool bOk = true;
3266     for( sal_uInt32 i = nParamCount; i && bOk ; i-- )
3267     {
3268         SbxVariable* pPar = refPar->Get32(i);
3269         switch( GetStackType() )
3270         {
3271             case svDouble:
3272                 pPar->PutDouble( GetDouble() );
3273             break;
3274             case svString:
3275                 pPar->PutString( GetString().getString() );
3276             break;
3277             case svExternalSingleRef:
3278             {
3279                 ScExternalRefCache::TokenRef pToken;
3280                 PopExternalSingleRef(pToken);
3281                 if (nGlobalError != FormulaError::NONE)
3282                     bOk = false;
3283                 else
3284                 {
3285                     if ( pToken->GetType() == svString )
3286                         pPar->PutString( pToken->GetString().getString() );
3287                     else if ( pToken->GetType() == svDouble )
3288                         pPar->PutDouble( pToken->GetDouble() );
3289                     else
3290                     {
3291                         SetError( FormulaError::IllegalArgument );
3292                         bOk = false;
3293                     }
3294                 }
3295             }
3296             break;
3297             case svSingleRef:
3298             {
3299                 ScAddress aAdr;
3300                 PopSingleRef( aAdr );
3301                 if ( bUseVBAObjects )
3302                 {
3303                     ScRange aRange( aAdr );
3304                     bOk = lcl_setVBARange( aRange, pDok, pPar );
3305                 }
3306                 else
3307                 {
3308                     bOk = SetSbxVariable( pPar, aAdr );
3309                 }
3310             }
3311             break;
3312             case svDoubleRef:
3313             {
3314                 SCCOL nCol1;
3315                 SCROW nRow1;
3316                 SCTAB nTab1;
3317                 SCCOL nCol2;
3318                 SCROW nRow2;
3319                 SCTAB nTab2;
3320                 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3321                 if( nTab1 != nTab2 )
3322                 {
3323                     SetError( FormulaError::IllegalParameter );
3324                     bOk = false;
3325                 }
3326                 else
3327                 {
3328                     if ( bUseVBAObjects )
3329                     {
3330                         ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3331                         bOk = lcl_setVBARange( aRange, pDok, pPar );
3332                     }
3333                     else
3334                     {
3335                         SbxDimArrayRef refArray = new SbxDimArray;
3336                         refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
3337                         refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
3338                         ScAddress aAdr( nCol1, nRow1, nTab1 );
3339                         for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3340                         {
3341                             aAdr.SetRow( nRow );
3342                             sal_Int32 nIdx[ 2 ];
3343                             nIdx[ 0 ] = nRow-nRow1+1;
3344                             for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3345                             {
3346                                 aAdr.SetCol( nCol );
3347                                 nIdx[ 1 ] = nCol-nCol1+1;
3348                                 SbxVariable* p = refArray->Get32( nIdx );
3349                                 bOk = SetSbxVariable( p, aAdr );
3350                             }
3351                         }
3352                         pPar->PutObject( refArray.get() );
3353                     }
3354                 }
3355             }
3356             break;
3357             case svExternalDoubleRef:
3358             case svMatrix:
3359             {
3360                 ScMatrixRef pMat = GetMatrix();
3361                 SCSIZE nC, nR;
3362                 if (pMat && nGlobalError == FormulaError::NONE)
3363                 {
3364                     pMat->GetDimensions(nC, nR);
3365                     SbxDimArrayRef refArray = new SbxDimArray;
3366                     refArray->AddDim32( 1, static_cast<sal_Int32>(nR) );
3367                     refArray->AddDim32( 1, static_cast<sal_Int32>(nC) );
3368                     for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3369                     {
3370                         sal_Int32 nIdx[ 2 ];
3371                         nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3372                         for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3373                         {
3374                             nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3375                             SbxVariable* p = refArray->Get32( nIdx );
3376                             if (pMat->IsStringOrEmpty(nMatCol, nMatRow))
3377                             {
3378                                 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() );
3379                             }
3380                             else
3381                             {
3382                                 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3383                             }
3384                         }
3385                     }
3386                     pPar->PutObject( refArray.get() );
3387                 }
3388                 else
3389                 {
3390                     SetError( FormulaError::IllegalParameter );
3391                 }
3392             }
3393             break;
3394             default:
3395                 SetError( FormulaError::IllegalParameter );
3396                 bOk = false;
3397         }
3398     }
3399     if( bOk )
3400     {
3401         pDok->LockTable( aPos.Tab() );
3402         SbxVariableRef refRes = new SbxVariable;
3403         pDok->IncMacroInterpretLevel();
3404         ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar.get(), refRes.get() );
3405         pDok->DecMacroInterpretLevel();
3406         pDok->UnlockTable( aPos.Tab() );
3407 
3408         ScMacroManager* pMacroMgr = pDok->GetMacroManager();
3409         if (pMacroMgr)
3410         {
3411             bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3412             pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3413         }
3414 
3415         double fVal;
3416         SbxDataType eResType = refRes->GetType();
3417         if( SbxBase::GetError() )
3418         {
3419             SetError( FormulaError::NoValue);
3420         }
3421         if ( eRet != ERRCODE_NONE )
3422         {
3423             PushNoValue();
3424         }
3425         else if (lcl_isNumericResult( fVal, refRes.get()))
3426         {
3427             switch (eResType)
3428             {
3429                 case SbxDATE:
3430                     nFuncFmtType = SvNumFormatType::DATE;
3431                 break;
3432                 case SbxBOOL:
3433                     nFuncFmtType = SvNumFormatType::LOGICAL;
3434                 break;
3435                 // Do not add SbxCURRENCY, we don't know which currency.
3436                 default:
3437                     ;   // nothing
3438             }
3439             PushDouble( fVal );
3440         }
3441         else if ( eResType & SbxARRAY )
3442         {
3443             SbxBase* pElemObj = refRes->GetObject();
3444             SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>(pElemObj);
3445             sal_Int32 nDim = pDimArray ? pDimArray->GetDims32() : 0;
3446             if ( 1 <= nDim && nDim <= 2 )
3447             {
3448                 sal_Int32 nCs, nCe, nRs, nRe;
3449                 SCSIZE nC, nR;
3450                 SCCOL nColIdx;
3451                 SCROW nRowIdx;
3452                 if ( nDim == 1 )
3453                 {   // array( cols )  one line, several columns
3454                     pDimArray->GetDim32( 1, nCs, nCe );
3455                     nC = static_cast<SCSIZE>(nCe - nCs + 1);
3456                     nRs = nRe = 0;
3457                     nR = 1;
3458                     nColIdx = 0;
3459                     nRowIdx = 1;
3460                 }
3461                 else
3462                 {   // array( rows, cols )
3463                     pDimArray->GetDim32( 1, nRs, nRe );
3464                     nR = static_cast<SCSIZE>(nRe - nRs + 1);
3465                     pDimArray->GetDim32( 2, nCs, nCe );
3466                     nC = static_cast<SCSIZE>(nCe - nCs + 1);
3467                     nColIdx = 1;
3468                     nRowIdx = 0;
3469                 }
3470                 ScMatrixRef pMat = GetNewMat( nC, nR);
3471                 if ( pMat )
3472                 {
3473                     SbxVariable* pV;
3474                     for ( SCSIZE j=0; j < nR; j++ )
3475                     {
3476                         sal_Int32 nIdx[ 2 ];
3477                         //  in one-dimensional array( cols )  nIdx[1]
3478                         // from SbxDimArray::Get is ignored
3479                         nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3480                         for ( SCSIZE i=0; i < nC; i++ )
3481                         {
3482                             nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3483                             pV = pDimArray->Get32( nIdx );
3484                             if ( lcl_isNumericResult( fVal, pV) )
3485                             {
3486                                 pMat->PutDouble( fVal, i, j );
3487                             }
3488                             else
3489                             {
3490                                 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j);
3491                             }
3492                         }
3493                     }
3494                     PushMatrix( pMat );
3495                 }
3496                 else
3497                 {
3498                     PushIllegalArgument();
3499                 }
3500             }
3501             else
3502             {
3503                 PushNoValue();
3504             }
3505         }
3506         else
3507         {
3508             PushString( refRes->GetOUString() );
3509         }
3510     }
3511 
3512     if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3513         meVolatileType = VOLATILE_MACRO;
3514 #endif
3515 }
3516 
3517 #if HAVE_FEATURE_SCRIPTING
3518 
3519 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3520 {
3521     bool bOk = true;
3522     ScRefCellValue aCell(*pDok, rPos);
3523     if (!aCell.isEmpty())
3524     {
3525         FormulaError nErr;
3526         double nVal;
3527         switch (aCell.meType)
3528         {
3529             case CELLTYPE_VALUE :
3530                 nVal = GetValueCellValue(rPos, aCell.mfValue);
3531                 pVar->PutDouble( nVal );
3532             break;
3533             case CELLTYPE_STRING :
3534             case CELLTYPE_EDIT :
3535                 pVar->PutString(aCell.getString(pDok));
3536             break;
3537             case CELLTYPE_FORMULA :
3538                 nErr = aCell.mpFormula->GetErrCode();
3539                 if( nErr == FormulaError::NONE )
3540                 {
3541                     if (aCell.mpFormula->IsValue())
3542                     {
3543                         nVal = aCell.mpFormula->GetValue();
3544                         pVar->PutDouble( nVal );
3545                     }
3546                     else
3547                         pVar->PutString(aCell.mpFormula->GetString().getString());
3548                 }
3549                 else
3550                 {
3551                     SetError( nErr );
3552                     bOk = false;
3553                 }
3554                 break;
3555             default :
3556                 pVar->PutEmpty();
3557         }
3558     }
3559     else
3560         pVar->PutEmpty();
3561 
3562     return bOk;
3563 }
3564 
3565 #endif
3566 
3567 void ScInterpreter::ScTableOp()
3568 {
3569     sal_uInt8 nParamCount = GetByte();
3570     if (nParamCount != 3 && nParamCount != 5)
3571     {
3572         PushIllegalParameter();
3573         return;
3574     }
3575     std::unique_ptr<ScInterpreterTableOpParams> pTableOp(new ScInterpreterTableOpParams);
3576     if (nParamCount == 5)
3577     {
3578         PopSingleRef( pTableOp->aNew2 );
3579         PopSingleRef( pTableOp->aOld2 );
3580     }
3581     PopSingleRef( pTableOp->aNew1 );
3582     PopSingleRef( pTableOp->aOld1 );
3583     PopSingleRef( pTableOp->aFormulaPos );
3584 
3585     pTableOp->bValid = true;
3586     pDok->m_TableOpList.push_back(pTableOp.get());
3587     pDok->IncInterpreterTableOpLevel();
3588 
3589     bool bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp);
3590     if ( bReuseLastParams )
3591     {
3592         pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos;
3593         pTableOp->bRefresh = true;
3594         for ( const auto& rPos : pTableOp->aNotifiedFormulaPos )
3595         {   // emulate broadcast and indirectly collect cell pointers
3596             ScRefCellValue aCell(*pDok, rPos);
3597             if (aCell.meType == CELLTYPE_FORMULA)
3598                 aCell.mpFormula->SetTableOpDirty();
3599         }
3600     }
3601     else
3602     {   // broadcast and indirectly collect cell pointers and positions
3603         pDok->SetTableOpDirty( pTableOp->aOld1 );
3604         if ( nParamCount == 5 )
3605             pDok->SetTableOpDirty( pTableOp->aOld2 );
3606     }
3607     pTableOp->bCollectNotifications = false;
3608 
3609     ScRefCellValue aCell(*pDok, pTableOp->aFormulaPos);
3610     if (aCell.meType == CELLTYPE_FORMULA)
3611         aCell.mpFormula->SetDirtyVar();
3612     if (aCell.hasNumeric())
3613     {
3614         PushDouble(GetCellValue(pTableOp->aFormulaPos, aCell));
3615     }
3616     else
3617     {
3618         svl::SharedString aCellString;
3619         GetCellString(aCellString, aCell);
3620         PushString( aCellString );
3621     }
3622 
3623     auto const itr =
3624         ::std::find(pDok->m_TableOpList.begin(), pDok->m_TableOpList.end(), pTableOp.get());
3625     if (itr != pDok->m_TableOpList.end())
3626     {
3627         pDok->m_TableOpList.erase(itr);
3628     }
3629 
3630     // set dirty again once more to be able to recalculate original
3631     for ( const auto& pCell : pTableOp->aNotifiedFormulaCells )
3632     {
3633         pCell->SetTableOpDirty();
3634     }
3635 
3636     // save these params for next incarnation
3637     if ( !bReuseLastParams )
3638         pDok->aLastTableOpParams = *pTableOp;
3639 
3640     if (aCell.meType == CELLTYPE_FORMULA)
3641     {
3642         aCell.mpFormula->SetDirtyVar();
3643         aCell.mpFormula->GetErrCode();     // recalculate original
3644     }
3645 
3646     // Reset all dirty flags so next incarnation does really collect all cell
3647     // pointers during notifications and not just non-dirty ones, which may
3648     // happen if a formula cell is used by more than one TableOp block.
3649     for ( const auto& pCell : pTableOp->aNotifiedFormulaCells )
3650     {
3651         pCell->ResetTableOpDirtyVar();
3652     }
3653     pTableOp.reset();
3654 
3655     pDok->DecInterpreterTableOpLevel();
3656 }
3657 
3658 void ScInterpreter::ScDBArea()
3659 {
3660     ScDBData* pDBData = pDok->GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3661     if (pDBData)
3662     {
3663         ScComplexRefData aRefData;
3664         aRefData.InitFlags();
3665         ScRange aRange;
3666         pDBData->GetArea(aRange);
3667         aRange.aEnd.SetTab(aRange.aStart.Tab());
3668         aRefData.SetRange(pDok->GetSheetLimits(), aRange, aPos);
3669         PushTempToken( new ScDoubleRefToken( pDok->GetSheetLimits(), aRefData ) );
3670     }
3671     else
3672         PushError( FormulaError::NoName);
3673 }
3674 
3675 void ScInterpreter::ScColRowNameAuto()
3676 {
3677     ScComplexRefData aRefData( *pCur->GetDoubleRef() );
3678     ScRange aAbs = aRefData.toAbs(pDok, aPos);
3679     if (!pDok->ValidRange(aAbs))
3680     {
3681         PushError( FormulaError::NoRef );
3682         return;
3683     }
3684 
3685     SCCOL nStartCol;
3686     SCROW nStartRow;
3687 
3688     // maybe remember limit by using defined ColRowNameRange
3689     SCCOL nCol2 = aAbs.aEnd.Col();
3690     SCROW nRow2 = aAbs.aEnd.Row();
3691     // DataArea of the first cell
3692     nStartCol = aAbs.aStart.Col();
3693     nStartRow = aAbs.aStart.Row();
3694     aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell.
3695 
3696     {
3697         // Expand to the data area. Only modify the end position.
3698         SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col();
3699         SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row();
3700         pDok->GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false);
3701         aAbs.aEnd.SetCol(nDACol2);
3702         aAbs.aEnd.SetRow(nDARow2);
3703     }
3704 
3705     // corresponds with ScCompiler::GetToken
3706     if ( aRefData.Ref1.IsColRel() )
3707     {   // ColName
3708         aAbs.aEnd.SetCol(nStartCol);
3709         // maybe get previous limit by using defined ColRowNameRange
3710         if (aAbs.aEnd.Row() > nRow2)
3711             aAbs.aEnd.SetRow(nRow2);
3712         SCROW nMyRow;
3713         if ( aPos.Col() == nStartCol
3714           && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aAbs.aEnd.Row())
3715         {   //Formula in the same column and within the range
3716             if ( nMyRow == nStartRow )
3717             {   // take the rest under the name
3718                 nStartRow++;
3719                 if ( nStartRow > pDok->MaxRow() )
3720                     nStartRow = pDok->MaxRow();
3721                 aAbs.aStart.SetRow(nStartRow);
3722             }
3723             else
3724             {   // below the name to the formula cell
3725                 aAbs.aEnd.SetRow(nMyRow - 1);
3726             }
3727         }
3728     }
3729     else
3730     {   // RowName
3731         aAbs.aEnd.SetRow(nStartRow);
3732         // maybe get previous limit by using defined ColRowNameRange
3733         if (aAbs.aEnd.Col() > nCol2)
3734             aAbs.aEnd.SetCol(nCol2);
3735         SCCOL nMyCol;
3736         if ( aPos.Row() == nStartRow
3737           && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aAbs.aEnd.Col())
3738         {   //Formula in the same column and within the range
3739             if ( nMyCol == nStartCol )
3740             {    // take the rest under the name
3741                 nStartCol++;
3742                 if ( nStartCol > pDok->MaxCol() )
3743                     nStartCol = pDok->MaxCol();
3744                 aAbs.aStart.SetCol(nStartCol);
3745             }
3746             else
3747             {   // below the name to the formula cell
3748                 aAbs.aEnd.SetCol(nMyCol - 1);
3749             }
3750         }
3751     }
3752     aRefData.SetRange(pDok->GetSheetLimits(), aAbs, aPos);
3753     PushTempToken( new ScDoubleRefToken( pDok->GetSheetLimits(), aRefData ) );
3754 }
3755 
3756 // --- internals ------------------------------------------------------------
3757 
3758 void ScInterpreter::ScTTT()
3759 {   // temporary test, testing functions etc.
3760     sal_uInt8 nParamCount = GetByte();
3761     // do something, count down nParamCount with Pops!
3762 
3763     // clean up Stack
3764     while ( nParamCount-- > 0)
3765         Pop();
3766     PushError(FormulaError::NoValue);
3767 }
3768 
3769 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext,
3770         const ScAddress& rPos, ScTokenArray& r, bool bForGroupThreading )
3771     : aCode(r)
3772     , aPos(rPos)
3773     , pArr(&r)
3774     , mrContext(rContext)
3775     , pDok(pDoc)
3776     , mpLinkManager(pDok->GetLinkManager())
3777     , mrStrPool(pDoc->GetSharedStringPool())
3778     , pJumpMatrix(nullptr)
3779     , pMyFormulaCell(pCell)
3780     , pFormatter(rContext.GetFormatTable())
3781     , pCur(nullptr)
3782     , nGlobalError(FormulaError::NONE)
3783     , sp(0)
3784     , maxsp(0)
3785     , nFuncFmtIndex(0)
3786     , nCurFmtIndex(0)
3787     , nRetFmtIndex(0)
3788     , nFuncFmtType(SvNumFormatType::ALL)
3789     , nCurFmtType(SvNumFormatType::ALL)
3790     , nRetFmtType(SvNumFormatType::ALL)
3791     , mnStringNoValueError(FormulaError::NoValue)
3792     , mnSubTotalFlags(SubtotalFlags::NONE)
3793     , cPar(0)
3794     , bCalcAsShown(pDoc->GetDocOptions().IsCalcAsShown())
3795     , meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3796 {
3797     MergeCalcConfig();
3798 
3799     if(pMyFormulaCell)
3800     {
3801         ScMatrixMode cMatFlag = pMyFormulaCell->GetMatrixFlag();
3802         bMatrixFormula = ( cMatFlag == ScMatrixMode::Formula );
3803     }
3804     else
3805         bMatrixFormula = false;
3806 
3807     // Lets not use the global stack while formula-group-threading.
3808     // as it complicates its life-cycle mgmt since for threading formula-groups,
3809     // ScInterpreter is preallocated (in main thread) for each worker thread.
3810     if (!bGlobalStackInUse && !bForGroupThreading)
3811     {
3812         bGlobalStackInUse = true;
3813         if (!pGlobalStack)
3814             pGlobalStack.reset(new ScTokenStack);
3815         pStackObj = pGlobalStack.get();
3816     }
3817     else
3818     {
3819         pStackObj = new ScTokenStack;
3820     }
3821     pStack = pStackObj->pPointer;
3822 }
3823 
3824 ScInterpreter::~ScInterpreter()
3825 {
3826     if ( pStackObj == pGlobalStack.get() )
3827         bGlobalStackInUse = false;
3828     else
3829         delete pStackObj;
3830 }
3831 
3832 void ScInterpreter::Init( ScFormulaCell* pCell, const ScAddress& rPos, ScTokenArray& rTokArray )
3833 {
3834     aCode.ReInit(rTokArray);
3835     aPos = rPos;
3836     pArr = &rTokArray;
3837     xResult = nullptr;
3838     pJumpMatrix = nullptr;
3839     pTokenMatrixMap.reset();
3840     pMyFormulaCell = pCell;
3841     pCur = nullptr;
3842     nGlobalError = FormulaError::NONE;
3843     sp = 0;
3844     maxsp = 0;
3845     nFuncFmtIndex = 0;
3846     nCurFmtIndex = 0;
3847     nRetFmtIndex = 0;
3848     nFuncFmtType = SvNumFormatType::ALL;
3849     nCurFmtType = SvNumFormatType::ALL;
3850     nRetFmtType = SvNumFormatType::ALL;
3851     mnStringNoValueError = FormulaError::NoValue;
3852     mnSubTotalFlags = SubtotalFlags::NONE;
3853     cPar = 0;
3854 }
3855 
3856 ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
3857 {
3858     if (!mpGlobalConfig)
3859         mpGlobalConfig = new ScCalcConfig();
3860     return *mpGlobalConfig;
3861 }
3862 
3863 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3864 {
3865     GetOrCreateGlobalConfig() = rConfig;
3866 }
3867 
3868 const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3869 {
3870     return GetOrCreateGlobalConfig();
3871 }
3872 
3873 void ScInterpreter::MergeCalcConfig()
3874 {
3875     maCalcConfig = GetOrCreateGlobalConfig();
3876     maCalcConfig.MergeDocumentSpecific( pDok->GetCalcConfig());
3877 }
3878 
3879 void ScInterpreter::GlobalExit()
3880 {
3881     OSL_ENSURE(!bGlobalStackInUse, "who is still using the TokenStack?");
3882     pGlobalStack.reset();
3883 }
3884 
3885 namespace {
3886 
3887 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
3888 {
3889     if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
3890     {
3891         SCROW nOffset = rPos.Row() - rMat.mnRow1;
3892         return rMat.mpMat->GetDouble(0, nOffset);
3893     }
3894 
3895     if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
3896     {
3897         SCROW nOffset = rPos.Col() - rMat.mnCol1;
3898         return rMat.mpMat->GetDouble(nOffset, 0);
3899     }
3900 
3901     double fVal;
3902     rtl::math::setNan(&fVal);
3903     return fVal;
3904 }
3905 
3906 // Test for Functions that evaluate an error code and directly set nGlobalError to 0
3907 bool IsErrFunc(OpCode oc)
3908 {
3909     switch (oc)
3910     {
3911         case ocCount :
3912         case ocCount2 :
3913         case ocErrorType :
3914         case ocIsEmpty :
3915         case ocIsErr :
3916         case ocIsError :
3917         case ocIsFormula :
3918         case ocIsLogical :
3919         case ocIsNA :
3920         case ocIsNonString :
3921         case ocIsRef :
3922         case ocIsString :
3923         case ocIsValue :
3924         case ocN :
3925         case ocType :
3926         case ocIfError :
3927         case ocIfNA :
3928         case ocErrorType_ODF :
3929         case ocIfs_MS:
3930         case ocSwitch_MS:
3931             return true;
3932         default:
3933             return false;
3934     }
3935 }
3936 
3937 } //namespace
3938 
3939 StackVar ScInterpreter::Interpret()
3940 {
3941     SvNumFormatType nRetTypeExpr = SvNumFormatType::UNDEFINED;
3942     sal_uInt32 nRetIndexExpr = 0;
3943     sal_uInt16 nErrorFunction = 0;
3944     sal_uInt16 nErrorFunctionCount = 0;
3945     std::vector<sal_uInt16> aErrorFunctionStack;
3946     sal_uInt16 nStackBase;
3947 
3948     nGlobalError = FormulaError::NONE;
3949     nStackBase = sp = maxsp = 0;
3950     nRetFmtType = SvNumFormatType::UNDEFINED;
3951     nFuncFmtType = SvNumFormatType::UNDEFINED;
3952     nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3953     xResult = nullptr;
3954     pJumpMatrix = nullptr;
3955     mnSubTotalFlags = SubtotalFlags::NONE;
3956     ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3957 
3958     // Once upon a time we used to have FP exceptions on, and there was a
3959     // Windows printer driver that kept switching off exceptions, so we had to
3960     // switch them back on again every time. Who knows if there isn't a driver
3961     // that keeps switching exceptions on, now that we run with exceptions off,
3962     // so reassure exceptions are really off.
3963     SAL_MATH_FPEXCEPTIONS_OFF();
3964 
3965     OpCode eOp = ocNone;
3966     aCode.Reset();
3967     while( ( pCur = aCode.Next() ) != nullptr
3968             && (nGlobalError == FormulaError::NONE || nErrorFunction <= nErrorFunctionCount) )
3969     {
3970         eOp = pCur->GetOpCode();
3971         cPar = pCur->GetByte();
3972         if ( eOp == ocPush )
3973         {
3974             // RPN code push without error
3975             PushWithoutError( *pCur );
3976             nCurFmtType = SvNumFormatType::UNDEFINED;
3977         }
3978         else if (pTokenMatrixMap &&
3979                  !FormulaCompiler::IsOpCodeJumpCommand( eOp ) &&
3980                 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
3981                  pTokenMatrixMap->end()) &&
3982                 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3983         {
3984             // Path already calculated, reuse result.
3985             nStackBase = sp - pCur->GetParamCount();
3986             if ( nStackBase > sp )
3987                 nStackBase = sp;        // underflow?!?
3988             sp = nStackBase;
3989             PushTokenRef( (*aTokenMatrixMapIter).second);
3990         }
3991         else
3992         {
3993             // previous expression determines the current number format
3994             nCurFmtType = nRetTypeExpr;
3995             nCurFmtIndex = nRetIndexExpr;
3996             // default function's format, others are set if needed
3997             nFuncFmtType = SvNumFormatType::NUMBER;
3998             nFuncFmtIndex = 0;
3999 
4000             if (FormulaCompiler::IsOpCodeJumpCommand( eOp ))
4001                 nStackBase = sp;        // don't mess around with the jumps
4002             else
4003             {
4004                 // Convert parameters to matrix if in array/matrix formula and
4005                 // parameters of function indicate doing so. Create JumpMatrix
4006                 // if necessary.
4007                 if ( MatrixParameterConversion() )
4008                 {
4009                     eOp = ocNone;       // JumpMatrix created
4010                     nStackBase = sp;
4011                 }
4012                 else if (sp >= pCur->GetParamCount())
4013                     nStackBase = sp - pCur->GetParamCount();
4014                 else
4015                     nStackBase = sp;    // underflow?!?
4016             }
4017 
4018             switch( eOp )
4019             {
4020                 case ocSep:
4021                 case ocClose:           // pushed by the compiler
4022                 case ocMissing          : ScMissing();                  break;
4023                 case ocMacro            : ScMacro();                    break;
4024                 case ocDBArea           : ScDBArea();                   break;
4025                 case ocColRowNameAuto   : ScColRowNameAuto();           break;
4026                 case ocIf               : ScIfJump();                   break;
4027                 case ocIfError          : ScIfError( false );           break;
4028                 case ocIfNA             : ScIfError( true );            break;
4029                 case ocChoose           : ScChooseJump();                break;
4030                 case ocAdd              : ScAdd();                      break;
4031                 case ocSub              : ScSub();                      break;
4032                 case ocMul              : ScMul();                      break;
4033                 case ocDiv              : ScDiv();                      break;
4034                 case ocAmpersand        : ScAmpersand();                break;
4035                 case ocPow              : ScPow();                      break;
4036                 case ocEqual            : ScEqual();                    break;
4037                 case ocNotEqual         : ScNotEqual();                 break;
4038                 case ocLess             : ScLess();                     break;
4039                 case ocGreater          : ScGreater();                  break;
4040                 case ocLessEqual        : ScLessEqual();                break;
4041                 case ocGreaterEqual     : ScGreaterEqual();             break;
4042                 case ocAnd              : ScAnd();                      break;
4043                 case ocOr               : ScOr();                       break;
4044                 case ocXor              : ScXor();                      break;
4045                 case ocIntersect        : ScIntersect();                break;
4046                 case ocRange            : ScRangeFunc();                break;
4047                 case ocUnion            : ScUnionFunc();                break;
4048                 case ocNot              : ScNot();                      break;
4049                 case ocNegSub           :
4050                 case ocNeg              : ScNeg();                      break;
4051                 case ocPercentSign      : ScPercentSign();              break;
4052                 case ocPi               : ScPi();                       break;
4053                 case ocRandom           : ScRandom();                   break;
4054                 case ocTrue             : ScTrue();                     break;
4055                 case ocFalse            : ScFalse();                    break;
4056                 case ocGetActDate       : ScGetActDate();               break;
4057                 case ocGetActTime       : ScGetActTime();               break;
4058                 case ocNotAvail         : PushError( FormulaError::NotAvailable); break;
4059                 case ocDeg              : ScDeg();                      break;
4060                 case ocRad              : ScRad();                      break;
4061                 case ocSin              : ScSin();                      break;
4062                 case ocCos              : ScCos();                      break;
4063                 case ocTan              : ScTan();                      break;
4064                 case ocCot              : ScCot();                      break;
4065                 case ocArcSin           : ScArcSin();                   break;
4066                 case ocArcCos           : ScArcCos();                   break;
4067                 case ocArcTan           : ScArcTan();                   break;
4068                 case ocArcCot           : ScArcCot();                   break;
4069                 case ocSinHyp           : ScSinHyp();                   break;
4070                 case ocCosHyp           : ScCosHyp();                   break;
4071                 case ocTanHyp           : ScTanHyp();                   break;
4072                 case ocCotHyp           : ScCotHyp();                   break;
4073                 case ocArcSinHyp        : ScArcSinHyp();                break;
4074                 case ocArcCosHyp        : ScArcCosHyp();                break;
4075                 case ocArcTanHyp        : ScArcTanHyp();                break;
4076                 case ocArcCotHyp        : ScArcCotHyp();                break;
4077                 case ocCosecant         : ScCosecant();                 break;
4078                 case ocSecant           : ScSecant();                   break;
4079                 case ocCosecantHyp      : ScCosecantHyp();              break;
4080                 case ocSecantHyp        : ScSecantHyp();                break;
4081                 case ocExp              : ScExp();                      break;
4082                 case ocLn               : ScLn();                       break;
4083                 case ocLog10            : ScLog10();                    break;
4084                 case ocSqrt             : ScSqrt();                     break;
4085                 case ocFact             : ScFact();                     break;
4086                 case ocGetYear          : ScGetYear();                  break;
4087                 case ocGetMonth         : ScGetMonth();                 break;
4088                 case ocGetDay           : ScGetDay();                   break;
4089                 case ocGetDayOfWeek     : ScGetDayOfWeek();             break;
4090                 case ocWeek             : ScGetWeekOfYear();            break;
4091                 case ocIsoWeeknum       : ScGetIsoWeekOfYear();         break;
4092                 case ocWeeknumOOo       : ScWeeknumOOo();               break;
4093                 case ocEasterSunday     : ScEasterSunday();             break;
4094                 case ocNetWorkdays      : ScNetWorkdays( false);        break;
4095                 case ocNetWorkdays_MS   : ScNetWorkdays( true );        break;
4096                 case ocWorkday_MS       : ScWorkday_MS();               break;
4097                 case ocGetHour          : ScGetHour();                  break;
4098                 case ocGetMin           : ScGetMin();                   break;
4099                 case ocGetSec           : ScGetSec();                   break;
4100                 case ocPlusMinus        : ScPlusMinus();                break;
4101                 case ocAbs              : ScAbs();                      break;
4102                 case ocInt              : ScInt();                      break;
4103                 case ocEven             : ScEven();                     break;
4104                 case ocOdd              : ScOdd();                      break;
4105                 case ocPhi              : ScPhi();                      break;
4106                 case ocGauss            : ScGauss();                    break;
4107                 case ocStdNormDist      : ScStdNormDist();              break;
4108                 case ocStdNormDist_MS   : ScStdNormDist_MS();           break;
4109                 case ocFisher           : ScFisher();                   break;
4110                 case ocFisherInv        : ScFisherInv();                break;
4111                 case ocIsEmpty          : ScIsEmpty();                  break;
4112                 case ocIsString         : ScIsString();                 break;
4113                 case ocIsNonString      : ScIsNonString();              break;
4114                 case ocIsLogical        : ScIsLogical();                break;
4115                 case ocType             : ScType();                     break;
4116                 case ocCell             : ScCell();                     break;
4117                 case ocIsRef            : ScIsRef();                    break;
4118                 case ocIsValue          : ScIsValue();                  break;
4119                 case ocIsFormula        : ScIsFormula();                break;
4120                 case ocFormula          : ScFormula();                  break;
4121                 case ocIsNA             : ScIsNV();                     break;
4122                 case ocIsErr            : ScIsErr();                    break;
4123                 case ocIsError          : ScIsError();                  break;
4124                 case ocIsEven           : ScIsEven();                   break;
4125                 case ocIsOdd            : ScIsOdd();                    break;
4126                 case ocN                : ScN();                        break;
4127                 case ocGetDateValue     : ScGetDateValue();             break;
4128                 case ocGetTimeValue     : ScGetTimeValue();             break;
4129                 case ocCode             : ScCode();                     break;
4130                 case ocTrim             : ScTrim();                     break;
4131                 case ocUpper            : ScUpper();                    break;
4132                 case ocProper           : ScProper();                   break;
4133                 case ocLower            : ScLower();                    break;
4134                 case ocLen              : ScLen();                      break;
4135                 case ocT                : ScT();                        break;
4136                 case ocClean            : ScClean();                    break;
4137                 case ocValue            : ScValue();                    break;
4138                 case ocNumberValue      : ScNumberValue();              break;
4139                 case ocChar             : ScChar();                     break;
4140                 case ocArcTan2          : ScArcTan2();                  break;
4141                 case ocMod              : ScMod();                      break;
4142                 case ocPower            : ScPower();                    break;
4143                 case ocRound            : ScRound();                    break;
4144                 case ocRoundSig         : ScRoundSignificant();         break;
4145                 case ocRoundUp          : ScRoundUp();                  break;
4146                 case ocTrunc            :
4147                 case ocRoundDown        : ScRoundDown();                break;
4148                 case ocCeil             : ScCeil( true );               break;
4149                 case ocCeil_MS          : ScCeil_MS();                  break;
4150                 case ocCeil_Precise     :
4151                 case ocCeil_ISO         : ScCeil_Precise();             break;
4152                 case ocCeil_Math        : ScCeil( false );              break;
4153                 case ocFloor            : ScFloor( true );              break;
4154                 case ocFloor_MS         : ScFloor_MS();                 break;
4155                 case ocFloor_Precise    : ScFloor_Precise();            break;
4156                 case ocFloor_Math       : ScFloor( false );             break;
4157                 case ocSumProduct       : ScSumProduct();               break;
4158                 case ocSumSQ            : ScSumSQ();                    break;
4159                 case ocSumX2MY2         : ScSumX2MY2();                 break;
4160                 case ocSumX2DY2         : ScSumX2DY2();                 break;
4161                 case ocSumXMY2          : ScSumXMY2();                  break;
4162                 case ocRawSubtract      : ScRawSubtract();              break;
4163                 case ocLog              : ScLog();                      break;
4164                 case ocGCD              : ScGCD();                      break;
4165                 case ocLCM              : ScLCM();                      break;
4166                 case ocGetDate          : ScGetDate();                  break;
4167                 case ocGetTime          : ScGetTime();                  break;
4168                 case ocGetDiffDate      : ScGetDiffDate();              break;
4169                 case ocGetDiffDate360   : ScGetDiffDate360();           break;
4170                 case ocGetDateDif       : ScGetDateDif();               break;
4171                 case ocMin              : ScMin()       ;               break;
4172                 case ocMinA             : ScMin( true );                break;
4173                 case ocMax              : ScMax();                      break;
4174                 case ocMaxA             : ScMax( true );                break;
4175                 case ocSum              : ScSum();                      break;
4176                 case ocProduct          : ScProduct();                  break;
4177                 case ocNPV              : ScNPV();                      break;
4178                 case ocIRR              : ScIRR();                      break;
4179                 case ocMIRR             : ScMIRR();                     break;
4180                 case ocISPMT            : ScISPMT();                    break;
4181                 case ocAverage          : ScAverage()       ;           break;
4182                 case ocAverageA         : ScAverage( true );            break;
4183                 case ocCount            : ScCount();                    break;
4184                 case ocCount2           : ScCount2();                   break;
4185                 case ocVar              :
4186                 case ocVarS             : ScVar();                      break;
4187                 case ocVarA             : ScVar( true );                break;
4188                 case ocVarP             :
4189                 case ocVarP_MS          : ScVarP();                     break;
4190                 case ocVarPA            : ScVarP( true );               break;
4191                 case ocStDev            :
4192                 case ocStDevS           : ScStDev();                    break;
4193                 case ocStDevA           : ScStDev( true );              break;
4194                 case ocStDevP           :
4195                 case ocStDevP_MS        : ScStDevP();                   break;
4196                 case ocStDevPA          : ScStDevP( true );             break;
4197                 case ocPV               : ScPV();                       break;
4198                 case ocSYD              : ScSYD();                      break;
4199                 case ocDDB              : ScDDB();                      break;
4200                 case ocDB               : ScDB();                       break;
4201                 case ocVBD              : ScVDB();                      break;
4202                 case ocPDuration        : ScPDuration();                break;
4203                 case ocSLN              : ScSLN();                      break;
4204                 case ocPMT              : ScPMT();                      break;
4205                 case ocColumns          : ScColumns();                  break;
4206                 case ocRows             : ScRows();                     break;
4207                 case ocSheets           : ScSheets();                   break;
4208                 case ocColumn           : ScColumn();                   break;
4209                 case ocRow              : ScRow();                      break;
4210                 case ocSheet            : ScSheet();                    break;
4211                 case ocRRI              : ScRRI();                      break;
4212                 case ocFV               : ScFV();                       break;
4213                 case ocNper             : ScNper();                     break;
4214                 case ocRate             : ScRate();                     break;
4215                 case ocFilterXML        : ScFilterXML();                break;
4216                 case ocWebservice       : ScWebservice();               break;
4217                 case ocEncodeURL        : ScEncodeURL();                break;
4218                 case ocColor            : ScColor();                    break;
4219                 case ocErf_MS           : ScErf();                      break;
4220                 case ocErfc_MS          : ScErfc();                     break;
4221                 case ocIpmt             : ScIpmt();                     break;
4222                 case ocPpmt             : ScPpmt();                     break;
4223                 case ocCumIpmt          : ScCumIpmt();                  break;
4224                 case ocCumPrinc         : ScCumPrinc();                 break;
4225                 case ocEffect           : ScEffect();                   break;
4226                 case ocNominal          : ScNominal();                  break;
4227                 case ocSubTotal         : ScSubTotal();                 break;
4228                 case ocAggregate        : ScAggregate();                break;
4229                 case ocDBSum            : ScDBSum();                    break;
4230                 case ocDBCount          : ScDBCount();                  break;
4231                 case ocDBCount2         : ScDBCount2();                 break;
4232                 case ocDBAverage        : ScDBAverage();                break;
4233                 case ocDBGet            : ScDBGet();                    break;
4234                 case ocDBMax            : ScDBMax();                    break;
4235                 case ocDBMin            : ScDBMin();                    break;
4236                 case ocDBProduct        : ScDBProduct();                break;
4237                 case ocDBStdDev         : ScDBStdDev();                 break;
4238                 case ocDBStdDevP        : ScDBStdDevP();                break;
4239                 case ocDBVar            : ScDBVar();                    break;
4240                 case ocDBVarP           : ScDBVarP();                   break;
4241                 case ocIndirect         : ScIndirect();                 break;
4242                 case ocAddress          : ScAddressFunc();              break;
4243                 case ocMatch            : ScMatch();                    break;
4244                 case ocCountEmptyCells  : ScCountEmptyCells();          break;
4245                 case ocCountIf          : ScCountIf();                  break;
4246                 case ocSumIf            : ScSumIf();                    break;
4247                 case ocAverageIf        : ScAverageIf();                break;
4248                 case ocSumIfs           : ScSumIfs();                   break;
4249                 case ocAverageIfs       : ScAverageIfs();               break;
4250                 case ocCountIfs         : ScCountIfs();                 break;
4251                 case ocLookup           : ScLookup();                   break;
4252                 case ocVLookup          : ScVLookup();                  break;
4253                 case ocHLookup          : ScHLookup();                  break;
4254                 case ocIndex            : ScIndex();                    break;
4255                 case ocMultiArea        : ScMultiArea();                break;
4256                 case ocOffset           : ScOffset();                   break;
4257                 case ocAreas            : ScAreas();                    break;
4258                 case ocCurrency         : ScCurrency();                 break;
4259                 case ocReplace          : ScReplace();                  break;
4260                 case ocFixed            : ScFixed();                    break;
4261                 case ocFind             : ScFind();                     break;
4262                 case ocExact            : ScExact();                    break;
4263                 case ocLeft             : ScLeft();                     break;
4264                 case ocRight            : ScRight();                    break;
4265                 case ocSearch           : ScSearch();                   break;
4266                 case ocMid              : ScMid();                      break;
4267                 case ocText             : ScText();                     break;
4268                 case ocSubstitute       : ScSubstitute();               break;
4269                 case ocRegex            : ScRegex();                    break;
4270                 case ocRept             : ScRept();                     break;
4271                 case ocConcat           : ScConcat();                   break;
4272                 case ocConcat_MS        : ScConcat_MS();                break;
4273                 case ocTextJoin_MS      : ScTextJoin_MS();              break;
4274                 case ocIfs_MS           : ScIfs_MS();                   break;
4275                 case ocSwitch_MS        : ScSwitch_MS();                break;
4276                 case ocMinIfs_MS        : ScMinIfs_MS();                break;
4277                 case ocMaxIfs_MS        : ScMaxIfs_MS();                break;
4278                 case ocMatValue         : ScMatValue();                 break;
4279                 case ocMatrixUnit       : ScEMat();                     break;
4280                 case ocMatDet           : ScMatDet();                   break;
4281                 case ocMatInv           : ScMatInv();                   break;
4282                 case ocMatMult          : ScMatMult();                  break;
4283                 case ocMatTrans         : ScMatTrans();                 break;
4284                 case ocMatRef           : ScMatRef();                   break;
4285                 case ocB                : ScB();                        break;
4286                 case ocNormDist         : ScNormDist( 3 );              break;
4287                 case ocNormDist_MS      : ScNormDist( 4 );              break;
4288                 case ocExpDist          :
4289                 case ocExpDist_MS       : ScExpDist();                  break;
4290                 case ocBinomDist        :
4291                 case ocBinomDist_MS     : ScBinomDist();                break;
4292                 case ocPoissonDist      : ScPoissonDist( true );        break;
4293                 case ocPoissonDist_MS   : ScPoissonDist( false );       break;
4294                 case ocCombin           : ScCombin();                   break;
4295                 case ocCombinA          : ScCombinA();                  break;
4296                 case ocPermut           : ScPermut();                   break;
4297                 case ocPermutationA     : ScPermutationA();             break;
4298                 case ocHypGeomDist      : ScHypGeomDist( 4 );           break;
4299                 case ocHypGeomDist_MS   : ScHypGeomDist( 5 );           break;
4300                 case ocLogNormDist      : ScLogNormDist( 1 );           break;
4301                 case ocLogNormDist_MS   : ScLogNormDist( 4 );           break;
4302                 case ocTDist            : ScTDist();                    break;
4303                 case ocTDist_MS         : ScTDist_MS();                 break;
4304                 case ocTDist_RT         : ScTDist_T( 1 );               break;
4305                 case ocTDist_2T         : ScTDist_T( 2 );               break;
4306                 case ocFDist            :
4307                 case ocFDist_RT         : ScFDist();                    break;
4308                 case ocFDist_LT         : ScFDist_LT();                 break;
4309                 case ocChiDist          : ScChiDist( true );            break;
4310                 case ocChiDist_MS       : ScChiDist( false );           break;
4311                 case ocChiSqDist        : ScChiSqDist();                break;
4312                 case ocChiSqDist_MS     : ScChiSqDist_MS();             break;
4313                 case ocStandard         : ScStandard();                 break;
4314                 case ocAveDev           : ScAveDev();                   break;
4315                 case ocDevSq            : ScDevSq();                    break;
4316                 case ocKurt             : ScKurt();                     break;
4317                 case ocSkew             : ScSkew();                     break;
4318                 case ocSkewp            : ScSkewp();                    break;
4319                 case ocModalValue       : ScModalValue();               break;
4320                 case ocModalValue_MS    : ScModalValue_MS( true );      break;
4321                 case ocModalValue_Multi : ScModalValue_MS( false );     break;
4322                 case ocMedian           : ScMedian();                   break;
4323                 case ocGeoMean          : ScGeoMean();                  break;
4324                 case ocHarMean          : ScHarMean();                  break;
4325                 case ocWeibull          :
4326                 case ocWeibull_MS       : ScWeibull();                  break;
4327                 case ocBinomInv         :
4328                 case ocCritBinom        : ScCritBinom();                break;
4329                 case ocNegBinomVert     : ScNegBinomDist();             break;
4330                 case ocNegBinomDist_MS  : ScNegBinomDist_MS();          break;
4331                 case ocNoName           : ScNoName();                   break;
4332                 case ocBad              : ScBadName();                  break;
4333                 case ocZTest            :
4334                 case ocZTest_MS         : ScZTest();                    break;
4335                 case ocTTest            :
4336                 case ocTTest_MS         : ScTTest();                    break;
4337                 case ocFTest            :
4338                 case ocFTest_MS         : ScFTest();                    break;
4339                 case ocRank             :
4340                 case ocRank_Eq          : ScRank( false );              break;
4341                 case ocRank_Avg         : ScRank( true );               break;
4342                 case ocPercentile       :
4343                 case ocPercentile_Inc   : ScPercentile( true );         break;
4344                 case ocPercentile_Exc   : ScPercentile( false );        break;
4345                 case ocPercentrank      :
4346                 case ocPercentrank_Inc  : ScPercentrank( true );        break;
4347                 case ocPercentrank_Exc  : ScPercentrank( false );       break;
4348                 case ocLarge            : ScLarge();                    break;
4349                 case ocSmall            : ScSmall();                    break;
4350                 case ocFrequency        : ScFrequency();                break;
4351                 case ocQuartile         :
4352                 case ocQuartile_Inc     : ScQuartile( true );           break;
4353                 case ocQuartile_Exc     : ScQuartile( false );          break;
4354                 case ocNormInv          :
4355                 case ocNormInv_MS       : ScNormInv();                  break;
4356                 case ocSNormInv         :
4357                 case ocSNormInv_MS      : ScSNormInv();                 break;
4358                 case ocConfidence       :
4359                 case ocConfidence_N     : ScConfidence();               break;
4360                 case ocConfidence_T     : ScConfidenceT();              break;
4361                 case ocTrimMean         : ScTrimMean();                 break;
4362                 case ocProb             : ScProbability();              break;
4363                 case ocCorrel           : ScCorrel();                   break;
4364                 case ocCovar            :
4365                 case ocCovarianceP      : ScCovarianceP();              break;
4366                 case ocCovarianceS      : ScCovarianceS();              break;
4367                 case ocPearson          : ScPearson();                  break;
4368                 case ocRSQ              : ScRSQ();                      break;
4369                 case ocSTEYX            : ScSTEYX();                    break;
4370                 case ocSlope            : ScSlope();                    break;
4371                 case ocIntercept        : ScIntercept();                break;
4372                 case ocTrend            : ScTrend();                    break;
4373                 case ocGrowth           : ScGrowth();                   break;
4374                 case ocLinest           : ScLinest();                   break;
4375                 case ocLogest           : ScLogest();                   break;
4376                 case ocForecast_LIN     :
4377                 case ocForecast         : ScForecast();                   break;
4378                 case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd );       break;
4379                 case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason );    break;
4380                 case ocForecast_ETS_MUL : ScForecast_Ets( etsMult );      break;
4381                 case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd );     break;
4382                 case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult );    break;
4383                 case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd );   break;
4384                 case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult );  break;
4385                 case ocGammaLn          :
4386                 case ocGammaLn_MS       : ScLogGamma();                 break;
4387                 case ocGamma            : ScGamma();                    break;
4388                 case ocGammaDist        : ScGammaDist( true );          break;
4389                 case ocGammaDist_MS     : ScGammaDist( false );         break;
4390                 case ocGammaInv         :
4391                 case ocGammaInv_MS      : ScGammaInv();                 break;
4392                 case ocChiTest          :
4393                 case ocChiTest_MS       : ScChiTest();                  break;
4394                 case ocChiInv           :
4395                 case ocChiInv_MS        : ScChiInv();                   break;
4396                 case ocChiSqInv         :
4397                 case ocChiSqInv_MS      : ScChiSqInv();                 break;
4398                 case ocTInv             :
4399                 case ocTInv_2T          : ScTInv( 2 );                  break;
4400                 case ocTInv_MS          : ScTInv( 4 );                  break;
4401                 case ocFInv             :
4402                 case ocFInv_RT          : ScFInv();                     break;
4403                 case ocFInv_LT          : ScFInv_LT();                  break;
4404                 case ocLogInv           :
4405                 case ocLogInv_MS        : ScLogNormInv();               break;
4406                 case ocBetaDist         : ScBetaDist();                 break;
4407                 case ocBetaDist_MS      : ScBetaDist_MS();              break;
4408                 case ocBetaInv          :
4409                 case ocBetaInv_MS       : ScBetaInv();                  break;
4410                 case ocFourier          : ScFourier();                  break;
4411                 case ocExternal         : ScExternal();                 break;
4412                 case ocTableOp          : ScTableOp();                  break;
4413                 case ocStop :                                           break;
4414                 case ocErrorType        : ScErrorType();                break;
4415                 case ocErrorType_ODF    : ScErrorType_ODF();            break;
4416                 case ocCurrent          : ScCurrent();                  break;
4417                 case ocStyle            : ScStyle();                    break;
4418                 case ocDde              : ScDde();                      break;
4419                 case ocBase             : ScBase();                     break;
4420                 case ocDecimal          : ScDecimal();                  break;
4421                 case ocConvertOOo       : ScConvertOOo();               break;
4422                 case ocEuroConvert      : ScEuroConvert();              break;
4423                 case ocRoman            : ScRoman();                    break;
4424                 case ocArabic           : ScArabic();                   break;
4425                 case ocInfo             : ScInfo();                     break;
4426                 case ocHyperLink        : ScHyperLink();                break;
4427                 case ocBahtText         : ScBahtText();                 break;
4428                 case ocGetPivotData     : ScGetPivotData();             break;
4429                 case ocJis              : ScJis();                      break;
4430                 case ocAsc              : ScAsc();                      break;
4431                 case ocLenB             : ScLenB();                     break;
4432                 case ocRightB           : ScRightB();                   break;
4433                 case ocLeftB            : ScLeftB();                    break;
4434                 case ocMidB             : ScMidB();                     break;
4435                 case ocReplaceB         : ScReplaceB();                 break;
4436                 case ocFindB            : ScFindB();                    break;
4437                 case ocSearchB          : ScSearchB();                  break;
4438                 case ocUnicode          : ScUnicode();                  break;
4439                 case ocUnichar          : ScUnichar();                  break;
4440                 case ocBitAnd           : ScBitAnd();                   break;
4441                 case ocBitOr            : ScBitOr();                    break;
4442                 case ocBitXor           : ScBitXor();                   break;
4443                 case ocBitRshift        : ScBitRshift();                break;
4444                 case ocBitLshift        : ScBitLshift();                break;
4445                 case ocTTT              : ScTTT();                      break;
4446                 case ocDebugVar         : ScDebugVar();                 break;
4447                 case ocNone : nFuncFmtType = SvNumFormatType::UNDEFINED;    break;
4448                 default : PushError( FormulaError::UnknownOpCode);                 break;
4449             }
4450 
4451             // If the function pushed a subroutine as result, continue with
4452             // execution of the subroutine.
4453             if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
4454             {
4455                 Pop(); continue;
4456             }
4457 
4458             if (FormulaCompiler::IsOpCodeVolatile(eOp))
4459                 meVolatileType = VOLATILE;
4460 
4461             // Remember result matrix in case it could be reused.
4462             if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
4463                 pTokenMatrixMap->emplace(pCur, pStack[sp-1]);
4464 
4465             // outer function determines format of an expression
4466             if ( nFuncFmtType != SvNumFormatType::UNDEFINED )
4467             {
4468                 nRetTypeExpr = nFuncFmtType;
4469                 // Inherit the format index for currency, date or time formats.
4470                 switch (nFuncFmtType)
4471                 {
4472                     case SvNumFormatType::CURRENCY:
4473                     case SvNumFormatType::DATE:
4474                     case SvNumFormatType::TIME:
4475                     case SvNumFormatType::DATETIME:
4476                     case SvNumFormatType::DURATION:
4477                         nRetIndexExpr = nFuncFmtIndex;
4478                     break;
4479                     default:
4480                         nRetIndexExpr = 0;
4481                 }
4482             }
4483         }
4484 
4485         // Need a clean stack environment for the JumpMatrix to work.
4486         if (nGlobalError != FormulaError::NONE && eOp != ocPush && sp > nStackBase + 1)
4487         {
4488             // Not all functions pop all parameters in case an error is
4489             // generated. Clean up stack. Assumes that every function pushes a
4490             // result, may be arbitrary in case of error.
4491             FormulaConstTokenRef xLocalResult = pStack[ sp - 1 ];
4492             while (sp > nStackBase)
4493                 Pop();
4494             PushTokenRef( xLocalResult );
4495         }
4496 
4497         bool bGotResult;
4498         do
4499         {
4500             bGotResult = false;
4501             sal_uInt8 nLevel = 0;
4502             if ( GetStackType( ++nLevel ) == svJumpMatrix )
4503                 ;   // nothing
4504             else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4505                 ;   // nothing
4506             else
4507                 nLevel = 0;
4508             if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4509             {
4510                 if (nLevel == 1)
4511                     aErrorFunctionStack.push_back( nErrorFunction);
4512                 bGotResult = JumpMatrix( nLevel );
4513                 if (aErrorFunctionStack.empty())
4514                     assert(!"ScInterpreter::Interpret - aErrorFunctionStack empty in JumpMatrix context");
4515                 else
4516                 {
4517                     nErrorFunction = aErrorFunctionStack.back();
4518                     if (bGotResult)
4519                         aErrorFunctionStack.pop_back();
4520                 }
4521             }
4522             else
4523                 pJumpMatrix = nullptr;
4524         } while ( bGotResult );
4525 
4526         if( IsErrFunc(eOp) )
4527             ++nErrorFunction;
4528 
4529         if ( nGlobalError != FormulaError::NONE )
4530         {
4531             if ( !nErrorFunctionCount )
4532             {   // count of errorcode functions in formula
4533                 FormulaTokenArrayPlainIterator aIter(*pArr);
4534                 for ( FormulaToken* t = aIter.FirstRPN(); t; t = aIter.NextRPN() )
4535                 {
4536                     if ( IsErrFunc(t->GetOpCode()) )
4537                         ++nErrorFunctionCount;
4538                 }
4539             }
4540             if ( nErrorFunction >= nErrorFunctionCount )
4541                 ++nErrorFunction;   // that's it, error => terminate
4542         }
4543     }
4544 
4545     // End: obtain result
4546 
4547     bool bForcedResultType;
4548     switch (eOp)
4549     {
4550         case ocGetDateValue:
4551         case ocGetTimeValue:
4552             // Force final result of DATEVALUE and TIMEVALUE to number type,
4553             // which so far was date or time for calculations.
4554             nRetTypeExpr = nFuncFmtType = SvNumFormatType::NUMBER;
4555             nRetIndexExpr = nFuncFmtIndex = 0;
4556             bForcedResultType = true;
4557         break;
4558         default:
4559             bForcedResultType = false;
4560     }
4561 
4562     if (sp == 1)
4563     {
4564         pCur = pStack[ sp-1 ];
4565         if( pCur->GetOpCode() == ocPush )
4566         {
4567             // An svRefList can be resolved if it a) contains just one
4568             // reference, or b) in array context contains an array of single
4569             // cell references.
4570             if (pCur->GetType() == svRefList)
4571             {
4572                 PopRefListPushMatrixOrRef();
4573                 pCur = pStack[ sp-1 ];
4574             }
4575             switch( pCur->GetType() )
4576             {
4577                 case svEmptyCell:
4578                     ;   // nothing
4579                 break;
4580                 case svError:
4581                     nGlobalError = pCur->GetError();
4582                 break;
4583                 case svDouble :
4584                     {
4585                         // If typed, pop token to obtain type information and
4586                         // push a plain untyped double so the result token to
4587                         // be transferred to the formula cell result does not
4588                         // unnecessarily duplicate the information.
4589                         if (pCur->GetDoubleType() != 0)
4590                         {
4591                             double fVal = PopDouble();
4592                             if (!bForcedResultType)
4593                             {
4594                                 if (nCurFmtType != nFuncFmtType)
4595                                     nRetIndexExpr = 0;  // carry format index only for matching type
4596                                 nRetTypeExpr = nFuncFmtType = nCurFmtType;
4597                             }
4598                             if (nRetTypeExpr == SvNumFormatType::DURATION)
4599                             {
4600                                 // Round the duration in case a wall clock time
4601                                 // display format is used instead of a duration
4602                                 // format. To micro seconds which then catches
4603                                 // the converted hh:mm:ss.9999997 cases.
4604                                 if (fVal != 0.0)
4605                                 {
4606                                     fVal *= 86400.0;
4607                                     fVal = rtl::math::round( fVal, 6);
4608                                     fVal /= 86400.0;
4609                                 }
4610                             }
4611                             PushTempToken( CreateFormulaDoubleToken( fVal));
4612                         }
4613                         if ( nFuncFmtType == SvNumFormatType::UNDEFINED )
4614                         {
4615                             nRetTypeExpr = SvNumFormatType::NUMBER;
4616                             nRetIndexExpr = 0;
4617                         }
4618                     }
4619                 break;
4620                 case svString :
4621                     nRetTypeExpr = SvNumFormatType::TEXT;
4622                     nRetIndexExpr = 0;
4623                 break;
4624                 case svSingleRef :
4625                 {
4626                     ScAddress aAdr;
4627                     PopSingleRef( aAdr );
4628                     if( nGlobalError == FormulaError::NONE)
4629                         PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4630                 }
4631                 break;
4632                 case svRefList :
4633                     PopError();     // maybe #REF! takes precedence over #VALUE!
4634                     PushError( FormulaError::NoValue);
4635                 break;
4636                 case svDoubleRef :
4637                 {
4638                     if ( bMatrixFormula )
4639                     {   // create matrix for {=A1:A5}
4640                         PopDoubleRefPushMatrix();
4641                         ScMatrixRef xMat = PopMatrix();
4642                         QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4643                     }
4644                     else
4645                     {
4646                         ScRange aRange;
4647                         PopDoubleRef( aRange );
4648                         ScAddress aAdr;
4649                         if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr))
4650                             PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4651                     }
4652                 }
4653                 break;
4654                 case svExternalDoubleRef:
4655                 {
4656                     ScMatrixRef xMat;
4657                     PopExternalDoubleRef(xMat);
4658                     QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4659                 }
4660                 break;
4661                 case svMatrix :
4662                 {
4663                     sc::RangeMatrix aMat = PopRangeMatrix();
4664                     if (aMat.isRangeValid())
4665                     {
4666                         // This matrix represents a range reference. Apply implicit intersection.
4667                         double fVal = applyImplicitIntersection(aMat, aPos);
4668                         if (rtl::math::isNan(fVal))
4669                             PushNoValue();
4670                         else
4671                             PushInt(fVal);
4672                     }
4673                     else
4674                         // This is a normal matrix.
4675                         QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
4676                 }
4677                 break;
4678                 case svExternalSingleRef:
4679                 {
4680                     FormulaTokenRef xToken;
4681                     ScExternalRefCache::CellFormat aFmt;
4682                     PopExternalSingleRef(xToken, &aFmt);
4683                     if (nGlobalError != FormulaError::NONE)
4684                         break;
4685 
4686                     PushTokenRef(xToken);
4687 
4688                     if (aFmt.mbIsSet)
4689                     {
4690                         nFuncFmtType = aFmt.mnType;
4691                         nFuncFmtIndex = aFmt.mnIndex;
4692                     }
4693                 }
4694                 break;
4695                 default :
4696                     SetError( FormulaError::UnknownStackVariable);
4697             }
4698         }
4699         else
4700             SetError( FormulaError::UnknownStackVariable);
4701     }
4702     else if (sp > 1)
4703         SetError( FormulaError::OperatorExpected);
4704     else
4705         SetError( FormulaError::NoCode);
4706 
4707     if (bForcedResultType || nRetTypeExpr != SvNumFormatType::UNDEFINED)
4708     {
4709         nRetFmtType = nRetTypeExpr;
4710         nRetFmtIndex = nRetIndexExpr;
4711     }
4712     else if( nFuncFmtType != SvNumFormatType::UNDEFINED )
4713     {
4714         nRetFmtType = nFuncFmtType;
4715         nRetFmtIndex = nFuncFmtIndex;
4716     }
4717     else
4718         nRetFmtType = SvNumFormatType::NUMBER;
4719 
4720     if (nGlobalError != FormulaError::NONE && GetStackType() != svError )
4721         PushError( nGlobalError);
4722 
4723     // THE final result.
4724     xResult = PopToken();
4725     if (!xResult)
4726         xResult = new FormulaErrorToken( FormulaError::UnknownStackVariable);
4727 
4728     // release tokens in expression stack
4729     const FormulaToken** p = pStack;
4730     while( maxsp-- )
4731         (*p++)->DecRef();
4732 
4733     StackVar eType = xResult->GetType();
4734     if (eType == svMatrix)
4735         // Results are immutable in case they would be reused as input for new
4736         // interpreters.
4737         xResult->GetMatrix()->SetImmutable();
4738     return eType;
4739 }
4740 
4741 void ScInterpreter::AssertFormulaMatrix()
4742 {
4743     bMatrixFormula = true;
4744 }
4745 
4746 svl::SharedString ScInterpreter::GetStringResult() const
4747 {
4748     return xResult->GetString();
4749 }
4750 
4751 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
4752