Bug Summary

File:home/maarten/src/libreoffice/core/sc/source/core/tool/interpr4.cxx
Warning:line 987, column 17
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

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