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