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