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