tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / core / tool / interpr4.cxx
blobfcc58c364ec49f79d198980d62e4119f104bd684
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <interpre.hxx>
24 #include <sal/log.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <rtl/math.hxx>
27 #include <sfx2/app.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <basic/sbmeth.hxx>
30 #include <basic/sbmod.hxx>
31 #include <basic/sbstar.hxx>
32 #include <basic/sbx.hxx>
33 #include <basic/sbxobj.hxx>
34 #include <basic/sbuno.hxx>
35 #include <osl/thread.h>
36 #include <svl/numformat.hxx>
37 #include <svl/zforlist.hxx>
38 #include <svl/sharedstringpool.hxx>
39 #include <unotools/charclass.hxx>
40 #include <stdlib.h>
41 #include <string.h>
43 #include <com/sun/star/table/XCellRange.hpp>
44 #include <com/sun/star/script/XInvocation.hpp>
45 #include <com/sun/star/sheet/XSheetCellRange.hpp>
47 #include <global.hxx>
48 #include <dbdata.hxx>
49 #include <formulacell.hxx>
50 #include <callform.hxx>
51 #include <addincol.hxx>
52 #include <document.hxx>
53 #include <dociter.hxx>
54 #include <docsh.hxx>
55 #include <docoptio.hxx>
56 #include <scmatrix.hxx>
57 #include <adiasync.hxx>
58 #include <cellsuno.hxx>
59 #include <optuno.hxx>
60 #include <rangeseq.hxx>
61 #include <addinlis.hxx>
62 #include <jumpmatrix.hxx>
63 #include <parclass.hxx>
64 #include <externalrefmgr.hxx>
65 #include <formula/FormulaCompiler.hxx>
66 #include <macromgr.hxx>
67 #include <doubleref.hxx>
68 #include <queryparam.hxx>
69 #include <tokenarray.hxx>
70 #include <compiler.hxx>
72 #include <map>
73 #include <algorithm>
74 #include <basic/basmgr.hxx>
75 #include <vbahelper/vbaaccesshelper.hxx>
76 #include <memory>
78 using namespace com::sun::star;
79 using namespace formula;
80 using ::std::unique_ptr;
82 #define ADDIN_MAXSTRLEN 256
84 thread_local std::unique_ptr<ScTokenStack> ScInterpreter::pGlobalStack;
85 thread_local bool ScInterpreter::bGlobalStackInUse = false;
87 // document access functions
89 void ScInterpreter::ReplaceCell( ScAddress& rPos )
91 size_t ListSize = mrDoc.m_TableOpList.size();
92 for ( size_t i = 0; i < ListSize; ++i )
94 ScInterpreterTableOpParams *const pTOp = mrDoc.m_TableOpList[ i ];
95 if ( rPos == pTOp->aOld1 )
97 rPos = pTOp->aNew1;
98 return ;
100 else if ( rPos == pTOp->aOld2 )
102 rPos = pTOp->aNew2;
103 return ;
108 bool ScInterpreter::IsTableOpInRange( const ScRange& rRange )
110 if ( rRange.aStart == rRange.aEnd )
111 return false; // not considered to be a range in TableOp sense
113 // we can't replace a single cell in a range
114 size_t ListSize = mrDoc.m_TableOpList.size();
115 for ( size_t i = 0; i < ListSize; ++i )
117 ScInterpreterTableOpParams *const pTOp = mrDoc.m_TableOpList[ i ];
118 if ( rRange.Contains( pTOp->aOld1 ) )
119 return true;
120 if ( rRange.Contains( pTOp->aOld2 ) )
121 return true;
123 return false;
126 sal_uInt32 ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, ScRefCellValue& rCell )
128 sal_uInt32 nFormat;
129 FormulaError nErr;
130 if (rCell.isEmpty())
132 nFormat = mrDoc.GetNumberFormat( mrContext, rPos );
133 nErr = FormulaError::NONE;
135 else
137 if (rCell.getType() == CELLTYPE_FORMULA)
138 nErr = rCell.getFormula()->GetErrCode();
139 else
140 nErr = FormulaError::NONE;
141 nFormat = mrDoc.GetNumberFormat( mrContext, rPos );
144 SetError(nErr);
145 return nFormat;
148 /// Only ValueCell, formula cells already store the result rounded.
149 double ScInterpreter::GetValueCellValue( const ScAddress& rPos, double fOrig )
151 if ( bCalcAsShown && fOrig != 0.0 )
153 sal_uInt32 nFormat = mrDoc.GetNumberFormat( mrContext, rPos );
154 fOrig = mrDoc.RoundValueAsShown( fOrig, nFormat, &mrContext );
156 return fOrig;
159 FormulaError ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell )
161 return rCell.getType() == CELLTYPE_FORMULA ? rCell.getFormula()->GetErrCode() : FormulaError::NONE;
164 double ScInterpreter::ConvertStringToValue( const OUString& rStr )
166 FormulaError nError = FormulaError::NONE;
167 double fValue = ScGlobal::ConvertStringToValue( rStr, maCalcConfig, nError, mnStringNoValueError,
168 mrContext, nCurFmtType);
169 if (nError != FormulaError::NONE)
170 SetError(nError);
171 return fValue;
174 double ScInterpreter::ConvertStringToValue( const OUString& rStr, FormulaError& rError, SvNumFormatType& rCurFmtType )
176 return ScGlobal::ConvertStringToValue( rStr, maCalcConfig, rError, mnStringNoValueError, mrContext, rCurFmtType);
179 double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& rCell )
181 FormulaError nErr = nGlobalError;
182 nGlobalError = FormulaError::NONE;
183 double nVal = GetCellValueOrZero(rPos, rCell);
184 // Propagate previous error, if any; nGlobalError==CellNoValue is not an
185 // error here, preserve previous error or non-error.
186 if (nErr != FormulaError::NONE || nGlobalError == FormulaError::CellNoValue)
187 nGlobalError = nErr;
188 return nVal;
191 double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& rCell )
193 double fValue = 0.0;
195 CellType eType = rCell.getType();
196 switch (eType)
198 case CELLTYPE_FORMULA:
200 ScFormulaCell* pFCell = rCell.getFormula();
201 FormulaError nErr = pFCell->GetErrCode();
202 if( nErr == FormulaError::NONE )
204 if (pFCell->IsValue())
206 fValue = pFCell->GetValue();
207 mrDoc.GetNumberFormatInfo( mrContext, nCurFmtType, nCurFmtIndex,
208 rPos );
210 else
212 fValue = ConvertStringToValue(pFCell->GetString().getString());
215 else
217 fValue = 0.0;
218 SetError(nErr);
221 break;
222 case CELLTYPE_VALUE:
224 fValue = rCell.getDouble();
225 nCurFmtIndex = mrDoc.GetNumberFormat( mrContext, rPos );
226 nCurFmtType = mrContext.NFGetType(nCurFmtIndex);
227 if ( bCalcAsShown && fValue != 0.0 )
228 fValue = mrDoc.RoundValueAsShown( fValue, nCurFmtIndex, &mrContext );
230 break;
231 case CELLTYPE_STRING:
232 case CELLTYPE_EDIT:
234 // SUM(A1:A2) differs from A1+A2. No good. But people insist on
235 // it ... #i5658#
236 OUString aStr = rCell.getString(&mrDoc);
237 fValue = ConvertStringToValue( aStr );
239 break;
240 case CELLTYPE_NONE:
241 fValue = 0.0; // empty or broadcaster cell
242 break;
245 return fValue;
248 void ScInterpreter::GetCellString( svl::SharedString& rStr, ScRefCellValue& rCell )
250 FormulaError nErr = FormulaError::NONE;
252 switch (rCell.getType())
254 case CELLTYPE_STRING:
255 case CELLTYPE_EDIT:
256 rStr = rCell.getSharedString(&mrDoc, mrStrPool);
257 break;
258 case CELLTYPE_FORMULA:
260 ScFormulaCell* pFCell = rCell.getFormula();
261 nErr = pFCell->GetErrCode();
262 if (pFCell->IsValue())
264 rStr = GetStringFromDouble( pFCell->GetValue() );
266 else
267 rStr = pFCell->GetString();
269 break;
270 case CELLTYPE_VALUE:
272 rStr = GetStringFromDouble( rCell.getDouble() );
274 break;
275 default:
276 rStr = svl::SharedString::getEmptyString();
277 break;
280 SetError(nErr);
283 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
284 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr)
287 // Old Add-Ins are hard limited to sal_uInt16 values.
288 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16 && MAXCOLCOUNT_JUMBO <= SAL_MAX_UINT16,
289 "Add check for columns > SAL_MAX_UINT16!");
290 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
291 return false;
293 sal_uInt16 nCount = 0;
294 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
295 *p++ = static_cast<sal_uInt16>(nCol1);
296 *p++ = static_cast<sal_uInt16>(nRow1);
297 *p++ = static_cast<sal_uInt16>(nTab1);
298 *p++ = static_cast<sal_uInt16>(nCol2);
299 *p++ = static_cast<sal_uInt16>(nRow2);
300 *p++ = static_cast<sal_uInt16>(nTab2);
301 sal_uInt16* pCount = p;
302 *p++ = 0;
303 sal_uInt16 nPos = 14;
304 SCTAB nTab = nTab1;
305 ScAddress aAdr;
306 while (nTab <= nTab2)
308 aAdr.SetTab( nTab );
309 SCROW nRow = nRow1;
310 while (nRow <= nRow2)
312 aAdr.SetRow( nRow );
313 SCCOL nCol = nCol1;
314 while (nCol <= nCol2)
316 aAdr.SetCol( nCol );
318 ScRefCellValue aCell(mrDoc, aAdr);
319 if (!aCell.isEmpty())
321 FormulaError nErr = FormulaError::NONE;
322 double nVal = 0.0;
323 bool bOk = true;
324 switch (aCell.getType())
326 case CELLTYPE_VALUE :
327 nVal = GetValueCellValue(aAdr, aCell.getDouble());
328 break;
329 case CELLTYPE_FORMULA :
330 if (aCell.getFormula()->IsValue())
332 nErr = aCell.getFormula()->GetErrCode();
333 nVal = aCell.getFormula()->GetValue();
335 else
336 bOk = false;
337 break;
338 default :
339 bOk = false;
340 break;
342 if (bOk)
344 if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
345 return false;
346 *p++ = static_cast<sal_uInt16>(nCol);
347 *p++ = static_cast<sal_uInt16>(nRow);
348 *p++ = static_cast<sal_uInt16>(nTab);
349 *p++ = static_cast<sal_uInt16>(nErr);
350 memcpy( p, &nVal, sizeof(double));
351 nPos += 8 + sizeof(double);
352 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
353 nCount++;
356 nCol++;
358 nRow++;
360 nTab++;
362 *pCount = nCount;
363 return true;
366 bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
367 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
368 sal_uInt8* pCellArr)
371 // Old Add-Ins are hard limited to sal_uInt16 values.
372 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16 && MAXCOLCOUNT_JUMBO <= SAL_MAX_UINT16,
373 "Add check for columns > SAL_MAX_UINT16!");
374 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
375 return false;
377 sal_uInt16 nCount = 0;
378 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
379 *p++ = static_cast<sal_uInt16>(nCol1);
380 *p++ = static_cast<sal_uInt16>(nRow1);
381 *p++ = static_cast<sal_uInt16>(nTab1);
382 *p++ = static_cast<sal_uInt16>(nCol2);
383 *p++ = static_cast<sal_uInt16>(nRow2);
384 *p++ = static_cast<sal_uInt16>(nTab2);
385 sal_uInt16* pCount = p;
386 *p++ = 0;
387 sal_uInt16 nPos = 14;
388 SCTAB nTab = nTab1;
389 while (nTab <= nTab2)
391 SCROW nRow = nRow1;
392 while (nRow <= nRow2)
394 SCCOL nCol = nCol1;
395 while (nCol <= nCol2)
397 ScRefCellValue aCell(mrDoc, ScAddress(nCol, nRow, nTab));
398 if (!aCell.isEmpty())
400 OUString aStr;
401 FormulaError nErr = FormulaError::NONE;
402 bool bOk = true;
403 switch (aCell.getType())
405 case CELLTYPE_STRING:
406 case CELLTYPE_EDIT:
407 aStr = aCell.getString(&mrDoc);
408 break;
409 case CELLTYPE_FORMULA:
410 if (!aCell.getFormula()->IsValue())
412 nErr = aCell.getFormula()->GetErrCode();
413 aStr = aCell.getFormula()->GetString().getString();
415 else
416 bOk = false;
417 break;
418 default :
419 bOk = false;
420 break;
422 if (bOk)
424 OString aTmp(OUStringToOString(aStr,
425 osl_getThreadTextEncoding()));
426 // Old Add-Ins are limited to sal_uInt16 string
427 // lengths, and room for pad byte check.
428 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
429 return false;
430 // Append a 0-pad-byte if string length is odd
431 // MUST be sal_uInt16
432 sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength());
433 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
435 if ((static_cast<sal_uLong>(nPos) + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
436 return false;
437 *p++ = static_cast<sal_uInt16>(nCol);
438 *p++ = static_cast<sal_uInt16>(nRow);
439 *p++ = static_cast<sal_uInt16>(nTab);
440 *p++ = static_cast<sal_uInt16>(nErr);
441 *p++ = nLen;
442 memcpy( p, aTmp.getStr(), nStrLen + 1);
443 nPos += 10 + nStrLen + 1;
444 sal_uInt8* q = pCellArr + nPos;
445 if( (nStrLen & 1) == 0 )
447 *q++ = 0;
448 nPos++;
450 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
451 nCount++;
454 nCol++;
456 nRow++;
458 nTab++;
460 *pCount = nCount;
461 return true;
464 bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
465 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
466 sal_uInt8* pCellArr)
469 // Old Add-Ins are hard limited to sal_uInt16 values.
470 static_assert(MAXCOLCOUNT <= SAL_MAX_UINT16 && MAXCOLCOUNT_JUMBO <= SAL_MAX_UINT16,
471 "Add check for columns > SAL_MAX_UINT16!");
472 if (nRow1 > SAL_MAX_UINT16 || nRow2 > SAL_MAX_UINT16)
473 return false;
475 sal_uInt16 nCount = 0;
476 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
477 *p++ = static_cast<sal_uInt16>(nCol1);
478 *p++ = static_cast<sal_uInt16>(nRow1);
479 *p++ = static_cast<sal_uInt16>(nTab1);
480 *p++ = static_cast<sal_uInt16>(nCol2);
481 *p++ = static_cast<sal_uInt16>(nRow2);
482 *p++ = static_cast<sal_uInt16>(nTab2);
483 sal_uInt16* pCount = p;
484 *p++ = 0;
485 sal_uInt16 nPos = 14;
486 SCTAB nTab = nTab1;
487 ScAddress aAdr;
488 while (nTab <= nTab2)
490 aAdr.SetTab( nTab );
491 SCROW nRow = nRow1;
492 while (nRow <= nRow2)
494 aAdr.SetRow( nRow );
495 SCCOL nCol = nCol1;
496 while (nCol <= nCol2)
498 aAdr.SetCol( nCol );
499 ScRefCellValue aCell(mrDoc, aAdr);
500 if (!aCell.isEmpty())
502 FormulaError nErr = FormulaError::NONE;
503 sal_uInt16 nType = 0; // 0 = number; 1 = string
504 double nVal = 0.0;
505 OUString aStr;
506 bool bOk = true;
507 switch (aCell.getType())
509 case CELLTYPE_STRING :
510 case CELLTYPE_EDIT :
511 aStr = aCell.getString(&mrDoc);
512 nType = 1;
513 break;
514 case CELLTYPE_VALUE :
515 nVal = GetValueCellValue(aAdr, aCell.getDouble());
516 break;
517 case CELLTYPE_FORMULA :
518 nErr = aCell.getFormula()->GetErrCode();
519 if (aCell.getFormula()->IsValue())
520 nVal = aCell.getFormula()->GetValue();
521 else
522 aStr = aCell.getFormula()->GetString().getString();
523 break;
524 default :
525 bOk = false;
526 break;
528 if (bOk)
530 if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
531 return false;
532 *p++ = static_cast<sal_uInt16>(nCol);
533 *p++ = static_cast<sal_uInt16>(nRow);
534 *p++ = static_cast<sal_uInt16>(nTab);
535 *p++ = static_cast<sal_uInt16>(nErr);
536 *p++ = nType;
537 nPos += 10;
538 if (nType == 0)
540 if ((nPos + sizeof(double)) > MAXARRSIZE)
541 return false;
542 memcpy( p, &nVal, sizeof(double));
543 nPos += sizeof(double);
545 else
547 OString aTmp(OUStringToOString(aStr,
548 osl_getThreadTextEncoding()));
549 // Old Add-Ins are limited to sal_uInt16 string
550 // lengths, and room for pad byte check.
551 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
552 return false;
553 // Append a 0-pad-byte if string length is odd
554 // MUST be sal_uInt16
555 sal_uInt16 nStrLen = static_cast<sal_uInt16>(aTmp.getLength());
556 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
557 if ( (static_cast<sal_uLong>(nPos) + 2 + nLen) > MAXARRSIZE)
558 return false;
559 *p++ = nLen;
560 memcpy( p, aTmp.getStr(), nStrLen + 1);
561 nPos += 2 + nStrLen + 1;
562 sal_uInt8* q = pCellArr + nPos;
563 if( (nStrLen & 1) == 0 )
565 *q++ = 0;
566 nPos++;
569 nCount++;
570 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
573 nCol++;
575 nRow++;
577 nTab++;
579 *pCount = nCount;
580 return true;
583 // Stack operations
585 // Also releases a TempToken if appropriate.
587 void ScInterpreter::PushWithoutError( const FormulaToken& r )
589 if ( sp >= MAXSTACK )
590 SetError( FormulaError::StackOverflow );
591 else
593 r.IncRef();
594 if( sp >= maxsp )
595 maxsp = sp + 1;
596 else
597 pStack[ sp ]->DecRef();
598 pStack[ sp ] = &r;
599 ++sp;
603 void ScInterpreter::Push( const FormulaToken& r )
605 if ( sp >= MAXSTACK )
606 SetError( FormulaError::StackOverflow );
607 else
609 if (nGlobalError != FormulaError::NONE)
611 if (r.GetType() == svError)
612 PushWithoutError( r);
613 else
614 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
616 else
617 PushWithoutError( r);
621 void ScInterpreter::PushTempToken( FormulaToken* p )
623 if ( sp >= MAXSTACK )
625 SetError( FormulaError::StackOverflow );
626 // p may be a dangling pointer hereafter!
627 p->DeleteIfZeroRef();
629 else
631 if (nGlobalError != FormulaError::NONE)
633 if (p->GetType() == svError)
635 p->SetError( nGlobalError);
636 PushTempTokenWithoutError( p);
638 else
640 // p may be a dangling pointer hereafter!
641 p->DeleteIfZeroRef();
642 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
645 else
646 PushTempTokenWithoutError( p);
650 void ScInterpreter::PushTempTokenWithoutError( const FormulaToken* p )
652 p->IncRef();
653 if ( sp >= MAXSTACK )
655 SetError( FormulaError::StackOverflow );
656 // p may be a dangling pointer hereafter!
657 p->DecRef();
659 else
661 if( sp >= maxsp )
662 maxsp = sp + 1;
663 else
664 pStack[ sp ]->DecRef();
665 pStack[ sp ] = p;
666 ++sp;
670 void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef& x )
672 if ( sp >= MAXSTACK )
674 SetError( FormulaError::StackOverflow );
676 else
678 if (nGlobalError != FormulaError::NONE)
680 if (x->GetType() == svError && x->GetError() == nGlobalError)
681 PushTempTokenWithoutError( x.get());
682 else
683 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
685 else
686 PushTempTokenWithoutError( x.get());
690 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
691 const ScAddress & rAddress, SvNumFormatType * pRetTypeExpr, sal_uInt32 * pRetIndexExpr, bool bFinalResult )
693 ScRefCellValue aCell(mrDoc, rAddress);
694 if (aCell.hasEmptyValue())
696 bool bInherited = (aCell.getType() == CELLTYPE_FORMULA);
697 if (pRetTypeExpr && pRetIndexExpr)
698 mrDoc.GetNumberFormatInfo(mrContext, *pRetTypeExpr, *pRetIndexExpr, rAddress);
699 PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
700 return;
703 FormulaError nErr = FormulaError::NONE;
704 if (aCell.getType() == CELLTYPE_FORMULA)
705 nErr = aCell.getFormula()->GetErrCode();
707 if (nErr != FormulaError::NONE)
709 PushError( nErr);
710 if (pRetTypeExpr)
711 *pRetTypeExpr = SvNumFormatType::UNDEFINED;
712 if (pRetIndexExpr)
713 *pRetIndexExpr = 0;
715 else if (aCell.hasString())
717 svl::SharedString aRes;
718 GetCellString( aRes, aCell);
719 PushString( aRes);
720 if (pRetTypeExpr)
721 *pRetTypeExpr = SvNumFormatType::TEXT;
722 if (pRetIndexExpr)
723 *pRetIndexExpr = 0;
725 else
727 double fVal = GetCellValue(rAddress, aCell);
728 if (bFinalResult)
730 TreatDoubleError( fVal);
731 if (!IfErrorPushError())
732 PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal));
734 else
736 PushDouble( fVal);
738 if (pRetTypeExpr)
739 *pRetTypeExpr = nCurFmtType;
740 if (pRetIndexExpr)
741 *pRetIndexExpr = nCurFmtIndex;
745 // Simply throw away TOS.
747 void ScInterpreter::Pop()
749 if( sp )
750 sp--;
751 else
752 SetError(FormulaError::UnknownStackVariable);
755 // Simply throw away TOS and set error code, used with ocIsError et al.
757 void ScInterpreter::PopError()
759 if( sp )
761 sp--;
762 if (pStack[sp]->GetType() == svError)
763 nGlobalError = pStack[sp]->GetError();
765 else
766 SetError(FormulaError::UnknownStackVariable);
769 FormulaConstTokenRef ScInterpreter::PopToken()
771 if (sp)
773 sp--;
774 const FormulaToken* p = pStack[ sp ];
775 if (p->GetType() == svError)
776 nGlobalError = p->GetError();
777 return p;
779 else
780 SetError(FormulaError::UnknownStackVariable);
781 return nullptr;
784 double ScInterpreter::PopDouble()
786 nCurFmtType = SvNumFormatType::NUMBER;
787 nCurFmtIndex = 0;
788 if( sp )
790 --sp;
791 const FormulaToken* p = pStack[ sp ];
792 switch (p->GetType())
794 case svError:
795 nGlobalError = p->GetError();
796 break;
797 case svDouble:
799 SvNumFormatType nType = static_cast<SvNumFormatType>(p->GetDoubleType());
800 if (nType != SvNumFormatType::ALL && nType != SvNumFormatType::UNDEFINED)
801 nCurFmtType = nType;
802 return p->GetDouble();
804 case svEmptyCell:
805 case svMissing:
806 return 0.0;
807 default:
808 SetError( FormulaError::IllegalArgument);
811 else
812 SetError( FormulaError::UnknownStackVariable);
813 return 0.0;
816 const svl::SharedString & ScInterpreter::PopString()
818 nCurFmtType = SvNumFormatType::TEXT;
819 nCurFmtIndex = 0;
820 if( sp )
822 --sp;
823 const FormulaToken* p = pStack[ sp ];
824 switch (p->GetType())
826 case svError:
827 nGlobalError = p->GetError();
828 break;
829 case svString:
830 return p->GetString();
831 case svEmptyCell:
832 case svMissing:
833 return svl::SharedString::getEmptyString();
834 default:
835 SetError( FormulaError::IllegalArgument);
838 else
839 SetError( FormulaError::UnknownStackVariable);
841 return svl::SharedString::getEmptyString();
844 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
846 SCCOL nCol;
847 SCROW nRow;
848 SCTAB nTab;
849 SingleRefToVars( rRef, nCol, nRow, nTab);
852 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
854 ValidateRef( rRef.Ref1);
855 ValidateRef( rRef.Ref2);
858 void ScInterpreter::ValidateRef( const ScRefList & rRefList )
860 for (const auto& rRef : rRefList)
862 ValidateRef( rRef);
866 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
867 SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
869 if ( rRef.IsColRel() )
870 rCol = aPos.Col() + rRef.Col();
871 else
872 rCol = rRef.Col();
874 if ( rRef.IsRowRel() )
875 rRow = aPos.Row() + rRef.Row();
876 else
877 rRow = rRef.Row();
879 if ( rRef.IsTabRel() )
880 rTab = aPos.Tab() + rRef.Tab();
881 else
882 rTab = rRef.Tab();
884 if( !mrDoc.ValidCol( rCol) || rRef.IsColDeleted() )
886 SetError( FormulaError::NoRef );
887 rCol = 0;
889 if( !mrDoc.ValidRow( rRow) || rRef.IsRowDeleted() )
891 SetError( FormulaError::NoRef );
892 rRow = 0;
894 if( !ValidTab( rTab, mrDoc.GetTableCount() - 1) || rRef.IsTabDeleted() )
896 SetError( FormulaError::NoRef );
897 rTab = 0;
901 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
903 ScAddress aAddr(rCol, rRow, rTab);
904 PopSingleRef(aAddr);
905 rCol = aAddr.Col();
906 rRow = aAddr.Row();
907 rTab = aAddr.Tab();
910 void ScInterpreter::PopSingleRef( ScAddress& rAdr )
912 if( sp )
914 --sp;
915 const FormulaToken* p = pStack[ sp ];
916 switch (p->GetType())
918 case svError:
919 nGlobalError = p->GetError();
920 break;
921 case svSingleRef:
923 const ScSingleRefData* pRefData = p->GetSingleRef();
924 if (pRefData->IsDeleted())
926 SetError( FormulaError::NoRef);
927 break;
930 SCCOL nCol;
931 SCROW nRow;
932 SCTAB nTab;
933 SingleRefToVars( *pRefData, nCol, nRow, nTab);
934 rAdr.Set( nCol, nRow, nTab );
935 if (!mrDoc.m_TableOpList.empty())
936 ReplaceCell( rAdr );
938 break;
939 default:
940 SetError( FormulaError::IllegalParameter);
943 else
944 SetError( FormulaError::UnknownStackVariable);
947 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken* p,
948 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
949 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 )
951 const ScComplexRefData& rCRef = *p->GetDoubleRef();
952 SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
953 SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
954 PutInOrder(rCol1, rCol2);
955 PutInOrder(rRow1, rRow2);
956 PutInOrder(rTab1, rTab2);
957 if (!mrDoc.m_TableOpList.empty())
959 ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
960 if ( IsTableOpInRange( aRange ) )
961 SetError( FormulaError::IllegalParameter );
965 ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
967 StackVar eType = GetStackType();
968 switch (eType)
970 case svUnknown:
971 SetError(FormulaError::UnknownStackVariable);
972 break;
973 case svError:
974 PopError();
975 break;
976 case svDoubleRef:
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(&mrDoc,
985 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
987 case svMatrix:
988 case svExternalDoubleRef:
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(&mrDoc, std::move(pMat));
999 default:
1000 SetError( FormulaError::IllegalParameter);
1003 return nullptr;
1006 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1007 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2)
1009 if( sp )
1011 --sp;
1012 const FormulaToken* p = pStack[ sp ];
1013 switch (p->GetType())
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);
1025 else
1026 SetError( FormulaError::UnknownStackVariable);
1029 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1030 ScRange & rRange, bool bDontCheckForTableOp )
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 (!mrDoc.m_TableOpList.empty() && !bDontCheckForTableOp)
1042 if ( IsTableOpInRange( rRange ) )
1043 SetError( FormulaError::IllegalParameter );
1047 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1049 if (sp)
1051 const formula::FormulaToken* pToken = pStack[ sp-1 ];
1052 switch (pToken->GetType())
1054 case svError:
1055 nGlobalError = pToken->GetError();
1056 break;
1057 case svDoubleRef:
1059 --sp;
1060 const ScComplexRefData* pRefData = pToken->GetDoubleRef();
1061 if (pRefData->IsDeleted())
1063 SetError( FormulaError::NoRef);
1064 break;
1066 DoubleRefToRange( *pRefData, rRange);
1067 break;
1069 case svRefList:
1071 const ScRefList* pList = pToken->GetRefList();
1072 if (rRefInList < pList->size())
1074 DoubleRefToRange( (*pList)[rRefInList], rRange);
1075 if (++rRefInList < pList->size())
1076 ++rParam;
1077 else
1079 --sp;
1080 rRefInList = 0;
1083 else
1085 --sp;
1086 rRefInList = 0;
1087 SetError( FormulaError::IllegalParameter);
1090 break;
1091 default:
1092 SetError( FormulaError::IllegalParameter);
1095 else
1096 SetError( FormulaError::UnknownStackVariable);
1099 void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1101 if( sp )
1103 --sp;
1104 const FormulaToken* p = pStack[ sp ];
1105 switch (p->GetType())
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);
1117 else
1118 SetError( FormulaError::UnknownStackVariable);
1121 const ScComplexRefData* ScInterpreter::GetStackDoubleRef(size_t rRefInList)
1123 if( sp )
1125 const FormulaToken* p = pStack[ sp - 1 ];
1126 switch (p->GetType())
1128 case svDoubleRef:
1129 return p->GetDoubleRef();
1130 case svRefList:
1132 const ScRefList* pList = p->GetRefList();
1133 if (rRefInList < pList->size())
1134 return &(*pList)[rRefInList];
1135 break;
1137 default:
1138 break;
1141 return nullptr;
1144 void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef)
1146 if (!sp)
1148 SetError(FormulaError::UnknownStackVariable);
1149 return;
1152 --sp;
1153 const FormulaToken* p = pStack[sp];
1154 StackVar eType = p->GetType();
1156 if (eType == svError)
1158 nGlobalError = p->GetError();
1159 return;
1162 if (eType != svExternalSingleRef)
1164 SetError( FormulaError::IllegalParameter);
1165 return;
1168 rFileId = p->GetIndex();
1169 rTabName = p->GetString().getString();
1170 rRef = *p->GetSingleRef();
1173 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1175 sal_uInt16 nFileId;
1176 OUString aTabName;
1177 ScSingleRefData aData;
1178 PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1181 void ScInterpreter::PopExternalSingleRef(
1182 sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
1183 ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1185 PopExternalSingleRef(rFileId, rTabName, rRef);
1186 if (nGlobalError != FormulaError::NONE)
1187 return;
1189 ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager();
1190 const OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1191 if (!pFile)
1193 SetError(FormulaError::NoName);
1194 return;
1197 if (rRef.IsTabRel())
1199 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1200 SetError(FormulaError::NoRef);
1201 return;
1204 ScAddress aAddr = rRef.toAbs(mrDoc, aPos);
1205 ScExternalRefCache::CellFormat aFmt;
1206 ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1207 rFileId, rTabName, aAddr, &aPos, nullptr, &aFmt);
1209 if (!xNew)
1211 SetError(FormulaError::NoRef);
1212 return;
1215 if (xNew->GetType() == svError)
1216 SetError( xNew->GetError());
1218 rToken = std::move(xNew);
1219 if (pFmt)
1220 *pFmt = aFmt;
1223 void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef)
1225 if (!sp)
1227 SetError(FormulaError::UnknownStackVariable);
1228 return;
1231 --sp;
1232 const FormulaToken* p = pStack[sp];
1233 StackVar eType = p->GetType();
1235 if (eType == svError)
1237 nGlobalError = p->GetError();
1238 return;
1241 if (eType != svExternalDoubleRef)
1243 SetError( FormulaError::IllegalParameter);
1244 return;
1247 rFileId = p->GetIndex();
1248 rTabName = p->GetString().getString();
1249 rRef = *p->GetDoubleRef();
1252 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1254 sal_uInt16 nFileId;
1255 OUString aTabName;
1256 ScComplexRefData aData;
1257 PopExternalDoubleRef(nFileId, aTabName, aData);
1258 if (nGlobalError != FormulaError::NONE)
1259 return;
1261 GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1262 if (nGlobalError != FormulaError::NONE)
1263 return;
1266 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1268 ScExternalRefCache::TokenArrayRef pArray;
1269 PopExternalDoubleRef(pArray);
1270 if (nGlobalError != FormulaError::NONE)
1271 return;
1273 // For now, we only support single range data for external
1274 // references, which means the array should only contain a
1275 // single matrix token.
1276 formula::FormulaToken* p = pArray->FirstToken();
1277 if (!p || p->GetType() != svMatrix)
1278 SetError( FormulaError::IllegalParameter);
1279 else
1281 rMat = p->GetMatrix();
1282 if (!rMat)
1283 SetError( FormulaError::UnknownVariable);
1287 void ScInterpreter::GetExternalDoubleRef(
1288 sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1290 ScExternalRefManager* pRefMgr = mrDoc.GetExternalRefManager();
1291 const OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1292 if (!pFile)
1294 SetError(FormulaError::NoName);
1295 return;
1297 if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
1299 OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1300 SetError(FormulaError::NoRef);
1301 return;
1304 ScComplexRefData aData(rData);
1305 ScRange aRange = aData.toAbs(mrDoc, aPos);
1306 if (!mrDoc.ValidColRow(aRange.aStart.Col(), aRange.aStart.Row()) || !mrDoc.ValidColRow(aRange.aEnd.Col(), aRange.aEnd.Row()))
1308 SetError(FormulaError::NoRef);
1309 return;
1312 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1313 nFileId, rTabName, aRange, &aPos);
1315 if (!pArray)
1317 SetError(FormulaError::IllegalArgument);
1318 return;
1321 formula::FormulaTokenArrayPlainIterator aIter(*pArray);
1322 formula::FormulaToken* pToken = aIter.First();
1323 assert(pToken);
1324 if (pToken->GetType() == svError)
1326 SetError( pToken->GetError());
1327 return;
1329 if (pToken->GetType() != svMatrix)
1331 SetError(FormulaError::IllegalArgument);
1332 return;
1335 if (aIter.Next())
1337 // Can't handle more than one matrix per parameter.
1338 SetError( FormulaError::IllegalArgument);
1339 return;
1342 rArray = std::move(pArray);
1345 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1347 switch ( GetStackType() )
1349 case svDoubleRef :
1351 ScRange aRange;
1352 PopDoubleRef( aRange, true );
1353 return DoubleRefToPosSingleRef( aRange, rAdr );
1355 case svSingleRef :
1357 PopSingleRef( rAdr );
1358 return true;
1360 default:
1361 PopError();
1362 SetError( FormulaError::NoRef );
1364 return false;
1367 void ScInterpreter::PopDoubleRefPushMatrix()
1369 if ( GetStackType() == svDoubleRef )
1371 ScMatrixRef pMat = GetMatrix();
1372 if ( pMat )
1373 PushMatrix( pMat );
1374 else
1375 PushIllegalParameter();
1377 else
1378 SetError( FormulaError::NoRef );
1381 void ScInterpreter::PopRefListPushMatrixOrRef()
1383 if ( GetStackType() == svRefList )
1385 FormulaConstTokenRef xTok = pStack[sp-1];
1386 const std::vector<ScComplexRefData>* pv = xTok->GetRefList();
1387 if (pv)
1389 const size_t nEntries = pv->size();
1390 if (nEntries == 1)
1392 --sp;
1393 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc.GetSheetLimits(), (*pv)[0] ));
1395 else if (bMatrixFormula)
1397 // Only single cells can be stuffed into a column vector.
1398 // XXX NOTE: Excel doesn't do this but returns #VALUE! instead.
1399 // Though there's no compelling reason not to...
1400 for (const auto & rRef : *pv)
1402 if (rRef.Ref1 != rRef.Ref2)
1403 return;
1405 ScMatrixRef xMat = GetNewMat( 1, nEntries, true); // init empty
1406 if (!xMat)
1407 return;
1408 for (size_t i=0; i < nEntries; ++i)
1410 SCCOL nCol; SCROW nRow; SCTAB nTab;
1411 SingleRefToVars( (*pv)[i].Ref1, nCol, nRow, nTab);
1412 if (nGlobalError == FormulaError::NONE)
1414 ScAddress aAdr( nCol, nRow, nTab);
1415 ScRefCellValue aCell(mrDoc, aAdr);
1416 if (aCell.hasError())
1417 xMat->PutError( aCell.getFormula()->GetErrCode(), 0, i);
1418 else if (aCell.hasEmptyValue())
1419 xMat->PutEmpty( 0, i);
1420 else if (aCell.hasString())
1421 xMat->PutString( mrStrPool.intern( aCell.getString(&mrDoc)), 0, i);
1422 else
1423 xMat->PutDouble( aCell.getValue(), 0, i);
1425 else
1427 xMat->PutError( nGlobalError, 0, i);
1428 nGlobalError = FormulaError::NONE;
1431 --sp;
1432 PushMatrix( xMat);
1435 // else: keep token on stack, something will handle the error
1437 else
1438 SetError( FormulaError::NoRef );
1441 void ScInterpreter::ConvertMatrixJumpConditionToMatrix()
1443 StackVar eStackType = GetStackType();
1444 if (eStackType == svUnknown)
1445 return; // can't do anything, some caller will catch that
1446 if (eStackType == svMatrix)
1447 return; // already matrix, nothing to do
1449 if (eStackType != svDoubleRef && GetStackType(2) != svJumpMatrix)
1450 return; // always convert svDoubleRef, others only in JumpMatrix context
1452 GetTokenMatrixMap(); // make sure it exists, create if not.
1453 ScMatrixRef pMat = GetMatrix();
1454 if ( pMat )
1455 PushMatrix( pMat );
1456 else
1457 PushIllegalParameter();
1460 bool ScInterpreter::ConvertMatrixParameters()
1462 sal_uInt16 nParams = pCur->GetParamCount();
1463 SAL_WARN_IF( nParams > sp, "sc.core", "ConvertMatrixParameters: stack/param count mismatch: eOp: "
1464 << static_cast<int>(pCur->GetOpCode()) << " sp: " << sp << " nParams: " << nParams);
1465 assert(nParams <= sp);
1466 SCSIZE nJumpCols = 0, nJumpRows = 0;
1467 for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
1469 const FormulaToken* p = pStack[ sp - i ];
1470 if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
1472 assert(!"ConvertMatrixParameters: not a push");
1474 else
1476 switch ( p->GetType() )
1478 case svDouble:
1479 case svString:
1480 case svSingleRef:
1481 case svExternalSingleRef:
1482 case svMissing:
1483 case svError:
1484 case svEmptyCell:
1485 // nothing to do
1486 break;
1487 case svMatrix:
1489 if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1490 == formula::ParamClass::Value )
1491 { // only if single value expected
1492 ScConstMatrixRef pMat = p->GetMatrix();
1493 if ( !pMat )
1494 SetError( FormulaError::UnknownVariable);
1495 else
1497 SCSIZE nCols, nRows;
1498 pMat->GetDimensions( nCols, nRows);
1499 if ( nJumpCols < nCols )
1500 nJumpCols = nCols;
1501 if ( nJumpRows < nRows )
1502 nJumpRows = nRows;
1506 break;
1507 case svDoubleRef:
1509 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1510 if ( eType != formula::ParamClass::Reference &&
1511 eType != formula::ParamClass::ReferenceOrRefArray &&
1512 eType != formula::ParamClass::ReferenceOrForceArray &&
1513 // For scalar Value: convert to Array/JumpMatrix
1514 // only if in array formula context, else (function
1515 // has ForceArray or ReferenceOrForceArray
1516 // parameter *somewhere else*) pick a normal
1517 // position dependent implicit intersection later.
1518 (eType != formula::ParamClass::Value || IsInArrayContext()))
1520 SCCOL nCol1, nCol2;
1521 SCROW nRow1, nRow2;
1522 SCTAB nTab1, nTab2;
1523 DoubleRefToVars( p, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1524 // Make sure the map exists, created if not.
1525 GetTokenMatrixMap();
1526 ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1527 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1528 if (pMat)
1530 if ( eType == formula::ParamClass::Value )
1531 { // only if single value expected
1532 if ( nJumpCols < o3tl::make_unsigned(nCol2 - nCol1 + 1) )
1533 nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1534 if ( nJumpRows < o3tl::make_unsigned(nRow2 - nRow1 + 1) )
1535 nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1537 formula::FormulaToken* pNew = new ScMatrixToken( std::move(pMat) );
1538 pNew->IncRef();
1539 pStack[ sp - i ] = pNew;
1540 p->DecRef(); // p may be dead now!
1544 break;
1545 case svExternalDoubleRef:
1547 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1548 if (eType == formula::ParamClass::Value || eType == formula::ParamClass::Array)
1550 sal_uInt16 nFileId = p->GetIndex();
1551 OUString aTabName = p->GetString().getString();
1552 const ScComplexRefData& rRef = *p->GetDoubleRef();
1553 ScExternalRefCache::TokenArrayRef pArray;
1554 GetExternalDoubleRef(nFileId, aTabName, rRef, pArray);
1555 if (nGlobalError != FormulaError::NONE || !pArray)
1556 break;
1557 formula::FormulaToken* pTemp = pArray->FirstToken();
1558 if (!pTemp)
1559 break;
1561 ScMatrixRef pMat = pTemp->GetMatrix();
1562 if (pMat)
1564 if (eType == formula::ParamClass::Value)
1565 { // only if single value expected
1566 SCSIZE nC, nR;
1567 pMat->GetDimensions( nC, nR);
1568 if (nJumpCols < nC)
1569 nJumpCols = nC;
1570 if (nJumpRows < nR)
1571 nJumpRows = nR;
1573 formula::FormulaToken* pNew = new ScMatrixToken( std::move(pMat) );
1574 pNew->IncRef();
1575 pStack[ sp - i ] = pNew;
1576 p->DecRef(); // p may be dead now!
1580 break;
1581 case svRefList:
1583 formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i);
1584 if ( eType != formula::ParamClass::Reference &&
1585 eType != formula::ParamClass::ReferenceOrRefArray &&
1586 eType != formula::ParamClass::ReferenceOrForceArray &&
1587 eType != formula::ParamClass::ForceArray)
1589 // can't convert to matrix
1590 SetError( FormulaError::NoRef);
1592 // else: the consuming function has to decide if and how to
1593 // handle a reference list argument in array context.
1595 break;
1596 default:
1597 assert(!"ConvertMatrixParameters: unknown parameter type");
1601 if( nJumpCols && nJumpRows )
1603 short nPC = aCode.GetPC();
1604 short nStart = nPC - 1; // restart on current code (-1)
1605 short nNext = nPC; // next instruction after subroutine
1606 short nStop = nPC + 1; // stop subroutine before reaching that
1607 FormulaConstTokenRef xNew;
1608 ScTokenMatrixMap::const_iterator aMapIter;
1609 if ((aMapIter = maTokenMatrixMap.find( pCur)) != maTokenMatrixMap.end())
1610 xNew = (*aMapIter).second;
1611 else
1613 std::shared_ptr<ScJumpMatrix> pJumpMat;
1616 pJumpMat = std::make_shared<ScJumpMatrix>( pCur->GetOpCode(), nJumpCols, nJumpRows);
1618 catch (const std::bad_alloc&)
1620 SAL_WARN("sc.core", "std::bad_alloc in ScJumpMatrix ctor with " << nJumpCols << " columns and " << nJumpRows << " rows");
1621 return false;
1623 pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1624 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1625 ScTokenVec aParams(nParams);
1626 for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
1628 const FormulaToken* p = pStack[ --sp ];
1629 p->IncRef();
1630 // store in reverse order such that a push may simply iterate
1631 aParams[ nParams - i ] = p;
1633 pJumpMat->SetJumpParameters( std::move(aParams) );
1634 xNew = new ScJumpMatrixToken( std::move(pJumpMat) );
1635 GetTokenMatrixMap().emplace(pCur, xNew);
1637 PushTempTokenWithoutError( xNew.get());
1638 // set continuation point of path for main code line
1639 aCode.Jump( nNext, nNext);
1640 return true;
1642 return false;
1645 ScMatrixRef ScInterpreter::PopMatrix()
1647 if( sp )
1649 --sp;
1650 const FormulaToken* p = pStack[ sp ];
1651 switch (p->GetType())
1653 case svError:
1654 nGlobalError = p->GetError();
1655 break;
1656 case svMatrix:
1658 // ScMatrix itself maintains an im/mutable flag that should
1659 // be obeyed where necessary... so we can return ScMatrixRef
1660 // here instead of ScConstMatrixRef.
1661 ScMatrix* pMat = const_cast<FormulaToken*>(p)->GetMatrix();
1662 if ( pMat )
1663 pMat->SetErrorInterpreter( this);
1664 else
1665 SetError( FormulaError::UnknownVariable);
1666 return pMat;
1668 default:
1669 SetError( FormulaError::IllegalParameter);
1672 else
1673 SetError( FormulaError::UnknownStackVariable);
1674 return nullptr;
1677 sc::RangeMatrix ScInterpreter::PopRangeMatrix()
1679 sc::RangeMatrix aRet;
1680 if (sp)
1682 switch (pStack[sp-1]->GetType())
1684 case svMatrix:
1686 --sp;
1687 const FormulaToken* p = pStack[sp];
1688 aRet.mpMat = const_cast<FormulaToken*>(p)->GetMatrix();
1689 if (aRet.mpMat)
1691 aRet.mpMat->SetErrorInterpreter(this);
1692 if (p->GetByte() == MATRIX_TOKEN_HAS_RANGE)
1694 const ScComplexRefData& rRef = *p->GetDoubleRef();
1695 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
1697 aRet.mnCol1 = rRef.Ref1.Col();
1698 aRet.mnRow1 = rRef.Ref1.Row();
1699 aRet.mnTab1 = rRef.Ref1.Tab();
1700 aRet.mnCol2 = rRef.Ref2.Col();
1701 aRet.mnRow2 = rRef.Ref2.Row();
1702 aRet.mnTab2 = rRef.Ref2.Tab();
1706 else
1707 SetError( FormulaError::UnknownVariable);
1709 break;
1710 default:
1711 aRet.mpMat = PopMatrix();
1714 return aRet;
1717 void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, SvNumFormatType& rRetTypeExpr, sal_uInt32& rRetIndexExpr)
1719 if (xMat)
1721 SCSIZE nCols, nRows;
1722 xMat->GetDimensions(nCols, nRows);
1723 ScMatrixValue nMatVal = xMat->Get(0, 0);
1724 ScMatValType nMatValType = nMatVal.nType;
1725 if (ScMatrix::IsNonValueType( nMatValType))
1727 if ( xMat->IsEmptyPath( 0, 0))
1728 { // result of empty FALSE jump path
1729 FormulaTokenRef xRes = CreateFormulaDoubleToken( 0.0);
1730 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1731 rRetTypeExpr = SvNumFormatType::LOGICAL;
1733 else if ( xMat->IsEmptyResult( 0, 0))
1734 { // empty formula result
1735 FormulaTokenRef xRes = new ScEmptyCellToken( true, true); // inherited, display empty
1736 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1738 else if ( xMat->IsEmpty( 0, 0))
1739 { // empty or empty cell
1740 FormulaTokenRef xRes = new ScEmptyCellToken( false, true); // not inherited, display empty
1741 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1743 else
1745 FormulaTokenRef xRes = new FormulaStringToken( nMatVal.GetString() );
1746 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1747 rRetTypeExpr = SvNumFormatType::TEXT;
1750 else
1752 FormulaError nErr = GetDoubleErrorValue( nMatVal.fVal);
1753 FormulaTokenRef xRes;
1754 if (nErr != FormulaError::NONE)
1755 xRes = new FormulaErrorToken( nErr);
1756 else
1757 xRes = CreateFormulaDoubleToken( nMatVal.fVal);
1758 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1759 if ( rRetTypeExpr != SvNumFormatType::LOGICAL )
1760 rRetTypeExpr = SvNumFormatType::NUMBER;
1762 rRetIndexExpr = 0;
1763 xMat->SetErrorInterpreter( nullptr);
1765 else
1766 SetError( FormulaError::UnknownStackVariable);
1769 formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, SvNumFormatType nFmt )
1771 assert( mrContext.maTokens.size() == TOKEN_CACHE_SIZE );
1773 // Find a spare token
1774 for ( auto p : mrContext.maTokens )
1776 if (p && p->GetRef() == 1)
1778 p->SetDouble(fVal);
1779 p->SetDoubleType( static_cast<sal_Int16>(nFmt) );
1780 return p;
1784 // Allocate a new token
1785 auto p = new FormulaTypedDoubleToken( fVal, static_cast<sal_Int16>(nFmt) );
1786 p->SetRefCntPolicy(RefCntPolicy::UnsafeRef);
1787 if ( mrContext.maTokens[mrContext.mnTokenCachePos] )
1788 mrContext.maTokens[mrContext.mnTokenCachePos]->DecRef();
1789 mrContext.maTokens[mrContext.mnTokenCachePos] = p;
1790 p->IncRef();
1791 mrContext.mnTokenCachePos = (mrContext.mnTokenCachePos + 1) % TOKEN_CACHE_SIZE;
1792 return p;
1795 formula::FormulaToken* ScInterpreter::CreateDoubleOrTypedToken( double fVal )
1797 // NumberFormat::NUMBER is the default untyped double.
1798 if (nFuncFmtType != SvNumFormatType::ALL && nFuncFmtType != SvNumFormatType::NUMBER &&
1799 nFuncFmtType != SvNumFormatType::UNDEFINED)
1800 return CreateFormulaDoubleToken( fVal, nFuncFmtType);
1801 else
1802 return CreateFormulaDoubleToken( fVal);
1805 void ScInterpreter::PushDouble(double nVal)
1807 TreatDoubleError( nVal );
1808 if (!IfErrorPushError())
1809 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal));
1812 void ScInterpreter::PushInt(int nVal)
1814 if (!IfErrorPushError())
1815 PushTempTokenWithoutError( CreateDoubleOrTypedToken( nVal));
1818 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1820 if ( pString )
1822 svl::SharedString aSS = mrDoc.GetSharedStringPool().intern(OUString(pString));
1823 PushString(aSS);
1825 else
1826 PushString(svl::SharedString::getEmptyString());
1829 void ScInterpreter::PushString( const OUString& rStr )
1831 PushString(mrDoc.GetSharedStringPool().intern(rStr));
1834 void ScInterpreter::PushString( const svl::SharedString& rString )
1836 if (!IfErrorPushError())
1837 PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1840 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1842 if (!IfErrorPushError())
1844 ScSingleRefData aRef;
1845 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1846 PushTempTokenWithoutError( new ScSingleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1850 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1851 SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1853 if (!IfErrorPushError())
1855 ScComplexRefData aRef;
1856 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1857 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1861 void ScInterpreter::PushExternalSingleRef(
1862 sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1864 if (!IfErrorPushError())
1866 ScSingleRefData aRef;
1867 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1868 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId,
1869 mrDoc.GetSharedStringPool().intern( rTabName), aRef)) ;
1873 void ScInterpreter::PushExternalDoubleRef(
1874 sal_uInt16 nFileId, const OUString& rTabName,
1875 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1877 if (!IfErrorPushError())
1879 ScComplexRefData aRef;
1880 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1881 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId,
1882 mrDoc.GetSharedStringPool().intern( rTabName), aRef) );
1886 void ScInterpreter::PushSingleRef( const ScRefAddress& rRef )
1888 if (!IfErrorPushError())
1890 ScSingleRefData aRef;
1891 aRef.InitFromRefAddress( mrDoc, rRef, aPos);
1892 PushTempTokenWithoutError( new ScSingleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1896 void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 )
1898 if (!IfErrorPushError())
1900 ScComplexRefData aRef;
1901 aRef.InitFromRefAddresses( mrDoc, rRef1, rRef2, aPos);
1902 PushTempTokenWithoutError( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRef ) );
1906 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
1908 if (!rMat.isRangeValid())
1910 // Just push the matrix part only.
1911 PushMatrix(rMat.mpMat);
1912 return;
1915 rMat.mpMat->SetErrorInterpreter(nullptr);
1916 nGlobalError = FormulaError::NONE;
1917 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat));
1920 void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
1922 pMat->SetErrorInterpreter( nullptr);
1923 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1924 // but with notifying ScInterpreter via nGlobalError, substituting it would
1925 // mean to inherit the error on all array elements in all following
1926 // operations.
1927 nGlobalError = FormulaError::NONE;
1928 PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
1931 void ScInterpreter::PushError( FormulaError nError )
1933 SetError( nError ); // only sets error if not already set
1934 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
1937 void ScInterpreter::PushParameterExpected()
1939 PushError( FormulaError::ParameterExpected);
1942 void ScInterpreter::PushIllegalParameter()
1944 PushError( FormulaError::IllegalParameter);
1947 void ScInterpreter::PushIllegalArgument()
1949 PushError( FormulaError::IllegalArgument);
1952 void ScInterpreter::PushNA()
1954 PushError( FormulaError::NotAvailable);
1957 void ScInterpreter::PushNoValue()
1959 PushError( FormulaError::NoValue);
1962 bool ScInterpreter::IsMissing() const
1964 return sp && pStack[sp - 1]->GetType() == svMissing;
1967 StackVar ScInterpreter::GetRawStackType()
1969 StackVar eRes;
1970 if( sp )
1972 eRes = pStack[sp - 1]->GetType();
1974 else
1976 SetError(FormulaError::UnknownStackVariable);
1977 eRes = svUnknown;
1979 return eRes;
1982 StackVar ScInterpreter::GetStackType()
1984 StackVar eRes;
1985 if( sp )
1987 eRes = pStack[sp - 1]->GetType();
1988 if( eRes == svMissing || eRes == svEmptyCell )
1989 eRes = svDouble; // default!
1991 else
1993 SetError(FormulaError::UnknownStackVariable);
1994 eRes = svUnknown;
1996 return eRes;
1999 StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
2001 StackVar eRes;
2002 if( sp > nParam-1 )
2004 eRes = pStack[sp - nParam]->GetType();
2005 if( eRes == svMissing || eRes == svEmptyCell )
2006 eRes = svDouble; // default!
2008 else
2009 eRes = svUnknown;
2010 return eRes;
2013 void ScInterpreter::ReverseStack( sal_uInt8 nParamCount )
2015 //reverse order of parameter stack
2016 assert( sp >= nParamCount && " less stack elements than parameters");
2017 sal_uInt16 nStackParams = std::min<sal_uInt16>( sp, nParamCount);
2018 std::reverse( pStack+(sp-nStackParams), pStack+sp );
2021 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
2023 // Check for a singleton first - no implicit intersection for them.
2024 if( rRange.aStart == rRange.aEnd )
2026 rAdr = rRange.aStart;
2027 return true;
2030 bool bOk = false;
2032 if ( pJumpMatrix )
2034 bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
2035 if ( !bOk )
2036 SetError( FormulaError::IllegalArgument);
2037 else
2039 SCSIZE nC, nR;
2040 pJumpMatrix->GetPos( nC, nR);
2041 rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
2042 rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
2043 rAdr.SetTab( rRange.aStart.Tab());
2044 bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
2045 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
2046 rAdr.Row() <= rRange.aEnd.Row();
2047 if ( !bOk )
2048 SetError( FormulaError::NoValue);
2050 return bOk;
2053 bOk = ScCompiler::DoubleRefToPosSingleRefScalarCase(rRange, rAdr, aPos);
2055 if ( !bOk )
2056 SetError( FormulaError::NoValue );
2057 return bOk;
2060 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
2062 if (!pMat)
2063 return 0.0;
2065 if ( !pJumpMatrix )
2067 double fVal = pMat->GetDoubleWithStringConversion( 0, 0);
2068 FormulaError nErr = GetDoubleErrorValue( fVal);
2069 if (nErr != FormulaError::NONE)
2071 // Do not propagate the coded double error, but set nGlobalError in
2072 // case the matrix did not have an error interpreter set.
2073 SetError( nErr);
2074 fVal = 0.0;
2076 return fVal;
2079 SCSIZE nCols, nRows, nC, nR;
2080 pMat->GetDimensions( nCols, nRows);
2081 pJumpMatrix->GetPos( nC, nR);
2082 // Use vector replication for single row/column arrays.
2083 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2085 double fVal = pMat->GetDoubleWithStringConversion( nC, nR);
2086 FormulaError nErr = GetDoubleErrorValue( fVal);
2087 if (nErr != FormulaError::NONE)
2089 // Do not propagate the coded double error, but set nGlobalError in
2090 // case the matrix did not have an error interpreter set.
2091 SetError( nErr);
2092 fVal = 0.0;
2094 return fVal;
2097 SetError( FormulaError::NoValue);
2098 return 0.0;
2101 double ScInterpreter::GetDouble()
2103 double nVal;
2104 switch( GetRawStackType() )
2106 case svDouble:
2107 nVal = PopDouble();
2108 break;
2109 case svString:
2110 nVal = ConvertStringToValue( PopString().getString());
2111 break;
2112 case svSingleRef:
2114 ScAddress aAdr;
2115 PopSingleRef( aAdr );
2116 ScRefCellValue aCell(mrDoc, aAdr);
2117 nVal = GetCellValue(aAdr, aCell);
2119 break;
2120 case svDoubleRef:
2121 { // generate position dependent SingleRef
2122 ScRange aRange;
2123 PopDoubleRef( aRange );
2124 ScAddress aAdr;
2125 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) )
2127 ScRefCellValue aCell(mrDoc, aAdr);
2128 nVal = GetCellValue(aAdr, aCell);
2130 else
2131 nVal = 0.0;
2133 break;
2134 case svExternalSingleRef:
2136 ScExternalRefCache::TokenRef pToken;
2137 PopExternalSingleRef(pToken);
2138 if (nGlobalError != FormulaError::NONE)
2140 nVal = 0.0;
2141 break;
2144 if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell)
2145 nVal = pToken->GetDouble();
2146 else
2147 nVal = ConvertStringToValue( pToken->GetString().getString());
2149 break;
2150 case svExternalDoubleRef:
2152 ScMatrixRef pMat;
2153 PopExternalDoubleRef(pMat);
2154 if (nGlobalError != FormulaError::NONE)
2156 nVal = 0.0;
2157 break;
2160 nVal = GetDoubleFromMatrix(pMat);
2162 break;
2163 case svMatrix:
2165 ScMatrixRef pMat = PopMatrix();
2166 nVal = GetDoubleFromMatrix(pMat);
2168 break;
2169 case svError:
2170 PopError();
2171 nVal = 0.0;
2172 break;
2173 case svEmptyCell:
2174 case svMissing:
2175 Pop();
2176 nVal = 0.0;
2177 break;
2178 default:
2179 PopError();
2180 SetError( FormulaError::IllegalParameter);
2181 nVal = 0.0;
2183 if ( nFuncFmtType == nCurFmtType )
2184 nFuncFmtIndex = nCurFmtIndex;
2185 return nVal;
2188 double ScInterpreter::GetDoubleWithDefault(double nDefault)
2190 bool bMissing = IsMissing();
2191 double nResultVal = GetDouble();
2192 if ( bMissing )
2193 nResultVal = nDefault;
2194 return nResultVal;
2197 bool ScInterpreter::GetBoolWithDefault(bool bDefault)
2199 bool bMissing = IsMissing();
2200 bool bResultVal = (GetDouble() != 0.0);
2201 if (bMissing)
2202 bResultVal = bDefault;
2203 return bResultVal;
2206 sal_Int32 ScInterpreter::double_to_int32(double fVal)
2208 if (!std::isfinite(fVal))
2210 SetError( GetDoubleErrorValue( fVal));
2211 return SAL_MAX_INT32;
2213 if (fVal > 0.0)
2215 fVal = rtl::math::approxFloor( fVal);
2216 if (fVal > SAL_MAX_INT32)
2218 SetError( FormulaError::IllegalArgument);
2219 return SAL_MAX_INT32;
2222 else if (fVal < 0.0)
2224 fVal = rtl::math::approxCeil( fVal);
2225 if (fVal < SAL_MIN_INT32)
2227 SetError( FormulaError::IllegalArgument);
2228 return SAL_MAX_INT32;
2231 return static_cast<sal_Int32>(fVal);
2234 sal_Int32 ScInterpreter::GetInt32()
2236 return double_to_int32(GetDouble());
2239 sal_Int32 ScInterpreter::GetInt32WithDefault( sal_Int32 nDefault )
2241 bool bMissing = IsMissing();
2242 double fVal = GetDouble();
2243 if ( bMissing )
2244 return nDefault;
2245 return double_to_int32(fVal);
2248 sal_Int32 ScInterpreter::GetFloor32()
2250 double fVal = GetDouble();
2251 if (!std::isfinite(fVal))
2253 SetError( GetDoubleErrorValue( fVal));
2254 return SAL_MAX_INT32;
2256 fVal = rtl::math::approxFloor( fVal);
2257 if (fVal < SAL_MIN_INT32 || SAL_MAX_INT32 < fVal)
2259 SetError( FormulaError::IllegalArgument);
2260 return SAL_MAX_INT32;
2262 return static_cast<sal_Int32>(fVal);
2265 sal_Int16 ScInterpreter::GetInt16()
2267 double fVal = GetDouble();
2268 if (!std::isfinite(fVal))
2270 SetError( GetDoubleErrorValue( fVal));
2271 return SAL_MAX_INT16;
2273 if (fVal > 0.0)
2275 fVal = rtl::math::approxFloor( fVal);
2276 if (fVal > SAL_MAX_INT16)
2278 SetError( FormulaError::IllegalArgument);
2279 return SAL_MAX_INT16;
2282 else if (fVal < 0.0)
2284 fVal = rtl::math::approxCeil( fVal);
2285 if (fVal < SAL_MIN_INT16)
2287 SetError( FormulaError::IllegalArgument);
2288 return SAL_MAX_INT16;
2291 return static_cast<sal_Int16>(fVal);
2294 sal_uInt32 ScInterpreter::GetUInt32()
2296 double fVal = rtl::math::approxFloor( GetDouble());
2297 if (!std::isfinite(fVal))
2299 SetError( GetDoubleErrorValue( fVal));
2300 return SAL_MAX_UINT32;
2302 if (fVal < 0.0 || fVal > SAL_MAX_UINT32)
2304 SetError( FormulaError::IllegalArgument);
2305 return SAL_MAX_UINT32;
2307 return static_cast<sal_uInt32>(fVal);
2310 bool ScInterpreter::GetDoubleOrString( double& rDouble, svl::SharedString& rString )
2312 bool bDouble = true;
2313 switch( GetRawStackType() )
2315 case svDouble:
2316 rDouble = PopDouble();
2317 break;
2318 case svString:
2319 rString = PopString();
2320 bDouble = false;
2321 break;
2322 case svDoubleRef :
2323 case svSingleRef :
2325 ScAddress aAdr;
2326 if (!PopDoubleRefOrSingleRef( aAdr))
2328 rDouble = 0.0;
2329 return true; // caller needs to check nGlobalError
2331 ScRefCellValue aCell( mrDoc, aAdr);
2332 if (aCell.hasNumeric())
2334 rDouble = GetCellValue( aAdr, aCell);
2336 else
2338 GetCellString( rString, aCell);
2339 bDouble = false;
2342 break;
2343 case svExternalSingleRef:
2344 case svExternalDoubleRef:
2345 case svMatrix:
2347 ScMatValType nType = GetDoubleOrStringFromMatrix( rDouble, rString);
2348 bDouble = ScMatrix::IsValueType( nType);
2350 break;
2351 case svError:
2352 PopError();
2353 rDouble = 0.0;
2354 break;
2355 case svEmptyCell:
2356 case svMissing:
2357 Pop();
2358 rDouble = 0.0;
2359 break;
2360 default:
2361 PopError();
2362 SetError( FormulaError::IllegalParameter);
2363 rDouble = 0.0;
2365 if ( nFuncFmtType == nCurFmtType )
2366 nFuncFmtIndex = nCurFmtIndex;
2367 return bDouble;
2370 svl::SharedString ScInterpreter::GetString()
2372 switch (GetRawStackType())
2374 case svError:
2375 PopError();
2376 return svl::SharedString::getEmptyString();
2377 case svMissing:
2378 case svEmptyCell:
2379 Pop();
2380 return svl::SharedString::getEmptyString();
2381 case svDouble:
2383 return GetStringFromDouble( PopDouble() );
2385 case svString:
2386 return PopString();
2387 case svSingleRef:
2389 ScAddress aAdr;
2390 PopSingleRef( aAdr );
2391 if (nGlobalError == FormulaError::NONE)
2393 ScRefCellValue aCell(mrDoc, aAdr);
2394 svl::SharedString aSS;
2395 GetCellString(aSS, aCell);
2396 return aSS;
2398 else
2399 return svl::SharedString::getEmptyString();
2401 case svDoubleRef:
2402 { // generate position dependent SingleRef
2403 ScRange aRange;
2404 PopDoubleRef( aRange );
2405 ScAddress aAdr;
2406 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr ) )
2408 ScRefCellValue aCell(mrDoc, aAdr);
2409 svl::SharedString aSS;
2410 GetCellString(aSS, aCell);
2411 return aSS;
2413 else
2414 return svl::SharedString::getEmptyString();
2416 case svExternalSingleRef:
2418 ScExternalRefCache::TokenRef pToken;
2419 PopExternalSingleRef(pToken);
2420 if (nGlobalError != FormulaError::NONE)
2421 return svl::SharedString::getEmptyString();
2423 if (pToken->GetType() == svDouble)
2425 return GetStringFromDouble( pToken->GetDouble() );
2427 else // svString or svEmpty
2428 return pToken->GetString();
2430 case svExternalDoubleRef:
2432 ScMatrixRef pMat;
2433 PopExternalDoubleRef(pMat);
2434 return GetStringFromMatrix(pMat);
2436 case svMatrix:
2438 ScMatrixRef pMat = PopMatrix();
2439 return GetStringFromMatrix(pMat);
2441 break;
2442 default:
2443 PopError();
2444 SetError( FormulaError::IllegalArgument);
2446 return svl::SharedString::getEmptyString();
2449 svl::SharedString ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2451 if ( !pMat )
2452 ; // nothing
2453 else if ( !pJumpMatrix )
2455 return pMat->GetString( mrContext, 0, 0);
2457 else
2459 SCSIZE nCols, nRows, nC, nR;
2460 pMat->GetDimensions( nCols, nRows);
2461 pJumpMatrix->GetPos( nC, nR);
2462 // Use vector replication for single row/column arrays.
2463 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2464 return pMat->GetString( mrContext, nC, nR);
2466 SetError( FormulaError::NoValue);
2468 return svl::SharedString::getEmptyString();
2471 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix(
2472 double& rDouble, svl::SharedString& rString )
2475 rDouble = 0.0;
2476 rString = svl::SharedString::getEmptyString();
2477 ScMatValType nMatValType = ScMatValType::Empty;
2479 ScMatrixRef pMat;
2480 StackVar eType = GetStackType();
2481 if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
2483 pMat = GetMatrix();
2485 else
2487 PopError();
2488 SetError( FormulaError::IllegalParameter);
2489 return nMatValType;
2492 ScMatrixValue nMatVal;
2493 if (!pMat)
2495 // nothing
2497 else if (!pJumpMatrix)
2499 nMatVal = pMat->Get(0, 0);
2500 nMatValType = nMatVal.nType;
2502 else
2504 SCSIZE nCols, nRows, nC, nR;
2505 pMat->GetDimensions( nCols, nRows);
2506 pJumpMatrix->GetPos( nC, nR);
2507 // Use vector replication for single row/column arrays.
2508 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
2510 nMatVal = pMat->Get( nC, nR);
2511 nMatValType = nMatVal.nType;
2513 else
2514 SetError( FormulaError::NoValue);
2517 if (ScMatrix::IsValueType( nMatValType))
2519 rDouble = nMatVal.fVal;
2520 FormulaError nError = nMatVal.GetError();
2521 if (nError != FormulaError::NONE)
2522 SetError( nError);
2524 else
2526 rString = nMatVal.GetString();
2529 return nMatValType;
2532 svl::SharedString ScInterpreter::GetStringFromDouble( double fVal )
2534 sal_uLong nIndex = mrContext.NFGetStandardFormat(
2535 SvNumFormatType::NUMBER,
2536 ScGlobal::eLnge);
2537 return mrStrPool.intern(mrContext.NFGetInputLineString(fVal, nIndex));
2540 void ScInterpreter::ScDBGet()
2542 bool bMissingField = false;
2543 unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2544 if (!pQueryParam)
2546 // Failed to create query param.
2547 PushIllegalParameter();
2548 return;
2551 pQueryParam->mbSkipString = false;
2552 ScDBQueryDataIterator aValIter(mrDoc, mrContext, std::move(pQueryParam));
2553 ScDBQueryDataIterator::Value aValue;
2554 if (!aValIter.GetFirst(aValue) || aValue.mnError != FormulaError::NONE)
2556 // No match found.
2557 PushNoValue();
2558 return;
2561 ScDBQueryDataIterator::Value aValNext;
2562 if (aValIter.GetNext(aValNext) && aValNext.mnError == FormulaError::NONE)
2564 // There should be only one unique match.
2565 PushIllegalArgument();
2566 return;
2569 if (aValue.mbIsNumber)
2570 PushDouble(aValue.mfValue);
2571 else
2572 PushString(aValue.maString);
2575 void ScInterpreter::ScExternal()
2577 sal_uInt8 nParamCount = GetByte();
2578 OUString aUnoName;
2579 OUString aFuncName( pCur->GetExternal().toAsciiUpperCase()); // programmatic name
2580 LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName);
2581 if (pLegacyFuncData)
2583 // Old binary non-UNO add-in function.
2584 // NOTE: parameter count is 1-based with the 0th "parameter" being the
2585 // return value, included in pLegacyFuncDatat->GetParamCount()
2586 if (nParamCount < MAXFUNCPARAM && nParamCount == pLegacyFuncData->GetParamCount() - 1)
2588 ParamType eParamType[MAXFUNCPARAM];
2589 void* ppParam[MAXFUNCPARAM];
2590 double nVal[MAXFUNCPARAM];
2591 char* pStr[MAXFUNCPARAM];
2592 sal_uInt8* pCellArr[MAXFUNCPARAM];
2593 short i;
2595 for (i = 0; i < MAXFUNCPARAM; i++)
2597 eParamType[i] = pLegacyFuncData->GetParamType(i);
2598 ppParam[i] = nullptr;
2599 nVal[i] = 0.0;
2600 pStr[i] = nullptr;
2601 pCellArr[i] = nullptr;
2604 for (i = nParamCount; (i > 0) && (nGlobalError == FormulaError::NONE); i--)
2606 if (IsMissing())
2608 // Old binary Add-In can't distinguish between missing
2609 // omitted argument and 0 (or any other value). Force
2610 // error.
2611 SetError( FormulaError::ParameterExpected);
2612 break; // for
2614 switch (eParamType[i])
2616 case ParamType::PTR_DOUBLE :
2618 nVal[i-1] = GetDouble();
2619 ppParam[i] = &nVal[i-1];
2621 break;
2622 case ParamType::PTR_STRING :
2624 OString aStr(OUStringToOString(GetString().getString(),
2625 osl_getThreadTextEncoding()));
2626 if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2627 SetError( FormulaError::StringOverflow );
2628 else
2630 pStr[i-1] = new char[ADDIN_MAXSTRLEN];
2631 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2632 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2633 ppParam[i] = pStr[i-1];
2636 break;
2637 case ParamType::PTR_DOUBLE_ARR :
2639 SCCOL nCol1;
2640 SCROW nRow1;
2641 SCTAB nTab1;
2642 SCCOL nCol2;
2643 SCROW nRow2;
2644 SCTAB nTab2;
2645 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2646 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2647 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2648 SetError(FormulaError::CodeOverflow);
2649 else
2650 ppParam[i] = pCellArr[i-1];
2652 break;
2653 case ParamType::PTR_STRING_ARR :
2655 SCCOL nCol1;
2656 SCROW nRow1;
2657 SCTAB nTab1;
2658 SCCOL nCol2;
2659 SCROW nRow2;
2660 SCTAB nTab2;
2661 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2662 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2663 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2664 SetError(FormulaError::CodeOverflow);
2665 else
2666 ppParam[i] = pCellArr[i-1];
2668 break;
2669 case ParamType::PTR_CELL_ARR :
2671 SCCOL nCol1;
2672 SCROW nRow1;
2673 SCTAB nTab1;
2674 SCCOL nCol2;
2675 SCROW nRow2;
2676 SCTAB nTab2;
2677 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2678 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2679 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2680 SetError(FormulaError::CodeOverflow);
2681 else
2682 ppParam[i] = pCellArr[i-1];
2684 break;
2685 default :
2686 SetError(FormulaError::IllegalParameter);
2687 break;
2690 while ( i-- )
2691 Pop(); // In case of error (otherwise i==0) pop all parameters
2693 if (nGlobalError == FormulaError::NONE)
2695 if ( pLegacyFuncData->GetAsyncType() == ParamType::NONE )
2697 switch ( eParamType[0] )
2699 case ParamType::PTR_DOUBLE :
2701 double nErg = 0.0;
2702 ppParam[0] = &nErg;
2703 pLegacyFuncData->Call(ppParam);
2704 PushDouble(nErg);
2706 break;
2707 case ParamType::PTR_STRING :
2709 std::unique_ptr<char[]> pcErg(new char[ADDIN_MAXSTRLEN]);
2710 ppParam[0] = pcErg.get();
2711 pLegacyFuncData->Call(ppParam);
2712 OUString aUni( pcErg.get(), strlen(pcErg.get()), osl_getThreadTextEncoding() );
2713 PushString( aUni );
2715 break;
2716 default:
2717 PushError( FormulaError::UnknownState );
2720 else
2722 // enable asyncs after loading
2723 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
2724 // assure identical handler with identical call?
2725 double nErg = 0.0;
2726 ppParam[0] = &nErg;
2727 pLegacyFuncData->Call(ppParam);
2728 sal_uLong nHandle = sal_uLong( nErg );
2729 if ( nHandle >= 65536 )
2731 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2732 if ( !pAs )
2734 pAs = new ScAddInAsync(nHandle, pLegacyFuncData, &mrDoc);
2735 pMyFormulaCell->StartListening( *pAs );
2737 else
2739 pMyFormulaCell->StartListening( *pAs );
2740 if ( !pAs->HasDocument( &mrDoc ) )
2741 pAs->AddDocument( &mrDoc );
2743 if ( pAs->IsValid() )
2745 switch ( pAs->GetType() )
2747 case ParamType::PTR_DOUBLE :
2748 PushDouble( pAs->GetValue() );
2749 break;
2750 case ParamType::PTR_STRING :
2751 PushString( pAs->GetString() );
2752 break;
2753 default:
2754 PushError( FormulaError::UnknownState );
2757 else
2758 PushNA();
2760 else
2761 PushNoValue();
2765 for (i = 0; i < MAXFUNCPARAM; i++)
2767 delete[] pStr[i];
2768 delete[] pCellArr[i];
2771 else
2773 while( nParamCount-- > 0)
2774 PopError();
2775 PushIllegalParameter();
2778 else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty() )
2780 // bLocalFirst=false in FindFunction, cFunc should be the stored
2781 // internal name
2783 ScUnoAddInCall aCall( mrDoc, *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2785 if ( !aCall.ValidParamCount() )
2786 SetError( FormulaError::IllegalParameter );
2788 if ( aCall.NeedsCaller() && GetError() == FormulaError::NONE )
2790 ScDocShell* pShell = mrDoc.GetDocumentShell();
2791 if (pShell)
2792 aCall.SetCallerFromObjectShell( pShell );
2793 else
2795 // use temporary model object (without document) to supply options
2796 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2797 new ScDocOptionsObj( mrDoc.GetDocOptions() ) ) );
2801 short nPar = nParamCount;
2802 while ( nPar > 0 && GetError() == FormulaError::NONE )
2804 --nPar; // 0 .. (nParamCount-1)
2806 uno::Any aParam;
2807 if (IsMissing())
2809 // Add-In has to explicitly handle an omitted empty missing
2810 // argument, do not default to anything like GetDouble() would
2811 // do (e.g. 0).
2812 Pop();
2813 aCall.SetParam( nPar, aParam );
2814 continue; // while
2817 StackVar nStackType = GetStackType();
2818 ScAddInArgumentType eType = aCall.GetArgType( nPar );
2819 switch (eType)
2821 case SC_ADDINARG_INTEGER:
2823 sal_Int32 nVal = GetInt32();
2824 if (nGlobalError == FormulaError::NONE)
2825 aParam <<= nVal;
2827 break;
2829 case SC_ADDINARG_DOUBLE:
2830 aParam <<= GetDouble();
2831 break;
2833 case SC_ADDINARG_STRING:
2834 aParam <<= GetString().getString();
2835 break;
2837 case SC_ADDINARG_INTEGER_ARRAY:
2838 switch( nStackType )
2840 case svDouble:
2841 case svString:
2842 case svSingleRef:
2844 sal_Int32 nVal = GetInt32();
2845 if (nGlobalError == FormulaError::NONE)
2847 uno::Sequence<sal_Int32> aInner( &nVal, 1 );
2848 uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2849 aParam <<= aOuter;
2852 break;
2853 case svDoubleRef:
2855 ScRange aRange;
2856 PopDoubleRef( aRange );
2857 if (!ScRangeToSequence::FillLongArray( aParam, mrDoc, aRange ))
2858 SetError(FormulaError::IllegalParameter);
2860 break;
2861 case svMatrix:
2862 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2863 SetError(FormulaError::IllegalParameter);
2864 break;
2865 default:
2866 PopError();
2867 SetError(FormulaError::IllegalParameter);
2869 break;
2871 case SC_ADDINARG_DOUBLE_ARRAY:
2872 switch( nStackType )
2874 case svDouble:
2875 case svString:
2876 case svSingleRef:
2878 double fVal = GetDouble();
2879 uno::Sequence<double> aInner( &fVal, 1 );
2880 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2881 aParam <<= aOuter;
2883 break;
2884 case svDoubleRef:
2886 ScRange aRange;
2887 PopDoubleRef( aRange );
2888 if (!ScRangeToSequence::FillDoubleArray( aParam, mrDoc, aRange ))
2889 SetError(FormulaError::IllegalParameter);
2891 break;
2892 case svMatrix:
2893 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2894 SetError(FormulaError::IllegalParameter);
2895 break;
2896 default:
2897 PopError();
2898 SetError(FormulaError::IllegalParameter);
2900 break;
2902 case SC_ADDINARG_STRING_ARRAY:
2903 switch( nStackType )
2905 case svDouble:
2906 case svString:
2907 case svSingleRef:
2909 OUString aString = GetString().getString();
2910 uno::Sequence<OUString> aInner( &aString, 1 );
2911 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 );
2912 aParam <<= aOuter;
2914 break;
2915 case svDoubleRef:
2917 ScRange aRange;
2918 PopDoubleRef( aRange );
2919 if (!ScRangeToSequence::FillStringArray( aParam, mrDoc, aRange ))
2920 SetError(FormulaError::IllegalParameter);
2922 break;
2923 case svMatrix:
2924 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), mrContext ))
2925 SetError(FormulaError::IllegalParameter);
2926 break;
2927 default:
2928 PopError();
2929 SetError(FormulaError::IllegalParameter);
2931 break;
2933 case SC_ADDINARG_MIXED_ARRAY:
2934 switch( nStackType )
2936 case svDouble:
2937 case svString:
2938 case svSingleRef:
2940 uno::Any aElem;
2941 if ( nStackType == svDouble )
2942 aElem <<= GetDouble();
2943 else if ( nStackType == svString )
2944 aElem <<= GetString().getString();
2945 else
2947 ScAddress aAdr;
2948 if ( PopDoubleRefOrSingleRef( aAdr ) )
2950 ScRefCellValue aCell(mrDoc, aAdr);
2951 if (aCell.hasString())
2953 svl::SharedString aStr;
2954 GetCellString(aStr, aCell);
2955 aElem <<= aStr.getString();
2957 else
2958 aElem <<= GetCellValue(aAdr, aCell);
2961 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2962 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2963 aParam <<= aOuter;
2965 break;
2966 case svDoubleRef:
2968 ScRange aRange;
2969 PopDoubleRef( aRange );
2970 if (!ScRangeToSequence::FillMixedArray( aParam, mrDoc, aRange ))
2971 SetError(FormulaError::IllegalParameter);
2973 break;
2974 case svMatrix:
2975 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2976 SetError(FormulaError::IllegalParameter);
2977 break;
2978 default:
2979 PopError();
2980 SetError(FormulaError::IllegalParameter);
2982 break;
2984 case SC_ADDINARG_VALUE_OR_ARRAY:
2985 switch( nStackType )
2987 case svDouble:
2988 aParam <<= GetDouble();
2989 break;
2990 case svString:
2991 aParam <<= GetString().getString();
2992 break;
2993 case svSingleRef:
2995 ScAddress aAdr;
2996 if ( PopDoubleRefOrSingleRef( aAdr ) )
2998 ScRefCellValue aCell(mrDoc, aAdr);
2999 if (aCell.hasString())
3001 svl::SharedString aStr;
3002 GetCellString(aStr, aCell);
3003 aParam <<= aStr.getString();
3005 else
3006 aParam <<= GetCellValue(aAdr, aCell);
3009 break;
3010 case svDoubleRef:
3012 ScRange aRange;
3013 PopDoubleRef( aRange );
3014 if (!ScRangeToSequence::FillMixedArray( aParam, mrDoc, aRange ))
3015 SetError(FormulaError::IllegalParameter);
3017 break;
3018 case svMatrix:
3019 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
3020 SetError(FormulaError::IllegalParameter);
3021 break;
3022 default:
3023 PopError();
3024 SetError(FormulaError::IllegalParameter);
3026 break;
3028 case SC_ADDINARG_CELLRANGE:
3029 switch( nStackType )
3031 case svSingleRef:
3033 ScAddress aAdr;
3034 PopSingleRef( aAdr );
3035 ScRange aRange( aAdr );
3036 uno::Reference<table::XCellRange> xObj =
3037 ScCellRangeObj::CreateRangeFromDoc( mrDoc, aRange );
3038 if (xObj.is())
3039 aParam <<= xObj;
3040 else
3041 SetError(FormulaError::IllegalParameter);
3043 break;
3044 case svDoubleRef:
3046 ScRange aRange;
3047 PopDoubleRef( aRange );
3048 uno::Reference<table::XCellRange> xObj =
3049 ScCellRangeObj::CreateRangeFromDoc( mrDoc, aRange );
3050 if (xObj.is())
3052 aParam <<= xObj;
3054 else
3056 SetError(FormulaError::IllegalParameter);
3059 break;
3060 default:
3061 PopError();
3062 SetError(FormulaError::IllegalParameter);
3064 break;
3066 default:
3067 PopError();
3068 SetError(FormulaError::IllegalParameter);
3070 aCall.SetParam( nPar, aParam );
3073 while (nPar-- > 0)
3075 Pop(); // in case of error, remove remaining args
3077 if ( GetError() == FormulaError::NONE )
3079 aCall.ExecuteCall();
3081 if ( aCall.HasVarRes() ) // handle async functions
3083 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
3084 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3085 ScAddInListener* pLis = ScAddInListener::Get( xRes );
3086 // In case there is no pMyFormulaCell, i.e. while interpreting
3087 // temporarily from within the Function Wizard, try to obtain a
3088 // valid result from an existing listener for that volatile, or
3089 // create a new and hope for an immediate result. If none
3090 // available that should lead to a void result and thus #N/A.
3091 bool bTemporaryListener = false;
3092 if ( !pLis )
3094 pLis = ScAddInListener::CreateListener( xRes, &mrDoc );
3095 if (pMyFormulaCell)
3096 pMyFormulaCell->StartListening( *pLis );
3097 else
3098 bTemporaryListener = true;
3100 else if (pMyFormulaCell)
3102 pMyFormulaCell->StartListening( *pLis );
3103 if ( !pLis->HasDocument( &mrDoc ) )
3105 pLis->AddDocument( &mrDoc );
3109 aCall.SetResult( pLis->GetResult() ); // use result from async
3111 if (bTemporaryListener)
3115 // EventObject can be any, not evaluated by
3116 // ScAddInListener::disposing()
3117 css::lang::EventObject aEvent;
3118 pLis->disposing(aEvent); // pLis is dead hereafter
3120 catch (const uno::Exception&)
3126 if ( aCall.GetErrCode() != FormulaError::NONE )
3128 PushError( aCall.GetErrCode() );
3130 else if ( aCall.HasMatrix() )
3132 PushMatrix( aCall.GetMatrix() );
3134 else if ( aCall.HasString() )
3136 PushString( aCall.GetString() );
3138 else
3140 PushDouble( aCall.GetValue() );
3143 else // error...
3144 PushError( GetError());
3146 else
3148 while( nParamCount-- > 0)
3150 PopError();
3152 PushError( FormulaError::NoAddin );
3156 void ScInterpreter::ScMissing()
3158 if ( aCode.IsEndOfPath() )
3159 PushTempToken( new ScEmptyCellToken( false, false ) );
3160 else
3161 PushTempToken( new FormulaMissingToken );
3164 #if HAVE_FEATURE_SCRIPTING
3166 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, const ScDocument* pDok )
3168 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3169 uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
3170 OUString sCodeName;
3171 xProps->getPropertyValue(u"CodeName"_ustr) >>= sCodeName;
3172 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3173 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3174 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3175 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3176 // create the special document module objects if they don't exist.
3177 BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3179 uno::Reference< uno::XInterface > xIf;
3180 if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
3182 OUString sProj( u"Standard"_ustr );
3183 if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3185 sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
3187 StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3188 if ( pBasic )
3190 SbModule* pMod = pBasic->FindModule( sCodeName );
3191 if ( pMod )
3193 xIf = pMod->GetUnoModule();
3197 return uno::Any( xIf );
3200 static bool lcl_setVBARange( const ScRange& aRange, const ScDocument& rDok, SbxVariable* pPar )
3202 bool bOk = false;
3205 uno::Reference< uno::XInterface > xVBARange;
3206 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( rDok, aRange );
3207 uno::Sequence< uno::Any > aArgs{ lcl_getSheetModule( xCellRange, &rDok ),
3208 uno::Any(xCellRange) };
3209 xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( rDok.GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
3210 if ( xVBARange.is() )
3212 SbxObjectRef aObj = GetSbUnoObject( u"A-Range"_ustr, uno::Any( xVBARange ) );
3213 SetSbUnoObjectDfltPropName( aObj.get() );
3214 bOk = pPar->PutObject( aObj.get() );
3217 catch( uno::Exception& )
3220 return bOk;
3223 static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar )
3225 switch (pVar->GetType())
3227 case SbxINTEGER:
3228 case SbxLONG:
3229 case SbxSINGLE:
3230 case SbxDOUBLE:
3231 case SbxCURRENCY:
3232 case SbxDATE:
3233 case SbxUSHORT:
3234 case SbxULONG:
3235 case SbxINT:
3236 case SbxUINT:
3237 case SbxSALINT64:
3238 case SbxSALUINT64:
3239 case SbxDECIMAL:
3240 fVal = pVar->GetDouble();
3241 return true;
3242 case SbxBOOL:
3243 fVal = (pVar->GetBool() ? 1.0 : 0.0);
3244 return true;
3245 default:
3246 ; // nothing
3248 return false;
3251 #endif
3253 void ScInterpreter::ScMacro()
3256 #if !HAVE_FEATURE_SCRIPTING
3257 PushNoValue(); // without DocShell no CallBasic
3258 return;
3259 #else
3260 SbxBase::ResetError();
3262 sal_uInt8 nParamCount = GetByte();
3263 OUString aMacro( pCur->GetExternal() );
3265 ScDocShell* pDocSh = mrDoc.GetDocumentShell();
3266 if ( !pDocSh )
3268 PushNoValue(); // without DocShell no CallBasic
3269 return;
3272 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic
3274 // If the Dok was loaded during a Basic-Calls,
3275 // is the Sbx-object created(?)
3276 // pDocSh->GetSbxObject();
3278 // search function with the name,
3279 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr
3281 StarBASIC* pRoot;
3285 pRoot = pDocSh->GetBasic();
3287 catch (...)
3289 pRoot = nullptr;
3292 SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr;
3293 if( !pVar || pVar->GetType() == SbxVOID )
3295 PushError( FormulaError::NoMacro );
3296 return;
3298 SbMethod* pMethod = dynamic_cast<SbMethod*>(pVar);
3299 if( !pMethod )
3301 PushError( FormulaError::NoMacro );
3302 return;
3305 bool bVolatileMacro = false;
3307 SbModule* pModule = pMethod->GetModule();
3308 bool bUseVBAObjects = pModule->IsVBASupport();
3309 SbxObject* pObject = pModule->GetParent();
3310 assert(pObject);
3311 OSL_ENSURE(dynamic_cast<const StarBASIC *>(pObject) != nullptr, "No Basic found!");
3312 OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName();
3313 OUString aBasicStr;
3314 if (pRoot && bUseVBAObjects)
3316 // just here to make sure the VBA objects when we run the macro during ODF import
3317 pRoot->getVBAGlobals();
3319 if (pObject->GetParent())
3321 aBasicStr = pObject->GetParent()->GetName(); // document BASIC
3323 else
3325 aBasicStr = SfxGetpApp()->GetName(); // application BASIC
3327 // assemble a parameter array
3329 SbxArrayRef refPar = new SbxArray;
3330 bool bOk = true;
3331 for( sal_uInt32 i = nParamCount; i && bOk ; i-- )
3333 SbxVariable* pPar = refPar->Get(i);
3334 switch( GetStackType() )
3336 case svDouble:
3337 pPar->PutDouble( GetDouble() );
3338 break;
3339 case svString:
3340 pPar->PutString( GetString().getString() );
3341 break;
3342 case svExternalSingleRef:
3344 ScExternalRefCache::TokenRef pToken;
3345 PopExternalSingleRef(pToken);
3346 if (nGlobalError != FormulaError::NONE)
3347 bOk = false;
3348 else
3350 if ( pToken->GetType() == svString )
3351 pPar->PutString( pToken->GetString().getString() );
3352 else if ( pToken->GetType() == svDouble )
3353 pPar->PutDouble( pToken->GetDouble() );
3354 else
3356 SetError( FormulaError::IllegalArgument );
3357 bOk = false;
3361 break;
3362 case svSingleRef:
3364 ScAddress aAdr;
3365 PopSingleRef( aAdr );
3366 if ( bUseVBAObjects )
3368 ScRange aRange( aAdr );
3369 bOk = lcl_setVBARange( aRange, mrDoc, pPar );
3371 else
3373 bOk = SetSbxVariable( pPar, aAdr );
3376 break;
3377 case svDoubleRef:
3379 SCCOL nCol1;
3380 SCROW nRow1;
3381 SCTAB nTab1;
3382 SCCOL nCol2;
3383 SCROW nRow2;
3384 SCTAB nTab2;
3385 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3386 if( nTab1 != nTab2 )
3388 SetError( FormulaError::IllegalParameter );
3389 bOk = false;
3391 else
3393 if ( bUseVBAObjects )
3395 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3396 bOk = lcl_setVBARange( aRange, mrDoc, pPar );
3398 else
3400 SbxDimArrayRef refArray = new SbxDimArray;
3401 refArray->AddDim(1, nRow2 - nRow1 + 1);
3402 refArray->AddDim(1, nCol2 - nCol1 + 1);
3403 ScAddress aAdr( nCol1, nRow1, nTab1 );
3404 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3406 aAdr.SetRow( nRow );
3407 sal_Int32 nIdx[ 2 ];
3408 nIdx[ 0 ] = nRow-nRow1+1;
3409 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3411 aAdr.SetCol( nCol );
3412 nIdx[ 1 ] = nCol-nCol1+1;
3413 SbxVariable* p = refArray->Get(nIdx);
3414 bOk = SetSbxVariable( p, aAdr );
3417 pPar->PutObject( refArray.get() );
3421 break;
3422 case svExternalDoubleRef:
3423 case svMatrix:
3425 ScMatrixRef pMat = GetMatrix();
3426 SCSIZE nC, nR;
3427 if (pMat && nGlobalError == FormulaError::NONE)
3429 pMat->GetDimensions(nC, nR);
3430 SbxDimArrayRef refArray = new SbxDimArray;
3431 refArray->AddDim(1, static_cast<sal_Int32>(nR));
3432 refArray->AddDim(1, static_cast<sal_Int32>(nC));
3433 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3435 sal_Int32 nIdx[ 2 ];
3436 nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3437 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3439 nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3440 SbxVariable* p = refArray->Get(nIdx);
3441 if (pMat->IsStringOrEmpty(nMatCol, nMatRow))
3443 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() );
3445 else
3447 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3451 pPar->PutObject( refArray.get() );
3453 else
3455 SetError( FormulaError::IllegalParameter );
3458 break;
3459 default:
3460 SetError( FormulaError::IllegalParameter );
3461 bOk = false;
3464 if( bOk )
3466 mrDoc.LockTable( aPos.Tab() );
3467 SbxVariableRef refRes = new SbxVariable;
3468 mrDoc.IncMacroInterpretLevel();
3469 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar.get(), refRes.get() );
3470 mrDoc.DecMacroInterpretLevel();
3471 mrDoc.UnlockTable( aPos.Tab() );
3473 ScMacroManager* pMacroMgr = mrDoc.GetMacroManager();
3474 if (pMacroMgr)
3476 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3477 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3480 double fVal;
3481 SbxDataType eResType = refRes->GetType();
3482 if( SbxBase::GetError() )
3484 SetError( FormulaError::NoValue);
3486 if ( eRet != ERRCODE_NONE )
3488 PushNoValue();
3490 else if (lcl_isNumericResult( fVal, refRes.get()))
3492 switch (eResType)
3494 case SbxDATE:
3495 nFuncFmtType = SvNumFormatType::DATE;
3496 break;
3497 case SbxBOOL:
3498 nFuncFmtType = SvNumFormatType::LOGICAL;
3499 break;
3500 // Do not add SbxCURRENCY, we don't know which currency.
3501 default:
3502 ; // nothing
3504 PushDouble( fVal );
3506 else if ( eResType & SbxARRAY )
3508 SbxBase* pElemObj = refRes->GetObject();
3509 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>(pElemObj);
3510 sal_Int32 nDim = pDimArray ? pDimArray->GetDims() : 0;
3511 if ( 1 <= nDim && nDim <= 2 )
3513 sal_Int32 nCs, nCe, nRs;
3514 SCSIZE nC, nR;
3515 SCCOL nColIdx;
3516 SCROW nRowIdx;
3517 if ( nDim == 1 )
3518 { // array( cols ) one line, several columns
3519 pDimArray->GetDim(1, nCs, nCe);
3520 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3521 nRs = 0;
3522 nR = 1;
3523 nColIdx = 0;
3524 nRowIdx = 1;
3526 else
3527 { // array( rows, cols )
3528 sal_Int32 nRe;
3529 pDimArray->GetDim(1, nRs, nRe);
3530 nR = static_cast<SCSIZE>(nRe - nRs + 1);
3531 pDimArray->GetDim(2, nCs, nCe);
3532 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3533 nColIdx = 1;
3534 nRowIdx = 0;
3536 ScMatrixRef pMat = GetNewMat( nC, nR, /*bEmpty*/true);
3537 if ( pMat )
3539 SbxVariable* pV;
3540 for ( SCSIZE j=0; j < nR; j++ )
3542 sal_Int32 nIdx[ 2 ];
3543 // in one-dimensional array( cols ) nIdx[1]
3544 // from SbxDimArray::Get is ignored
3545 nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3546 for ( SCSIZE i=0; i < nC; i++ )
3548 nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3549 pV = pDimArray->Get(nIdx);
3550 if ( lcl_isNumericResult( fVal, pV) )
3552 pMat->PutDouble( fVal, i, j );
3554 else
3556 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j);
3560 PushMatrix( pMat );
3562 else
3564 PushIllegalArgument();
3567 else
3569 PushNoValue();
3572 else
3574 PushString( refRes->GetOUString() );
3578 if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3579 meVolatileType = VOLATILE_MACRO;
3580 #endif
3583 #if HAVE_FEATURE_SCRIPTING
3585 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3587 bool bOk = true;
3588 ScRefCellValue aCell(mrDoc, rPos);
3589 if (!aCell.isEmpty())
3591 FormulaError nErr;
3592 double nVal;
3593 switch (aCell.getType())
3595 case CELLTYPE_VALUE :
3596 nVal = GetValueCellValue(rPos, aCell.getDouble());
3597 pVar->PutDouble( nVal );
3598 break;
3599 case CELLTYPE_STRING :
3600 case CELLTYPE_EDIT :
3601 pVar->PutString(aCell.getString(&mrDoc));
3602 break;
3603 case CELLTYPE_FORMULA :
3604 nErr = aCell.getFormula()->GetErrCode();
3605 if( nErr == FormulaError::NONE )
3607 if (aCell.getFormula()->IsValue())
3609 nVal = aCell.getFormula()->GetValue();
3610 pVar->PutDouble( nVal );
3612 else
3613 pVar->PutString(aCell.getFormula()->GetString().getString());
3615 else
3617 SetError( nErr );
3618 bOk = false;
3620 break;
3621 default :
3622 pVar->PutEmpty();
3625 else
3626 pVar->PutEmpty();
3628 return bOk;
3631 #endif
3633 void ScInterpreter::ScTableOp()
3635 sal_uInt8 nParamCount = GetByte();
3636 if (nParamCount != 3 && nParamCount != 5)
3638 PushIllegalParameter();
3639 return;
3641 ScInterpreterTableOpParams aTableOp;
3642 if (nParamCount == 5)
3644 PopSingleRef( aTableOp.aNew2 );
3645 PopSingleRef( aTableOp.aOld2 );
3647 PopSingleRef( aTableOp.aNew1 );
3648 PopSingleRef( aTableOp.aOld1 );
3649 PopSingleRef( aTableOp.aFormulaPos );
3651 aTableOp.bValid = true;
3652 mrDoc.m_TableOpList.push_back(&aTableOp);
3653 mrDoc.IncInterpreterTableOpLevel();
3655 bool bReuseLastParams = (mrDoc.aLastTableOpParams == aTableOp);
3656 if ( bReuseLastParams )
3658 aTableOp.aNotifiedFormulaPos = mrDoc.aLastTableOpParams.aNotifiedFormulaPos;
3659 aTableOp.bRefresh = true;
3660 for ( const auto& rPos : aTableOp.aNotifiedFormulaPos )
3661 { // emulate broadcast and indirectly collect cell pointers
3662 ScRefCellValue aCell(mrDoc, rPos);
3663 if (aCell.getType() == CELLTYPE_FORMULA)
3664 aCell.getFormula()->SetTableOpDirty();
3667 else
3668 { // broadcast and indirectly collect cell pointers and positions
3669 mrDoc.SetTableOpDirty( ScRange(aTableOp.aOld1) );
3670 if ( nParamCount == 5 )
3671 mrDoc.SetTableOpDirty( ScRange(aTableOp.aOld2) );
3673 aTableOp.bCollectNotifications = false;
3675 ScRefCellValue aCell(mrDoc, aTableOp.aFormulaPos);
3676 if (aCell.getType() == CELLTYPE_FORMULA)
3677 aCell.getFormula()->SetDirtyVar();
3678 if (aCell.hasNumeric())
3680 PushDouble(GetCellValue(aTableOp.aFormulaPos, aCell));
3682 else
3684 svl::SharedString aCellString;
3685 GetCellString(aCellString, aCell);
3686 PushString( aCellString );
3689 auto const itr =
3690 ::std::find(mrDoc.m_TableOpList.begin(), mrDoc.m_TableOpList.end(), &aTableOp);
3691 if (itr != mrDoc.m_TableOpList.end())
3693 mrDoc.m_TableOpList.erase(itr);
3696 // set dirty again once more to be able to recalculate original
3697 for ( const auto& pCell : aTableOp.aNotifiedFormulaCells )
3699 pCell->SetTableOpDirty();
3702 // save these params for next incarnation
3703 if ( !bReuseLastParams )
3704 mrDoc.aLastTableOpParams = aTableOp;
3706 if (aCell.getType() == CELLTYPE_FORMULA)
3708 aCell.getFormula()->SetDirtyVar();
3709 aCell.getFormula()->GetErrCode(); // recalculate original
3712 // Reset all dirty flags so next incarnation does really collect all cell
3713 // pointers during notifications and not just non-dirty ones, which may
3714 // happen if a formula cell is used by more than one TableOp block.
3715 for ( const auto& pCell : aTableOp.aNotifiedFormulaCells )
3717 pCell->ResetTableOpDirtyVar();
3720 mrDoc.DecInterpreterTableOpLevel();
3723 void ScInterpreter::ScDBArea()
3725 ScDBData* pDBData = mrDoc.GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3726 if (pDBData)
3728 ScComplexRefData aRefData;
3729 aRefData.InitFlags();
3730 ScRange aRange;
3731 pDBData->GetArea(aRange);
3732 aRange.aEnd.SetTab(aRange.aStart.Tab());
3733 aRefData.SetRange(mrDoc.GetSheetLimits(), aRange, aPos);
3734 PushTempToken( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRefData ) );
3736 else
3737 PushError( FormulaError::NoName);
3740 void ScInterpreter::ScColRowNameAuto()
3742 ScComplexRefData aRefData( *pCur->GetDoubleRef() );
3743 ScRange aAbs = aRefData.toAbs(mrDoc, aPos);
3744 if (!mrDoc.ValidRange(aAbs))
3746 PushError( FormulaError::NoRef );
3747 return;
3750 SCCOL nStartCol;
3751 SCROW nStartRow;
3753 // maybe remember limit by using defined ColRowNameRange
3754 SCCOL nCol2 = aAbs.aEnd.Col();
3755 SCROW nRow2 = aAbs.aEnd.Row();
3756 // DataArea of the first cell
3757 nStartCol = aAbs.aStart.Col();
3758 nStartRow = aAbs.aStart.Row();
3759 aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell.
3762 // Expand to the data area. Only modify the end position.
3763 SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col();
3764 SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row();
3765 mrDoc.GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false);
3766 aAbs.aEnd.SetCol(nDACol2);
3767 aAbs.aEnd.SetRow(nDARow2);
3770 // corresponds with ScCompiler::GetToken
3771 if ( aRefData.Ref1.IsColRel() )
3772 { // ColName
3773 aAbs.aEnd.SetCol(nStartCol);
3774 // maybe get previous limit by using defined ColRowNameRange
3775 if (aAbs.aEnd.Row() > nRow2)
3776 aAbs.aEnd.SetRow(nRow2);
3777 if ( aPos.Col() == nStartCol )
3779 SCROW nMyRow = aPos.Row();
3780 if ( nStartRow <= nMyRow && nMyRow <= aAbs.aEnd.Row())
3781 { //Formula in the same column and within the range
3782 if ( nMyRow == nStartRow )
3783 { // take the rest under the name
3784 nStartRow++;
3785 if ( nStartRow > mrDoc.MaxRow() )
3786 nStartRow = mrDoc.MaxRow();
3787 aAbs.aStart.SetRow(nStartRow);
3789 else
3790 { // below the name to the formula cell
3791 aAbs.aEnd.SetRow(nMyRow - 1);
3796 else
3797 { // RowName
3798 aAbs.aEnd.SetRow(nStartRow);
3799 // maybe get previous limit by using defined ColRowNameRange
3800 if (aAbs.aEnd.Col() > nCol2)
3801 aAbs.aEnd.SetCol(nCol2);
3802 if ( aPos.Row() == nStartRow )
3804 SCCOL nMyCol = aPos.Col();
3805 if (nStartCol <= nMyCol && nMyCol <= aAbs.aEnd.Col())
3806 { //Formula in the same column and within the range
3807 if ( nMyCol == nStartCol )
3808 { // take the rest under the name
3809 nStartCol++;
3810 if ( nStartCol > mrDoc.MaxCol() )
3811 nStartCol = mrDoc.MaxCol();
3812 aAbs.aStart.SetCol(nStartCol);
3814 else
3815 { // below the name to the formula cell
3816 aAbs.aEnd.SetCol(nMyCol - 1);
3821 aRefData.SetRange(mrDoc.GetSheetLimits(), aAbs, aPos);
3822 PushTempToken( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRefData ) );
3825 // --- internals ------------------------------------------------------------
3827 void ScInterpreter::ScTTT()
3828 { // temporary test, testing functions etc.
3829 sal_uInt8 nParamCount = GetByte();
3830 // do something, count down nParamCount with Pops!
3832 // clean up Stack
3833 while ( nParamCount-- > 0)
3834 Pop();
3835 PushError(FormulaError::NoValue);
3838 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument& rDoc, ScInterpreterContext& rContext,
3839 const ScAddress& rPos, ScTokenArray& r, bool bForGroupThreading )
3840 : aCode(r)
3841 , aPos(rPos)
3842 , pArr(&r)
3843 , mrContext(rContext)
3844 , mrDoc(rDoc)
3845 , mpLinkManager(rDoc.GetLinkManager())
3846 , mrStrPool(rDoc.GetSharedStringPool())
3847 , pJumpMatrix(nullptr)
3848 , pMyFormulaCell(pCell)
3849 , pCur(nullptr)
3850 , nGlobalError(FormulaError::NONE)
3851 , sp(0)
3852 , maxsp(0)
3853 , nFuncFmtIndex(0)
3854 , nCurFmtIndex(0)
3855 , nRetFmtIndex(0)
3856 , nFuncFmtType(SvNumFormatType::ALL)
3857 , nCurFmtType(SvNumFormatType::ALL)
3858 , nRetFmtType(SvNumFormatType::ALL)
3859 , mnStringNoValueError(FormulaError::NoValue)
3860 , mnSubTotalFlags(SubtotalFlags::NONE)
3861 , cPar(0)
3862 , bCalcAsShown(rDoc.GetDocOptions().IsCalcAsShown())
3863 , meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3865 MergeCalcConfig();
3867 if(pMyFormulaCell)
3869 ScMatrixMode cMatFlag = pMyFormulaCell->GetMatrixFlag();
3870 bMatrixFormula = ( cMatFlag == ScMatrixMode::Formula );
3872 else
3873 bMatrixFormula = false;
3875 // Let's not use the global stack while formula-group-threading.
3876 // as it complicates its life-cycle mgmt since for threading formula-groups,
3877 // ScInterpreter is preallocated (in main thread) for each worker thread.
3878 if (!bGlobalStackInUse && !bForGroupThreading)
3880 bGlobalStackInUse = true;
3881 if (!pGlobalStack)
3882 pGlobalStack.reset(new ScTokenStack);
3883 pStackObj = pGlobalStack.get();
3885 else
3887 pStackObj = new ScTokenStack;
3889 pStack = pStackObj->pPointer;
3892 ScInterpreter::~ScInterpreter()
3894 if ( pStackObj == pGlobalStack.get() )
3895 bGlobalStackInUse = false;
3896 else
3897 delete pStackObj;
3900 void ScInterpreter::Init( ScFormulaCell* pCell, const ScAddress& rPos, ScTokenArray& rTokArray )
3902 aCode.ReInit(rTokArray);
3903 aPos = rPos;
3904 pArr = &rTokArray;
3905 pJumpMatrix = nullptr;
3906 DropTokenCaches();
3907 pMyFormulaCell = pCell;
3908 pCur = nullptr;
3909 nGlobalError = FormulaError::NONE;
3910 sp = 0;
3911 maxsp = 0;
3912 nFuncFmtIndex = 0;
3913 nCurFmtIndex = 0;
3914 nRetFmtIndex = 0;
3915 nFuncFmtType = SvNumFormatType::ALL;
3916 nCurFmtType = SvNumFormatType::ALL;
3917 nRetFmtType = SvNumFormatType::ALL;
3918 mnStringNoValueError = FormulaError::NoValue;
3919 mnSubTotalFlags = SubtotalFlags::NONE;
3920 cPar = 0;
3923 void ScInterpreter::DropTokenCaches()
3925 xResult = nullptr;
3926 maTokenMatrixMap.clear();
3929 ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
3931 if (!mpGlobalConfig)
3932 mpGlobalConfig = new ScCalcConfig();
3933 return *mpGlobalConfig;
3936 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3938 GetOrCreateGlobalConfig() = rConfig;
3941 const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3943 return GetOrCreateGlobalConfig();
3946 void ScInterpreter::MergeCalcConfig()
3948 maCalcConfig = GetOrCreateGlobalConfig();
3949 maCalcConfig.MergeDocumentSpecific( mrDoc.GetCalcConfig());
3952 void ScInterpreter::GlobalExit()
3954 OSL_ENSURE(!bGlobalStackInUse, "who is still using the TokenStack?");
3955 pGlobalStack.reset();
3958 namespace {
3960 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
3962 if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
3964 SCROW nOffset = rPos.Row() - rMat.mnRow1;
3965 return rMat.mpMat->GetDouble(0, nOffset);
3968 if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
3970 SCROW nOffset = rPos.Col() - rMat.mnCol1;
3971 return rMat.mpMat->GetDouble(nOffset, 0);
3974 return std::numeric_limits<double>::quiet_NaN();
3977 // Test for Functions that evaluate an error code and directly set nGlobalError to 0
3978 bool IsErrFunc(OpCode oc)
3980 switch (oc)
3982 case ocCount :
3983 case ocCount2 :
3984 case ocErrorType :
3985 case ocIsEmpty :
3986 case ocIsErr :
3987 case ocIsError :
3988 case ocIsFormula :
3989 case ocIsLogical :
3990 case ocIsNA :
3991 case ocIsNonString :
3992 case ocIsRef :
3993 case ocIsString :
3994 case ocIsValue :
3995 case ocN :
3996 case ocType :
3997 case ocIfError :
3998 case ocIfNA :
3999 case ocErrorType_ODF :
4000 case ocAggregate: // may ignore errors depending on option
4001 case ocIfs_MS:
4002 case ocSwitch_MS:
4003 case ocXLookup:
4004 return true;
4005 default:
4006 return false;
4010 } //namespace
4012 StackVar ScInterpreter::Interpret()
4014 SvNumFormatType nRetTypeExpr = SvNumFormatType::UNDEFINED;
4015 sal_uInt32 nRetIndexExpr = 0;
4016 sal_uInt16 nErrorFunction = 0;
4017 sal_uInt16 nErrorFunctionCount = 0;
4018 std::vector<sal_uInt16> aErrorFunctionStack;
4019 sal_uInt16 nStackBase;
4021 nGlobalError = FormulaError::NONE;
4022 nStackBase = sp = maxsp = 0;
4023 nRetFmtType = SvNumFormatType::UNDEFINED;
4024 nFuncFmtType = SvNumFormatType::UNDEFINED;
4025 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
4026 xResult = nullptr;
4027 pJumpMatrix = nullptr;
4028 mnSubTotalFlags = SubtotalFlags::NONE;
4029 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
4031 // Once upon a time we used to have FP exceptions on, and there was a
4032 // Windows printer driver that kept switching off exceptions, so we had to
4033 // switch them back on again every time. Who knows if there isn't a driver
4034 // that keeps switching exceptions on, now that we run with exceptions off,
4035 // so reassure exceptions are really off.
4036 SAL_MATH_FPEXCEPTIONS_OFF();
4038 OpCode eOp = ocNone;
4039 aCode.Reset();
4040 for (;;)
4042 pCur = aCode.Next();
4043 if (!pCur || (nGlobalError != FormulaError::NONE && nErrorFunction > nErrorFunctionCount) )
4044 break;
4045 eOp = pCur->GetOpCode();
4046 cPar = pCur->GetByte();
4047 if ( eOp == ocPush )
4049 // RPN code push without error
4050 PushWithoutError( *pCur );
4051 nCurFmtType = SvNumFormatType::UNDEFINED;
4053 else
4055 const bool bIsOpCodeJumpCommand = FormulaCompiler::IsOpCodeJumpCommand(eOp);
4056 if (!bIsOpCodeJumpCommand &&
4057 ((aTokenMatrixMapIter = maTokenMatrixMap.find( pCur)) !=
4058 maTokenMatrixMap.end()) &&
4059 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
4061 // Path already calculated, reuse result.
4062 const sal_uInt8 nParamCount = pCur->GetParamCount();
4063 if (sp >= nParamCount)
4064 nStackBase = sp - nParamCount;
4065 else
4067 SAL_WARN("sc.core", "Stack anomaly with calculated path at "
4068 << aPos.Tab() << "," << aPos.Col() << "," << aPos.Row()
4069 << " " << aPos.Format(
4070 ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc)
4071 << " eOp: " << static_cast<int>(eOp)
4072 << " params: " << static_cast<int>(nParamCount)
4073 << " nStackBase: " << nStackBase << " sp: " << sp);
4074 nStackBase = sp;
4075 assert(!"underflow");
4077 sp = nStackBase;
4078 PushTokenRef( (*aTokenMatrixMapIter).second);
4080 else
4082 // previous expression determines the current number format
4083 nCurFmtType = nRetTypeExpr;
4084 nCurFmtIndex = nRetIndexExpr;
4085 // default function's format, others are set if needed
4086 nFuncFmtType = SvNumFormatType::NUMBER;
4087 nFuncFmtIndex = 0;
4089 if (bIsOpCodeJumpCommand)
4090 nStackBase = sp; // don't mess around with the jumps
4091 else
4093 // Convert parameters to matrix if in array/matrix formula and
4094 // parameters of function indicate doing so. Create JumpMatrix
4095 // if necessary.
4096 if ( MatrixParameterConversion() )
4098 eOp = ocNone; // JumpMatrix created
4099 nStackBase = sp;
4101 else
4103 const sal_uInt8 nParamCount = pCur->GetParamCount();
4104 if (sp >= nParamCount)
4105 nStackBase = sp - nParamCount;
4106 else
4108 SAL_WARN("sc.core", "Stack anomaly at " << aPos.Tab() << "," << aPos.Col() << "," << aPos.Row()
4109 << " " << aPos.Format(
4110 ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc)
4111 << " eOp: " << static_cast<int>(eOp)
4112 << " params: " << static_cast<int>(nParamCount)
4113 << " nStackBase: " << nStackBase << " sp: " << sp);
4114 nStackBase = sp;
4115 assert(!"underflow");
4120 switch( eOp )
4122 case ocSep:
4123 case ocClose: // pushed by the compiler
4124 case ocMissing : ScMissing(); break;
4125 case ocMacro : ScMacro(); break;
4126 case ocDBArea : ScDBArea(); break;
4127 case ocColRowNameAuto : ScColRowNameAuto(); break;
4128 case ocIf : ScIfJump(); break;
4129 case ocIfError : ScIfError( false ); break;
4130 case ocIfNA : ScIfError( true ); break;
4131 case ocChoose : ScChooseJump(); break;
4132 case ocAdd : ScAdd(); break;
4133 case ocSub : ScSub(); break;
4134 case ocMul : ScMul(); break;
4135 case ocDiv : ScDiv(); break;
4136 case ocAmpersand : ScAmpersand(); break;
4137 case ocPow : ScPow(); break;
4138 case ocEqual : ScEqual(); break;
4139 case ocNotEqual : ScNotEqual(); break;
4140 case ocLess : ScLess(); break;
4141 case ocGreater : ScGreater(); break;
4142 case ocLessEqual : ScLessEqual(); break;
4143 case ocGreaterEqual : ScGreaterEqual(); break;
4144 case ocAnd : ScAnd(); break;
4145 case ocOr : ScOr(); break;
4146 case ocXor : ScXor(); break;
4147 case ocIntersect : ScIntersect(); break;
4148 case ocRange : ScRangeFunc(); break;
4149 case ocUnion : ScUnionFunc(); break;
4150 case ocNot : ScNot(); break;
4151 case ocNegSub :
4152 case ocNeg : ScNeg(); break;
4153 case ocPercentSign : ScPercentSign(); break;
4154 case ocPi : ScPi(); break;
4155 case ocRandom : ScRandom(); break;
4156 case ocRandArray : ScRandArray(); break;
4157 case ocRandomNV : ScRandom(); break;
4158 case ocRandbetweenNV : ScRandbetween(); break;
4159 case ocFilter : ScFilter(); break;
4160 case ocSort : ScSort(); break;
4161 case ocSortBy : ScSortBy(); break;
4162 case ocUnique : ScUnique(); break;
4163 case ocLet : ScLet(); break;
4164 case ocTrue : ScTrue(); break;
4165 case ocFalse : ScFalse(); break;
4166 case ocGetActDate : ScGetActDate(); break;
4167 case ocGetActTime : ScGetActTime(); break;
4168 case ocNotAvail : PushError( FormulaError::NotAvailable); break;
4169 case ocDeg : ScDeg(); break;
4170 case ocRad : ScRad(); break;
4171 case ocSin : ScSin(); break;
4172 case ocCos : ScCos(); break;
4173 case ocTan : ScTan(); break;
4174 case ocCot : ScCot(); break;
4175 case ocArcSin : ScArcSin(); break;
4176 case ocArcCos : ScArcCos(); break;
4177 case ocArcTan : ScArcTan(); break;
4178 case ocArcCot : ScArcCot(); break;
4179 case ocSinHyp : ScSinHyp(); break;
4180 case ocCosHyp : ScCosHyp(); break;
4181 case ocTanHyp : ScTanHyp(); break;
4182 case ocCotHyp : ScCotHyp(); break;
4183 case ocArcSinHyp : ScArcSinHyp(); break;
4184 case ocArcCosHyp : ScArcCosHyp(); break;
4185 case ocArcTanHyp : ScArcTanHyp(); break;
4186 case ocArcCotHyp : ScArcCotHyp(); break;
4187 case ocCosecant : ScCosecant(); break;
4188 case ocSecant : ScSecant(); break;
4189 case ocCosecantHyp : ScCosecantHyp(); break;
4190 case ocSecantHyp : ScSecantHyp(); break;
4191 case ocExp : ScExp(); break;
4192 case ocLn : ScLn(); break;
4193 case ocLog10 : ScLog10(); break;
4194 case ocSqrt : ScSqrt(); break;
4195 case ocFact : ScFact(); break;
4196 case ocGetYear : ScGetYear(); break;
4197 case ocGetMonth : ScGetMonth(); break;
4198 case ocGetDay : ScGetDay(); break;
4199 case ocGetDayOfWeek : ScGetDayOfWeek(); break;
4200 case ocWeek : ScGetWeekOfYear(); break;
4201 case ocIsoWeeknum : ScGetIsoWeekOfYear(); break;
4202 case ocWeeknumOOo : ScWeeknumOOo(); break;
4203 case ocEasterSunday : ScEasterSunday(); break;
4204 case ocNetWorkdays : ScNetWorkdays( false); break;
4205 case ocNetWorkdays_MS : ScNetWorkdays( true ); break;
4206 case ocWorkday_MS : ScWorkday_MS(); break;
4207 case ocGetHour : ScGetHour(); break;
4208 case ocGetMin : ScGetMin(); break;
4209 case ocGetSec : ScGetSec(); break;
4210 case ocPlusMinus : ScPlusMinus(); break;
4211 case ocAbs : ScAbs(); break;
4212 case ocInt : ScInt(); break;
4213 case ocEven : ScEven(); break;
4214 case ocOdd : ScOdd(); break;
4215 case ocPhi : ScPhi(); break;
4216 case ocGauss : ScGauss(); break;
4217 case ocStdNormDist : ScStdNormDist(); break;
4218 case ocStdNormDist_MS : ScStdNormDist_MS(); break;
4219 case ocFisher : ScFisher(); break;
4220 case ocFisherInv : ScFisherInv(); break;
4221 case ocIsEmpty : ScIsEmpty(); break;
4222 case ocIsString : ScIsString(); break;
4223 case ocIsNonString : ScIsNonString(); break;
4224 case ocIsLogical : ScIsLogical(); break;
4225 case ocType : ScType(); break;
4226 case ocCell : ScCell(); break;
4227 case ocIsRef : ScIsRef(); break;
4228 case ocIsValue : ScIsValue(); break;
4229 case ocIsFormula : ScIsFormula(); break;
4230 case ocFormula : ScFormula(); break;
4231 case ocIsNA : ScIsNV(); break;
4232 case ocIsErr : ScIsErr(); break;
4233 case ocIsError : ScIsError(); break;
4234 case ocIsEven : ScIsEven(); break;
4235 case ocIsOdd : ScIsOdd(); break;
4236 case ocN : ScN(); break;
4237 case ocGetDateValue : ScGetDateValue(); break;
4238 case ocGetTimeValue : ScGetTimeValue(); break;
4239 case ocCode : ScCode(); break;
4240 case ocTrim : ScTrim(); break;
4241 case ocUpper : ScUpper(); break;
4242 case ocProper : ScProper(); break;
4243 case ocLower : ScLower(); break;
4244 case ocLen : ScLen(); break;
4245 case ocT : ScT(); break;
4246 case ocClean : ScClean(); break;
4247 case ocValue : ScValue(); break;
4248 case ocNumberValue : ScNumberValue(); break;
4249 case ocChar : ScChar(); break;
4250 case ocArcTan2 : ScArcTan2(); break;
4251 case ocMod : ScMod(); break;
4252 case ocPower : ScPower(); break;
4253 case ocRound : ScRound(); break;
4254 case ocRoundSig : ScRoundSignificant(); break;
4255 case ocRoundUp : ScRoundUp(); break;
4256 case ocTrunc :
4257 case ocRoundDown : ScRoundDown(); break;
4258 case ocCeil : ScCeil( true ); break;
4259 case ocCeil_MS : ScCeil_MS(); break;
4260 case ocCeil_Precise :
4261 case ocCeil_ISO : ScCeil_Precise(); break;
4262 case ocCeil_Math : ScCeil( false ); break;
4263 case ocFloor : ScFloor( true ); break;
4264 case ocFloor_MS : ScFloor_MS(); break;
4265 case ocFloor_Precise : ScFloor_Precise(); break;
4266 case ocFloor_Math : ScFloor( false ); break;
4267 case ocSumProduct : ScSumProduct(); break;
4268 case ocSumSQ : ScSumSQ(); break;
4269 case ocSumX2MY2 : ScSumX2MY2(); break;
4270 case ocSumX2DY2 : ScSumX2DY2(); break;
4271 case ocSumXMY2 : ScSumXMY2(); break;
4272 case ocRawSubtract : ScRawSubtract(); break;
4273 case ocLog : ScLog(); break;
4274 case ocGCD : ScGCD(); break;
4275 case ocLCM : ScLCM(); break;
4276 case ocGetDate : ScGetDate(); break;
4277 case ocGetTime : ScGetTime(); break;
4278 case ocGetDiffDate : ScGetDiffDate(); break;
4279 case ocGetDiffDate360 : ScGetDiffDate360(); break;
4280 case ocGetDateDif : ScGetDateDif(); break;
4281 case ocMin : ScMin() ; break;
4282 case ocMinA : ScMin( true ); break;
4283 case ocMax : ScMax(); break;
4284 case ocMaxA : ScMax( true ); break;
4285 case ocSum : ScSum(); break;
4286 case ocProduct : ScProduct(); break;
4287 case ocNPV : ScNPV(); break;
4288 case ocIRR : ScIRR(); break;
4289 case ocMIRR : ScMIRR(); break;
4290 case ocISPMT : ScISPMT(); break;
4291 case ocAverage : ScAverage() ; break;
4292 case ocAverageA : ScAverage( true ); break;
4293 case ocCount : ScCount(); break;
4294 case ocCount2 : ScCount2(); break;
4295 case ocVar :
4296 case ocVarS : ScVar(); break;
4297 case ocVarA : ScVar( true ); break;
4298 case ocVarP :
4299 case ocVarP_MS : ScVarP(); break;
4300 case ocVarPA : ScVarP( true ); break;
4301 case ocStDev :
4302 case ocStDevS : ScStDev(); break;
4303 case ocStDevA : ScStDev( true ); break;
4304 case ocStDevP :
4305 case ocStDevP_MS : ScStDevP(); break;
4306 case ocStDevPA : ScStDevP( true ); break;
4307 case ocPV : ScPV(); break;
4308 case ocSYD : ScSYD(); break;
4309 case ocDDB : ScDDB(); break;
4310 case ocDB : ScDB(); break;
4311 case ocVBD : ScVDB(); break;
4312 case ocPDuration : ScPDuration(); break;
4313 case ocSLN : ScSLN(); break;
4314 case ocPMT : ScPMT(); break;
4315 case ocColumns : ScColumns(); break;
4316 case ocRows : ScRows(); break;
4317 case ocSheets : ScSheets(); break;
4318 case ocColumn : ScColumn(); break;
4319 case ocRow : ScRow(); break;
4320 case ocSheet : ScSheet(); break;
4321 case ocRRI : ScRRI(); break;
4322 case ocFV : ScFV(); break;
4323 case ocNper : ScNper(); break;
4324 case ocRate : ScRate(); break;
4325 case ocFilterXML : ScFilterXML(); break;
4326 case ocWebservice : ScWebservice(); break;
4327 case ocEncodeURL : ScEncodeURL(); break;
4328 case ocColor : ScColor(); break;
4329 case ocErf_MS : ScErf(); break;
4330 case ocErfc_MS : ScErfc(); break;
4331 case ocIpmt : ScIpmt(); break;
4332 case ocPpmt : ScPpmt(); break;
4333 case ocCumIpmt : ScCumIpmt(); break;
4334 case ocCumPrinc : ScCumPrinc(); break;
4335 case ocEffect : ScEffect(); break;
4336 case ocNominal : ScNominal(); break;
4337 case ocSubTotal : ScSubTotal(); break;
4338 case ocAggregate : ScAggregate(); break;
4339 case ocDBSum : ScDBSum(); break;
4340 case ocDBCount : ScDBCount(); break;
4341 case ocDBCount2 : ScDBCount2(); break;
4342 case ocDBAverage : ScDBAverage(); break;
4343 case ocDBGet : ScDBGet(); break;
4344 case ocDBMax : ScDBMax(); break;
4345 case ocDBMin : ScDBMin(); break;
4346 case ocDBProduct : ScDBProduct(); break;
4347 case ocDBStdDev : ScDBStdDev(); break;
4348 case ocDBStdDevP : ScDBStdDevP(); break;
4349 case ocDBVar : ScDBVar(); break;
4350 case ocDBVarP : ScDBVarP(); break;
4351 case ocIndirect : ScIndirect(); break;
4352 case ocAddress : ScAddressFunc(); break;
4353 case ocMatch : ScMatch(); break;
4354 case ocXMatch : ScXMatch(); break;
4355 case ocCountEmptyCells : ScCountEmptyCells(); break;
4356 case ocCountIf : ScCountIf(); break;
4357 case ocSumIf : ScSumIf(); break;
4358 case ocAverageIf : ScAverageIf(); break;
4359 case ocSumIfs : ScSumIfs(); break;
4360 case ocAverageIfs : ScAverageIfs(); break;
4361 case ocCountIfs : ScCountIfs(); break;
4362 case ocLookup : ScLookup(); break;
4363 case ocVLookup : ScVLookup(); break;
4364 case ocXLookup : ScXLookup(); break;
4365 case ocHLookup : ScHLookup(); break;
4366 case ocIndex : ScIndex(); break;
4367 case ocMultiArea : ScMultiArea(); break;
4368 case ocOffset : ScOffset(); break;
4369 case ocAreas : ScAreas(); break;
4370 case ocCurrency : ScCurrency(); break;
4371 case ocReplace : ScReplace(); break;
4372 case ocFixed : ScFixed(); break;
4373 case ocFind : ScFind(); break;
4374 case ocExact : ScExact(); break;
4375 case ocLeft : ScLeft(); break;
4376 case ocRight : ScRight(); break;
4377 case ocSearch : ScSearch(); break;
4378 case ocMid : ScMid(); break;
4379 case ocText : ScText(); break;
4380 case ocSubstitute : ScSubstitute(); break;
4381 case ocRegex : ScRegex(); break;
4382 case ocRept : ScRept(); break;
4383 case ocConcat : ScConcat(); break;
4384 case ocConcat_MS : ScConcat_MS(); break;
4385 case ocTextJoin_MS : ScTextJoin_MS(); break;
4386 case ocIfs_MS : ScIfs_MS(); break;
4387 case ocSwitch_MS : ScSwitch_MS(); break;
4388 case ocMinIfs_MS : ScMinIfs_MS(); break;
4389 case ocMaxIfs_MS : ScMaxIfs_MS(); break;
4390 case ocMatValue : ScMatValue(); break;
4391 case ocMatrixUnit : ScEMat(); break;
4392 case ocMatDet : ScMatDet(); break;
4393 case ocMatInv : ScMatInv(); break;
4394 case ocMatMult : ScMatMult(); break;
4395 case ocMatSequence : ScMatSequence(); break;
4396 case ocMatTrans : ScMatTrans(); break;
4397 case ocMatRef : ScMatRef(); break;
4398 case ocB : ScB(); break;
4399 case ocNormDist : ScNormDist( 3 ); break;
4400 case ocNormDist_MS : ScNormDist( 4 ); break;
4401 case ocExpDist :
4402 case ocExpDist_MS : ScExpDist(); break;
4403 case ocBinomDist :
4404 case ocBinomDist_MS : ScBinomDist(); break;
4405 case ocPoissonDist : ScPoissonDist( true ); break;
4406 case ocPoissonDist_MS : ScPoissonDist( false ); break;
4407 case ocCombin : ScCombin(); break;
4408 case ocCombinA : ScCombinA(); break;
4409 case ocPermut : ScPermut(); break;
4410 case ocPermutationA : ScPermutationA(); break;
4411 case ocHypGeomDist : ScHypGeomDist( 4 ); break;
4412 case ocHypGeomDist_MS : ScHypGeomDist( 5 ); break;
4413 case ocLogNormDist : ScLogNormDist( 1 ); break;
4414 case ocLogNormDist_MS : ScLogNormDist( 4 ); break;
4415 case ocTDist : ScTDist(); break;
4416 case ocTDist_MS : ScTDist_MS(); break;
4417 case ocTDist_RT : ScTDist_T( 1 ); break;
4418 case ocTDist_2T : ScTDist_T( 2 ); break;
4419 case ocFDist :
4420 case ocFDist_RT : ScFDist(); break;
4421 case ocFDist_LT : ScFDist_LT(); break;
4422 case ocChiDist : ScChiDist( true ); break;
4423 case ocChiDist_MS : ScChiDist( false ); break;
4424 case ocChiSqDist : ScChiSqDist(); break;
4425 case ocChiSqDist_MS : ScChiSqDist_MS(); break;
4426 case ocStandard : ScStandard(); break;
4427 case ocAveDev : ScAveDev(); break;
4428 case ocDevSq : ScDevSq(); break;
4429 case ocKurt : ScKurt(); break;
4430 case ocSkew : ScSkew(); break;
4431 case ocSkewp : ScSkewp(); break;
4432 case ocModalValue : ScModalValue(); break;
4433 case ocModalValue_MS : ScModalValue_MS( true ); break;
4434 case ocModalValue_Multi : ScModalValue_MS( false ); break;
4435 case ocMedian : ScMedian(); break;
4436 case ocGeoMean : ScGeoMean(); break;
4437 case ocHarMean : ScHarMean(); break;
4438 case ocWeibull :
4439 case ocWeibull_MS : ScWeibull(); break;
4440 case ocBinomInv :
4441 case ocCritBinom : ScCritBinom(); break;
4442 case ocNegBinomVert : ScNegBinomDist(); break;
4443 case ocNegBinomDist_MS : ScNegBinomDist_MS(); break;
4444 case ocNoName : ScNoName(); break;
4445 case ocBad : ScBadName(); break;
4446 case ocZTest :
4447 case ocZTest_MS : ScZTest(); break;
4448 case ocTTest :
4449 case ocTTest_MS : ScTTest(); break;
4450 case ocFTest :
4451 case ocFTest_MS : ScFTest(); break;
4452 case ocRank :
4453 case ocRank_Eq : ScRank( false ); break;
4454 case ocRank_Avg : ScRank( true ); break;
4455 case ocPercentile :
4456 case ocPercentile_Inc : ScPercentile( true ); break;
4457 case ocPercentile_Exc : ScPercentile( false ); break;
4458 case ocPercentrank :
4459 case ocPercentrank_Inc : ScPercentrank( true ); break;
4460 case ocPercentrank_Exc : ScPercentrank( false ); break;
4461 case ocLarge : ScLarge(); break;
4462 case ocSmall : ScSmall(); break;
4463 case ocFrequency : ScFrequency(); break;
4464 case ocQuartile :
4465 case ocQuartile_Inc : ScQuartile( true ); break;
4466 case ocQuartile_Exc : ScQuartile( false ); break;
4467 case ocNormInv :
4468 case ocNormInv_MS : ScNormInv(); break;
4469 case ocSNormInv :
4470 case ocSNormInv_MS : ScSNormInv(); break;
4471 case ocConfidence :
4472 case ocConfidence_N : ScConfidence(); break;
4473 case ocConfidence_T : ScConfidenceT(); break;
4474 case ocTrimMean : ScTrimMean(); break;
4475 case ocProb : ScProbability(); break;
4476 case ocCorrel : ScCorrel(); break;
4477 case ocCovar :
4478 case ocCovarianceP : ScCovarianceP(); break;
4479 case ocCovarianceS : ScCovarianceS(); break;
4480 case ocPearson : ScPearson(); break;
4481 case ocRSQ : ScRSQ(); break;
4482 case ocSTEYX : ScSTEYX(); break;
4483 case ocSlope : ScSlope(); break;
4484 case ocIntercept : ScIntercept(); break;
4485 case ocTrend : ScTrend(); break;
4486 case ocGrowth : ScGrowth(); break;
4487 case ocLinest : ScLinest(); break;
4488 case ocLogest : ScLogest(); break;
4489 case ocForecast_LIN :
4490 case ocForecast : ScForecast(); break;
4491 case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd ); break;
4492 case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason ); break;
4493 case ocForecast_ETS_MUL : ScForecast_Ets( etsMult ); break;
4494 case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd ); break;
4495 case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult ); break;
4496 case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd ); break;
4497 case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult ); break;
4498 case ocGammaLn :
4499 case ocGammaLn_MS : ScLogGamma(); break;
4500 case ocGamma : ScGamma(); break;
4501 case ocGammaDist : ScGammaDist( true ); break;
4502 case ocGammaDist_MS : ScGammaDist( false ); break;
4503 case ocGammaInv :
4504 case ocGammaInv_MS : ScGammaInv(); break;
4505 case ocChiTest :
4506 case ocChiTest_MS : ScChiTest(); break;
4507 case ocChiInv :
4508 case ocChiInv_MS : ScChiInv(); break;
4509 case ocChiSqInv :
4510 case ocChiSqInv_MS : ScChiSqInv(); break;
4511 case ocTInv :
4512 case ocTInv_2T : ScTInv( 2 ); break;
4513 case ocTInv_MS : ScTInv( 4 ); break;
4514 case ocFInv :
4515 case ocFInv_RT : ScFInv(); break;
4516 case ocFInv_LT : ScFInv_LT(); break;
4517 case ocLogInv :
4518 case ocLogInv_MS : ScLogNormInv(); break;
4519 case ocBetaDist : ScBetaDist(); break;
4520 case ocBetaDist_MS : ScBetaDist_MS(); break;
4521 case ocBetaInv :
4522 case ocBetaInv_MS : ScBetaInv(); break;
4523 case ocFourier : ScFourier(); break;
4524 case ocExternal : ScExternal(); break;
4525 case ocTableOp : ScTableOp(); break;
4526 case ocStop : break;
4527 case ocErrorType : ScErrorType(); break;
4528 case ocErrorType_ODF : ScErrorType_ODF(); break;
4529 case ocCurrent : ScCurrent(); break;
4530 case ocStyle : ScStyle(); break;
4531 case ocDde : ScDde(); break;
4532 case ocBase : ScBase(); break;
4533 case ocDecimal : ScDecimal(); break;
4534 case ocConvertOOo : ScConvertOOo(); break;
4535 case ocEuroConvert : ScEuroConvert(); break;
4536 case ocRoman : ScRoman(); break;
4537 case ocArabic : ScArabic(); break;
4538 case ocInfo : ScInfo(); break;
4539 case ocHyperLink : ScHyperLink(); break;
4540 case ocBahtText : ScBahtText(); break;
4541 case ocGetPivotData : ScGetPivotData(); break;
4542 case ocJis : ScJis(); break;
4543 case ocAsc : ScAsc(); break;
4544 case ocLenB : ScLenB(); break;
4545 case ocRightB : ScRightB(); break;
4546 case ocLeftB : ScLeftB(); break;
4547 case ocMidB : ScMidB(); break;
4548 case ocReplaceB : ScReplaceB(); break;
4549 case ocFindB : ScFindB(); break;
4550 case ocSearchB : ScSearchB(); break;
4551 case ocUnicode : ScUnicode(); break;
4552 case ocUnichar : ScUnichar(); break;
4553 case ocBitAnd : ScBitAnd(); break;
4554 case ocBitOr : ScBitOr(); break;
4555 case ocBitXor : ScBitXor(); break;
4556 case ocBitRshift : ScBitRshift(); break;
4557 case ocBitLshift : ScBitLshift(); break;
4558 case ocTTT : ScTTT(); break;
4559 case ocDebugVar : ScDebugVar(); break;
4560 case ocNone : nFuncFmtType = SvNumFormatType::UNDEFINED; break;
4561 default : PushError( FormulaError::UnknownOpCode); break;
4564 // If the function pushed a subroutine as result, continue with
4565 // execution of the subroutine.
4566 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
4568 Pop(); continue;
4571 if (FormulaCompiler::IsOpCodeVolatile(eOp))
4572 meVolatileType = VOLATILE;
4574 // Remember result matrix in case it could be reused.
4575 if (sp && GetStackType() == svMatrix)
4576 maTokenMatrixMap.emplace(pCur, pStack[sp-1]);
4578 // outer function determines format of an expression
4579 if ( nFuncFmtType != SvNumFormatType::UNDEFINED )
4581 nRetTypeExpr = nFuncFmtType;
4582 // Inherit the format index for currency, date or time formats.
4583 switch (nFuncFmtType)
4585 case SvNumFormatType::CURRENCY:
4586 case SvNumFormatType::DATE:
4587 case SvNumFormatType::TIME:
4588 case SvNumFormatType::DATETIME:
4589 case SvNumFormatType::DURATION:
4590 nRetIndexExpr = nFuncFmtIndex;
4591 break;
4592 default:
4593 nRetIndexExpr = 0;
4599 // Need a clean stack environment for the JumpMatrix to work.
4600 if (nGlobalError != FormulaError::NONE && eOp != ocPush && sp > nStackBase + 1)
4602 // Not all functions pop all parameters in case an error is
4603 // generated. Clean up stack. Assumes that every function pushes a
4604 // result, may be arbitrary in case of error.
4605 FormulaConstTokenRef xLocalResult = pStack[ sp - 1 ];
4606 while (sp > nStackBase)
4607 Pop();
4608 PushTokenRef( xLocalResult );
4611 bool bGotResult;
4614 bGotResult = false;
4615 sal_uInt8 nLevel = 0;
4616 if ( GetStackType( ++nLevel ) == svJumpMatrix )
4617 ; // nothing
4618 else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4619 ; // nothing
4620 else
4621 nLevel = 0;
4622 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4624 if (nLevel == 1)
4625 aErrorFunctionStack.push_back( nErrorFunction);
4626 bGotResult = JumpMatrix( nLevel );
4627 if (aErrorFunctionStack.empty())
4628 assert(!"ScInterpreter::Interpret - aErrorFunctionStack empty in JumpMatrix context");
4629 else
4631 nErrorFunction = aErrorFunctionStack.back();
4632 if (bGotResult)
4633 aErrorFunctionStack.pop_back();
4636 else
4637 pJumpMatrix = nullptr;
4638 } while ( bGotResult );
4640 if( IsErrFunc(eOp) )
4641 ++nErrorFunction;
4643 if ( nGlobalError != FormulaError::NONE )
4645 if ( !nErrorFunctionCount )
4646 { // count of errorcode functions in formula
4647 FormulaTokenArrayPlainIterator aIter(*pArr);
4648 for ( FormulaToken* t = aIter.FirstRPN(); t; t = aIter.NextRPN() )
4650 if ( IsErrFunc(t->GetOpCode()) )
4651 ++nErrorFunctionCount;
4654 if ( nErrorFunction >= nErrorFunctionCount )
4655 ++nErrorFunction; // that's it, error => terminate
4656 else if (nErrorFunctionCount && sp && GetStackType() == svError)
4658 // Clear global error if we have an individual error result, so
4659 // an error evaluating function can receive multiple arguments
4660 // and not all evaluated arguments inheriting the error.
4661 // This is important for at least IFS() and SWITCH() as long as
4662 // they are classified as error evaluating functions and not
4663 // implemented as short-cutting jump code paths, but also for
4664 // more than one evaluated argument to AGGREGATE() or COUNT()
4665 // that may ignore errors.
4666 nGlobalError = FormulaError::NONE;
4671 // End: obtain result
4673 bool bForcedResultType;
4674 switch (eOp)
4676 case ocGetDateValue:
4677 case ocGetTimeValue:
4678 // Force final result of DATEVALUE and TIMEVALUE to number type,
4679 // which so far was date or time for calculations.
4680 nRetTypeExpr = nFuncFmtType = SvNumFormatType::NUMBER;
4681 nRetIndexExpr = nFuncFmtIndex = 0;
4682 bForcedResultType = true;
4683 break;
4684 default:
4685 bForcedResultType = false;
4688 if (sp == 1)
4690 pCur = pStack[ sp-1 ];
4691 if( pCur->GetOpCode() == ocPush )
4693 // An svRefList can be resolved if it a) contains just one
4694 // reference, or b) in array context contains an array of single
4695 // cell references.
4696 if (pCur->GetType() == svRefList)
4698 PopRefListPushMatrixOrRef();
4699 pCur = pStack[ sp-1 ];
4701 switch( pCur->GetType() )
4703 case svEmptyCell:
4704 ; // nothing
4705 break;
4706 case svError:
4707 nGlobalError = pCur->GetError();
4708 break;
4709 case svDouble :
4711 // If typed, pop token to obtain type information and
4712 // push a plain untyped double so the result token to
4713 // be transferred to the formula cell result does not
4714 // unnecessarily duplicate the information.
4715 if (pCur->GetDoubleType() != 0)
4717 double fVal = PopDouble();
4718 if (!bForcedResultType)
4720 if (nCurFmtType != nFuncFmtType)
4721 nRetIndexExpr = 0; // carry format index only for matching type
4722 nRetTypeExpr = nFuncFmtType = nCurFmtType;
4724 if (nRetTypeExpr == SvNumFormatType::DURATION)
4726 // Round the duration in case a wall clock time
4727 // display format is used instead of a duration
4728 // format. To micro seconds which then catches
4729 // the converted hh:mm:ss.9999997 cases.
4730 if (fVal != 0.0)
4732 fVal *= 86400.0;
4733 fVal = rtl::math::round( fVal, 6);
4734 fVal /= 86400.0;
4737 PushTempToken( CreateFormulaDoubleToken( fVal));
4739 if ( nFuncFmtType == SvNumFormatType::UNDEFINED )
4741 nRetTypeExpr = SvNumFormatType::NUMBER;
4742 nRetIndexExpr = 0;
4745 break;
4746 case svString :
4747 nRetTypeExpr = SvNumFormatType::TEXT;
4748 nRetIndexExpr = 0;
4749 break;
4750 case svSingleRef :
4752 ScAddress aAdr;
4753 PopSingleRef( aAdr );
4754 if( nGlobalError == FormulaError::NONE)
4755 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4757 break;
4758 case svRefList :
4759 PopError(); // maybe #REF! takes precedence over #VALUE!
4760 PushError( FormulaError::NoValue);
4761 break;
4762 case svDoubleRef :
4764 if ( bMatrixFormula )
4765 { // create matrix for {=A1:A5}
4766 PopDoubleRefPushMatrix();
4767 ScMatrixRef xMat = PopMatrix();
4768 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4770 else
4772 ScRange aRange;
4773 PopDoubleRef( aRange );
4774 ScAddress aAdr;
4775 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr))
4776 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4779 break;
4780 case svExternalDoubleRef:
4782 ScMatrixRef xMat;
4783 PopExternalDoubleRef(xMat);
4784 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4786 break;
4787 case svMatrix :
4789 sc::RangeMatrix aMat = PopRangeMatrix();
4790 if (aMat.isRangeValid())
4792 // This matrix represents a range reference. Apply implicit intersection.
4793 double fVal = applyImplicitIntersection(aMat, aPos);
4794 if (std::isnan(fVal))
4795 PushNoValue();
4796 else
4797 PushInt(fVal);
4799 else
4800 // This is a normal matrix.
4801 QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
4803 break;
4804 case svExternalSingleRef:
4806 FormulaTokenRef xToken;
4807 ScExternalRefCache::CellFormat aFmt;
4808 PopExternalSingleRef(xToken, &aFmt);
4809 if (nGlobalError != FormulaError::NONE)
4810 break;
4812 PushTokenRef(xToken);
4814 if (aFmt.mbIsSet)
4816 nFuncFmtType = aFmt.mnType;
4817 nFuncFmtIndex = aFmt.mnIndex;
4820 break;
4821 default :
4822 SetError( FormulaError::UnknownStackVariable);
4825 else
4826 SetError( FormulaError::UnknownStackVariable);
4828 else if (sp > 1)
4829 SetError( FormulaError::OperatorExpected);
4830 else
4831 SetError( FormulaError::NoCode);
4833 if (bForcedResultType || nRetTypeExpr != SvNumFormatType::UNDEFINED)
4835 nRetFmtType = nRetTypeExpr;
4836 nRetFmtIndex = nRetIndexExpr;
4838 else if( nFuncFmtType != SvNumFormatType::UNDEFINED )
4840 nRetFmtType = nFuncFmtType;
4841 nRetFmtIndex = nFuncFmtIndex;
4843 else
4844 nRetFmtType = SvNumFormatType::NUMBER;
4846 if (nGlobalError != FormulaError::NONE && GetStackType() != svError )
4847 PushError( nGlobalError);
4849 // THE final result.
4850 xResult = PopToken();
4851 if (!xResult)
4852 xResult = new FormulaErrorToken( FormulaError::UnknownStackVariable);
4854 // release tokens in expression stack
4855 const FormulaToken** p = pStack;
4856 while( maxsp-- )
4857 (*p++)->DecRef();
4859 StackVar eType = xResult->GetType();
4860 if (eType == svMatrix)
4861 // Results are immutable in case they would be reused as input for new
4862 // interpreters.
4863 xResult->GetMatrix()->SetImmutable();
4864 return eType;
4867 void ScInterpreter::AssertFormulaMatrix()
4869 bMatrixFormula = true;
4872 const svl::SharedString & ScInterpreter::GetStringResult() const
4874 return xResult->GetString();
4877 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */