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