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