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