Resolves: tdf#162093 TableRef item specifier may occur standalone
[LibreOffice.git] / sc / source / core / tool / interpr4.cxx
blobbea16130257f6528a322da958c9aafe9661a7903
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 = mrStrPool.intern(rCell.getString(&mrDoc));
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 = 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 = 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 OUString aStr;
2538 mrContext.NFGetInputLineString(fVal, nIndex, aStr);
2539 return mrStrPool.intern(aStr);
2542 void ScInterpreter::ScDBGet()
2544 bool bMissingField = false;
2545 unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2546 if (!pQueryParam)
2548 // Failed to create query param.
2549 PushIllegalParameter();
2550 return;
2553 pQueryParam->mbSkipString = false;
2554 ScDBQueryDataIterator aValIter(mrDoc, mrContext, std::move(pQueryParam));
2555 ScDBQueryDataIterator::Value aValue;
2556 if (!aValIter.GetFirst(aValue) || aValue.mnError != FormulaError::NONE)
2558 // No match found.
2559 PushNoValue();
2560 return;
2563 ScDBQueryDataIterator::Value aValNext;
2564 if (aValIter.GetNext(aValNext) && aValNext.mnError == FormulaError::NONE)
2566 // There should be only one unique match.
2567 PushIllegalArgument();
2568 return;
2571 if (aValue.mbIsNumber)
2572 PushDouble(aValue.mfValue);
2573 else
2574 PushString(aValue.maString);
2577 void ScInterpreter::ScExternal()
2579 sal_uInt8 nParamCount = GetByte();
2580 OUString aUnoName;
2581 OUString aFuncName( pCur->GetExternal().toAsciiUpperCase()); // programmatic name
2582 LegacyFuncData* pLegacyFuncData = ScGlobal::GetLegacyFuncCollection()->findByName(aFuncName);
2583 if (pLegacyFuncData)
2585 // Old binary non-UNO add-in function.
2586 // NOTE: parameter count is 1-based with the 0th "parameter" being the
2587 // return value, included in pLegacyFuncDatat->GetParamCount()
2588 if (nParamCount < MAXFUNCPARAM && nParamCount == pLegacyFuncData->GetParamCount() - 1)
2590 ParamType eParamType[MAXFUNCPARAM];
2591 void* ppParam[MAXFUNCPARAM];
2592 double nVal[MAXFUNCPARAM];
2593 char* pStr[MAXFUNCPARAM];
2594 sal_uInt8* pCellArr[MAXFUNCPARAM];
2595 short i;
2597 for (i = 0; i < MAXFUNCPARAM; i++)
2599 eParamType[i] = pLegacyFuncData->GetParamType(i);
2600 ppParam[i] = nullptr;
2601 nVal[i] = 0.0;
2602 pStr[i] = nullptr;
2603 pCellArr[i] = nullptr;
2606 for (i = nParamCount; (i > 0) && (nGlobalError == FormulaError::NONE); i--)
2608 if (IsMissing())
2610 // Old binary Add-In can't distinguish between missing
2611 // omitted argument and 0 (or any other value). Force
2612 // error.
2613 SetError( FormulaError::ParameterExpected);
2614 break; // for
2616 switch (eParamType[i])
2618 case ParamType::PTR_DOUBLE :
2620 nVal[i-1] = GetDouble();
2621 ppParam[i] = &nVal[i-1];
2623 break;
2624 case ParamType::PTR_STRING :
2626 OString aStr(OUStringToOString(GetString().getString(),
2627 osl_getThreadTextEncoding()));
2628 if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2629 SetError( FormulaError::StringOverflow );
2630 else
2632 pStr[i-1] = new char[ADDIN_MAXSTRLEN];
2633 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2634 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2635 ppParam[i] = pStr[i-1];
2638 break;
2639 case ParamType::PTR_DOUBLE_ARR :
2641 SCCOL nCol1;
2642 SCROW nRow1;
2643 SCTAB nTab1;
2644 SCCOL nCol2;
2645 SCROW nRow2;
2646 SCTAB nTab2;
2647 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2648 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2649 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2650 SetError(FormulaError::CodeOverflow);
2651 else
2652 ppParam[i] = pCellArr[i-1];
2654 break;
2655 case ParamType::PTR_STRING_ARR :
2657 SCCOL nCol1;
2658 SCROW nRow1;
2659 SCTAB nTab1;
2660 SCCOL nCol2;
2661 SCROW nRow2;
2662 SCTAB nTab2;
2663 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2664 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2665 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2666 SetError(FormulaError::CodeOverflow);
2667 else
2668 ppParam[i] = pCellArr[i-1];
2670 break;
2671 case ParamType::PTR_CELL_ARR :
2673 SCCOL nCol1;
2674 SCROW nRow1;
2675 SCTAB nTab1;
2676 SCCOL nCol2;
2677 SCROW nRow2;
2678 SCTAB nTab2;
2679 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2680 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2681 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2682 SetError(FormulaError::CodeOverflow);
2683 else
2684 ppParam[i] = pCellArr[i-1];
2686 break;
2687 default :
2688 SetError(FormulaError::IllegalParameter);
2689 break;
2692 while ( i-- )
2693 Pop(); // In case of error (otherwise i==0) pop all parameters
2695 if (nGlobalError == FormulaError::NONE)
2697 if ( pLegacyFuncData->GetAsyncType() == ParamType::NONE )
2699 switch ( eParamType[0] )
2701 case ParamType::PTR_DOUBLE :
2703 double nErg = 0.0;
2704 ppParam[0] = &nErg;
2705 pLegacyFuncData->Call(ppParam);
2706 PushDouble(nErg);
2708 break;
2709 case ParamType::PTR_STRING :
2711 std::unique_ptr<char[]> pcErg(new char[ADDIN_MAXSTRLEN]);
2712 ppParam[0] = pcErg.get();
2713 pLegacyFuncData->Call(ppParam);
2714 OUString aUni( pcErg.get(), strlen(pcErg.get()), osl_getThreadTextEncoding() );
2715 PushString( aUni );
2717 break;
2718 default:
2719 PushError( FormulaError::UnknownState );
2722 else
2724 // enable asyncs after loading
2725 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
2726 // assure identical handler with identical call?
2727 double nErg = 0.0;
2728 ppParam[0] = &nErg;
2729 pLegacyFuncData->Call(ppParam);
2730 sal_uLong nHandle = sal_uLong( nErg );
2731 if ( nHandle >= 65536 )
2733 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2734 if ( !pAs )
2736 pAs = new ScAddInAsync(nHandle, pLegacyFuncData, &mrDoc);
2737 pMyFormulaCell->StartListening( *pAs );
2739 else
2741 pMyFormulaCell->StartListening( *pAs );
2742 if ( !pAs->HasDocument( &mrDoc ) )
2743 pAs->AddDocument( &mrDoc );
2745 if ( pAs->IsValid() )
2747 switch ( pAs->GetType() )
2749 case ParamType::PTR_DOUBLE :
2750 PushDouble( pAs->GetValue() );
2751 break;
2752 case ParamType::PTR_STRING :
2753 PushString( pAs->GetString() );
2754 break;
2755 default:
2756 PushError( FormulaError::UnknownState );
2759 else
2760 PushNA();
2762 else
2763 PushNoValue();
2767 for (i = 0; i < MAXFUNCPARAM; i++)
2769 delete[] pStr[i];
2770 delete[] pCellArr[i];
2773 else
2775 while( nParamCount-- > 0)
2776 PopError();
2777 PushIllegalParameter();
2780 else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty() )
2782 // bLocalFirst=false in FindFunction, cFunc should be the stored
2783 // internal name
2785 ScUnoAddInCall aCall( mrDoc, *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2787 if ( !aCall.ValidParamCount() )
2788 SetError( FormulaError::IllegalParameter );
2790 if ( aCall.NeedsCaller() && GetError() == FormulaError::NONE )
2792 ScDocShell* pShell = mrDoc.GetDocumentShell();
2793 if (pShell)
2794 aCall.SetCallerFromObjectShell( pShell );
2795 else
2797 // use temporary model object (without document) to supply options
2798 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2799 new ScDocOptionsObj( mrDoc.GetDocOptions() ) ) );
2803 short nPar = nParamCount;
2804 while ( nPar > 0 && GetError() == FormulaError::NONE )
2806 --nPar; // 0 .. (nParamCount-1)
2808 uno::Any aParam;
2809 if (IsMissing())
2811 // Add-In has to explicitly handle an omitted empty missing
2812 // argument, do not default to anything like GetDouble() would
2813 // do (e.g. 0).
2814 Pop();
2815 aCall.SetParam( nPar, aParam );
2816 continue; // while
2819 StackVar nStackType = GetStackType();
2820 ScAddInArgumentType eType = aCall.GetArgType( nPar );
2821 switch (eType)
2823 case SC_ADDINARG_INTEGER:
2825 sal_Int32 nVal = GetInt32();
2826 if (nGlobalError == FormulaError::NONE)
2827 aParam <<= nVal;
2829 break;
2831 case SC_ADDINARG_DOUBLE:
2832 aParam <<= GetDouble();
2833 break;
2835 case SC_ADDINARG_STRING:
2836 aParam <<= GetString().getString();
2837 break;
2839 case SC_ADDINARG_INTEGER_ARRAY:
2840 switch( nStackType )
2842 case svDouble:
2843 case svString:
2844 case svSingleRef:
2846 sal_Int32 nVal = GetInt32();
2847 if (nGlobalError == FormulaError::NONE)
2849 uno::Sequence<sal_Int32> aInner( &nVal, 1 );
2850 uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2851 aParam <<= aOuter;
2854 break;
2855 case svDoubleRef:
2857 ScRange aRange;
2858 PopDoubleRef( aRange );
2859 if (!ScRangeToSequence::FillLongArray( aParam, mrDoc, aRange ))
2860 SetError(FormulaError::IllegalParameter);
2862 break;
2863 case svMatrix:
2864 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2865 SetError(FormulaError::IllegalParameter);
2866 break;
2867 default:
2868 PopError();
2869 SetError(FormulaError::IllegalParameter);
2871 break;
2873 case SC_ADDINARG_DOUBLE_ARRAY:
2874 switch( nStackType )
2876 case svDouble:
2877 case svString:
2878 case svSingleRef:
2880 double fVal = GetDouble();
2881 uno::Sequence<double> aInner( &fVal, 1 );
2882 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2883 aParam <<= aOuter;
2885 break;
2886 case svDoubleRef:
2888 ScRange aRange;
2889 PopDoubleRef( aRange );
2890 if (!ScRangeToSequence::FillDoubleArray( aParam, mrDoc, aRange ))
2891 SetError(FormulaError::IllegalParameter);
2893 break;
2894 case svMatrix:
2895 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2896 SetError(FormulaError::IllegalParameter);
2897 break;
2898 default:
2899 PopError();
2900 SetError(FormulaError::IllegalParameter);
2902 break;
2904 case SC_ADDINARG_STRING_ARRAY:
2905 switch( nStackType )
2907 case svDouble:
2908 case svString:
2909 case svSingleRef:
2911 OUString aString = GetString().getString();
2912 uno::Sequence<OUString> aInner( &aString, 1 );
2913 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 );
2914 aParam <<= aOuter;
2916 break;
2917 case svDoubleRef:
2919 ScRange aRange;
2920 PopDoubleRef( aRange );
2921 if (!ScRangeToSequence::FillStringArray( aParam, mrDoc, aRange ))
2922 SetError(FormulaError::IllegalParameter);
2924 break;
2925 case svMatrix:
2926 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), mrContext ))
2927 SetError(FormulaError::IllegalParameter);
2928 break;
2929 default:
2930 PopError();
2931 SetError(FormulaError::IllegalParameter);
2933 break;
2935 case SC_ADDINARG_MIXED_ARRAY:
2936 switch( nStackType )
2938 case svDouble:
2939 case svString:
2940 case svSingleRef:
2942 uno::Any aElem;
2943 if ( nStackType == svDouble )
2944 aElem <<= GetDouble();
2945 else if ( nStackType == svString )
2946 aElem <<= GetString().getString();
2947 else
2949 ScAddress aAdr;
2950 if ( PopDoubleRefOrSingleRef( aAdr ) )
2952 ScRefCellValue aCell(mrDoc, aAdr);
2953 if (aCell.hasString())
2955 svl::SharedString aStr;
2956 GetCellString(aStr, aCell);
2957 aElem <<= aStr.getString();
2959 else
2960 aElem <<= GetCellValue(aAdr, aCell);
2963 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2964 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2965 aParam <<= aOuter;
2967 break;
2968 case svDoubleRef:
2970 ScRange aRange;
2971 PopDoubleRef( aRange );
2972 if (!ScRangeToSequence::FillMixedArray( aParam, mrDoc, aRange ))
2973 SetError(FormulaError::IllegalParameter);
2975 break;
2976 case svMatrix:
2977 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2978 SetError(FormulaError::IllegalParameter);
2979 break;
2980 default:
2981 PopError();
2982 SetError(FormulaError::IllegalParameter);
2984 break;
2986 case SC_ADDINARG_VALUE_OR_ARRAY:
2987 switch( nStackType )
2989 case svDouble:
2990 aParam <<= GetDouble();
2991 break;
2992 case svString:
2993 aParam <<= GetString().getString();
2994 break;
2995 case svSingleRef:
2997 ScAddress aAdr;
2998 if ( PopDoubleRefOrSingleRef( aAdr ) )
3000 ScRefCellValue aCell(mrDoc, aAdr);
3001 if (aCell.hasString())
3003 svl::SharedString aStr;
3004 GetCellString(aStr, aCell);
3005 aParam <<= aStr.getString();
3007 else
3008 aParam <<= GetCellValue(aAdr, aCell);
3011 break;
3012 case svDoubleRef:
3014 ScRange aRange;
3015 PopDoubleRef( aRange );
3016 if (!ScRangeToSequence::FillMixedArray( aParam, mrDoc, aRange ))
3017 SetError(FormulaError::IllegalParameter);
3019 break;
3020 case svMatrix:
3021 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
3022 SetError(FormulaError::IllegalParameter);
3023 break;
3024 default:
3025 PopError();
3026 SetError(FormulaError::IllegalParameter);
3028 break;
3030 case SC_ADDINARG_CELLRANGE:
3031 switch( nStackType )
3033 case svSingleRef:
3035 ScAddress aAdr;
3036 PopSingleRef( aAdr );
3037 ScRange aRange( aAdr );
3038 uno::Reference<table::XCellRange> xObj =
3039 ScCellRangeObj::CreateRangeFromDoc( mrDoc, aRange );
3040 if (xObj.is())
3041 aParam <<= xObj;
3042 else
3043 SetError(FormulaError::IllegalParameter);
3045 break;
3046 case svDoubleRef:
3048 ScRange aRange;
3049 PopDoubleRef( aRange );
3050 uno::Reference<table::XCellRange> xObj =
3051 ScCellRangeObj::CreateRangeFromDoc( mrDoc, aRange );
3052 if (xObj.is())
3054 aParam <<= xObj;
3056 else
3058 SetError(FormulaError::IllegalParameter);
3061 break;
3062 default:
3063 PopError();
3064 SetError(FormulaError::IllegalParameter);
3066 break;
3068 default:
3069 PopError();
3070 SetError(FormulaError::IllegalParameter);
3072 aCall.SetParam( nPar, aParam );
3075 while (nPar-- > 0)
3077 Pop(); // in case of error, remove remaining args
3079 if ( GetError() == FormulaError::NONE )
3081 aCall.ExecuteCall();
3083 if ( aCall.HasVarRes() ) // handle async functions
3085 pArr->AddRecalcMode( ScRecalcMode::ONLOAD_LENIENT );
3086 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3087 ScAddInListener* pLis = ScAddInListener::Get( xRes );
3088 // In case there is no pMyFormulaCell, i.e. while interpreting
3089 // temporarily from within the Function Wizard, try to obtain a
3090 // valid result from an existing listener for that volatile, or
3091 // create a new and hope for an immediate result. If none
3092 // available that should lead to a void result and thus #N/A.
3093 bool bTemporaryListener = false;
3094 if ( !pLis )
3096 pLis = ScAddInListener::CreateListener( xRes, &mrDoc );
3097 if (pMyFormulaCell)
3098 pMyFormulaCell->StartListening( *pLis );
3099 else
3100 bTemporaryListener = true;
3102 else if (pMyFormulaCell)
3104 pMyFormulaCell->StartListening( *pLis );
3105 if ( !pLis->HasDocument( &mrDoc ) )
3107 pLis->AddDocument( &mrDoc );
3111 aCall.SetResult( pLis->GetResult() ); // use result from async
3113 if (bTemporaryListener)
3117 // EventObject can be any, not evaluated by
3118 // ScAddInListener::disposing()
3119 css::lang::EventObject aEvent;
3120 pLis->disposing(aEvent); // pLis is dead hereafter
3122 catch (const uno::Exception&)
3128 if ( aCall.GetErrCode() != FormulaError::NONE )
3130 PushError( aCall.GetErrCode() );
3132 else if ( aCall.HasMatrix() )
3134 PushMatrix( aCall.GetMatrix() );
3136 else if ( aCall.HasString() )
3138 PushString( aCall.GetString() );
3140 else
3142 PushDouble( aCall.GetValue() );
3145 else // error...
3146 PushError( GetError());
3148 else
3150 while( nParamCount-- > 0)
3152 PopError();
3154 PushError( FormulaError::NoAddin );
3158 void ScInterpreter::ScMissing()
3160 if ( aCode.IsEndOfPath() )
3161 PushTempToken( new ScEmptyCellToken( false, false ) );
3162 else
3163 PushTempToken( new FormulaMissingToken );
3166 #if HAVE_FEATURE_SCRIPTING
3168 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, const ScDocument* pDok )
3170 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3171 uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
3172 OUString sCodeName;
3173 xProps->getPropertyValue(u"CodeName"_ustr) >>= sCodeName;
3174 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3175 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3176 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3177 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3178 // create the special document module objects if they don't exist.
3179 BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3181 uno::Reference< uno::XInterface > xIf;
3182 if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
3184 OUString sProj( u"Standard"_ustr );
3185 if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3187 sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
3189 StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3190 if ( pBasic )
3192 SbModule* pMod = pBasic->FindModule( sCodeName );
3193 if ( pMod )
3195 xIf = pMod->GetUnoModule();
3199 return uno::Any( xIf );
3202 static bool lcl_setVBARange( const ScRange& aRange, const ScDocument& rDok, SbxVariable* pPar )
3204 bool bOk = false;
3207 uno::Reference< uno::XInterface > xVBARange;
3208 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( rDok, aRange );
3209 uno::Sequence< uno::Any > aArgs{ lcl_getSheetModule( xCellRange, &rDok ),
3210 uno::Any(xCellRange) };
3211 xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( rDok.GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
3212 if ( xVBARange.is() )
3214 SbxObjectRef aObj = GetSbUnoObject( u"A-Range"_ustr, uno::Any( xVBARange ) );
3215 SetSbUnoObjectDfltPropName( aObj.get() );
3216 bOk = pPar->PutObject( aObj.get() );
3219 catch( uno::Exception& )
3222 return bOk;
3225 static bool lcl_isNumericResult( double& fVal, const SbxVariable* pVar )
3227 switch (pVar->GetType())
3229 case SbxINTEGER:
3230 case SbxLONG:
3231 case SbxSINGLE:
3232 case SbxDOUBLE:
3233 case SbxCURRENCY:
3234 case SbxDATE:
3235 case SbxUSHORT:
3236 case SbxULONG:
3237 case SbxINT:
3238 case SbxUINT:
3239 case SbxSALINT64:
3240 case SbxSALUINT64:
3241 case SbxDECIMAL:
3242 fVal = pVar->GetDouble();
3243 return true;
3244 case SbxBOOL:
3245 fVal = (pVar->GetBool() ? 1.0 : 0.0);
3246 return true;
3247 default:
3248 ; // nothing
3250 return false;
3253 #endif
3255 void ScInterpreter::ScMacro()
3258 #if !HAVE_FEATURE_SCRIPTING
3259 PushNoValue(); // without DocShell no CallBasic
3260 return;
3261 #else
3262 SbxBase::ResetError();
3264 sal_uInt8 nParamCount = GetByte();
3265 OUString aMacro( pCur->GetExternal() );
3267 ScDocShell* pDocSh = mrDoc.GetDocumentShell();
3268 if ( !pDocSh )
3270 PushNoValue(); // without DocShell no CallBasic
3271 return;
3274 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic
3276 // If the Dok was loaded during a Basic-Calls,
3277 // is the Sbx-object created(?)
3278 // pDocSh->GetSbxObject();
3280 // search function with the name,
3281 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr
3283 StarBASIC* pRoot;
3287 pRoot = pDocSh->GetBasic();
3289 catch (...)
3291 pRoot = nullptr;
3294 SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxClassType::Method) : nullptr;
3295 if( !pVar || pVar->GetType() == SbxVOID )
3297 PushError( FormulaError::NoMacro );
3298 return;
3300 SbMethod* pMethod = dynamic_cast<SbMethod*>(pVar);
3301 if( !pMethod )
3303 PushError( FormulaError::NoMacro );
3304 return;
3307 bool bVolatileMacro = false;
3309 SbModule* pModule = pMethod->GetModule();
3310 bool bUseVBAObjects = pModule->IsVBASupport();
3311 SbxObject* pObject = pModule->GetParent();
3312 assert(pObject);
3313 OSL_ENSURE(dynamic_cast<const StarBASIC *>(pObject) != nullptr, "No Basic found!");
3314 OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName();
3315 OUString aBasicStr;
3316 if (pRoot && bUseVBAObjects)
3318 // just here to make sure the VBA objects when we run the macro during ODF import
3319 pRoot->getVBAGlobals();
3321 if (pObject->GetParent())
3323 aBasicStr = pObject->GetParent()->GetName(); // document BASIC
3325 else
3327 aBasicStr = SfxGetpApp()->GetName(); // application BASIC
3329 // assemble a parameter array
3331 SbxArrayRef refPar = new SbxArray;
3332 bool bOk = true;
3333 for( sal_uInt32 i = nParamCount; i && bOk ; i-- )
3335 SbxVariable* pPar = refPar->Get(i);
3336 switch( GetStackType() )
3338 case svDouble:
3339 pPar->PutDouble( GetDouble() );
3340 break;
3341 case svString:
3342 pPar->PutString( GetString().getString() );
3343 break;
3344 case svExternalSingleRef:
3346 ScExternalRefCache::TokenRef pToken;
3347 PopExternalSingleRef(pToken);
3348 if (nGlobalError != FormulaError::NONE)
3349 bOk = false;
3350 else
3352 if ( pToken->GetType() == svString )
3353 pPar->PutString( pToken->GetString().getString() );
3354 else if ( pToken->GetType() == svDouble )
3355 pPar->PutDouble( pToken->GetDouble() );
3356 else
3358 SetError( FormulaError::IllegalArgument );
3359 bOk = false;
3363 break;
3364 case svSingleRef:
3366 ScAddress aAdr;
3367 PopSingleRef( aAdr );
3368 if ( bUseVBAObjects )
3370 ScRange aRange( aAdr );
3371 bOk = lcl_setVBARange( aRange, mrDoc, pPar );
3373 else
3375 bOk = SetSbxVariable( pPar, aAdr );
3378 break;
3379 case svDoubleRef:
3381 SCCOL nCol1;
3382 SCROW nRow1;
3383 SCTAB nTab1;
3384 SCCOL nCol2;
3385 SCROW nRow2;
3386 SCTAB nTab2;
3387 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3388 if( nTab1 != nTab2 )
3390 SetError( FormulaError::IllegalParameter );
3391 bOk = false;
3393 else
3395 if ( bUseVBAObjects )
3397 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3398 bOk = lcl_setVBARange( aRange, mrDoc, pPar );
3400 else
3402 SbxDimArrayRef refArray = new SbxDimArray;
3403 refArray->AddDim(1, nRow2 - nRow1 + 1);
3404 refArray->AddDim(1, nCol2 - nCol1 + 1);
3405 ScAddress aAdr( nCol1, nRow1, nTab1 );
3406 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3408 aAdr.SetRow( nRow );
3409 sal_Int32 nIdx[ 2 ];
3410 nIdx[ 0 ] = nRow-nRow1+1;
3411 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3413 aAdr.SetCol( nCol );
3414 nIdx[ 1 ] = nCol-nCol1+1;
3415 SbxVariable* p = refArray->Get(nIdx);
3416 bOk = SetSbxVariable( p, aAdr );
3419 pPar->PutObject( refArray.get() );
3423 break;
3424 case svExternalDoubleRef:
3425 case svMatrix:
3427 ScMatrixRef pMat = GetMatrix();
3428 SCSIZE nC, nR;
3429 if (pMat && nGlobalError == FormulaError::NONE)
3431 pMat->GetDimensions(nC, nR);
3432 SbxDimArrayRef refArray = new SbxDimArray;
3433 refArray->AddDim(1, static_cast<sal_Int32>(nR));
3434 refArray->AddDim(1, static_cast<sal_Int32>(nC));
3435 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3437 sal_Int32 nIdx[ 2 ];
3438 nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3439 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3441 nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3442 SbxVariable* p = refArray->Get(nIdx);
3443 if (pMat->IsStringOrEmpty(nMatCol, nMatRow))
3445 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() );
3447 else
3449 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3453 pPar->PutObject( refArray.get() );
3455 else
3457 SetError( FormulaError::IllegalParameter );
3460 break;
3461 default:
3462 SetError( FormulaError::IllegalParameter );
3463 bOk = false;
3466 if( bOk )
3468 mrDoc.LockTable( aPos.Tab() );
3469 SbxVariableRef refRes = new SbxVariable;
3470 mrDoc.IncMacroInterpretLevel();
3471 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar.get(), refRes.get() );
3472 mrDoc.DecMacroInterpretLevel();
3473 mrDoc.UnlockTable( aPos.Tab() );
3475 ScMacroManager* pMacroMgr = mrDoc.GetMacroManager();
3476 if (pMacroMgr)
3478 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3479 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3482 double fVal;
3483 SbxDataType eResType = refRes->GetType();
3484 if( SbxBase::GetError() )
3486 SetError( FormulaError::NoValue);
3488 if ( eRet != ERRCODE_NONE )
3490 PushNoValue();
3492 else if (lcl_isNumericResult( fVal, refRes.get()))
3494 switch (eResType)
3496 case SbxDATE:
3497 nFuncFmtType = SvNumFormatType::DATE;
3498 break;
3499 case SbxBOOL:
3500 nFuncFmtType = SvNumFormatType::LOGICAL;
3501 break;
3502 // Do not add SbxCURRENCY, we don't know which currency.
3503 default:
3504 ; // nothing
3506 PushDouble( fVal );
3508 else if ( eResType & SbxARRAY )
3510 SbxBase* pElemObj = refRes->GetObject();
3511 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>(pElemObj);
3512 sal_Int32 nDim = pDimArray ? pDimArray->GetDims() : 0;
3513 if ( 1 <= nDim && nDim <= 2 )
3515 sal_Int32 nCs, nCe, nRs;
3516 SCSIZE nC, nR;
3517 SCCOL nColIdx;
3518 SCROW nRowIdx;
3519 if ( nDim == 1 )
3520 { // array( cols ) one line, several columns
3521 pDimArray->GetDim(1, nCs, nCe);
3522 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3523 nRs = 0;
3524 nR = 1;
3525 nColIdx = 0;
3526 nRowIdx = 1;
3528 else
3529 { // array( rows, cols )
3530 sal_Int32 nRe;
3531 pDimArray->GetDim(1, nRs, nRe);
3532 nR = static_cast<SCSIZE>(nRe - nRs + 1);
3533 pDimArray->GetDim(2, nCs, nCe);
3534 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3535 nColIdx = 1;
3536 nRowIdx = 0;
3538 ScMatrixRef pMat = GetNewMat( nC, nR, /*bEmpty*/true);
3539 if ( pMat )
3541 SbxVariable* pV;
3542 for ( SCSIZE j=0; j < nR; j++ )
3544 sal_Int32 nIdx[ 2 ];
3545 // in one-dimensional array( cols ) nIdx[1]
3546 // from SbxDimArray::Get is ignored
3547 nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3548 for ( SCSIZE i=0; i < nC; i++ )
3550 nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3551 pV = pDimArray->Get(nIdx);
3552 if ( lcl_isNumericResult( fVal, pV) )
3554 pMat->PutDouble( fVal, i, j );
3556 else
3558 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j);
3562 PushMatrix( pMat );
3564 else
3566 PushIllegalArgument();
3569 else
3571 PushNoValue();
3574 else
3576 PushString( refRes->GetOUString() );
3580 if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3581 meVolatileType = VOLATILE_MACRO;
3582 #endif
3585 #if HAVE_FEATURE_SCRIPTING
3587 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3589 bool bOk = true;
3590 ScRefCellValue aCell(mrDoc, rPos);
3591 if (!aCell.isEmpty())
3593 FormulaError nErr;
3594 double nVal;
3595 switch (aCell.getType())
3597 case CELLTYPE_VALUE :
3598 nVal = GetValueCellValue(rPos, aCell.getDouble());
3599 pVar->PutDouble( nVal );
3600 break;
3601 case CELLTYPE_STRING :
3602 case CELLTYPE_EDIT :
3603 pVar->PutString(aCell.getString(&mrDoc));
3604 break;
3605 case CELLTYPE_FORMULA :
3606 nErr = aCell.getFormula()->GetErrCode();
3607 if( nErr == FormulaError::NONE )
3609 if (aCell.getFormula()->IsValue())
3611 nVal = aCell.getFormula()->GetValue();
3612 pVar->PutDouble( nVal );
3614 else
3615 pVar->PutString(aCell.getFormula()->GetString().getString());
3617 else
3619 SetError( nErr );
3620 bOk = false;
3622 break;
3623 default :
3624 pVar->PutEmpty();
3627 else
3628 pVar->PutEmpty();
3630 return bOk;
3633 #endif
3635 void ScInterpreter::ScTableOp()
3637 sal_uInt8 nParamCount = GetByte();
3638 if (nParamCount != 3 && nParamCount != 5)
3640 PushIllegalParameter();
3641 return;
3643 ScInterpreterTableOpParams aTableOp;
3644 if (nParamCount == 5)
3646 PopSingleRef( aTableOp.aNew2 );
3647 PopSingleRef( aTableOp.aOld2 );
3649 PopSingleRef( aTableOp.aNew1 );
3650 PopSingleRef( aTableOp.aOld1 );
3651 PopSingleRef( aTableOp.aFormulaPos );
3653 aTableOp.bValid = true;
3654 mrDoc.m_TableOpList.push_back(&aTableOp);
3655 mrDoc.IncInterpreterTableOpLevel();
3657 bool bReuseLastParams = (mrDoc.aLastTableOpParams == aTableOp);
3658 if ( bReuseLastParams )
3660 aTableOp.aNotifiedFormulaPos = mrDoc.aLastTableOpParams.aNotifiedFormulaPos;
3661 aTableOp.bRefresh = true;
3662 for ( const auto& rPos : aTableOp.aNotifiedFormulaPos )
3663 { // emulate broadcast and indirectly collect cell pointers
3664 ScRefCellValue aCell(mrDoc, rPos);
3665 if (aCell.getType() == CELLTYPE_FORMULA)
3666 aCell.getFormula()->SetTableOpDirty();
3669 else
3670 { // broadcast and indirectly collect cell pointers and positions
3671 mrDoc.SetTableOpDirty( aTableOp.aOld1 );
3672 if ( nParamCount == 5 )
3673 mrDoc.SetTableOpDirty( aTableOp.aOld2 );
3675 aTableOp.bCollectNotifications = false;
3677 ScRefCellValue aCell(mrDoc, aTableOp.aFormulaPos);
3678 if (aCell.getType() == CELLTYPE_FORMULA)
3679 aCell.getFormula()->SetDirtyVar();
3680 if (aCell.hasNumeric())
3682 PushDouble(GetCellValue(aTableOp.aFormulaPos, aCell));
3684 else
3686 svl::SharedString aCellString;
3687 GetCellString(aCellString, aCell);
3688 PushString( aCellString );
3691 auto const itr =
3692 ::std::find(mrDoc.m_TableOpList.begin(), mrDoc.m_TableOpList.end(), &aTableOp);
3693 if (itr != mrDoc.m_TableOpList.end())
3695 mrDoc.m_TableOpList.erase(itr);
3698 // set dirty again once more to be able to recalculate original
3699 for ( const auto& pCell : aTableOp.aNotifiedFormulaCells )
3701 pCell->SetTableOpDirty();
3704 // save these params for next incarnation
3705 if ( !bReuseLastParams )
3706 mrDoc.aLastTableOpParams = aTableOp;
3708 if (aCell.getType() == CELLTYPE_FORMULA)
3710 aCell.getFormula()->SetDirtyVar();
3711 aCell.getFormula()->GetErrCode(); // recalculate original
3714 // Reset all dirty flags so next incarnation does really collect all cell
3715 // pointers during notifications and not just non-dirty ones, which may
3716 // happen if a formula cell is used by more than one TableOp block.
3717 for ( const auto& pCell : aTableOp.aNotifiedFormulaCells )
3719 pCell->ResetTableOpDirtyVar();
3722 mrDoc.DecInterpreterTableOpLevel();
3725 void ScInterpreter::ScDBArea()
3727 ScDBData* pDBData = mrDoc.GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3728 if (pDBData)
3730 ScComplexRefData aRefData;
3731 aRefData.InitFlags();
3732 ScRange aRange;
3733 pDBData->GetArea(aRange);
3734 aRange.aEnd.SetTab(aRange.aStart.Tab());
3735 aRefData.SetRange(mrDoc.GetSheetLimits(), aRange, aPos);
3736 PushTempToken( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRefData ) );
3738 else
3739 PushError( FormulaError::NoName);
3742 void ScInterpreter::ScColRowNameAuto()
3744 ScComplexRefData aRefData( *pCur->GetDoubleRef() );
3745 ScRange aAbs = aRefData.toAbs(mrDoc, aPos);
3746 if (!mrDoc.ValidRange(aAbs))
3748 PushError( FormulaError::NoRef );
3749 return;
3752 SCCOL nStartCol;
3753 SCROW nStartRow;
3755 // maybe remember limit by using defined ColRowNameRange
3756 SCCOL nCol2 = aAbs.aEnd.Col();
3757 SCROW nRow2 = aAbs.aEnd.Row();
3758 // DataArea of the first cell
3759 nStartCol = aAbs.aStart.Col();
3760 nStartRow = aAbs.aStart.Row();
3761 aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell.
3764 // Expand to the data area. Only modify the end position.
3765 SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col();
3766 SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row();
3767 mrDoc.GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false);
3768 aAbs.aEnd.SetCol(nDACol2);
3769 aAbs.aEnd.SetRow(nDARow2);
3772 // corresponds with ScCompiler::GetToken
3773 if ( aRefData.Ref1.IsColRel() )
3774 { // ColName
3775 aAbs.aEnd.SetCol(nStartCol);
3776 // maybe get previous limit by using defined ColRowNameRange
3777 if (aAbs.aEnd.Row() > nRow2)
3778 aAbs.aEnd.SetRow(nRow2);
3779 if ( aPos.Col() == nStartCol )
3781 SCROW nMyRow = aPos.Row();
3782 if ( nStartRow <= nMyRow && nMyRow <= aAbs.aEnd.Row())
3783 { //Formula in the same column and within the range
3784 if ( nMyRow == nStartRow )
3785 { // take the rest under the name
3786 nStartRow++;
3787 if ( nStartRow > mrDoc.MaxRow() )
3788 nStartRow = mrDoc.MaxRow();
3789 aAbs.aStart.SetRow(nStartRow);
3791 else
3792 { // below the name to the formula cell
3793 aAbs.aEnd.SetRow(nMyRow - 1);
3798 else
3799 { // RowName
3800 aAbs.aEnd.SetRow(nStartRow);
3801 // maybe get previous limit by using defined ColRowNameRange
3802 if (aAbs.aEnd.Col() > nCol2)
3803 aAbs.aEnd.SetCol(nCol2);
3804 if ( aPos.Row() == nStartRow )
3806 SCCOL nMyCol = aPos.Col();
3807 if (nStartCol <= nMyCol && nMyCol <= aAbs.aEnd.Col())
3808 { //Formula in the same column and within the range
3809 if ( nMyCol == nStartCol )
3810 { // take the rest under the name
3811 nStartCol++;
3812 if ( nStartCol > mrDoc.MaxCol() )
3813 nStartCol = mrDoc.MaxCol();
3814 aAbs.aStart.SetCol(nStartCol);
3816 else
3817 { // below the name to the formula cell
3818 aAbs.aEnd.SetCol(nMyCol - 1);
3823 aRefData.SetRange(mrDoc.GetSheetLimits(), aAbs, aPos);
3824 PushTempToken( new ScDoubleRefToken( mrDoc.GetSheetLimits(), aRefData ) );
3827 // --- internals ------------------------------------------------------------
3829 void ScInterpreter::ScTTT()
3830 { // temporary test, testing functions etc.
3831 sal_uInt8 nParamCount = GetByte();
3832 // do something, count down nParamCount with Pops!
3834 // clean up Stack
3835 while ( nParamCount-- > 0)
3836 Pop();
3837 PushError(FormulaError::NoValue);
3840 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument& rDoc, ScInterpreterContext& rContext,
3841 const ScAddress& rPos, ScTokenArray& r, bool bForGroupThreading )
3842 : aCode(r)
3843 , aPos(rPos)
3844 , pArr(&r)
3845 , mrContext(rContext)
3846 , mrDoc(rDoc)
3847 , mpLinkManager(rDoc.GetLinkManager())
3848 , mrStrPool(rDoc.GetSharedStringPool())
3849 , pJumpMatrix(nullptr)
3850 , pMyFormulaCell(pCell)
3851 , pCur(nullptr)
3852 , nGlobalError(FormulaError::NONE)
3853 , sp(0)
3854 , maxsp(0)
3855 , nFuncFmtIndex(0)
3856 , nCurFmtIndex(0)
3857 , nRetFmtIndex(0)
3858 , nFuncFmtType(SvNumFormatType::ALL)
3859 , nCurFmtType(SvNumFormatType::ALL)
3860 , nRetFmtType(SvNumFormatType::ALL)
3861 , mnStringNoValueError(FormulaError::NoValue)
3862 , mnSubTotalFlags(SubtotalFlags::NONE)
3863 , cPar(0)
3864 , bCalcAsShown(rDoc.GetDocOptions().IsCalcAsShown())
3865 , meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3867 MergeCalcConfig();
3869 if(pMyFormulaCell)
3871 ScMatrixMode cMatFlag = pMyFormulaCell->GetMatrixFlag();
3872 bMatrixFormula = ( cMatFlag == ScMatrixMode::Formula );
3874 else
3875 bMatrixFormula = false;
3877 // Lets not use the global stack while formula-group-threading.
3878 // as it complicates its life-cycle mgmt since for threading formula-groups,
3879 // ScInterpreter is preallocated (in main thread) for each worker thread.
3880 if (!bGlobalStackInUse && !bForGroupThreading)
3882 bGlobalStackInUse = true;
3883 if (!pGlobalStack)
3884 pGlobalStack.reset(new ScTokenStack);
3885 pStackObj = pGlobalStack.get();
3887 else
3889 pStackObj = new ScTokenStack;
3891 pStack = pStackObj->pPointer;
3894 ScInterpreter::~ScInterpreter()
3896 if ( pStackObj == pGlobalStack.get() )
3897 bGlobalStackInUse = false;
3898 else
3899 delete pStackObj;
3902 void ScInterpreter::Init( ScFormulaCell* pCell, const ScAddress& rPos, ScTokenArray& rTokArray )
3904 aCode.ReInit(rTokArray);
3905 aPos = rPos;
3906 pArr = &rTokArray;
3907 pJumpMatrix = nullptr;
3908 DropTokenCaches();
3909 pMyFormulaCell = pCell;
3910 pCur = nullptr;
3911 nGlobalError = FormulaError::NONE;
3912 sp = 0;
3913 maxsp = 0;
3914 nFuncFmtIndex = 0;
3915 nCurFmtIndex = 0;
3916 nRetFmtIndex = 0;
3917 nFuncFmtType = SvNumFormatType::ALL;
3918 nCurFmtType = SvNumFormatType::ALL;
3919 nRetFmtType = SvNumFormatType::ALL;
3920 mnStringNoValueError = FormulaError::NoValue;
3921 mnSubTotalFlags = SubtotalFlags::NONE;
3922 cPar = 0;
3925 void ScInterpreter::DropTokenCaches()
3927 xResult = nullptr;
3928 maTokenMatrixMap.clear();
3931 ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
3933 if (!mpGlobalConfig)
3934 mpGlobalConfig = new ScCalcConfig();
3935 return *mpGlobalConfig;
3938 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3940 GetOrCreateGlobalConfig() = rConfig;
3943 const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3945 return GetOrCreateGlobalConfig();
3948 void ScInterpreter::MergeCalcConfig()
3950 maCalcConfig = GetOrCreateGlobalConfig();
3951 maCalcConfig.MergeDocumentSpecific( mrDoc.GetCalcConfig());
3954 void ScInterpreter::GlobalExit()
3956 OSL_ENSURE(!bGlobalStackInUse, "who is still using the TokenStack?");
3957 pGlobalStack.reset();
3960 namespace {
3962 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
3964 if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
3966 SCROW nOffset = rPos.Row() - rMat.mnRow1;
3967 return rMat.mpMat->GetDouble(0, nOffset);
3970 if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
3972 SCROW nOffset = rPos.Col() - rMat.mnCol1;
3973 return rMat.mpMat->GetDouble(nOffset, 0);
3976 return std::numeric_limits<double>::quiet_NaN();
3979 // Test for Functions that evaluate an error code and directly set nGlobalError to 0
3980 bool IsErrFunc(OpCode oc)
3982 switch (oc)
3984 case ocCount :
3985 case ocCount2 :
3986 case ocErrorType :
3987 case ocIsEmpty :
3988 case ocIsErr :
3989 case ocIsError :
3990 case ocIsFormula :
3991 case ocIsLogical :
3992 case ocIsNA :
3993 case ocIsNonString :
3994 case ocIsRef :
3995 case ocIsString :
3996 case ocIsValue :
3997 case ocN :
3998 case ocType :
3999 case ocIfError :
4000 case ocIfNA :
4001 case ocErrorType_ODF :
4002 case ocAggregate: // may ignore errors depending on option
4003 case ocIfs_MS:
4004 case ocSwitch_MS:
4005 case ocXLookup:
4006 return true;
4007 default:
4008 return false;
4012 } //namespace
4014 StackVar ScInterpreter::Interpret()
4016 SvNumFormatType nRetTypeExpr = SvNumFormatType::UNDEFINED;
4017 sal_uInt32 nRetIndexExpr = 0;
4018 sal_uInt16 nErrorFunction = 0;
4019 sal_uInt16 nErrorFunctionCount = 0;
4020 std::vector<sal_uInt16> aErrorFunctionStack;
4021 sal_uInt16 nStackBase;
4023 nGlobalError = FormulaError::NONE;
4024 nStackBase = sp = maxsp = 0;
4025 nRetFmtType = SvNumFormatType::UNDEFINED;
4026 nFuncFmtType = SvNumFormatType::UNDEFINED;
4027 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
4028 xResult = nullptr;
4029 pJumpMatrix = nullptr;
4030 mnSubTotalFlags = SubtotalFlags::NONE;
4031 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
4033 // Once upon a time we used to have FP exceptions on, and there was a
4034 // Windows printer driver that kept switching off exceptions, so we had to
4035 // switch them back on again every time. Who knows if there isn't a driver
4036 // that keeps switching exceptions on, now that we run with exceptions off,
4037 // so reassure exceptions are really off.
4038 SAL_MATH_FPEXCEPTIONS_OFF();
4040 OpCode eOp = ocNone;
4041 aCode.Reset();
4042 for (;;)
4044 pCur = aCode.Next();
4045 if (!pCur || (nGlobalError != FormulaError::NONE && nErrorFunction > nErrorFunctionCount) )
4046 break;
4047 eOp = pCur->GetOpCode();
4048 cPar = pCur->GetByte();
4049 if ( eOp == ocPush )
4051 // RPN code push without error
4052 PushWithoutError( *pCur );
4053 nCurFmtType = SvNumFormatType::UNDEFINED;
4055 else
4057 const bool bIsOpCodeJumpCommand = FormulaCompiler::IsOpCodeJumpCommand(eOp);
4058 if (!bIsOpCodeJumpCommand &&
4059 ((aTokenMatrixMapIter = maTokenMatrixMap.find( pCur)) !=
4060 maTokenMatrixMap.end()) &&
4061 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
4063 // Path already calculated, reuse result.
4064 const sal_uInt8 nParamCount = pCur->GetParamCount();
4065 if (sp >= nParamCount)
4066 nStackBase = sp - nParamCount;
4067 else
4069 SAL_WARN("sc.core", "Stack anomaly with calculated path at "
4070 << aPos.Tab() << "," << aPos.Col() << "," << aPos.Row()
4071 << " " << aPos.Format(
4072 ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc)
4073 << " eOp: " << static_cast<int>(eOp)
4074 << " params: " << static_cast<int>(nParamCount)
4075 << " nStackBase: " << nStackBase << " sp: " << sp);
4076 nStackBase = sp;
4077 assert(!"underflow");
4079 sp = nStackBase;
4080 PushTokenRef( (*aTokenMatrixMapIter).second);
4082 else
4084 // previous expression determines the current number format
4085 nCurFmtType = nRetTypeExpr;
4086 nCurFmtIndex = nRetIndexExpr;
4087 // default function's format, others are set if needed
4088 nFuncFmtType = SvNumFormatType::NUMBER;
4089 nFuncFmtIndex = 0;
4091 if (bIsOpCodeJumpCommand)
4092 nStackBase = sp; // don't mess around with the jumps
4093 else
4095 // Convert parameters to matrix if in array/matrix formula and
4096 // parameters of function indicate doing so. Create JumpMatrix
4097 // if necessary.
4098 if ( MatrixParameterConversion() )
4100 eOp = ocNone; // JumpMatrix created
4101 nStackBase = sp;
4103 else
4105 const sal_uInt8 nParamCount = pCur->GetParamCount();
4106 if (sp >= nParamCount)
4107 nStackBase = sp - nParamCount;
4108 else
4110 SAL_WARN("sc.core", "Stack anomaly at " << aPos.Tab() << "," << aPos.Col() << "," << aPos.Row()
4111 << " " << aPos.Format(
4112 ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc)
4113 << " eOp: " << static_cast<int>(eOp)
4114 << " params: " << static_cast<int>(nParamCount)
4115 << " nStackBase: " << nStackBase << " sp: " << sp);
4116 nStackBase = sp;
4117 assert(!"underflow");
4122 switch( eOp )
4124 case ocSep:
4125 case ocClose: // pushed by the compiler
4126 case ocMissing : ScMissing(); break;
4127 case ocMacro : ScMacro(); break;
4128 case ocDBArea : ScDBArea(); break;
4129 case ocColRowNameAuto : ScColRowNameAuto(); break;
4130 case ocIf : ScIfJump(); break;
4131 case ocIfError : ScIfError( false ); break;
4132 case ocIfNA : ScIfError( true ); break;
4133 case ocChoose : ScChooseJump(); break;
4134 case ocAdd : ScAdd(); break;
4135 case ocSub : ScSub(); break;
4136 case ocMul : ScMul(); break;
4137 case ocDiv : ScDiv(); break;
4138 case ocAmpersand : ScAmpersand(); break;
4139 case ocPow : ScPow(); break;
4140 case ocEqual : ScEqual(); break;
4141 case ocNotEqual : ScNotEqual(); break;
4142 case ocLess : ScLess(); break;
4143 case ocGreater : ScGreater(); break;
4144 case ocLessEqual : ScLessEqual(); break;
4145 case ocGreaterEqual : ScGreaterEqual(); break;
4146 case ocAnd : ScAnd(); break;
4147 case ocOr : ScOr(); break;
4148 case ocXor : ScXor(); break;
4149 case ocIntersect : ScIntersect(); break;
4150 case ocRange : ScRangeFunc(); break;
4151 case ocUnion : ScUnionFunc(); break;
4152 case ocNot : ScNot(); break;
4153 case ocNegSub :
4154 case ocNeg : ScNeg(); break;
4155 case ocPercentSign : ScPercentSign(); break;
4156 case ocPi : ScPi(); break;
4157 case ocRandom : ScRandom(); break;
4158 case ocRandArray : ScRandArray(); break;
4159 case ocRandomNV : ScRandom(); break;
4160 case ocRandbetweenNV : ScRandbetween(); break;
4161 case ocFilter : ScFilter(); break;
4162 case ocSort : ScSort(); break;
4163 case ocSortBy : ScSortBy(); break;
4164 case ocUnique : ScUnique(); break;
4165 case ocLet : ScLet(); break;
4166 case ocTrue : ScTrue(); break;
4167 case ocFalse : ScFalse(); break;
4168 case ocGetActDate : ScGetActDate(); break;
4169 case ocGetActTime : ScGetActTime(); break;
4170 case ocNotAvail : PushError( FormulaError::NotAvailable); break;
4171 case ocDeg : ScDeg(); break;
4172 case ocRad : ScRad(); break;
4173 case ocSin : ScSin(); break;
4174 case ocCos : ScCos(); break;
4175 case ocTan : ScTan(); break;
4176 case ocCot : ScCot(); break;
4177 case ocArcSin : ScArcSin(); break;
4178 case ocArcCos : ScArcCos(); break;
4179 case ocArcTan : ScArcTan(); break;
4180 case ocArcCot : ScArcCot(); break;
4181 case ocSinHyp : ScSinHyp(); break;
4182 case ocCosHyp : ScCosHyp(); break;
4183 case ocTanHyp : ScTanHyp(); break;
4184 case ocCotHyp : ScCotHyp(); break;
4185 case ocArcSinHyp : ScArcSinHyp(); break;
4186 case ocArcCosHyp : ScArcCosHyp(); break;
4187 case ocArcTanHyp : ScArcTanHyp(); break;
4188 case ocArcCotHyp : ScArcCotHyp(); break;
4189 case ocCosecant : ScCosecant(); break;
4190 case ocSecant : ScSecant(); break;
4191 case ocCosecantHyp : ScCosecantHyp(); break;
4192 case ocSecantHyp : ScSecantHyp(); break;
4193 case ocExp : ScExp(); break;
4194 case ocLn : ScLn(); break;
4195 case ocLog10 : ScLog10(); break;
4196 case ocSqrt : ScSqrt(); break;
4197 case ocFact : ScFact(); break;
4198 case ocGetYear : ScGetYear(); break;
4199 case ocGetMonth : ScGetMonth(); break;
4200 case ocGetDay : ScGetDay(); break;
4201 case ocGetDayOfWeek : ScGetDayOfWeek(); break;
4202 case ocWeek : ScGetWeekOfYear(); break;
4203 case ocIsoWeeknum : ScGetIsoWeekOfYear(); break;
4204 case ocWeeknumOOo : ScWeeknumOOo(); break;
4205 case ocEasterSunday : ScEasterSunday(); break;
4206 case ocNetWorkdays : ScNetWorkdays( false); break;
4207 case ocNetWorkdays_MS : ScNetWorkdays( true ); break;
4208 case ocWorkday_MS : ScWorkday_MS(); break;
4209 case ocGetHour : ScGetHour(); break;
4210 case ocGetMin : ScGetMin(); break;
4211 case ocGetSec : ScGetSec(); break;
4212 case ocPlusMinus : ScPlusMinus(); break;
4213 case ocAbs : ScAbs(); break;
4214 case ocInt : ScInt(); break;
4215 case ocEven : ScEven(); break;
4216 case ocOdd : ScOdd(); break;
4217 case ocPhi : ScPhi(); break;
4218 case ocGauss : ScGauss(); break;
4219 case ocStdNormDist : ScStdNormDist(); break;
4220 case ocStdNormDist_MS : ScStdNormDist_MS(); break;
4221 case ocFisher : ScFisher(); break;
4222 case ocFisherInv : ScFisherInv(); break;
4223 case ocIsEmpty : ScIsEmpty(); break;
4224 case ocIsString : ScIsString(); break;
4225 case ocIsNonString : ScIsNonString(); break;
4226 case ocIsLogical : ScIsLogical(); break;
4227 case ocType : ScType(); break;
4228 case ocCell : ScCell(); break;
4229 case ocIsRef : ScIsRef(); break;
4230 case ocIsValue : ScIsValue(); break;
4231 case ocIsFormula : ScIsFormula(); break;
4232 case ocFormula : ScFormula(); break;
4233 case ocIsNA : ScIsNV(); break;
4234 case ocIsErr : ScIsErr(); break;
4235 case ocIsError : ScIsError(); break;
4236 case ocIsEven : ScIsEven(); break;
4237 case ocIsOdd : ScIsOdd(); break;
4238 case ocN : ScN(); break;
4239 case ocGetDateValue : ScGetDateValue(); break;
4240 case ocGetTimeValue : ScGetTimeValue(); break;
4241 case ocCode : ScCode(); break;
4242 case ocTrim : ScTrim(); break;
4243 case ocUpper : ScUpper(); break;
4244 case ocProper : ScProper(); break;
4245 case ocLower : ScLower(); break;
4246 case ocLen : ScLen(); break;
4247 case ocT : ScT(); break;
4248 case ocClean : ScClean(); break;
4249 case ocValue : ScValue(); break;
4250 case ocNumberValue : ScNumberValue(); break;
4251 case ocChar : ScChar(); break;
4252 case ocArcTan2 : ScArcTan2(); break;
4253 case ocMod : ScMod(); break;
4254 case ocPower : ScPower(); break;
4255 case ocRound : ScRound(); break;
4256 case ocRoundSig : ScRoundSignificant(); break;
4257 case ocRoundUp : ScRoundUp(); break;
4258 case ocTrunc :
4259 case ocRoundDown : ScRoundDown(); break;
4260 case ocCeil : ScCeil( true ); break;
4261 case ocCeil_MS : ScCeil_MS(); break;
4262 case ocCeil_Precise :
4263 case ocCeil_ISO : ScCeil_Precise(); break;
4264 case ocCeil_Math : ScCeil( false ); break;
4265 case ocFloor : ScFloor( true ); break;
4266 case ocFloor_MS : ScFloor_MS(); break;
4267 case ocFloor_Precise : ScFloor_Precise(); break;
4268 case ocFloor_Math : ScFloor( false ); break;
4269 case ocSumProduct : ScSumProduct(); break;
4270 case ocSumSQ : ScSumSQ(); break;
4271 case ocSumX2MY2 : ScSumX2MY2(); break;
4272 case ocSumX2DY2 : ScSumX2DY2(); break;
4273 case ocSumXMY2 : ScSumXMY2(); break;
4274 case ocRawSubtract : ScRawSubtract(); break;
4275 case ocLog : ScLog(); break;
4276 case ocGCD : ScGCD(); break;
4277 case ocLCM : ScLCM(); break;
4278 case ocGetDate : ScGetDate(); break;
4279 case ocGetTime : ScGetTime(); break;
4280 case ocGetDiffDate : ScGetDiffDate(); break;
4281 case ocGetDiffDate360 : ScGetDiffDate360(); break;
4282 case ocGetDateDif : ScGetDateDif(); break;
4283 case ocMin : ScMin() ; break;
4284 case ocMinA : ScMin( true ); break;
4285 case ocMax : ScMax(); break;
4286 case ocMaxA : ScMax( true ); break;
4287 case ocSum : ScSum(); break;
4288 case ocProduct : ScProduct(); break;
4289 case ocNPV : ScNPV(); break;
4290 case ocIRR : ScIRR(); break;
4291 case ocMIRR : ScMIRR(); break;
4292 case ocISPMT : ScISPMT(); break;
4293 case ocAverage : ScAverage() ; break;
4294 case ocAverageA : ScAverage( true ); break;
4295 case ocCount : ScCount(); break;
4296 case ocCount2 : ScCount2(); break;
4297 case ocVar :
4298 case ocVarS : ScVar(); break;
4299 case ocVarA : ScVar( true ); break;
4300 case ocVarP :
4301 case ocVarP_MS : ScVarP(); break;
4302 case ocVarPA : ScVarP( true ); break;
4303 case ocStDev :
4304 case ocStDevS : ScStDev(); break;
4305 case ocStDevA : ScStDev( true ); break;
4306 case ocStDevP :
4307 case ocStDevP_MS : ScStDevP(); break;
4308 case ocStDevPA : ScStDevP( true ); break;
4309 case ocPV : ScPV(); break;
4310 case ocSYD : ScSYD(); break;
4311 case ocDDB : ScDDB(); break;
4312 case ocDB : ScDB(); break;
4313 case ocVBD : ScVDB(); break;
4314 case ocPDuration : ScPDuration(); break;
4315 case ocSLN : ScSLN(); break;
4316 case ocPMT : ScPMT(); break;
4317 case ocColumns : ScColumns(); break;
4318 case ocRows : ScRows(); break;
4319 case ocSheets : ScSheets(); break;
4320 case ocColumn : ScColumn(); break;
4321 case ocRow : ScRow(); break;
4322 case ocSheet : ScSheet(); break;
4323 case ocRRI : ScRRI(); break;
4324 case ocFV : ScFV(); break;
4325 case ocNper : ScNper(); break;
4326 case ocRate : ScRate(); break;
4327 case ocFilterXML : ScFilterXML(); break;
4328 case ocWebservice : ScWebservice(); break;
4329 case ocEncodeURL : ScEncodeURL(); break;
4330 case ocColor : ScColor(); break;
4331 case ocErf_MS : ScErf(); break;
4332 case ocErfc_MS : ScErfc(); break;
4333 case ocIpmt : ScIpmt(); break;
4334 case ocPpmt : ScPpmt(); break;
4335 case ocCumIpmt : ScCumIpmt(); break;
4336 case ocCumPrinc : ScCumPrinc(); break;
4337 case ocEffect : ScEffect(); break;
4338 case ocNominal : ScNominal(); break;
4339 case ocSubTotal : ScSubTotal(); break;
4340 case ocAggregate : ScAggregate(); break;
4341 case ocDBSum : ScDBSum(); break;
4342 case ocDBCount : ScDBCount(); break;
4343 case ocDBCount2 : ScDBCount2(); break;
4344 case ocDBAverage : ScDBAverage(); break;
4345 case ocDBGet : ScDBGet(); break;
4346 case ocDBMax : ScDBMax(); break;
4347 case ocDBMin : ScDBMin(); break;
4348 case ocDBProduct : ScDBProduct(); break;
4349 case ocDBStdDev : ScDBStdDev(); break;
4350 case ocDBStdDevP : ScDBStdDevP(); break;
4351 case ocDBVar : ScDBVar(); break;
4352 case ocDBVarP : ScDBVarP(); break;
4353 case ocIndirect : ScIndirect(); break;
4354 case ocAddress : ScAddressFunc(); break;
4355 case ocMatch : ScMatch(); break;
4356 case ocXMatch : ScXMatch(); break;
4357 case ocCountEmptyCells : ScCountEmptyCells(); break;
4358 case ocCountIf : ScCountIf(); break;
4359 case ocSumIf : ScSumIf(); break;
4360 case ocAverageIf : ScAverageIf(); break;
4361 case ocSumIfs : ScSumIfs(); break;
4362 case ocAverageIfs : ScAverageIfs(); break;
4363 case ocCountIfs : ScCountIfs(); break;
4364 case ocLookup : ScLookup(); break;
4365 case ocVLookup : ScVLookup(); break;
4366 case ocXLookup : ScXLookup(); break;
4367 case ocHLookup : ScHLookup(); break;
4368 case ocIndex : ScIndex(); break;
4369 case ocMultiArea : ScMultiArea(); break;
4370 case ocOffset : ScOffset(); break;
4371 case ocAreas : ScAreas(); break;
4372 case ocCurrency : ScCurrency(); break;
4373 case ocReplace : ScReplace(); break;
4374 case ocFixed : ScFixed(); break;
4375 case ocFind : ScFind(); break;
4376 case ocExact : ScExact(); break;
4377 case ocLeft : ScLeft(); break;
4378 case ocRight : ScRight(); break;
4379 case ocSearch : ScSearch(); break;
4380 case ocMid : ScMid(); break;
4381 case ocText : ScText(); break;
4382 case ocSubstitute : ScSubstitute(); break;
4383 case ocRegex : ScRegex(); break;
4384 case ocRept : ScRept(); break;
4385 case ocConcat : ScConcat(); break;
4386 case ocConcat_MS : ScConcat_MS(); break;
4387 case ocTextJoin_MS : ScTextJoin_MS(); break;
4388 case ocIfs_MS : ScIfs_MS(); break;
4389 case ocSwitch_MS : ScSwitch_MS(); break;
4390 case ocMinIfs_MS : ScMinIfs_MS(); break;
4391 case ocMaxIfs_MS : ScMaxIfs_MS(); break;
4392 case ocMatValue : ScMatValue(); break;
4393 case ocMatrixUnit : ScEMat(); break;
4394 case ocMatDet : ScMatDet(); break;
4395 case ocMatInv : ScMatInv(); break;
4396 case ocMatMult : ScMatMult(); break;
4397 case ocMatSequence : ScMatSequence(); break;
4398 case ocMatTrans : ScMatTrans(); break;
4399 case ocMatRef : ScMatRef(); break;
4400 case ocB : ScB(); break;
4401 case ocNormDist : ScNormDist( 3 ); break;
4402 case ocNormDist_MS : ScNormDist( 4 ); break;
4403 case ocExpDist :
4404 case ocExpDist_MS : ScExpDist(); break;
4405 case ocBinomDist :
4406 case ocBinomDist_MS : ScBinomDist(); break;
4407 case ocPoissonDist : ScPoissonDist( true ); break;
4408 case ocPoissonDist_MS : ScPoissonDist( false ); break;
4409 case ocCombin : ScCombin(); break;
4410 case ocCombinA : ScCombinA(); break;
4411 case ocPermut : ScPermut(); break;
4412 case ocPermutationA : ScPermutationA(); break;
4413 case ocHypGeomDist : ScHypGeomDist( 4 ); break;
4414 case ocHypGeomDist_MS : ScHypGeomDist( 5 ); break;
4415 case ocLogNormDist : ScLogNormDist( 1 ); break;
4416 case ocLogNormDist_MS : ScLogNormDist( 4 ); break;
4417 case ocTDist : ScTDist(); break;
4418 case ocTDist_MS : ScTDist_MS(); break;
4419 case ocTDist_RT : ScTDist_T( 1 ); break;
4420 case ocTDist_2T : ScTDist_T( 2 ); break;
4421 case ocFDist :
4422 case ocFDist_RT : ScFDist(); break;
4423 case ocFDist_LT : ScFDist_LT(); break;
4424 case ocChiDist : ScChiDist( true ); break;
4425 case ocChiDist_MS : ScChiDist( false ); break;
4426 case ocChiSqDist : ScChiSqDist(); break;
4427 case ocChiSqDist_MS : ScChiSqDist_MS(); break;
4428 case ocStandard : ScStandard(); break;
4429 case ocAveDev : ScAveDev(); break;
4430 case ocDevSq : ScDevSq(); break;
4431 case ocKurt : ScKurt(); break;
4432 case ocSkew : ScSkew(); break;
4433 case ocSkewp : ScSkewp(); break;
4434 case ocModalValue : ScModalValue(); break;
4435 case ocModalValue_MS : ScModalValue_MS( true ); break;
4436 case ocModalValue_Multi : ScModalValue_MS( false ); break;
4437 case ocMedian : ScMedian(); break;
4438 case ocGeoMean : ScGeoMean(); break;
4439 case ocHarMean : ScHarMean(); break;
4440 case ocWeibull :
4441 case ocWeibull_MS : ScWeibull(); break;
4442 case ocBinomInv :
4443 case ocCritBinom : ScCritBinom(); break;
4444 case ocNegBinomVert : ScNegBinomDist(); break;
4445 case ocNegBinomDist_MS : ScNegBinomDist_MS(); break;
4446 case ocNoName : ScNoName(); break;
4447 case ocBad : ScBadName(); break;
4448 case ocZTest :
4449 case ocZTest_MS : ScZTest(); break;
4450 case ocTTest :
4451 case ocTTest_MS : ScTTest(); break;
4452 case ocFTest :
4453 case ocFTest_MS : ScFTest(); break;
4454 case ocRank :
4455 case ocRank_Eq : ScRank( false ); break;
4456 case ocRank_Avg : ScRank( true ); break;
4457 case ocPercentile :
4458 case ocPercentile_Inc : ScPercentile( true ); break;
4459 case ocPercentile_Exc : ScPercentile( false ); break;
4460 case ocPercentrank :
4461 case ocPercentrank_Inc : ScPercentrank( true ); break;
4462 case ocPercentrank_Exc : ScPercentrank( false ); break;
4463 case ocLarge : ScLarge(); break;
4464 case ocSmall : ScSmall(); break;
4465 case ocFrequency : ScFrequency(); break;
4466 case ocQuartile :
4467 case ocQuartile_Inc : ScQuartile( true ); break;
4468 case ocQuartile_Exc : ScQuartile( false ); break;
4469 case ocNormInv :
4470 case ocNormInv_MS : ScNormInv(); break;
4471 case ocSNormInv :
4472 case ocSNormInv_MS : ScSNormInv(); break;
4473 case ocConfidence :
4474 case ocConfidence_N : ScConfidence(); break;
4475 case ocConfidence_T : ScConfidenceT(); break;
4476 case ocTrimMean : ScTrimMean(); break;
4477 case ocProb : ScProbability(); break;
4478 case ocCorrel : ScCorrel(); break;
4479 case ocCovar :
4480 case ocCovarianceP : ScCovarianceP(); break;
4481 case ocCovarianceS : ScCovarianceS(); break;
4482 case ocPearson : ScPearson(); break;
4483 case ocRSQ : ScRSQ(); break;
4484 case ocSTEYX : ScSTEYX(); break;
4485 case ocSlope : ScSlope(); break;
4486 case ocIntercept : ScIntercept(); break;
4487 case ocTrend : ScTrend(); break;
4488 case ocGrowth : ScGrowth(); break;
4489 case ocLinest : ScLinest(); break;
4490 case ocLogest : ScLogest(); break;
4491 case ocForecast_LIN :
4492 case ocForecast : ScForecast(); break;
4493 case ocForecast_ETS_ADD : ScForecast_Ets( etsAdd ); break;
4494 case ocForecast_ETS_SEA : ScForecast_Ets( etsSeason ); break;
4495 case ocForecast_ETS_MUL : ScForecast_Ets( etsMult ); break;
4496 case ocForecast_ETS_PIA : ScForecast_Ets( etsPIAdd ); break;
4497 case ocForecast_ETS_PIM : ScForecast_Ets( etsPIMult ); break;
4498 case ocForecast_ETS_STA : ScForecast_Ets( etsStatAdd ); break;
4499 case ocForecast_ETS_STM : ScForecast_Ets( etsStatMult ); break;
4500 case ocGammaLn :
4501 case ocGammaLn_MS : ScLogGamma(); break;
4502 case ocGamma : ScGamma(); break;
4503 case ocGammaDist : ScGammaDist( true ); break;
4504 case ocGammaDist_MS : ScGammaDist( false ); break;
4505 case ocGammaInv :
4506 case ocGammaInv_MS : ScGammaInv(); break;
4507 case ocChiTest :
4508 case ocChiTest_MS : ScChiTest(); break;
4509 case ocChiInv :
4510 case ocChiInv_MS : ScChiInv(); break;
4511 case ocChiSqInv :
4512 case ocChiSqInv_MS : ScChiSqInv(); break;
4513 case ocTInv :
4514 case ocTInv_2T : ScTInv( 2 ); break;
4515 case ocTInv_MS : ScTInv( 4 ); break;
4516 case ocFInv :
4517 case ocFInv_RT : ScFInv(); break;
4518 case ocFInv_LT : ScFInv_LT(); break;
4519 case ocLogInv :
4520 case ocLogInv_MS : ScLogNormInv(); break;
4521 case ocBetaDist : ScBetaDist(); break;
4522 case ocBetaDist_MS : ScBetaDist_MS(); break;
4523 case ocBetaInv :
4524 case ocBetaInv_MS : ScBetaInv(); break;
4525 case ocFourier : ScFourier(); break;
4526 case ocExternal : ScExternal(); break;
4527 case ocTableOp : ScTableOp(); break;
4528 case ocStop : break;
4529 case ocErrorType : ScErrorType(); break;
4530 case ocErrorType_ODF : ScErrorType_ODF(); break;
4531 case ocCurrent : ScCurrent(); break;
4532 case ocStyle : ScStyle(); break;
4533 case ocDde : ScDde(); break;
4534 case ocBase : ScBase(); break;
4535 case ocDecimal : ScDecimal(); break;
4536 case ocConvertOOo : ScConvertOOo(); break;
4537 case ocEuroConvert : ScEuroConvert(); break;
4538 case ocRoman : ScRoman(); break;
4539 case ocArabic : ScArabic(); break;
4540 case ocInfo : ScInfo(); break;
4541 case ocHyperLink : ScHyperLink(); break;
4542 case ocBahtText : ScBahtText(); break;
4543 case ocGetPivotData : ScGetPivotData(); break;
4544 case ocJis : ScJis(); break;
4545 case ocAsc : ScAsc(); break;
4546 case ocLenB : ScLenB(); break;
4547 case ocRightB : ScRightB(); break;
4548 case ocLeftB : ScLeftB(); break;
4549 case ocMidB : ScMidB(); break;
4550 case ocReplaceB : ScReplaceB(); break;
4551 case ocFindB : ScFindB(); break;
4552 case ocSearchB : ScSearchB(); break;
4553 case ocUnicode : ScUnicode(); break;
4554 case ocUnichar : ScUnichar(); break;
4555 case ocBitAnd : ScBitAnd(); break;
4556 case ocBitOr : ScBitOr(); break;
4557 case ocBitXor : ScBitXor(); break;
4558 case ocBitRshift : ScBitRshift(); break;
4559 case ocBitLshift : ScBitLshift(); break;
4560 case ocTTT : ScTTT(); break;
4561 case ocDebugVar : ScDebugVar(); break;
4562 case ocNone : nFuncFmtType = SvNumFormatType::UNDEFINED; break;
4563 default : PushError( FormulaError::UnknownOpCode); break;
4566 // If the function pushed a subroutine as result, continue with
4567 // execution of the subroutine.
4568 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
4570 Pop(); continue;
4573 if (FormulaCompiler::IsOpCodeVolatile(eOp))
4574 meVolatileType = VOLATILE;
4576 // Remember result matrix in case it could be reused.
4577 if (sp && GetStackType() == svMatrix)
4578 maTokenMatrixMap.emplace(pCur, pStack[sp-1]);
4580 // outer function determines format of an expression
4581 if ( nFuncFmtType != SvNumFormatType::UNDEFINED )
4583 nRetTypeExpr = nFuncFmtType;
4584 // Inherit the format index for currency, date or time formats.
4585 switch (nFuncFmtType)
4587 case SvNumFormatType::CURRENCY:
4588 case SvNumFormatType::DATE:
4589 case SvNumFormatType::TIME:
4590 case SvNumFormatType::DATETIME:
4591 case SvNumFormatType::DURATION:
4592 nRetIndexExpr = nFuncFmtIndex;
4593 break;
4594 default:
4595 nRetIndexExpr = 0;
4601 // Need a clean stack environment for the JumpMatrix to work.
4602 if (nGlobalError != FormulaError::NONE && eOp != ocPush && sp > nStackBase + 1)
4604 // Not all functions pop all parameters in case an error is
4605 // generated. Clean up stack. Assumes that every function pushes a
4606 // result, may be arbitrary in case of error.
4607 FormulaConstTokenRef xLocalResult = pStack[ sp - 1 ];
4608 while (sp > nStackBase)
4609 Pop();
4610 PushTokenRef( xLocalResult );
4613 bool bGotResult;
4616 bGotResult = false;
4617 sal_uInt8 nLevel = 0;
4618 if ( GetStackType( ++nLevel ) == svJumpMatrix )
4619 ; // nothing
4620 else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4621 ; // nothing
4622 else
4623 nLevel = 0;
4624 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4626 if (nLevel == 1)
4627 aErrorFunctionStack.push_back( nErrorFunction);
4628 bGotResult = JumpMatrix( nLevel );
4629 if (aErrorFunctionStack.empty())
4630 assert(!"ScInterpreter::Interpret - aErrorFunctionStack empty in JumpMatrix context");
4631 else
4633 nErrorFunction = aErrorFunctionStack.back();
4634 if (bGotResult)
4635 aErrorFunctionStack.pop_back();
4638 else
4639 pJumpMatrix = nullptr;
4640 } while ( bGotResult );
4642 if( IsErrFunc(eOp) )
4643 ++nErrorFunction;
4645 if ( nGlobalError != FormulaError::NONE )
4647 if ( !nErrorFunctionCount )
4648 { // count of errorcode functions in formula
4649 FormulaTokenArrayPlainIterator aIter(*pArr);
4650 for ( FormulaToken* t = aIter.FirstRPN(); t; t = aIter.NextRPN() )
4652 if ( IsErrFunc(t->GetOpCode()) )
4653 ++nErrorFunctionCount;
4656 if ( nErrorFunction >= nErrorFunctionCount )
4657 ++nErrorFunction; // that's it, error => terminate
4658 else if (nErrorFunctionCount && sp && GetStackType() == svError)
4660 // Clear global error if we have an individual error result, so
4661 // an error evaluating function can receive multiple arguments
4662 // and not all evaluated arguments inheriting the error.
4663 // This is important for at least IFS() and SWITCH() as long as
4664 // they are classified as error evaluating functions and not
4665 // implemented as short-cutting jump code paths, but also for
4666 // more than one evaluated argument to AGGREGATE() or COUNT()
4667 // that may ignore errors.
4668 nGlobalError = FormulaError::NONE;
4673 // End: obtain result
4675 bool bForcedResultType;
4676 switch (eOp)
4678 case ocGetDateValue:
4679 case ocGetTimeValue:
4680 // Force final result of DATEVALUE and TIMEVALUE to number type,
4681 // which so far was date or time for calculations.
4682 nRetTypeExpr = nFuncFmtType = SvNumFormatType::NUMBER;
4683 nRetIndexExpr = nFuncFmtIndex = 0;
4684 bForcedResultType = true;
4685 break;
4686 default:
4687 bForcedResultType = false;
4690 if (sp == 1)
4692 pCur = pStack[ sp-1 ];
4693 if( pCur->GetOpCode() == ocPush )
4695 // An svRefList can be resolved if it a) contains just one
4696 // reference, or b) in array context contains an array of single
4697 // cell references.
4698 if (pCur->GetType() == svRefList)
4700 PopRefListPushMatrixOrRef();
4701 pCur = pStack[ sp-1 ];
4703 switch( pCur->GetType() )
4705 case svEmptyCell:
4706 ; // nothing
4707 break;
4708 case svError:
4709 nGlobalError = pCur->GetError();
4710 break;
4711 case svDouble :
4713 // If typed, pop token to obtain type information and
4714 // push a plain untyped double so the result token to
4715 // be transferred to the formula cell result does not
4716 // unnecessarily duplicate the information.
4717 if (pCur->GetDoubleType() != 0)
4719 double fVal = PopDouble();
4720 if (!bForcedResultType)
4722 if (nCurFmtType != nFuncFmtType)
4723 nRetIndexExpr = 0; // carry format index only for matching type
4724 nRetTypeExpr = nFuncFmtType = nCurFmtType;
4726 if (nRetTypeExpr == SvNumFormatType::DURATION)
4728 // Round the duration in case a wall clock time
4729 // display format is used instead of a duration
4730 // format. To micro seconds which then catches
4731 // the converted hh:mm:ss.9999997 cases.
4732 if (fVal != 0.0)
4734 fVal *= 86400.0;
4735 fVal = rtl::math::round( fVal, 6);
4736 fVal /= 86400.0;
4739 PushTempToken( CreateFormulaDoubleToken( fVal));
4741 if ( nFuncFmtType == SvNumFormatType::UNDEFINED )
4743 nRetTypeExpr = SvNumFormatType::NUMBER;
4744 nRetIndexExpr = 0;
4747 break;
4748 case svString :
4749 nRetTypeExpr = SvNumFormatType::TEXT;
4750 nRetIndexExpr = 0;
4751 break;
4752 case svSingleRef :
4754 ScAddress aAdr;
4755 PopSingleRef( aAdr );
4756 if( nGlobalError == FormulaError::NONE)
4757 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4759 break;
4760 case svRefList :
4761 PopError(); // maybe #REF! takes precedence over #VALUE!
4762 PushError( FormulaError::NoValue);
4763 break;
4764 case svDoubleRef :
4766 if ( bMatrixFormula )
4767 { // create matrix for {=A1:A5}
4768 PopDoubleRefPushMatrix();
4769 ScMatrixRef xMat = PopMatrix();
4770 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4772 else
4774 ScRange aRange;
4775 PopDoubleRef( aRange );
4776 ScAddress aAdr;
4777 if ( nGlobalError == FormulaError::NONE && DoubleRefToPosSingleRef( aRange, aAdr))
4778 PushCellResultToken( false, aAdr, &nRetTypeExpr, &nRetIndexExpr, true);
4781 break;
4782 case svExternalDoubleRef:
4784 ScMatrixRef xMat;
4785 PopExternalDoubleRef(xMat);
4786 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4788 break;
4789 case svMatrix :
4791 sc::RangeMatrix aMat = PopRangeMatrix();
4792 if (aMat.isRangeValid())
4794 // This matrix represents a range reference. Apply implicit intersection.
4795 double fVal = applyImplicitIntersection(aMat, aPos);
4796 if (std::isnan(fVal))
4797 PushNoValue();
4798 else
4799 PushInt(fVal);
4801 else
4802 // This is a normal matrix.
4803 QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
4805 break;
4806 case svExternalSingleRef:
4808 FormulaTokenRef xToken;
4809 ScExternalRefCache::CellFormat aFmt;
4810 PopExternalSingleRef(xToken, &aFmt);
4811 if (nGlobalError != FormulaError::NONE)
4812 break;
4814 PushTokenRef(xToken);
4816 if (aFmt.mbIsSet)
4818 nFuncFmtType = aFmt.mnType;
4819 nFuncFmtIndex = aFmt.mnIndex;
4822 break;
4823 default :
4824 SetError( FormulaError::UnknownStackVariable);
4827 else
4828 SetError( FormulaError::UnknownStackVariable);
4830 else if (sp > 1)
4831 SetError( FormulaError::OperatorExpected);
4832 else
4833 SetError( FormulaError::NoCode);
4835 if (bForcedResultType || nRetTypeExpr != SvNumFormatType::UNDEFINED)
4837 nRetFmtType = nRetTypeExpr;
4838 nRetFmtIndex = nRetIndexExpr;
4840 else if( nFuncFmtType != SvNumFormatType::UNDEFINED )
4842 nRetFmtType = nFuncFmtType;
4843 nRetFmtIndex = nFuncFmtIndex;
4845 else
4846 nRetFmtType = SvNumFormatType::NUMBER;
4848 if (nGlobalError != FormulaError::NONE && GetStackType() != svError )
4849 PushError( nGlobalError);
4851 // THE final result.
4852 xResult = PopToken();
4853 if (!xResult)
4854 xResult = new FormulaErrorToken( FormulaError::UnknownStackVariable);
4856 // release tokens in expression stack
4857 const FormulaToken** p = pStack;
4858 while( maxsp-- )
4859 (*p++)->DecRef();
4861 StackVar eType = xResult->GetType();
4862 if (eType == svMatrix)
4863 // Results are immutable in case they would be reused as input for new
4864 // interpreters.
4865 xResult->GetMatrix()->SetImmutable();
4866 return eType;
4869 void ScInterpreter::AssertFormulaMatrix()
4871 bMatrixFormula = true;
4874 const svl::SharedString & ScInterpreter::GetStringResult() const
4876 return xResult->GetString();
4879 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */