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