Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <rangelst.hxx>
30 : : #include <sfx2/app.hxx>
31 : : #include <sfx2/docfile.hxx>
32 : : #include <sfx2/objsh.hxx>
33 : : #include <sfx2/docfilt.hxx>
34 : : #include <basic/sbmeth.hxx>
35 : : #include <basic/sbmod.hxx>
36 : : #include <basic/sbstar.hxx>
37 : : #include <basic/sbx.hxx>
38 : : #include <basic/sbxobj.hxx>
39 : : #include <basic/sbuno.hxx>
40 : : #include <svl/zforlist.hxx>
41 : : #include <rtl/logfile.hxx>
42 : : #include <stdlib.h>
43 : : #include <string.h>
44 : : #include <signal.h>
45 : :
46 : : #include <com/sun/star/table/XCellRange.hpp>
47 : : #include <com/sun/star/sheet/XSheetCellRange.hpp>
48 : : #include <comphelper/processfactory.hxx>
49 : :
50 : : #include "interpre.hxx"
51 : : #include "global.hxx"
52 : : #include "dbdata.hxx"
53 : : #include "cell.hxx"
54 : : #include "callform.hxx"
55 : : #include "addincol.hxx"
56 : : #include "document.hxx"
57 : : #include "dociter.hxx"
58 : : #include "docoptio.hxx"
59 : : #include "scmatrix.hxx"
60 : : #include "adiasync.hxx"
61 : : #include "sc.hrc"
62 : : #include "cellsuno.hxx"
63 : : #include "optuno.hxx"
64 : : #include "rangeseq.hxx"
65 : : #include "addinlis.hxx"
66 : : #include "jumpmatrix.hxx"
67 : : #include "parclass.hxx"
68 : : #include "externalrefmgr.hxx"
69 : : #include "formula/FormulaCompiler.hxx"
70 : : #include "macromgr.hxx"
71 : : #include "doubleref.hxx"
72 : : #include "queryparam.hxx"
73 : :
74 : : #include <math.h>
75 : : #include <float.h>
76 : : #include <map>
77 : : #include <algorithm>
78 : : #include <functional>
79 : : #include <basic/basmgr.hxx>
80 : : #include <vbahelper/vbaaccesshelper.hxx>
81 : : #include <memory>
82 : :
83 : : using namespace com::sun::star;
84 : : using namespace formula;
85 : : using ::std::auto_ptr;
86 : :
87 : : #define ADDIN_MAXSTRLEN 256
88 : :
89 : : //-----------------------------static data -----------------
90 : :
91 : : //-------------------------------------------------------------------------
92 : : // Funktionen fuer den Zugriff auf das Document
93 : : //-------------------------------------------------------------------------
94 : :
95 : :
96 : 110 : void ScInterpreter::ReplaceCell( ScAddress& rPos )
97 : : {
98 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ReplaceCell" );
99 : 110 : size_t ListSize = pDok->aTableOpList.size();
100 [ + + ]: 220 : for ( size_t i = 0; i < ListSize; ++i )
101 : : {
102 : 110 : ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
103 [ + + ]: 110 : if ( rPos == pTOp->aOld1 )
104 : : {
105 : 55 : rPos = pTOp->aNew1;
106 : 55 : return ;
107 : : }
108 [ + + ]: 55 : else if ( rPos == pTOp->aOld2 )
109 : : {
110 : 21 : rPos = pTOp->aNew2;
111 : 21 : return ;
112 : : }
113 : : }
114 : : }
115 : :
116 : :
117 : 0 : void ScInterpreter::ReplaceCell( SCCOL& rCol, SCROW& rRow, SCTAB& rTab )
118 : : {
119 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ReplaceCell" );
120 : 0 : ScAddress aCellPos( rCol, rRow, rTab );
121 : 0 : size_t ListSize = pDok->aTableOpList.size();
122 [ # # ]: 0 : for ( size_t i = 0; i < ListSize; ++i )
123 : : {
124 [ # # ]: 0 : ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
125 [ # # ]: 0 : if ( aCellPos == pTOp->aOld1 )
126 : : {
127 : 0 : rCol = pTOp->aNew1.Col();
128 : 0 : rRow = pTOp->aNew1.Row();
129 : 0 : rTab = pTOp->aNew1.Tab();
130 : : return ;
131 : : }
132 [ # # ]: 0 : else if ( aCellPos == pTOp->aOld2 )
133 : : {
134 : 0 : rCol = pTOp->aNew2.Col();
135 : 0 : rRow = pTOp->aNew2.Row();
136 : 0 : rTab = pTOp->aNew2.Tab();
137 : : return ;
138 : : }
139 : : }
140 : : }
141 : :
142 : :
143 : 0 : bool ScInterpreter::IsTableOpInRange( const ScRange& rRange )
144 : : {
145 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsTableOpInRange" );
146 [ # # ]: 0 : if ( rRange.aStart == rRange.aEnd )
147 : 0 : return false; // not considered to be a range in TableOp sense
148 : :
149 : : // we can't replace a single cell in a range
150 : 0 : size_t ListSize = pDok->aTableOpList.size();
151 [ # # ]: 0 : for ( size_t i = 0; i < ListSize; ++i )
152 : : {
153 : 0 : ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
154 [ # # ]: 0 : if ( rRange.In( pTOp->aOld1 ) )
155 : 0 : return true;
156 [ # # ]: 0 : if ( rRange.In( pTOp->aOld2 ) )
157 : 0 : return true;
158 : : }
159 : 0 : return false;
160 : : }
161 : :
162 : :
163 : 3 : sal_uLong ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, const ScBaseCell* pCell)
164 : : {
165 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellNumberFormat" );
166 : : sal_uLong nFormat;
167 : : sal_uInt16 nErr;
168 [ + - ]: 3 : if ( pCell )
169 : : {
170 [ + - ]: 3 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
171 [ + - ]: 3 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
172 : : else
173 : 0 : nErr = 0;
174 : 3 : nFormat = pDok->GetNumberFormat( rPos );
175 [ - + ][ - + ]: 3 : if ( pCell->GetCellType() == CELLTYPE_FORMULA
[ + - ]
176 : : && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) )
177 : : nFormat = ((ScFormulaCell*)pCell)->GetStandardFormat( *pFormatter,
178 [ # # ]: 0 : nFormat );
179 : : }
180 : : else
181 : : {
182 : 0 : nFormat = pDok->GetNumberFormat( rPos );
183 : 0 : nErr = 0;
184 : : }
185 : 3 : SetError(nErr);
186 : 3 : return nFormat;
187 : : }
188 : :
189 : :
190 : : /// Only ValueCell, formula cells already store the result rounded.
191 : 0 : double ScInterpreter::GetValueCellValue( const ScAddress& rPos, const ScValueCell* pCell )
192 : : {
193 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetValueCellValue" );
194 : 0 : double fVal = pCell->GetValue();
195 [ # # ][ # # ]: 0 : if ( bCalcAsShown && fVal != 0.0 )
196 : : {
197 : 0 : sal_uLong nFormat = pDok->GetNumberFormat( rPos );
198 : 0 : fVal = pDok->RoundValueAsShown( fVal, nFormat );
199 : : }
200 : 0 : return fVal;
201 : : }
202 : :
203 : :
204 : : /** Convert string content to numeric value.
205 : :
206 : : Converted are only integer numbers including exponent, and ISO 8601 dates
207 : : and times in their extended formats with separators. Anything else,
208 : : especially fractional numeric values with decimal separators or dates other
209 : : than ISO 8601 would be locale dependent and is a no-no. Leading and
210 : : trailing blanks are ignored.
211 : :
212 : : The following ISO 8601 formats are converted:
213 : :
214 : : CCYY-MM-DD
215 : : CCYY-MM-DDThh:mm
216 : : CCYY-MM-DDThh:mm:ss
217 : : CCYY-MM-DDThh:mm:ss,s
218 : : CCYY-MM-DDThh:mm:ss.s
219 : : hh:mm
220 : : hh:mm:ss
221 : : hh:mm:ss,s
222 : : hh:mm:ss.s
223 : :
224 : : The century CC may not be omitted and the two-digit year setting is not
225 : : taken into account. Instead of the T date and time separator exactly one
226 : : blank may be used.
227 : :
228 : : If a date is given, it must be a valid Gregorian calendar date. In this
229 : : case the optional time must be in the range 00:00 to 23:59:59.99999...
230 : : If only time is given, it may have any value for hours, taking elapsed time
231 : : into account; minutes and seconds are limited to the value 59 as well.
232 : : */
233 : :
234 : 99 : double ScInterpreter::ConvertStringToValue( const String& rStr )
235 : : {
236 : : #if 1
237 : : // We keep this code until we provide a friendly way to convert string
238 : : // numbers into numbers in the UI.
239 : 99 : double fValue = 0.0;
240 [ + + ]: 99 : if (mnStringNoValueError == errCellNoValue)
241 : : {
242 : : // Requested that all strings result in 0, error handled by caller.
243 : 39 : SetError( mnStringNoValueError);
244 : 39 : return fValue;
245 : : }
246 : :
247 [ + + ]: 60 : if (GetGlobalConfig().mbEmptyStringAsZero)
248 : : {
249 : : // The number scanner does not accept empty strings or strings
250 : : // containing only spaces, be on par in these cases with what was
251 : : // accepted in OOo and is in AOO (see also the else branch below) and
252 : : // convert to 0 to prevent interoperability nightmares.
253 [ + + ]: 12 : if (!rStr.Len())
254 : 3 : return fValue;
255 [ + - ]: 9 : else if (rStr.GetChar(0) == ' ')
256 : : {
257 : 9 : const sal_Unicode* p = rStr.GetBuffer() + 1;
258 : 9 : const sal_Unicode* const pStop = p - 1 + rStr.Len();
259 [ + + ][ - + ]: 9 : while (p < pStop && *p == ' ')
[ - + ]
260 : 0 : ++p;
261 [ + + ]: 9 : if (p == pStop)
262 : 3 : return fValue;
263 : : }
264 : : }
265 : :
266 : 54 : sal_uInt32 nFIndex = 0;
267 [ + - ][ + + ]: 54 : if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
268 : : {
269 : 48 : SetError( mnStringNoValueError);
270 : 48 : fValue = 0.0;
271 : : }
272 : 99 : return fValue;
273 : : #else
274 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ConvertStringToValue" );
275 : : double fValue = 0.0;
276 : : if (mnStringNoValueError == errCellNoValue)
277 : : {
278 : : // Requested that all strings result in 0, error handled by caller.
279 : : SetError( mnStringNoValueError);
280 : : return fValue;
281 : : }
282 : : ::rtl::OUString aStr( rStr);
283 : : rtl_math_ConversionStatus eStatus;
284 : : sal_Int32 nParseEnd;
285 : : // Decimal and group separator 0 => only integer and possibly exponent,
286 : : // stops at first non-digit non-sign.
287 : : fValue = ::rtl::math::stringToDouble( aStr, 0, 0, &eStatus, &nParseEnd);
288 : : sal_Int32 nLen;
289 : : if (eStatus == rtl_math_ConversionStatus_Ok && nParseEnd < (nLen = aStr.getLength()))
290 : : {
291 : : // Not at string end, check for trailing blanks or switch to date or
292 : : // time parsing or bail out.
293 : : const sal_Unicode* const pStart = aStr.getStr();
294 : : const sal_Unicode* p = pStart + nParseEnd;
295 : : const sal_Unicode* const pStop = pStart + nLen;
296 : : switch (*p++)
297 : : {
298 : : case ' ':
299 : : while (p < pStop && *p == ' ')
300 : : ++p;
301 : : if (p < pStop)
302 : : SetError( mnStringNoValueError);
303 : : break;
304 : : case '-':
305 : : case ':':
306 : : {
307 : : bool bDate = (*(p-1) == '-');
308 : : enum State { year = 0, month, day, hour, minute, second, fraction, done, blank, stop };
309 : : sal_Int32 nUnit[done] = {0,0,0,0,0,0,0};
310 : : const sal_Int32 nLimit[done] = {0,12,31,0,59,59,0};
311 : : State eState = (bDate ? month : minute);
312 : : nCurFmtType = (bDate ? NUMBERFORMAT_DATE : NUMBERFORMAT_TIME);
313 : : nUnit[eState-1] = aStr.copy( 0, nParseEnd).toInt32();
314 : : const sal_Unicode* pLastStart = p;
315 : : // Ensure there's no preceding sign. Negative dates
316 : : // currently aren't handled correctly. Also discard
317 : : // +CCYY-MM-DD
318 : : p = pStart;
319 : : while (p < pStop && *p == ' ')
320 : : ++p;
321 : : if (p < pStop && !CharClass::isAsciiDigit(*p))
322 : : SetError( mnStringNoValueError);
323 : : p = pLastStart;
324 : : while (p < pStop && !nGlobalError && eState < blank)
325 : : {
326 : : if (eState == minute)
327 : : nCurFmtType |= NUMBERFORMAT_TIME;
328 : : if (CharClass::isAsciiDigit(*p))
329 : : {
330 : : // Maximum 2 digits per unit, except fractions.
331 : : if (p - pLastStart >= 2 && eState != fraction)
332 : : SetError( mnStringNoValueError);
333 : : }
334 : : else if (p > pLastStart)
335 : : {
336 : : // We had at least one digit.
337 : : if (eState < done)
338 : : {
339 : : nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32();
340 : : if (nLimit[eState] && nLimit[eState] < nUnit[eState])
341 : : SetError( mnStringNoValueError);
342 : : }
343 : : pLastStart = p + 1; // hypothetical next start
344 : : // Delimiters must match, a trailing delimiter
345 : : // yields an invalid date/time.
346 : : switch (eState)
347 : : {
348 : : case month:
349 : : // Month must be followed by separator and
350 : : // day, no trailing blanks.
351 : : if (*p != '-' || (p+1 == pStop))
352 : : SetError( mnStringNoValueError);
353 : : break;
354 : : case day:
355 : : if ((*p != 'T' || (p+1 == pStop)) && *p != ' ')
356 : : SetError( mnStringNoValueError);
357 : : // Take one blank as a valid delimiter
358 : : // between date and time.
359 : : break;
360 : : case hour:
361 : : // Hour must be followed by separator and
362 : : // minute, no trailing blanks.
363 : : if (*p != ':' || (p+1 == pStop))
364 : : SetError( mnStringNoValueError);
365 : : break;
366 : : case minute:
367 : : if ((*p != ':' || (p+1 == pStop)) && *p != ' ')
368 : : SetError( mnStringNoValueError);
369 : : if (*p == ' ')
370 : : eState = done;
371 : : break;
372 : : case second:
373 : : if (((*p != ',' && *p != '.') || (p+1 == pStop)) && *p != ' ')
374 : : SetError( mnStringNoValueError);
375 : : if (*p == ' ')
376 : : eState = done;
377 : : break;
378 : : case fraction:
379 : : eState = done;
380 : : break;
381 : : case year:
382 : : case done:
383 : : case blank:
384 : : case stop:
385 : : SetError( mnStringNoValueError);
386 : : break;
387 : : }
388 : : eState = static_cast<State>(eState + 1);
389 : : }
390 : : else
391 : : SetError( mnStringNoValueError);
392 : : ++p;
393 : : }
394 : : if (eState == blank)
395 : : {
396 : : while (p < pStop && *p == ' ')
397 : : ++p;
398 : : if (p < pStop)
399 : : SetError( mnStringNoValueError);
400 : : eState = stop;
401 : : }
402 : :
403 : : // Month without day, or hour without minute.
404 : : if (eState == month || (eState == day && p <= pLastStart) ||
405 : : eState == hour || (eState == minute && p <= pLastStart))
406 : : SetError( mnStringNoValueError);
407 : :
408 : : if (!nGlobalError)
409 : : {
410 : : // Catch the very last unit at end of string.
411 : : if (p > pLastStart && eState < done)
412 : : {
413 : : nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32();
414 : : if (nLimit[eState] && nLimit[eState] < nUnit[eState])
415 : : SetError( mnStringNoValueError);
416 : : }
417 : : if (bDate && nUnit[hour] > 23)
418 : : SetError( mnStringNoValueError);
419 : : if (!nGlobalError)
420 : : {
421 : : if (bDate && nUnit[day] == 0)
422 : : nUnit[day] = 1;
423 : : double fFraction = (nUnit[fraction] <= 0 ? 0.0 :
424 : : ::rtl::math::pow10Exp( nUnit[fraction],
425 : : static_cast<int>( -ceil( log10( static_cast<double>( nUnit[fraction]))))));
426 : : fValue = (bDate ? GetDateSerial(
427 : : sal::static_int_cast<sal_Int16>(nUnit[year]),
428 : : sal::static_int_cast<sal_Int16>(nUnit[month]),
429 : : sal::static_int_cast<sal_Int16>(nUnit[day]),
430 : : true, false) : 0.0);
431 : : fValue += ((nUnit[hour] * 3600) + (nUnit[minute] * 60) + nUnit[second] + fFraction) / 86400.0;
432 : : }
433 : : }
434 : : }
435 : : break;
436 : : default:
437 : : SetError( mnStringNoValueError);
438 : : }
439 : : if (nGlobalError)
440 : : fValue = 0.0;
441 : : }
442 : : return fValue;
443 : : #endif
444 : : }
445 : :
446 : :
447 : 1804 : double ScInterpreter::GetCellValue( const ScAddress& rPos, const ScBaseCell* pCell )
448 : : {
449 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellValue" );
450 : 1804 : sal_uInt16 nErr = nGlobalError;
451 : 1804 : nGlobalError = 0;
452 : 1804 : double nVal = GetCellValueOrZero( rPos, pCell );
453 [ + + ][ + + ]: 1804 : if ( !nGlobalError || nGlobalError == errCellNoValue )
454 : 1740 : nGlobalError = nErr;
455 : 1804 : return nVal;
456 : : }
457 : :
458 : :
459 : 1804 : double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, const ScBaseCell* pCell )
460 : : {
461 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellValueOrZero" );
462 : 1804 : double fValue = 0.0;
463 [ + - ]: 1804 : if (pCell)
464 : : {
465 : 1804 : CellType eType = pCell->GetCellType();
466 [ + + + + : 1804 : switch ( eType )
- - ]
467 : : {
468 : : case CELLTYPE_FORMULA:
469 : : {
470 [ + - ]: 203 : ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
471 : 203 : sal_uInt16 nErr = pFCell->GetErrCode();
472 [ + + ]: 203 : if( !nErr )
473 : : {
474 [ + + ]: 175 : if (pFCell->IsValue())
475 : : {
476 : 148 : fValue = pFCell->GetValue();
477 : : pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
478 [ + - ]: 148 : rPos, pFCell );
479 : : }
480 : : else
481 : : {
482 [ + - ][ + - ]: 27 : String aStr = pFCell->GetString();
483 [ + - ][ + - ]: 27 : fValue = ConvertStringToValue( aStr );
484 : : }
485 : : }
486 : : else
487 : : {
488 : 28 : fValue = 0.0;
489 : 28 : SetError(nErr);
490 : : }
491 : : }
492 : 203 : break;
493 : : case CELLTYPE_VALUE:
494 : : {
495 : 1331 : fValue = ((ScValueCell*)pCell)->GetValue();
496 : 1331 : nCurFmtIndex = pDok->GetNumberFormat( rPos );
497 : 1331 : nCurFmtType = pFormatter->GetType( nCurFmtIndex );
498 [ + - ][ + + ]: 1331 : if ( bCalcAsShown && fValue != 0.0 )
499 : 31 : fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex );
500 : : }
501 : 1331 : break;
502 : : case CELLTYPE_STRING:
503 : : case CELLTYPE_EDIT:
504 : : {
505 : : // SUM(A1:A2) differs from A1+A2. No good. But people insist on
506 : : // it ... #i5658#
507 [ + - ]: 18 : String aStr;
508 [ + - ]: 18 : if ( eType == CELLTYPE_STRING )
509 [ + - ]: 18 : aStr = ((ScStringCell*)pCell)->GetString();
510 : : else
511 [ # # ][ # # ]: 0 : aStr = ((ScEditCell*)pCell)->GetString();
512 [ + - ][ + - ]: 18 : fValue = ConvertStringToValue( aStr );
513 : : }
514 : 18 : break;
515 : : case CELLTYPE_NONE:
516 : : case CELLTYPE_NOTE:
517 : 252 : fValue = 0.0; // empty or broadcaster cell
518 : 252 : break;
519 : : case CELLTYPE_SYMBOLS:
520 : : #if OSL_DEBUG_LEVEL > 0
521 : : case CELLTYPE_DESTROYED:
522 : : #endif
523 : 0 : SetError(errCellNoValue);
524 : 0 : fValue = 0.0;
525 : 1804 : break;
526 : : }
527 : : }
528 : : else
529 : 0 : fValue = 0.0;
530 : 1804 : return fValue;
531 : : }
532 : :
533 : :
534 : 555 : void ScInterpreter::GetCellString( String& rStr, const ScBaseCell* pCell )
535 : : {
536 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellString" );
537 : 555 : sal_uInt16 nErr = 0;
538 [ + - ]: 555 : if (pCell)
539 : : {
540 [ + - - - : 555 : switch (pCell->GetCellType())
+ ]
541 : : {
542 : : case CELLTYPE_STRING:
543 : 521 : rStr = ((ScStringCell*) pCell)->GetString();
544 : 521 : break;
545 : : case CELLTYPE_EDIT:
546 [ # # ]: 0 : rStr = ((ScEditCell*) pCell)->GetString();
547 : 0 : break;
548 : : case CELLTYPE_FORMULA:
549 : : {
550 [ # # ]: 0 : ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
551 : 0 : nErr = pFCell->GetErrCode();
552 [ # # ]: 0 : if (pFCell->IsValue())
553 : : {
554 [ # # ]: 0 : double fVal = pFCell->GetValue();
555 : : sal_uLong nIndex = pFormatter->GetStandardFormat(
556 : : NUMBERFORMAT_NUMBER,
557 [ # # ]: 0 : ScGlobal::eLnge);
558 [ # # ]: 0 : pFormatter->GetInputLineString(fVal, nIndex, rStr);
559 : : }
560 : : else
561 [ # # ]: 0 : rStr = pFCell->GetString();
562 : : }
563 : 0 : break;
564 : : case CELLTYPE_VALUE:
565 : : {
566 : 0 : double fVal = ((ScValueCell*) pCell)->GetValue();
567 : : sal_uLong nIndex = pFormatter->GetStandardFormat(
568 : : NUMBERFORMAT_NUMBER,
569 [ # # ]: 0 : ScGlobal::eLnge);
570 [ # # ]: 0 : pFormatter->GetInputLineString(fVal, nIndex, rStr);
571 : : }
572 : 0 : break;
573 : : default:
574 : 34 : rStr = ScGlobal::GetEmptyString();
575 : 555 : break;
576 : : }
577 : : }
578 : : else
579 : 0 : rStr = ScGlobal::GetEmptyString();
580 : 555 : SetError(nErr);
581 : 555 : }
582 : :
583 : :
584 : 0 : bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
585 : : SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr)
586 : : {
587 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateDoubleArr" );
588 : :
589 : : // Old Add-Ins are hard limited to sal_uInt16 values.
590 : : #if MAXCOLCOUNT_DEFINE > USHRT_MAX
591 : : #error Add check for columns > USHRT_MAX!
592 : : #endif
593 [ # # ][ # # ]: 0 : if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
594 : 0 : return false;
595 : :
596 : 0 : sal_uInt16 nCount = 0;
597 : 0 : sal_uInt16* p = (sal_uInt16*) pCellArr;
598 : 0 : *p++ = static_cast<sal_uInt16>(nCol1);
599 : 0 : *p++ = static_cast<sal_uInt16>(nRow1);
600 : 0 : *p++ = static_cast<sal_uInt16>(nTab1);
601 : 0 : *p++ = static_cast<sal_uInt16>(nCol2);
602 : 0 : *p++ = static_cast<sal_uInt16>(nRow2);
603 : 0 : *p++ = static_cast<sal_uInt16>(nTab2);
604 : 0 : sal_uInt16* pCount = p;
605 : 0 : *p++ = 0;
606 : 0 : sal_uInt16 nPos = 14;
607 : 0 : SCTAB nTab = nTab1;
608 : 0 : ScAddress aAdr;
609 [ # # ]: 0 : while (nTab <= nTab2)
610 : : {
611 : 0 : aAdr.SetTab( nTab );
612 : 0 : SCROW nRow = nRow1;
613 [ # # ]: 0 : while (nRow <= nRow2)
614 : : {
615 : 0 : aAdr.SetRow( nRow );
616 : 0 : SCCOL nCol = nCol1;
617 [ # # ]: 0 : while (nCol <= nCol2)
618 : : {
619 : 0 : aAdr.SetCol( nCol );
620 [ # # ]: 0 : ScBaseCell* pCell = pDok->GetCell( aAdr );
621 [ # # ]: 0 : if (pCell)
622 : : {
623 : 0 : sal_uInt16 nErr = 0;
624 : 0 : double nVal = 0.0;
625 : 0 : bool bOk = true;
626 [ # # # ]: 0 : switch ( pCell->GetCellType() )
627 : : {
628 : : case CELLTYPE_VALUE :
629 [ # # ]: 0 : nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
630 : 0 : break;
631 : : case CELLTYPE_FORMULA :
632 [ # # ][ # # ]: 0 : if (((ScFormulaCell*)pCell)->IsValue())
[ # # ]
633 : : {
634 [ # # ][ # # ]: 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
635 [ # # ][ # # ]: 0 : nVal = ((ScFormulaCell*)pCell)->GetValue();
636 : : }
637 : : else
638 : 0 : bOk = false;
639 : 0 : break;
640 : : default :
641 : 0 : bOk = false;
642 : 0 : break;
643 : : }
644 [ # # ]: 0 : if (bOk)
645 : : {
646 [ # # ]: 0 : if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
647 : 0 : return false;
648 : 0 : *p++ = static_cast<sal_uInt16>(nCol);
649 : 0 : *p++ = static_cast<sal_uInt16>(nRow);
650 : 0 : *p++ = static_cast<sal_uInt16>(nTab);
651 : 0 : *p++ = nErr;
652 : 0 : memcpy( p, &nVal, sizeof(double));
653 : 0 : nPos += 8 + sizeof(double);
654 : 0 : p = (sal_uInt16*) ( pCellArr + nPos );
655 : 0 : nCount++;
656 : : }
657 : : }
658 : 0 : nCol++;
659 : : }
660 : 0 : nRow++;
661 : : }
662 : 0 : nTab++;
663 : : }
664 : 0 : *pCount = nCount;
665 : 0 : return true;
666 : : }
667 : :
668 : :
669 : 0 : bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
670 : : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
671 : : sal_uInt8* pCellArr)
672 : : {
673 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateStringArr" );
674 : :
675 : : // Old Add-Ins are hard limited to sal_uInt16 values.
676 : : #if MAXCOLCOUNT_DEFINE > USHRT_MAX
677 : : #error Add check for columns > USHRT_MAX!
678 : : #endif
679 [ # # ][ # # ]: 0 : if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
680 : 0 : return false;
681 : :
682 : 0 : sal_uInt16 nCount = 0;
683 : 0 : sal_uInt16* p = (sal_uInt16*) pCellArr;
684 : 0 : *p++ = static_cast<sal_uInt16>(nCol1);
685 : 0 : *p++ = static_cast<sal_uInt16>(nRow1);
686 : 0 : *p++ = static_cast<sal_uInt16>(nTab1);
687 : 0 : *p++ = static_cast<sal_uInt16>(nCol2);
688 : 0 : *p++ = static_cast<sal_uInt16>(nRow2);
689 : 0 : *p++ = static_cast<sal_uInt16>(nTab2);
690 : 0 : sal_uInt16* pCount = p;
691 : 0 : *p++ = 0;
692 : 0 : sal_uInt16 nPos = 14;
693 : 0 : SCTAB nTab = nTab1;
694 [ # # ]: 0 : while (nTab <= nTab2)
695 : : {
696 : 0 : SCROW nRow = nRow1;
697 [ # # ]: 0 : while (nRow <= nRow2)
698 : : {
699 : 0 : SCCOL nCol = nCol1;
700 [ # # ]: 0 : while (nCol <= nCol2)
701 : : {
702 : : ScBaseCell* pCell;
703 [ # # ]: 0 : pDok->GetCell(nCol, nRow, nTab, pCell);
704 [ # # ]: 0 : if (pCell)
705 : : {
706 [ # # ]: 0 : String aStr;
707 : 0 : sal_uInt16 nErr = 0;
708 : 0 : bool bOk = true;
709 [ # # # # ]: 0 : switch ( pCell->GetCellType() )
710 : : {
711 : : case CELLTYPE_STRING :
712 [ # # ]: 0 : aStr = ((ScStringCell*)pCell)->GetString();
713 : 0 : break;
714 : : case CELLTYPE_EDIT :
715 [ # # ][ # # ]: 0 : aStr = ((ScEditCell*)pCell)->GetString();
716 : 0 : break;
717 : : case CELLTYPE_FORMULA :
718 [ # # ][ # # ]: 0 : if (!((ScFormulaCell*)pCell)->IsValue())
[ # # ]
719 : : {
720 [ # # ][ # # ]: 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
721 [ # # ][ # # ]: 0 : aStr = ((ScFormulaCell*)pCell)->GetString();
[ # # ]
722 : : }
723 : : else
724 : 0 : bOk = false;
725 : 0 : break;
726 : : default :
727 : 0 : bOk = false;
728 : 0 : break;
729 : : }
730 [ # # ]: 0 : if (bOk)
731 : : {
732 : : rtl::OString aTmp(rtl::OUStringToOString(aStr,
733 [ # # ][ # # ]: 0 : osl_getThreadTextEncoding()));
[ # # ]
734 : : // In case the xub_StrLen will be longer than USHORT
735 : : // one day, and room for pad byte check.
736 [ # # ]: 0 : if ( aTmp.getLength() > ((sal_uInt16)(~0)) - 2 )
737 : 0 : return false;
738 : : // Append a 0-pad-byte if string length is not even
739 : : //! MUST be sal_uInt16 and not xub_StrLen
740 : 0 : sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
741 : 0 : sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
742 : :
743 [ # # ]: 0 : if (((sal_uLong)nPos + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
744 : 0 : return false;
745 : 0 : *p++ = static_cast<sal_uInt16>(nCol);
746 : 0 : *p++ = static_cast<sal_uInt16>(nRow);
747 : 0 : *p++ = static_cast<sal_uInt16>(nTab);
748 : 0 : *p++ = nErr;
749 : 0 : *p++ = nLen;
750 : 0 : memcpy( p, aTmp.getStr(), nStrLen + 1);
751 : 0 : nPos += 10 + nStrLen + 1;
752 : 0 : sal_uInt8* q = ( pCellArr + nPos );
753 [ # # ]: 0 : if( !nStrLen & 1 )
754 : 0 : *q++ = 0, nPos++;
755 : 0 : p = (sal_uInt16*) ( pCellArr + nPos );
756 [ # # ]: 0 : nCount++;
757 [ # # ][ # # ]: 0 : }
758 : : }
759 : 0 : nCol++;
760 : : }
761 : 0 : nRow++;
762 : : }
763 : 0 : nTab++;
764 : : }
765 : 0 : *pCount = nCount;
766 : 0 : return true;
767 : : }
768 : :
769 : :
770 : 0 : bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
771 : : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
772 : : sal_uInt8* pCellArr)
773 : : {
774 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateCellArr" );
775 : :
776 : : // Old Add-Ins are hard limited to sal_uInt16 values.
777 : : #if MAXCOLCOUNT_DEFINE > USHRT_MAX
778 : : #error Add check for columns > USHRT_MAX!
779 : : #endif
780 [ # # ][ # # ]: 0 : if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
781 : 0 : return false;
782 : :
783 : 0 : sal_uInt16 nCount = 0;
784 : 0 : sal_uInt16* p = (sal_uInt16*) pCellArr;
785 : 0 : *p++ = static_cast<sal_uInt16>(nCol1);
786 : 0 : *p++ = static_cast<sal_uInt16>(nRow1);
787 : 0 : *p++ = static_cast<sal_uInt16>(nTab1);
788 : 0 : *p++ = static_cast<sal_uInt16>(nCol2);
789 : 0 : *p++ = static_cast<sal_uInt16>(nRow2);
790 : 0 : *p++ = static_cast<sal_uInt16>(nTab2);
791 : 0 : sal_uInt16* pCount = p;
792 : 0 : *p++ = 0;
793 : 0 : sal_uInt16 nPos = 14;
794 : 0 : SCTAB nTab = nTab1;
795 : 0 : ScAddress aAdr;
796 [ # # ]: 0 : while (nTab <= nTab2)
797 : : {
798 : 0 : aAdr.SetTab( nTab );
799 : 0 : SCROW nRow = nRow1;
800 [ # # ]: 0 : while (nRow <= nRow2)
801 : : {
802 : 0 : aAdr.SetRow( nRow );
803 : 0 : SCCOL nCol = nCol1;
804 [ # # ]: 0 : while (nCol <= nCol2)
805 : : {
806 : 0 : aAdr.SetCol( nCol );
807 [ # # ]: 0 : ScBaseCell* pCell = pDok->GetCell( aAdr );
808 [ # # ]: 0 : if (pCell)
809 : : {
810 : 0 : sal_uInt16 nErr = 0;
811 : 0 : sal_uInt16 nType = 0; // 0 = Zahl; 1 = String
812 : 0 : double nVal = 0.0;
813 [ # # ]: 0 : String aStr;
814 : 0 : bool bOk = true;
815 [ # # # # : 0 : switch ( pCell->GetCellType() )
# ]
816 : : {
817 : : case CELLTYPE_STRING :
818 [ # # ]: 0 : aStr = ((ScStringCell*)pCell)->GetString();
819 : 0 : nType = 1;
820 : 0 : break;
821 : : case CELLTYPE_EDIT :
822 [ # # ][ # # ]: 0 : aStr = ((ScEditCell*)pCell)->GetString();
823 : 0 : nType = 1;
824 : 0 : break;
825 : : case CELLTYPE_VALUE :
826 [ # # ]: 0 : nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
827 : 0 : break;
828 : : case CELLTYPE_FORMULA :
829 [ # # ][ # # ]: 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
830 [ # # ][ # # ]: 0 : if (((ScFormulaCell*)pCell)->IsValue())
[ # # ]
831 [ # # ][ # # ]: 0 : nVal = ((ScFormulaCell*)pCell)->GetValue();
832 : : else
833 [ # # ][ # # ]: 0 : aStr = ((ScFormulaCell*)pCell)->GetString();
[ # # ]
834 : 0 : break;
835 : : default :
836 : 0 : bOk = false;
837 : 0 : break;
838 : : }
839 [ # # ]: 0 : if (bOk)
840 : : {
841 [ # # ]: 0 : if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
842 : 0 : return false;
843 : 0 : *p++ = static_cast<sal_uInt16>(nCol);
844 : 0 : *p++ = static_cast<sal_uInt16>(nRow);
845 : 0 : *p++ = static_cast<sal_uInt16>(nTab);
846 : 0 : *p++ = nErr;
847 : 0 : *p++ = nType;
848 : 0 : nPos += 10;
849 [ # # ]: 0 : if (nType == 0)
850 : : {
851 [ # # ]: 0 : if ((nPos + sizeof(double)) > MAXARRSIZE)
852 : 0 : return false;
853 : 0 : memcpy( p, &nVal, sizeof(double));
854 : 0 : nPos += sizeof(double);
855 : : }
856 : : else
857 : : {
858 : : rtl::OString aTmp(rtl::OUStringToOString(aStr,
859 [ # # ][ # # ]: 0 : osl_getThreadTextEncoding()));
[ # # ]
860 : : // In case the xub_StrLen will be longer than USHORT
861 : : // one day, and room for pad byte check.
862 [ # # ]: 0 : if ( aTmp.getLength() > ((sal_uInt16)(~0)) - 2 )
863 : 0 : return false;
864 : : // Append a 0-pad-byte if string length is not even
865 : : //! MUST be sal_uInt16 and not xub_StrLen
866 : 0 : sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
867 : 0 : sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
868 [ # # ]: 0 : if ( ((sal_uLong)nPos + 2 + nLen) > MAXARRSIZE)
869 : 0 : return false;
870 : 0 : *p++ = nLen;
871 : 0 : memcpy( p, aTmp.getStr(), nStrLen + 1);
872 : 0 : nPos += 2 + nStrLen + 1;
873 : 0 : sal_uInt8* q = ( pCellArr + nPos );
874 [ # # ]: 0 : if( !nStrLen & 1 )
875 [ # # ]: 0 : *q++ = 0, nPos++;
876 : : }
877 : 0 : nCount++;
878 : 0 : p = (sal_uInt16*) ( pCellArr + nPos );
879 [ # # ][ # # ]: 0 : }
880 : : }
881 : 0 : nCol++;
882 : : }
883 : 0 : nRow++;
884 : : }
885 : 0 : nTab++;
886 : : }
887 : 0 : *pCount = nCount;
888 : 0 : return true;
889 : : }
890 : :
891 : :
892 : : //-----------------------------------------------------------------------------
893 : : // Stack operations
894 : : //-----------------------------------------------------------------------------
895 : :
896 : :
897 : : // Also releases a TempToken if appropriate.
898 : :
899 : 4597 : void ScInterpreter::PushWithoutError( FormulaToken& r )
900 : : {
901 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushWithoutError" );
902 [ - + ]: 4597 : if ( sp >= MAXSTACK )
903 : 0 : SetError( errStackOverflow );
904 : : else
905 : : {
906 : 4597 : nCurFmtType = NUMBERFORMAT_UNDEFINED;
907 : 4597 : r.IncRef();
908 [ + + ]: 4597 : if( sp >= maxsp )
909 : 4466 : maxsp = sp + 1;
910 : : else
911 : 131 : pStack[ sp ]->DecRef();
912 : 4597 : pStack[ sp ] = (ScToken*) &r;
913 : 4597 : ++sp;
914 : : }
915 : 4597 : }
916 : :
917 : 154 : void ScInterpreter::Push( FormulaToken& r )
918 : : {
919 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Push" );
920 [ - + ]: 154 : if ( sp >= MAXSTACK )
921 : 0 : SetError( errStackOverflow );
922 : : else
923 : : {
924 [ - + ]: 154 : if (nGlobalError)
925 : : {
926 [ # # ]: 0 : if (r.GetType() == svError)
927 : : {
928 : 0 : r.SetError( nGlobalError);
929 : 0 : PushWithoutError( r);
930 : : }
931 : : else
932 [ # # ]: 0 : PushWithoutError( *(new FormulaErrorToken( nGlobalError)));
933 : : }
934 : : else
935 : 154 : PushWithoutError( r);
936 : : }
937 : 154 : }
938 : :
939 : :
940 : 138 : void ScInterpreter::PushTempToken( FormulaToken* p )
941 : : {
942 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushTempToken" );
943 [ - + ]: 138 : if ( sp >= MAXSTACK )
944 : : {
945 : 0 : SetError( errStackOverflow );
946 [ # # ]: 0 : if (!p->GetRef())
947 : : //! p is a dangling pointer hereafter!
948 : 0 : p->Delete();
949 : : }
950 : : else
951 : : {
952 [ - + ]: 138 : if (nGlobalError)
953 : : {
954 [ # # ]: 0 : if (p->GetType() == svError)
955 : : {
956 : 0 : p->SetError( nGlobalError);
957 : 0 : PushTempTokenWithoutError( p);
958 : : }
959 : : else
960 : : {
961 [ # # ]: 0 : if (!p->GetRef())
962 : : //! p is a dangling pointer hereafter!
963 : 0 : p->Delete();
964 [ # # ]: 0 : PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
965 : : }
966 : : }
967 : : else
968 : 138 : PushTempTokenWithoutError( p);
969 : : }
970 : 138 : }
971 : :
972 : :
973 : 3219 : void ScInterpreter::PushTempTokenWithoutError( FormulaToken* p )
974 : : {
975 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushTempTokenWithoutError" );
976 : 3219 : p->IncRef();
977 [ - + ]: 3219 : if ( sp >= MAXSTACK )
978 : : {
979 : 0 : SetError( errStackOverflow );
980 : : //! p may be a dangling pointer hereafter!
981 : 0 : p->DecRef();
982 : : }
983 : : else
984 : : {
985 [ + + ]: 3219 : if( sp >= maxsp )
986 : 175 : maxsp = sp + 1;
987 : : else
988 : 3044 : pStack[ sp ]->DecRef();
989 : 3219 : pStack[ sp ] = p;
990 : 3219 : ++sp;
991 : : }
992 : 3219 : }
993 : :
994 : :
995 : 67 : void ScInterpreter::PushTempToken( const FormulaToken& r )
996 : : {
997 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushTempToken" );
998 [ + - ]: 67 : if (!IfErrorPushError())
999 : 67 : PushTempTokenWithoutError( r.Clone());
1000 : 67 : }
1001 : :
1002 : :
1003 : 268 : void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
1004 : : const ScAddress & rAddress, short * pRetTypeExpr, sal_uLong * pRetIndexExpr )
1005 : : {
1006 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushCellResultToken" );
1007 : 268 : ScBaseCell* pCell = pDok->GetCell( rAddress);
1008 [ + + ][ + + ]: 268 : if (!pCell || pCell->HasEmptyData())
[ + - ]
1009 : : {
1010 [ + - ][ + - ]: 30 : if (pRetTypeExpr && pRetIndexExpr)
1011 : 30 : pDok->GetNumberFormatInfo( *pRetTypeExpr, *pRetIndexExpr, rAddress, pCell);
1012 : 30 : bool bInherited = (GetCellType( pCell) == CELLTYPE_FORMULA);
1013 [ + - ]: 30 : PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
1014 : 268 : return;
1015 : : }
1016 : : sal_uInt16 nErr;
1017 [ - + ]: 238 : if ((nErr = pCell->GetErrorCode()) != 0)
1018 : : {
1019 : 0 : PushError( nErr);
1020 [ # # ]: 0 : if (pRetTypeExpr)
1021 : 0 : *pRetTypeExpr = NUMBERFORMAT_UNDEFINED;
1022 [ # # ]: 0 : if (pRetIndexExpr)
1023 : 0 : *pRetIndexExpr = 0;
1024 : : }
1025 [ + + ]: 238 : else if (pCell->HasStringData())
1026 : : {
1027 [ + - ]: 44 : String aRes;
1028 [ + - ]: 44 : GetCellString( aRes, pCell);
1029 [ + - ]: 44 : PushString( aRes);
1030 [ + - ]: 44 : if (pRetTypeExpr)
1031 : 44 : *pRetTypeExpr = NUMBERFORMAT_TEXT;
1032 [ + - ]: 44 : if (pRetIndexExpr)
1033 [ + - ]: 44 : *pRetIndexExpr = 0;
1034 : : }
1035 : : else
1036 : : {
1037 : 194 : double fVal = GetCellValue( rAddress, pCell);
1038 : 194 : PushDouble( fVal);
1039 [ + + ]: 194 : if (pRetTypeExpr)
1040 : 146 : *pRetTypeExpr = nCurFmtType;
1041 [ + + ]: 194 : if (pRetIndexExpr)
1042 : 146 : *pRetIndexExpr = nCurFmtIndex;
1043 : : }
1044 : : }
1045 : :
1046 : :
1047 : : // Simply throw away TOS.
1048 : :
1049 : 43 : void ScInterpreter::Pop()
1050 : : {
1051 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Pop" );
1052 [ + - ]: 43 : if( sp )
1053 : 43 : sp--;
1054 : : else
1055 : 0 : SetError(errUnknownStackVariable);
1056 : 43 : }
1057 : :
1058 : :
1059 : : // Simply throw away TOS and set error code, used with ocIsError et al.
1060 : :
1061 : 39 : void ScInterpreter::PopError()
1062 : : {
1063 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopError" );
1064 [ + - ]: 39 : if( sp )
1065 : : {
1066 : 39 : sp--;
1067 [ + + ]: 39 : if (pStack[sp]->GetType() == svError)
1068 : 21 : nGlobalError = pStack[sp]->GetError();
1069 : : }
1070 : : else
1071 : 0 : SetError(errUnknownStackVariable);
1072 : 39 : }
1073 : :
1074 : :
1075 : 2622 : FormulaTokenRef ScInterpreter::PopToken()
1076 : : {
1077 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopToken" );
1078 [ + - ]: 2622 : if (sp)
1079 : : {
1080 : 2622 : sp--;
1081 : 2622 : FormulaToken* p = pStack[ sp ];
1082 [ + + ]: 2622 : if (p->GetType() == svError)
1083 : 312 : nGlobalError = p->GetError();
1084 : 2622 : return p;
1085 : : }
1086 : : else
1087 : 0 : SetError(errUnknownStackVariable);
1088 : 2622 : return NULL;
1089 : : }
1090 : :
1091 : :
1092 : 1386 : double ScInterpreter::PopDouble()
1093 : : {
1094 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDouble" );
1095 : 1386 : nCurFmtType = NUMBERFORMAT_NUMBER;
1096 : 1386 : nCurFmtIndex = 0;
1097 [ + - ]: 1386 : if( sp )
1098 : : {
1099 : 1386 : --sp;
1100 : 1386 : FormulaToken* p = pStack[ sp ];
1101 [ - + - - ]: 1386 : switch (p->GetType())
1102 : : {
1103 : : case svError:
1104 : 0 : nGlobalError = p->GetError();
1105 : 0 : break;
1106 : : case svDouble:
1107 : 1386 : return p->GetDouble();
1108 : : case svEmptyCell:
1109 : : case svMissing:
1110 : 0 : return 0.0;
1111 : : default:
1112 : 0 : SetError( errIllegalArgument);
1113 : : }
1114 : : }
1115 : : else
1116 : 0 : SetError( errUnknownStackVariable);
1117 : 1386 : return 0.0;
1118 : : }
1119 : :
1120 : :
1121 : 252 : const String& ScInterpreter::PopString()
1122 : : {
1123 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopString" );
1124 : 252 : nCurFmtType = NUMBERFORMAT_TEXT;
1125 : 252 : nCurFmtIndex = 0;
1126 [ + - ]: 252 : if( sp )
1127 : : {
1128 : 252 : --sp;
1129 : 252 : FormulaToken* p = pStack[ sp ];
1130 [ - + - - ]: 252 : switch (p->GetType())
1131 : : {
1132 : : case svError:
1133 : 0 : nGlobalError = p->GetError();
1134 : 0 : break;
1135 : : case svString:
1136 : 252 : return p->GetString();
1137 : : case svEmptyCell:
1138 : : case svMissing:
1139 : 0 : return EMPTY_STRING;
1140 : : default:
1141 : 0 : SetError( errIllegalArgument);
1142 : : }
1143 : : }
1144 : : else
1145 : 0 : SetError( errUnknownStackVariable);
1146 : 252 : return EMPTY_STRING;
1147 : : }
1148 : :
1149 : :
1150 : 0 : void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
1151 : : {
1152 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ValidateRef" );
1153 : : SCCOL nCol;
1154 : : SCROW nRow;
1155 : : SCTAB nTab;
1156 [ # # ]: 0 : SingleRefToVars( rRef, nCol, nRow, nTab);
1157 : 0 : }
1158 : :
1159 : :
1160 : 0 : void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
1161 : : {
1162 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ValidateRef" );
1163 : 0 : ValidateRef( rRef.Ref1);
1164 : 0 : ValidateRef( rRef.Ref2);
1165 : 0 : }
1166 : :
1167 : :
1168 : 0 : void ScInterpreter::ValidateRef( const ScRefList & rRefList )
1169 : : {
1170 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ValidateRef" );
1171 : 0 : ScRefList::const_iterator it( rRefList.begin());
1172 : 0 : ScRefList::const_iterator end( rRefList.end());
1173 [ # # ][ # # ]: 0 : for ( ; it != end; ++it)
1174 : : {
1175 [ # # ]: 0 : ValidateRef( *it);
1176 : : }
1177 : 0 : }
1178 : :
1179 : :
1180 : 3769 : void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
1181 : : SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
1182 : : {
1183 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::SingleRefToVars" );
1184 [ + + ]: 3769 : if ( rRef.IsColRel() )
1185 : 3246 : rCol = aPos.Col() + rRef.nRelCol;
1186 : : else
1187 : 523 : rCol = rRef.nCol;
1188 [ + + ]: 3769 : if ( rRef.IsRowRel() )
1189 : 3093 : rRow = aPos.Row() + rRef.nRelRow;
1190 : : else
1191 : 676 : rRow = rRef.nRow;
1192 [ + + ]: 3769 : if ( rRef.IsTabRel() )
1193 : 3484 : rTab = aPos.Tab() + rRef.nRelTab;
1194 : : else
1195 : 285 : rTab = rRef.nTab;
1196 [ + - ][ - + ]: 3769 : if( !ValidCol( rCol) || rRef.IsColDeleted() )
[ - + ]
1197 : 0 : SetError( errNoRef ), rCol = 0;
1198 [ + - ][ - + ]: 3769 : if( !ValidRow( rRow) || rRef.IsRowDeleted() )
[ - + ]
1199 : 0 : SetError( errNoRef ), rRow = 0;
1200 [ + - ][ - + ]: 3769 : if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() )
[ - + ]
1201 : 0 : SetError( errNoRef ), rTab = 0;
1202 : 3769 : }
1203 : :
1204 : :
1205 : 45 : void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
1206 : : {
1207 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopSingleRef" );
1208 [ + - ]: 45 : if( sp )
1209 : : {
1210 : 45 : --sp;
1211 : 45 : FormulaToken* p = pStack[ sp ];
1212 [ - + - ]: 45 : switch (p->GetType())
1213 : : {
1214 : : case svError:
1215 : 0 : nGlobalError = p->GetError();
1216 : 0 : break;
1217 : : case svSingleRef:
1218 : 45 : SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), rCol, rRow, rTab);
1219 [ - + ]: 45 : if ( !pDok->aTableOpList.empty() )
1220 : 0 : ReplaceCell( rCol, rRow, rTab );
1221 : 45 : break;
1222 : : default:
1223 : 45 : SetError( errIllegalParameter);
1224 : : }
1225 : : }
1226 : : else
1227 : 0 : SetError( errUnknownStackVariable);
1228 : 45 : }
1229 : :
1230 : :
1231 : 2642 : void ScInterpreter::PopSingleRef( ScAddress& rAdr )
1232 : : {
1233 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopSingleRef" );
1234 [ + - ]: 2642 : if( sp )
1235 : : {
1236 : 2642 : --sp;
1237 : 2642 : FormulaToken* p = pStack[ sp ];
1238 [ - + - ]: 2642 : switch (p->GetType())
1239 : : {
1240 : : case svError:
1241 : 0 : nGlobalError = p->GetError();
1242 : 0 : break;
1243 : : case svSingleRef:
1244 : : {
1245 : : SCCOL nCol;
1246 : : SCROW nRow;
1247 : : SCTAB nTab;
1248 [ + - ][ + - ]: 2642 : SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), nCol, nRow, nTab);
1249 : 2642 : rAdr.Set( nCol, nRow, nTab );
1250 [ + + ]: 2642 : if ( !pDok->aTableOpList.empty() )
1251 [ + - ]: 110 : ReplaceCell( rAdr );
1252 : : }
1253 : 2642 : break;
1254 : : default:
1255 : 2642 : SetError( errIllegalParameter);
1256 : : }
1257 : : }
1258 : : else
1259 : 0 : SetError( errUnknownStackVariable);
1260 : 2642 : }
1261 : :
1262 : :
1263 : 295 : void ScInterpreter::DoubleRefToVars( const ScToken* p,
1264 : : SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1265 : : SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1266 : : bool bDontCheckForTableOp )
1267 : : {
1268 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DoubleRefToVars" );
1269 : 295 : const ScComplexRefData& rCRef = p->GetDoubleRef();
1270 : 295 : SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
1271 : 295 : SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
1272 [ # # ][ - + ]: 295 : if ( !pDok->aTableOpList.empty() && !bDontCheckForTableOp )
[ - + ]
1273 : : {
1274 : 0 : ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
1275 [ # # ][ # # ]: 0 : if ( IsTableOpInRange( aRange ) )
1276 : 0 : SetError( errIllegalParameter );
1277 : : }
1278 : 295 : }
1279 : :
1280 : 48 : ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
1281 : : {
1282 : 48 : StackVar eType = GetStackType();
1283 [ - - + - : 48 : switch (eType)
- ]
1284 : : {
1285 : : case svUnknown:
1286 : 0 : SetError(errUnknownStackVariable);
1287 : 0 : break;
1288 : : case svError:
1289 : 0 : PopError();
1290 : 0 : break;
1291 : : case svDoubleRef:
1292 : : {
1293 : : SCCOL nCol1, nCol2;
1294 : : SCROW nRow1, nRow2;
1295 : : SCTAB nTab1, nTab2;
1296 [ + - ]: 48 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
1297 [ + - ]: 48 : if (nGlobalError)
1298 : : break;
1299 : : return new ScDBInternalRange(pDok,
1300 [ + - ][ + - ]: 48 : ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
1301 : : }
1302 : : case svMatrix:
1303 : : case svExternalDoubleRef:
1304 : : {
1305 : 0 : ScMatrixRef pMat;
1306 [ # # ]: 0 : if (eType == svMatrix)
1307 [ # # ][ # # ]: 0 : pMat = PopMatrix();
[ # # ]
1308 : : else
1309 [ # # ]: 0 : PopExternalDoubleRef(pMat);
1310 [ # # ]: 0 : if (nGlobalError)
1311 : : break;
1312 [ # # ][ # # ]: 0 : return new ScDBExternalRange(pDok, pMat);
[ # # ][ # # ]
1313 : : }
1314 : : default:
1315 : 0 : SetError( errIllegalParameter);
1316 : : }
1317 : :
1318 : 48 : return NULL;
1319 : : }
1320 : :
1321 : 223 : void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1322 : : SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1323 : : bool bDontCheckForTableOp )
1324 : : {
1325 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRef" );
1326 [ + - ]: 223 : if( sp )
1327 : : {
1328 : 223 : --sp;
1329 : 223 : FormulaToken* p = pStack[ sp ];
1330 [ - + - ]: 223 : switch (p->GetType())
1331 : : {
1332 : : case svError:
1333 : 0 : nGlobalError = p->GetError();
1334 : 0 : break;
1335 : : case svDoubleRef:
1336 : : DoubleRefToVars( static_cast<ScToken*>(p), rCol1, rRow1, rTab1, rCol2, rRow2, rTab2,
1337 : 223 : bDontCheckForTableOp);
1338 : 223 : break;
1339 : : default:
1340 : 223 : SetError( errIllegalParameter);
1341 : : }
1342 : : }
1343 : : else
1344 : 0 : SetError( errUnknownStackVariable);
1345 : 223 : }
1346 : :
1347 : :
1348 : 246 : void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1349 : : ScRange & rRange, bool bDontCheckForTableOp )
1350 : : {
1351 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DoubleRefToRange" );
1352 : : SCCOL nCol;
1353 : : SCROW nRow;
1354 : : SCTAB nTab;
1355 [ + - ]: 246 : SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1356 : 246 : rRange.aStart.Set( nCol, nRow, nTab );
1357 [ + - ]: 246 : SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1358 : 246 : rRange.aEnd.Set( nCol, nRow, nTab );
1359 [ # # ][ - + ]: 246 : if (! pDok->aTableOpList.empty() && !bDontCheckForTableOp )
[ - + ]
1360 : : {
1361 [ # # ][ # # ]: 0 : if ( IsTableOpInRange( rRange ) )
1362 : 0 : SetError( errIllegalParameter );
1363 : : }
1364 : 246 : }
1365 : :
1366 : :
1367 : 198 : void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1368 : : {
1369 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRef" );
1370 [ + - ]: 198 : if (sp)
1371 : : {
1372 : 198 : formula::FormulaToken* pToken = pStack[ sp-1 ];
1373 : 198 : ScToken* p = static_cast<ScToken*>(pToken);
1374 [ - + - - ]: 198 : switch (pToken->GetType())
1375 : : {
1376 : : case svError:
1377 : 0 : nGlobalError = p->GetError();
1378 : 0 : break;
1379 : : case svDoubleRef:
1380 : 198 : --sp;
1381 : 198 : DoubleRefToRange( p->GetDoubleRef(), rRange);
1382 : 198 : break;
1383 : : case svRefList:
1384 : : {
1385 : 0 : const ScRefList* pList = p->GetRefList();
1386 [ # # ]: 0 : if (rRefInList < pList->size())
1387 : : {
1388 : 0 : DoubleRefToRange( (*pList)[rRefInList], rRange);
1389 [ # # ]: 0 : if (++rRefInList < pList->size())
1390 : 0 : ++rParam;
1391 : : else
1392 : : {
1393 : 0 : --sp;
1394 : 0 : rRefInList = 0;
1395 : : }
1396 : : }
1397 : : else
1398 : : {
1399 : 0 : --sp;
1400 : 0 : rRefInList = 0;
1401 : 0 : SetError( errIllegalParameter);
1402 : : }
1403 : : }
1404 : 0 : break;
1405 : : default:
1406 : 198 : SetError( errIllegalParameter);
1407 : : }
1408 : : }
1409 : : else
1410 : 0 : SetError( errUnknownStackVariable);
1411 : 198 : }
1412 : :
1413 : :
1414 : 48 : void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1415 : : {
1416 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRef" );
1417 [ + - ]: 48 : if( sp )
1418 : : {
1419 : 48 : --sp;
1420 : 48 : FormulaToken* p = pStack[ sp ];
1421 [ - + - ]: 48 : switch (p->GetType())
1422 : : {
1423 : : case svError:
1424 : 0 : nGlobalError = p->GetError();
1425 : 0 : break;
1426 : : case svDoubleRef:
1427 : 48 : DoubleRefToRange( static_cast<ScToken*>(p)->GetDoubleRef(), rRange, bDontCheckForTableOp);
1428 : 48 : break;
1429 : : default:
1430 : 48 : SetError( errIllegalParameter);
1431 : : }
1432 : : }
1433 : : else
1434 : 0 : SetError( errUnknownStackVariable);
1435 : 48 : }
1436 : :
1437 : 69 : void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, String& rTabName, ScSingleRefData& rRef)
1438 : : {
1439 [ - + ]: 69 : if (!sp)
1440 : : {
1441 : 0 : SetError(errUnknownStackVariable);
1442 : 0 : return;
1443 : : }
1444 : :
1445 : 69 : --sp;
1446 : 69 : FormulaToken* p = pStack[sp];
1447 : 69 : StackVar eType = p->GetType();
1448 : :
1449 [ - + ]: 69 : if (eType == svError)
1450 : : {
1451 : 0 : nGlobalError = p->GetError();
1452 : 0 : return;
1453 : : }
1454 : :
1455 [ - + ]: 69 : if (eType != svExternalSingleRef)
1456 : : {
1457 : 0 : SetError( errIllegalParameter);
1458 : 0 : return;
1459 : : }
1460 : :
1461 : 69 : rFileId = p->GetIndex();
1462 : 69 : rTabName = p->GetString();
1463 : 69 : rRef = static_cast<ScToken*>(p)->GetSingleRef();
1464 : : }
1465 : :
1466 : 69 : void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1467 : : {
1468 : : sal_uInt16 nFileId;
1469 [ + - ]: 69 : String aTabName;
1470 : : ScSingleRefData aData;
1471 [ + - ][ + - ]: 69 : PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1472 : 69 : }
1473 : :
1474 : 69 : void ScInterpreter::PopExternalSingleRef(
1475 : : sal_uInt16& rFileId, String& rTabName, ScSingleRefData& rRef,
1476 : : ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1477 : : {
1478 [ + - ]: 69 : PopExternalSingleRef(rFileId, rTabName, rRef);
1479 [ + - ]: 69 : if (nGlobalError)
1480 : : return;
1481 : :
1482 [ + - ]: 69 : ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1483 [ + - ]: 69 : const rtl::OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1484 [ - + ]: 69 : if (!pFile)
1485 : : {
1486 : 0 : SetError(errNoName);
1487 : : return;
1488 : : }
1489 : :
1490 [ - + ]: 69 : if (rRef.IsTabRel())
1491 : : {
1492 : : OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1493 : 0 : SetError(errNoRef);
1494 : : return;
1495 : : }
1496 : :
1497 [ + - ]: 69 : rRef.CalcAbsIfRel(aPos);
1498 : 69 : ScAddress aAddr(rRef.nCol, rRef.nRow, rRef.nTab);
1499 [ + - ]: 69 : ScExternalRefCache::CellFormat aFmt;
1500 : : ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1501 [ + - ][ + - ]: 69 : rFileId, rTabName, aAddr, &aPos, NULL, &aFmt);
1502 : :
1503 [ - + ]: 69 : if (!xNew)
1504 : : {
1505 : 0 : SetError(errNoRef);
1506 : : return;
1507 : : }
1508 : :
1509 [ + - ]: 69 : rToken = xNew;
1510 [ + + ]: 69 : if (pFmt)
1511 [ + - ][ + - ]: 69 : *pFmt = aFmt;
1512 : : }
1513 : :
1514 : 18 : void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef)
1515 : : {
1516 [ - + ]: 18 : if (!sp)
1517 : : {
1518 : 0 : SetError(errUnknownStackVariable);
1519 : 0 : return;
1520 : : }
1521 : :
1522 : 18 : --sp;
1523 : 18 : FormulaToken* p = pStack[sp];
1524 : 18 : StackVar eType = p->GetType();
1525 : :
1526 [ - + ]: 18 : if (eType == svError)
1527 : : {
1528 : 0 : nGlobalError = p->GetError();
1529 : 0 : return;
1530 : : }
1531 : :
1532 [ - + ]: 18 : if (eType != svExternalDoubleRef)
1533 : : {
1534 : 0 : SetError( errIllegalParameter);
1535 : 0 : return;
1536 : : }
1537 : :
1538 : 18 : rFileId = p->GetIndex();
1539 : 18 : rTabName = p->GetString();
1540 : 18 : rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1541 : : }
1542 : :
1543 : 18 : void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1544 : : {
1545 : : sal_uInt16 nFileId;
1546 [ + - ]: 18 : String aTabName;
1547 : : ScComplexRefData aData;
1548 [ + - ]: 18 : PopExternalDoubleRef(nFileId, aTabName, aData);
1549 [ - + ]: 18 : if (nGlobalError)
1550 : : return;
1551 : :
1552 [ + - ]: 18 : GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1553 [ - + ]: 18 : if (nGlobalError)
1554 [ + - ][ + - ]: 18 : return;
1555 : : }
1556 : :
1557 : 18 : void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1558 : : {
1559 [ + - ]: 18 : ScExternalRefCache::TokenArrayRef pArray;
1560 [ + - ]: 18 : PopExternalDoubleRef(pArray);
1561 [ - + ]: 18 : if (nGlobalError)
1562 : 18 : return;
1563 : :
1564 : : // For now, we only support single range data for external
1565 : : // references, which means the array should only contain a
1566 : : // single matrix token.
1567 [ + - ]: 18 : ScToken* p = static_cast<ScToken*>(pArray->First());
1568 [ + - ][ - + ]: 18 : if (!p || p->GetType() != svMatrix)
[ - + ]
1569 : 0 : SetError( errIllegalParameter);
1570 : : else
1571 : : {
1572 [ + - ][ + - ]: 18 : rMat = p->GetMatrix();
1573 [ - + ]: 18 : if (!rMat)
1574 : 18 : SetError( errUnknownVariable);
1575 [ + - ][ + - ]: 18 : }
1576 : : }
1577 : :
1578 : 18 : void ScInterpreter::GetExternalDoubleRef(
1579 : : sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1580 : : {
1581 [ + - ]: 18 : ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1582 [ + - ]: 18 : const rtl::OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1583 [ - + ]: 18 : if (!pFile)
1584 : : {
1585 : 0 : SetError(errNoName);
1586 : : return;
1587 : : }
1588 [ + - ][ - + ]: 18 : if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
[ - + ]
1589 : : {
1590 : : OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1591 : 0 : SetError(errNoRef);
1592 : : return;
1593 : : }
1594 : :
1595 : 18 : ScComplexRefData aData(rData);
1596 [ + - ]: 18 : aData.CalcAbsIfRel(aPos);
1597 : : ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
1598 : 18 : aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
1599 : : ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1600 [ + - ][ + - ]: 18 : nFileId, rTabName, aRange, &aPos);
1601 : :
1602 [ - + ]: 18 : if (!pArray)
1603 : : {
1604 : 0 : SetError(errIllegalArgument);
1605 : : return;
1606 : : }
1607 : :
1608 [ + - ]: 18 : ScToken* pToken = static_cast<ScToken*>(pArray->First());
1609 [ - + ]: 18 : if (pToken->GetType() != svMatrix)
1610 : : {
1611 : 0 : SetError(errIllegalArgument);
1612 : : return;
1613 : : }
1614 : :
1615 [ + - ][ - + ]: 18 : if (pArray->Next())
1616 : : {
1617 : : // Can't handle more than one matrix per parameter.
1618 : 0 : SetError( errIllegalArgument);
1619 : : return;
1620 : : }
1621 : :
1622 [ + - ][ + - ]: 18 : rArray = pArray;
[ + - ]
1623 : : }
1624 : :
1625 : 324 : bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1626 : : {
1627 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefOrSingleRef" );
1628 [ - + - ]: 324 : switch ( GetStackType() )
1629 : : {
1630 : : case svDoubleRef :
1631 : : {
1632 : 0 : ScRange aRange;
1633 [ # # ]: 0 : PopDoubleRef( aRange, true );
1634 [ # # ]: 0 : return DoubleRefToPosSingleRef( aRange, rAdr );
1635 : : }
1636 : : case svSingleRef :
1637 : : {
1638 : 324 : PopSingleRef( rAdr );
1639 : 324 : return true;
1640 : : }
1641 : : default:
1642 : 0 : PopError();
1643 : 0 : SetError( errNoRef );
1644 : : }
1645 : 324 : return false;
1646 : : }
1647 : :
1648 : :
1649 : 10 : void ScInterpreter::PopDoubleRefPushMatrix()
1650 : : {
1651 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefPushMatrix" );
1652 [ + - ]: 10 : if ( GetStackType() == svDoubleRef )
1653 : : {
1654 [ + - ]: 10 : ScMatrixRef pMat = GetMatrix();
1655 [ + - ]: 10 : if ( pMat )
1656 [ + - ]: 10 : PushMatrix( pMat );
1657 : : else
1658 [ # # ][ + - ]: 10 : PushIllegalParameter();
1659 : : }
1660 : : else
1661 : 0 : SetError( errNoRef );
1662 : 10 : }
1663 : :
1664 : :
1665 : 36 : ScTokenMatrixMap* ScInterpreter::CreateTokenMatrixMap()
1666 : : {
1667 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateTokenMatrixMap" );
1668 [ + - ]: 36 : return new ScTokenMatrixMap;
1669 : : }
1670 : :
1671 : :
1672 : 246 : bool ScInterpreter::ConvertMatrixParameters()
1673 : : {
1674 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ConvertMatrixParameters" );
1675 : 246 : sal_uInt16 nParams = pCur->GetParamCount();
1676 : : OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch");
1677 : 246 : SCSIZE nJumpCols = 0, nJumpRows = 0;
1678 [ + + ][ + - ]: 684 : for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
[ + + ]
1679 : : {
1680 : 438 : FormulaToken* p = pStack[ sp - i ];
1681 [ - + ][ # # ]: 438 : if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
[ + - ]
1682 : : {
1683 : : OSL_FAIL( "ConvertMatrixParameters: not a push");
1684 : : }
1685 : : else
1686 : : {
1687 [ + + + - : 438 : switch ( p->GetType() )
- - ]
1688 : : {
1689 : : case svDouble:
1690 : : case svString:
1691 : : case svSingleRef:
1692 : : case svExternalSingleRef:
1693 : : case svMissing:
1694 : : case svError:
1695 : : case svEmptyCell:
1696 : : // nothing to do
1697 : 261 : break;
1698 : : case svMatrix:
1699 : : {
1700 [ - + ]: 72 : if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1701 : : == ScParameterClassification::Value )
1702 : : { // only if single value expected
1703 [ # # ]: 0 : ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
1704 [ # # ]: 0 : if ( !pMat )
1705 : 0 : SetError( errUnknownVariable);
1706 : : else
1707 : : {
1708 : : SCSIZE nCols, nRows;
1709 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
1710 [ # # ]: 0 : if ( nJumpCols < nCols )
1711 : 0 : nJumpCols = nCols;
1712 [ # # ]: 0 : if ( nJumpRows < nRows )
1713 : 0 : nJumpRows = nRows;
1714 [ # # ]: 0 : }
1715 : : }
1716 : : }
1717 : 72 : break;
1718 : : case svDoubleRef:
1719 : : {
1720 : : ScParameterClassification::Type eType =
1721 : 105 : ScParameterClassification::GetParameterType( pCur, nParams - i);
1722 [ + - ][ + + ]: 105 : if ( eType != ScParameterClassification::Reference &&
1723 : : eType != ScParameterClassification::ReferenceOrForceArray)
1724 : : {
1725 : : SCCOL nCol1, nCol2;
1726 : : SCROW nRow1, nRow2;
1727 : : SCTAB nTab1, nTab2;
1728 [ + - ]: 72 : DoubleRefToVars( static_cast<const ScToken*>( p), nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1729 : : // Make sure the map exists, created if not.
1730 [ + - ]: 72 : GetTokenMatrixMap();
1731 : : ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1732 [ + - ]: 72 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1733 [ + - ]: 72 : if (pMat)
1734 : : {
1735 [ - + ]: 72 : if ( eType == ScParameterClassification::Value )
1736 : : { // only if single value expected
1737 [ # # ]: 0 : if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) )
1738 : 0 : nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1739 [ # # ]: 0 : if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) )
1740 : 0 : nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1741 : : }
1742 [ + - ][ + - ]: 72 : ScToken* pNew = new ScMatrixToken( pMat);
[ + - ]
1743 : 72 : pNew->IncRef();
1744 : 72 : pStack[ sp - i ] = pNew;
1745 [ + - ]: 72 : p->DecRef(); // p may be dead now!
1746 [ + - ]: 72 : }
1747 : : }
1748 : : }
1749 : 105 : break;
1750 : : case svExternalDoubleRef:
1751 : : {
1752 : : ScParameterClassification::Type eType =
1753 : 0 : ScParameterClassification::GetParameterType( pCur, nParams - i);
1754 [ # # ]: 0 : if (eType == ScParameterClassification::Array)
1755 : : {
1756 [ # # ]: 0 : sal_uInt16 nFileId = p->GetIndex();
1757 [ # # ]: 0 : const String& rTabName = p->GetString();
1758 [ # # ]: 0 : const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1759 [ # # ]: 0 : ScExternalRefCache::TokenArrayRef pArray;
1760 [ # # ]: 0 : GetExternalDoubleRef(nFileId, rTabName, rRef, pArray);
1761 [ # # ]: 0 : if (nGlobalError)
1762 : : break;
1763 : :
1764 [ # # ]: 0 : ScToken* pTemp = static_cast<ScToken*>(pArray->First());
1765 [ # # ]: 0 : if (!pTemp)
1766 : : break;
1767 : :
1768 [ # # ]: 0 : ScMatrixRef pMat = pTemp->GetMatrix();
1769 [ # # ]: 0 : if (pMat)
1770 : : {
1771 [ # # ][ # # ]: 0 : ScToken* pNew = new ScMatrixToken( pMat);
[ # # ]
1772 : 0 : pNew->IncRef();
1773 : 0 : pStack[ sp - i ] = pNew;
1774 [ # # ]: 0 : p->DecRef(); // p may be dead now!
1775 [ # # ][ # # ]: 0 : }
[ # # ]
1776 : : }
1777 : : }
1778 : 0 : break;
1779 : : case svRefList:
1780 : : {
1781 : : ScParameterClassification::Type eType =
1782 : 0 : ScParameterClassification::GetParameterType( pCur, nParams - i);
1783 [ # # ][ # # ]: 0 : if ( eType != ScParameterClassification::Reference &&
1784 : : eType != ScParameterClassification::ReferenceOrForceArray)
1785 : : {
1786 : : // can't convert to matrix
1787 : 0 : SetError( errNoValue);
1788 : : }
1789 : : }
1790 : 0 : break;
1791 : : default:
1792 : : OSL_FAIL( "ConvertMatrixParameters: unknown parameter type");
1793 : : }
1794 : : }
1795 : : }
1796 [ - + ][ # # ]: 246 : if( nJumpCols && nJumpRows )
1797 : : {
1798 : 0 : short nPC = aCode.GetPC();
1799 : 0 : short nStart = nPC - 1; // restart on current code (-1)
1800 : 0 : short nNext = nPC; // next instruction after subroutine
1801 : 0 : short nStop = nPC + 1; // stop subroutine before reaching that
1802 : 0 : FormulaTokenRef xNew;
1803 : 0 : ScTokenMatrixMap::const_iterator aMapIter;
1804 [ # # ][ # # ]: 0 : if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) !=
[ # # # # ]
[ # # # # ]
1805 [ # # ][ # # ]: 0 : pTokenMatrixMap->end()))
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# ]
1806 [ # # ]: 0 : xNew = (*aMapIter).second;
1807 : : else
1808 : : {
1809 [ # # ][ # # ]: 0 : ScJumpMatrix* pJumpMat = new ScJumpMatrix( nJumpCols, nJumpRows);
1810 : 0 : pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1811 : : // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1812 [ # # ][ # # ]: 0 : ScTokenVec* pParams = new ScTokenVec( nParams);
1813 [ # # ][ # # ]: 0 : for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
[ # # ]
1814 : : {
1815 : 0 : FormulaToken* p = pStack[ --sp ];
1816 : 0 : p->IncRef();
1817 : : // store in reverse order such that a push may simply iterate
1818 [ # # ]: 0 : (*pParams)[ nParams - i ] = p;
1819 : : }
1820 : 0 : pJumpMat->SetJumpParameters( pParams);
1821 [ # # ][ # # ]: 0 : xNew = new ScJumpMatrixToken( pJumpMat );
[ # # ]
1822 [ # # ]: 0 : GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur,
1823 [ # # ][ # # ]: 0 : xNew));
[ # # ]
1824 : : }
1825 [ # # ]: 0 : PushTempToken( xNew.get());
1826 : : // set continuation point of path for main code line
1827 [ # # ]: 0 : aCode.Jump( nNext, nNext);
1828 [ # # ]: 0 : return true;
1829 : : }
1830 : 246 : return false;
1831 : : }
1832 : :
1833 : :
1834 : 231 : ScMatrixRef ScInterpreter::PopMatrix()
1835 : : {
1836 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopMatrix" );
1837 [ + - ]: 231 : if( sp )
1838 : : {
1839 : 231 : --sp;
1840 : 231 : FormulaToken* p = pStack[ sp ];
1841 [ - + - ]: 231 : switch (p->GetType())
1842 : : {
1843 : : case svError:
1844 : 0 : nGlobalError = p->GetError();
1845 : 0 : break;
1846 : : case svMatrix:
1847 : : {
1848 : 231 : ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
1849 [ + - ]: 231 : if ( pMat )
1850 : 231 : pMat->SetErrorInterpreter( this);
1851 : : else
1852 : 0 : SetError( errUnknownVariable);
1853 : 231 : return pMat;
1854 : : }
1855 : : default:
1856 : 0 : SetError( errIllegalParameter);
1857 : : }
1858 : : }
1859 : : else
1860 : 0 : SetError( errUnknownStackVariable);
1861 : 231 : return NULL;
1862 : : }
1863 : :
1864 : 81 : void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
1865 : : {
1866 [ + - ]: 81 : if (xMat)
1867 : : {
1868 [ + - ]: 81 : ScMatrixValue nMatVal = xMat->Get(0, 0);
1869 : 81 : ScMatValType nMatValType = nMatVal.nType;
1870 [ - + ]: 81 : if (ScMatrix::IsNonValueType( nMatValType))
1871 : : {
1872 [ # # ][ # # ]: 0 : if ( xMat->IsEmptyPath( 0, 0))
1873 : : { // result of empty FALSE jump path
1874 [ # # ][ # # ]: 0 : FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
1875 [ # # ][ # # ]: 0 : PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
[ # # ][ # # ]
1876 [ # # ]: 0 : rRetTypeExpr = NUMBERFORMAT_LOGICAL;
1877 : : }
1878 : : else
1879 : : {
1880 [ # # ]: 0 : String aStr( nMatVal.GetString());
1881 [ # # ][ # # ]: 0 : FormulaTokenRef xRes = new FormulaStringToken( aStr);
1882 [ # # ][ # # ]: 0 : PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
[ # # ][ # # ]
1883 [ # # ][ # # ]: 0 : rRetTypeExpr = NUMBERFORMAT_TEXT;
1884 : : }
1885 : : }
1886 : : else
1887 : : {
1888 : 81 : sal_uInt16 nErr = GetDoubleErrorValue( nMatVal.fVal);
1889 : 81 : FormulaTokenRef xRes;
1890 [ + + ]: 81 : if (nErr)
1891 [ + - ][ + - ]: 1 : xRes = new FormulaErrorToken( nErr);
[ + - ]
1892 : : else
1893 [ + - ][ + - ]: 80 : xRes = new FormulaDoubleToken( nMatVal.fVal);
[ + - ]
1894 [ + - ][ + - ]: 81 : PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
[ + - ][ + - ]
1895 [ + - ]: 81 : if ( rRetTypeExpr != NUMBERFORMAT_LOGICAL )
1896 [ + - ]: 81 : rRetTypeExpr = NUMBERFORMAT_NUMBER;
1897 : : }
1898 : 81 : rRetIndexExpr = 0;
1899 [ + - ]: 81 : xMat->SetErrorInterpreter( NULL);
1900 : : }
1901 : : else
1902 : 0 : SetError( errUnknownStackVariable);
1903 : 81 : }
1904 : :
1905 : :
1906 : 1892 : void ScInterpreter::PushDouble(double nVal)
1907 : : {
1908 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushDouble" );
1909 : 1892 : TreatDoubleError( nVal );
1910 [ + + ]: 1892 : if (!IfErrorPushError())
1911 [ + - ]: 1865 : PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1912 : 1892 : }
1913 : :
1914 : :
1915 : 444 : void ScInterpreter::PushInt(int nVal)
1916 : : {
1917 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushInt" );
1918 [ + - ]: 444 : if (!IfErrorPushError())
1919 [ + - ]: 444 : PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1920 : 444 : }
1921 : :
1922 : :
1923 : 0 : void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1924 : : {
1925 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushStringBuffer" );
1926 [ # # ]: 0 : if ( pString )
1927 [ # # ][ # # ]: 0 : PushString( rtl::OUString(pString) );
[ # # ]
1928 : : else
1929 : 0 : PushString( EMPTY_STRING );
1930 : 0 : }
1931 : :
1932 : :
1933 : 147 : void ScInterpreter::PushString( const String& rString )
1934 : : {
1935 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushString" );
1936 [ + - ]: 147 : if (!IfErrorPushError())
1937 [ + - ]: 147 : PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1938 : 147 : }
1939 : :
1940 : :
1941 : 78 : void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1942 : : {
1943 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushSingleRef" );
1944 [ + - ]: 78 : if (!IfErrorPushError())
1945 : : {
1946 : : ScSingleRefData aRef;
1947 : 78 : aRef.InitFlags();
1948 : 78 : aRef.nCol = nCol;
1949 : 78 : aRef.nRow = nRow;
1950 : 78 : aRef.nTab = nTab;
1951 [ + - ][ + - ]: 78 : PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
[ + - ]
1952 : : }
1953 : 78 : }
1954 : :
1955 : :
1956 : 0 : void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1957 : : SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1958 : : {
1959 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushDoubleRef" );
1960 [ # # ]: 0 : if (!IfErrorPushError())
1961 : : {
1962 : : ScComplexRefData aRef;
1963 : 0 : aRef.InitFlags();
1964 : 0 : aRef.Ref1.nCol = nCol1;
1965 : 0 : aRef.Ref1.nRow = nRow1;
1966 : 0 : aRef.Ref1.nTab = nTab1;
1967 : 0 : aRef.Ref2.nCol = nCol2;
1968 : 0 : aRef.Ref2.nRow = nRow2;
1969 : 0 : aRef.Ref2.nTab = nTab2;
1970 [ # # ][ # # ]: 0 : PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
[ # # ]
1971 : : }
1972 : 0 : }
1973 : :
1974 : :
1975 : 0 : void ScInterpreter::PushExternalSingleRef(
1976 : : sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1977 : : {
1978 [ # # ]: 0 : if (!IfErrorPushError())
1979 : : {
1980 : : ScSingleRefData aRef;
1981 : 0 : aRef.InitFlags();
1982 : 0 : aRef.nCol = nCol;
1983 : 0 : aRef.nRow = nRow;
1984 : 0 : aRef.nTab = nTab;
1985 [ # # ][ # # ]: 0 : PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId, rTabName, aRef)) ;
[ # # ]
1986 : : }
1987 : 0 : }
1988 : :
1989 : :
1990 : 0 : void ScInterpreter::PushExternalDoubleRef(
1991 : : sal_uInt16 nFileId, const String& rTabName,
1992 : : SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1993 : : {
1994 [ # # ]: 0 : if (!IfErrorPushError())
1995 : : {
1996 : : ScComplexRefData aRef;
1997 : 0 : aRef.InitFlags();
1998 : 0 : aRef.Ref1.nCol = nCol1;
1999 : 0 : aRef.Ref1.nRow = nRow1;
2000 : 0 : aRef.Ref1.nTab = nTab1;
2001 : 0 : aRef.Ref2.nCol = nCol2;
2002 : 0 : aRef.Ref2.nRow = nRow2;
2003 : 0 : aRef.Ref2.nTab = nTab2;
2004 [ # # ][ # # ]: 0 : PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId, rTabName, aRef) );
[ # # ]
2005 : : }
2006 : 0 : }
2007 : :
2008 : :
2009 : 141 : void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
2010 : : {
2011 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushMatrix" );
2012 : 141 : pMat->SetErrorInterpreter( NULL);
2013 : : // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
2014 : : // but with notifying ScInterpreter via nGlobalError, substituting it would
2015 : : // mean to inherit the error on all array elements in all following
2016 : : // operations.
2017 : 141 : nGlobalError = 0;
2018 [ + - ][ + - ]: 141 : PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
[ + - ]
2019 : 141 : }
2020 : :
2021 : :
2022 : 312 : void ScInterpreter::PushError( sal_uInt16 nError )
2023 : : {
2024 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushError" );
2025 : 312 : SetError( nError ); // only sets error if not already set
2026 [ + - ]: 312 : PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
2027 : 312 : }
2028 : :
2029 : 0 : void ScInterpreter::PushParameterExpected()
2030 : : {
2031 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushParameterExpected" );
2032 : 0 : PushError( errParameterExpected);
2033 : 0 : }
2034 : :
2035 : :
2036 : 0 : void ScInterpreter::PushIllegalParameter()
2037 : : {
2038 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushIllegalParameter" );
2039 : 0 : PushError( errIllegalParameter);
2040 : 0 : }
2041 : :
2042 : :
2043 : 144 : void ScInterpreter::PushIllegalArgument()
2044 : : {
2045 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushIllegalArgument" );
2046 : 144 : PushError( errIllegalArgument);
2047 : 144 : }
2048 : :
2049 : :
2050 : 15 : void ScInterpreter::PushNA()
2051 : : {
2052 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushNA" );
2053 : 15 : PushError( NOTAVAILABLE);
2054 : 15 : }
2055 : :
2056 : :
2057 : 0 : void ScInterpreter::PushNoValue()
2058 : : {
2059 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushNoValue" );
2060 : 0 : PushError( errNoValue);
2061 : 0 : }
2062 : :
2063 : :
2064 : 12 : bool ScInterpreter::IsMissing()
2065 : : {
2066 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsMissing" );
2067 [ + - ][ + + ]: 12 : return sp && pStack[sp - 1]->GetType() == svMissing;
2068 : : }
2069 : :
2070 : :
2071 : 3529 : StackVar ScInterpreter::GetRawStackType()
2072 : : {
2073 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetRawStackType" );
2074 : : StackVar eRes;
2075 [ + - ]: 3529 : if( sp )
2076 : : {
2077 : 3529 : eRes = pStack[sp - 1]->GetType();
2078 : : }
2079 : : else
2080 : : {
2081 : 0 : SetError(errUnknownStackVariable);
2082 : 0 : eRes = svUnknown;
2083 : : }
2084 : 3529 : return eRes;
2085 : : }
2086 : :
2087 : :
2088 : 3163 : StackVar ScInterpreter::GetStackType()
2089 : : {
2090 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStackType" );
2091 : : StackVar eRes;
2092 [ + - ]: 3163 : if( sp )
2093 : : {
2094 : 3163 : eRes = pStack[sp - 1]->GetType();
2095 [ - + ][ + + ]: 3163 : if( eRes == svMissing || eRes == svEmptyCell )
2096 : 15 : eRes = svDouble; // default!
2097 : : }
2098 : : else
2099 : : {
2100 : 0 : SetError(errUnknownStackVariable);
2101 : 0 : eRes = svUnknown;
2102 : : }
2103 : 3163 : return eRes;
2104 : : }
2105 : :
2106 : :
2107 : 14728 : StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
2108 : : {
2109 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStackType" );
2110 : : StackVar eRes;
2111 [ + + ]: 14728 : if( sp > nParam-1 )
2112 : : {
2113 : 9637 : eRes = pStack[sp - nParam]->GetType();
2114 [ + + ][ + + ]: 9637 : if( eRes == svMissing || eRes == svEmptyCell )
2115 : 30 : eRes = svDouble; // default!
2116 : : }
2117 : : else
2118 : 5091 : eRes = svUnknown;
2119 : 14728 : return eRes;
2120 : : }
2121 : :
2122 : :
2123 : 39 : bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
2124 : : {
2125 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DoubleRefToPosSingleRef" );
2126 : : // Check for a singleton first - no implicit intersection for them.
2127 [ - + ]: 39 : if( rRange.aStart == rRange.aEnd )
2128 : : {
2129 : 0 : rAdr = rRange.aStart;
2130 : 0 : return true;
2131 : : }
2132 : :
2133 : 39 : bool bOk = false;
2134 : :
2135 [ - + ]: 39 : if ( pJumpMatrix )
2136 : : {
2137 : 0 : bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
2138 [ # # ]: 0 : if ( !bOk )
2139 : 0 : SetError( errIllegalArgument);
2140 : : else
2141 : : {
2142 : : SCSIZE nC, nR;
2143 : 0 : pJumpMatrix->GetPos( nC, nR);
2144 : 0 : rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
2145 : 0 : rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
2146 : 0 : rAdr.SetTab( rRange.aStart.Tab());
2147 : 0 : bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
2148 : 0 : rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
2149 [ # # ][ # # : 0 : rAdr.Row() <= rRange.aEnd.Row();
# # # # ]
2150 [ # # ]: 0 : if ( !bOk )
2151 : 0 : SetError( errNoValue);
2152 : : }
2153 : 0 : return bOk;
2154 : : }
2155 : :
2156 : 39 : SCCOL nMyCol = aPos.Col();
2157 : 39 : SCROW nMyRow = aPos.Row();
2158 : 39 : SCTAB nMyTab = aPos.Tab();
2159 : 39 : SCCOL nCol = 0;
2160 : 39 : SCROW nRow = 0;
2161 : : SCTAB nTab;
2162 : 39 : nTab = rRange.aStart.Tab();
2163 [ - + ][ - + ]: 39 : if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
[ + - ]
2164 : : {
2165 : 0 : nRow = rRange.aStart.Row();
2166 [ # # ]: 0 : if ( nRow == rRange.aEnd.Row() )
2167 : : {
2168 : 0 : bOk = true;
2169 : 0 : nCol = nMyCol;
2170 : : }
2171 [ # # ][ # # : 0 : else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
# # # # ]
[ # # ]
2172 : 0 : && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
2173 : : {
2174 : 0 : bOk = true;
2175 : 0 : nCol = nMyCol;
2176 : 0 : nRow = nMyRow;
2177 : : }
2178 : : }
2179 [ + - ][ + - ]: 39 : else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
[ + - ]
2180 : : {
2181 : 39 : nCol = rRange.aStart.Col();
2182 [ + - ]: 39 : if ( nCol == rRange.aEnd.Col() )
2183 : : {
2184 : 39 : bOk = true;
2185 : 39 : nRow = nMyRow;
2186 : : }
2187 [ # # ][ # # : 0 : else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
# # # # ]
[ # # ]
2188 : 0 : && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
2189 : : {
2190 : 0 : bOk = true;
2191 : 0 : nCol = nMyCol;
2192 : 0 : nRow = nMyRow;
2193 : : }
2194 : : }
2195 [ + - ]: 39 : if ( bOk )
2196 : : {
2197 [ - + ]: 39 : if ( nTab == rRange.aEnd.Tab() )
2198 : : ; // all done
2199 [ # # ][ # # ]: 0 : else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
[ # # ]
2200 : 0 : nTab = nMyTab;
2201 : : else
2202 : 0 : bOk = false;
2203 [ + - ]: 39 : if ( bOk )
2204 : 39 : rAdr.Set( nCol, nRow, nTab );
2205 : : }
2206 [ - + ]: 39 : if ( !bOk )
2207 : 0 : SetError( errNoValue );
2208 : 39 : return bOk;
2209 : : }
2210 : :
2211 : 0 : double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
2212 : : {
2213 [ # # ]: 0 : if (!pMat)
2214 : 0 : return 0.0;
2215 : :
2216 [ # # ]: 0 : if ( !pJumpMatrix )
2217 [ # # ]: 0 : return pMat->GetDouble( 0 );
2218 : :
2219 : : SCSIZE nCols, nRows, nC, nR;
2220 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2221 : 0 : pJumpMatrix->GetPos( nC, nR);
2222 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2223 [ # # ]: 0 : return pMat->GetDouble( nC, nR);
2224 : :
2225 : 0 : SetError( errNoValue);
2226 : 0 : return 0.0;
2227 : : }
2228 : :
2229 : 2652 : double ScInterpreter::GetDouble()
2230 : : {
2231 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDouble" );
2232 : 2652 : double nVal(0.0);
2233 [ + + + + : 2652 : switch( GetRawStackType() )
- - - - +
- ]
2234 : : {
2235 : : case svDouble:
2236 : 1284 : nVal = PopDouble();
2237 : 1284 : break;
2238 : : case svString:
2239 : 54 : nVal = ConvertStringToValue( PopString());
2240 : 54 : break;
2241 : : case svSingleRef:
2242 : : {
2243 : 1257 : ScAddress aAdr;
2244 [ + - ]: 1257 : PopSingleRef( aAdr );
2245 [ + - ]: 1257 : ScBaseCell* pCell = GetCell( aAdr );
2246 [ + - ]: 1257 : nVal = GetCellValue( aAdr, pCell );
2247 : : }
2248 : 1257 : break;
2249 : : case svDoubleRef:
2250 : : { // generate position dependent SingleRef
2251 : 39 : ScRange aRange;
2252 [ + - ]: 39 : PopDoubleRef( aRange );
2253 : 39 : ScAddress aAdr;
2254 [ + - ][ + - ]: 39 : if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
[ + - ][ + - ]
2255 : : {
2256 [ + - ]: 39 : ScBaseCell* pCell = GetCell( aAdr );
2257 [ + - ]: 39 : nVal = GetCellValue( aAdr, pCell );
2258 : : }
2259 : : else
2260 : 0 : nVal = 0.0;
2261 : : }
2262 : 39 : break;
2263 : : case svExternalSingleRef:
2264 : : {
2265 : 0 : ScExternalRefCache::TokenRef pToken;
2266 [ # # ]: 0 : PopExternalSingleRef(pToken);
2267 [ # # ][ # # ]: 0 : if (!nGlobalError && pToken)
[ # # ]
2268 [ # # ][ # # ]: 0 : nVal = pToken->GetDouble();
2269 : : }
2270 : 0 : break;
2271 : : case svExternalDoubleRef:
2272 : : {
2273 : 0 : ScMatrixRef pMat;
2274 [ # # ]: 0 : PopExternalDoubleRef(pMat);
2275 [ # # ]: 0 : if (nGlobalError)
2276 : : break;
2277 : :
2278 [ # # ][ # # ]: 0 : nVal = GetDoubleFromMatrix(pMat);
[ # # ]
2279 : : }
2280 : 0 : break;
2281 : : case svMatrix:
2282 : : {
2283 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2284 [ # # ][ # # ]: 0 : nVal = GetDoubleFromMatrix(pMat);
2285 : : }
2286 : 0 : break;
2287 : : case svError:
2288 : 0 : PopError();
2289 : 0 : nVal = 0.0;
2290 : 0 : break;
2291 : : case svEmptyCell:
2292 : : case svMissing:
2293 : 18 : Pop();
2294 : 18 : nVal = 0.0;
2295 : 18 : break;
2296 : : default:
2297 : 0 : PopError();
2298 : 0 : SetError( errIllegalParameter);
2299 : 0 : nVal = 0.0;
2300 : : }
2301 [ + + ]: 2652 : if ( nFuncFmtType == nCurFmtType )
2302 : 1723 : nFuncFmtIndex = nCurFmtIndex;
2303 : 2652 : return nVal;
2304 : : }
2305 : :
2306 : :
2307 : 12 : double ScInterpreter::GetDoubleWithDefault(double nDefault)
2308 : : {
2309 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDoubleWithDefault" );
2310 : 12 : bool bMissing = IsMissing();
2311 : 12 : double nResultVal = GetDouble();
2312 [ + + ]: 12 : if ( bMissing )
2313 : 3 : nResultVal = nDefault;
2314 : 12 : return nResultVal;
2315 : : }
2316 : :
2317 : :
2318 : 495 : const String& ScInterpreter::GetString()
2319 : : {
2320 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetString" );
2321 [ - - - + : 495 : switch (GetRawStackType())
+ - - - -
- ]
2322 : : {
2323 : : case svError:
2324 : 0 : PopError();
2325 : 0 : return EMPTY_STRING;
2326 : : case svMissing:
2327 : : case svEmptyCell:
2328 : 0 : Pop();
2329 : 0 : return EMPTY_STRING;
2330 : : case svDouble:
2331 : : {
2332 [ # # ]: 0 : double fVal = PopDouble();
2333 : : sal_uLong nIndex = pFormatter->GetStandardFormat(
2334 : : NUMBERFORMAT_NUMBER,
2335 [ # # ]: 0 : ScGlobal::eLnge);
2336 [ # # ]: 0 : pFormatter->GetInputLineString(fVal, nIndex, aTempStr);
2337 : 0 : return aTempStr;
2338 : : }
2339 : : case svString:
2340 : 198 : return PopString();
2341 : : case svSingleRef:
2342 : : {
2343 : 297 : ScAddress aAdr;
2344 [ + - ]: 297 : PopSingleRef( aAdr );
2345 [ + - ]: 297 : if (nGlobalError == 0)
2346 : : {
2347 [ + - ]: 297 : ScBaseCell* pCell = GetCell( aAdr );
2348 [ + - ]: 297 : GetCellString( aTempStr, pCell );
2349 : 297 : return aTempStr;
2350 : : }
2351 : : else
2352 [ # # ]: 297 : return EMPTY_STRING;
2353 : : }
2354 : : case svDoubleRef:
2355 : : { // generate position dependent SingleRef
2356 : 0 : ScRange aRange;
2357 [ # # ]: 0 : PopDoubleRef( aRange );
2358 : 0 : ScAddress aAdr;
2359 [ # # ][ # # ]: 0 : if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
[ # # ][ # # ]
2360 : : {
2361 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
2362 [ # # ]: 0 : GetCellString( aTempStr, pCell );
2363 : 0 : return aTempStr;
2364 : : }
2365 : : else
2366 [ # # ]: 0 : return EMPTY_STRING;
2367 : : }
2368 : : case svExternalSingleRef:
2369 : : {
2370 : 0 : ScExternalRefCache::TokenRef pToken;
2371 [ # # ]: 0 : PopExternalSingleRef(pToken);
2372 [ # # ][ # # ]: 0 : return nGlobalError ? EMPTY_STRING : pToken->GetString();
[ # # ][ # # ]
2373 : : }
2374 : : case svExternalDoubleRef:
2375 : : {
2376 : 0 : ScMatrixRef pMat;
2377 [ # # ]: 0 : PopExternalDoubleRef(pMat);
2378 [ # # ][ # # ]: 0 : return GetStringFromMatrix(pMat);
2379 : : }
2380 : : case svMatrix:
2381 : : {
2382 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2383 [ # # ][ # # ]: 0 : return GetStringFromMatrix(pMat);
2384 : : }
2385 : : break;
2386 : : default:
2387 : 0 : PopError();
2388 : 0 : SetError( errIllegalArgument);
2389 : : }
2390 : 495 : return EMPTY_STRING;
2391 : : }
2392 : :
2393 : 0 : const String& ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2394 : : {
2395 [ # # ]: 0 : if ( !pMat )
2396 : : ; // nothing
2397 [ # # ]: 0 : else if ( !pJumpMatrix )
2398 : : {
2399 [ # # ]: 0 : aTempStr = pMat->GetString( *pFormatter, 0, 0);
2400 : 0 : return aTempStr;
2401 : : }
2402 : : else
2403 : : {
2404 : : SCSIZE nCols, nRows, nC, nR;
2405 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2406 : 0 : pJumpMatrix->GetPos( nC, nR);
2407 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2408 : : {
2409 [ # # ][ # # ]: 0 : aTempStr = pMat->GetString( *pFormatter, nC, nR);
2410 : 0 : return aTempStr;
2411 : : }
2412 : : else
2413 : 0 : SetError( errNoValue);
2414 : : }
2415 : 0 : return EMPTY_STRING;
2416 : : }
2417 : :
2418 : 9 : ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
2419 : : String& rString )
2420 : : {
2421 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDoubleOrStringFromMatrix" );
2422 : :
2423 : 9 : rDouble = 0.0;
2424 [ + - ]: 9 : rString.Erase();
2425 : 9 : ScMatValType nMatValType = SC_MATVAL_EMPTY;
2426 : :
2427 : 9 : ScMatrixRef pMat;
2428 : 9 : StackVar eType = GetStackType();
2429 [ - + ][ # # ]: 9 : if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
[ + - ]
2430 : : {
2431 [ + - ][ + - ]: 9 : pMat = GetMatrix();
[ + - ]
2432 : : }
2433 : : else
2434 : : {
2435 [ # # ]: 0 : PopError();
2436 : 0 : SetError( errIllegalParameter);
2437 : 0 : return nMatValType;
2438 : : }
2439 : :
2440 : 9 : ScMatrixValue nMatVal;
2441 [ + - ]: 9 : if (!pMat)
2442 : : {
2443 : : // nothing
2444 : : }
2445 [ + - ]: 9 : else if (!pJumpMatrix)
2446 : : {
2447 [ + - ]: 9 : nMatVal = pMat->Get(0, 0);
2448 : 9 : nMatValType = nMatVal.nType;
2449 : : }
2450 : : else
2451 : : {
2452 : : SCSIZE nCols, nRows, nC, nR;
2453 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2454 : 0 : pJumpMatrix->GetPos( nC, nR);
2455 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2456 : : {
2457 [ # # ]: 0 : nMatVal = pMat->Get( nC, nR);
2458 : 0 : nMatValType = nMatVal.nType;
2459 : : }
2460 : : else
2461 : 0 : SetError( errNoValue);
2462 : : }
2463 : :
2464 [ + + ]: 9 : if (nMatValType == SC_MATVAL_VALUE)
2465 : 3 : rDouble = nMatVal.fVal;
2466 [ - + ]: 6 : else if (nMatValType == SC_MATVAL_BOOLEAN)
2467 : : {
2468 : 0 : rDouble = nMatVal.fVal;
2469 : 0 : nMatValType = SC_MATVAL_VALUE;
2470 : : }
2471 : : else
2472 [ + - ]: 6 : rString = nMatVal.GetString();
2473 : :
2474 [ + + ]: 9 : if (ScMatrix::IsValueType( nMatValType))
2475 : : {
2476 : 3 : sal_uInt16 nError = nMatVal.GetError();
2477 [ - + ]: 3 : if (nError)
2478 : 0 : SetError( nError);
2479 : : }
2480 : :
2481 [ + - ]: 9 : return nMatValType;
2482 : : }
2483 : :
2484 : :
2485 : 0 : void ScInterpreter::ScDBGet()
2486 : : {
2487 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBGet" );
2488 : 0 : bool bMissingField = false;
2489 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2490 [ # # ]: 0 : auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2491 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2492 [ # # ]: 0 : if (!pQueryParam.get())
2493 : : {
2494 : : // Failed to create query param.
2495 [ # # ]: 0 : PushIllegalParameter();
2496 : : return;
2497 : : }
2498 : :
2499 : 0 : pQueryParam->mbSkipString = false;
2500 [ # # ]: 0 : ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2501 [ # # ]: 0 : ScDBQueryDataIterator::Value aValue;
2502 [ # # ][ # # ]: 0 : if (!aValIter.GetFirst(aValue) || aValue.mnError)
[ # # ][ # # ]
2503 : : {
2504 : : // No match found.
2505 [ # # ]: 0 : PushNoValue();
2506 : : return;
2507 : : }
2508 : :
2509 [ # # ]: 0 : ScDBQueryDataIterator::Value aValNext;
2510 [ # # ][ # # ]: 0 : if (aValIter.GetNext(aValNext) && !aValNext.mnError)
[ # # ][ # # ]
2511 : : {
2512 : : // There should be only one unique match.
2513 [ # # ]: 0 : PushIllegalArgument();
2514 : : return;
2515 : : }
2516 : :
2517 [ # # ]: 0 : if (aValue.mbIsNumber)
2518 [ # # ]: 0 : PushDouble(aValue.mfValue);
2519 : : else
2520 [ # # ][ # # ]: 0 : PushString(aValue.maString);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2521 : : }
2522 : :
2523 : :
2524 : 0 : void ScInterpreter::ScExternal()
2525 : : {
2526 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExternal" );
2527 : 0 : sal_uInt8 nParamCount = GetByte();
2528 [ # # ]: 0 : String aUnoName;
2529 [ # # ][ # # ]: 0 : String aFuncName( ScGlobal::pCharClass->uppercase( pCur->GetExternal() ) );
[ # # ][ # # ]
2530 [ # # ][ # # ]: 0 : FuncData* pFuncData = ScGlobal::GetFuncCollection()->findByName(aFuncName);
[ # # ]
2531 [ # # ]: 0 : if (pFuncData)
2532 : : {
2533 [ # # ][ # # ]: 0 : if (nParamCount <= MAXFUNCPARAM && nParamCount == pFuncData->GetParamCount() - 1)
[ # # ]
2534 : : {
2535 : : ParamType eParamType[MAXFUNCPARAM];
2536 : : void* ppParam[MAXFUNCPARAM];
2537 : : double nVal[MAXFUNCPARAM];
2538 : : sal_Char* pStr[MAXFUNCPARAM];
2539 : : sal_uInt8* pCellArr[MAXFUNCPARAM];
2540 : : short i;
2541 : :
2542 [ # # ]: 0 : for (i = 0; i < MAXFUNCPARAM; i++)
2543 : : {
2544 : 0 : eParamType[i] = pFuncData->GetParamType(i);
2545 : 0 : ppParam[i] = NULL;
2546 : 0 : nVal[i] = 0.0;
2547 : 0 : pStr[i] = NULL;
2548 : 0 : pCellArr[i] = NULL;
2549 : : }
2550 : :
2551 [ # # ][ # # ]: 0 : for (i = nParamCount; (i > 0) && (nGlobalError == 0); i--)
[ # # ]
2552 : : {
2553 [ # # # # : 0 : switch (eParamType[i])
# # ]
2554 : : {
2555 : : case PTR_DOUBLE :
2556 : : {
2557 [ # # ]: 0 : nVal[i-1] = GetDouble();
2558 : 0 : ppParam[i] = &nVal[i-1];
2559 : : }
2560 : 0 : break;
2561 : : case PTR_STRING :
2562 : : {
2563 [ # # ]: 0 : rtl::OString aStr(rtl::OUStringToOString(GetString(),
2564 [ # # ][ # # ]: 0 : osl_getThreadTextEncoding()));
[ # # ]
2565 [ # # ]: 0 : if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2566 : 0 : SetError( errStringOverflow );
2567 : : else
2568 : : {
2569 [ # # ]: 0 : pStr[i-1] = new sal_Char[ADDIN_MAXSTRLEN];
2570 : 0 : strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2571 : 0 : pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2572 : 0 : ppParam[i] = pStr[i-1];
2573 : 0 : }
2574 : : }
2575 : 0 : break;
2576 : : case PTR_DOUBLE_ARR :
2577 : : {
2578 : : SCCOL nCol1;
2579 : : SCROW nRow1;
2580 : : SCTAB nTab1;
2581 : : SCCOL nCol2;
2582 : : SCROW nRow2;
2583 : : SCTAB nTab2;
2584 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2585 [ # # ]: 0 : pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2586 [ # # ][ # # ]: 0 : if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2587 : 0 : SetError(errCodeOverflow);
2588 : : else
2589 : 0 : ppParam[i] = pCellArr[i-1];
2590 : : }
2591 : 0 : break;
2592 : : case PTR_STRING_ARR :
2593 : : {
2594 : : SCCOL nCol1;
2595 : : SCROW nRow1;
2596 : : SCTAB nTab1;
2597 : : SCCOL nCol2;
2598 : : SCROW nRow2;
2599 : : SCTAB nTab2;
2600 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2601 [ # # ]: 0 : pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2602 [ # # ][ # # ]: 0 : if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2603 : 0 : SetError(errCodeOverflow);
2604 : : else
2605 : 0 : ppParam[i] = pCellArr[i-1];
2606 : : }
2607 : 0 : break;
2608 : : case PTR_CELL_ARR :
2609 : : {
2610 : : SCCOL nCol1;
2611 : : SCROW nRow1;
2612 : : SCTAB nTab1;
2613 : : SCCOL nCol2;
2614 : : SCROW nRow2;
2615 : : SCTAB nTab2;
2616 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2617 [ # # ]: 0 : pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2618 [ # # ][ # # ]: 0 : if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2619 : 0 : SetError(errCodeOverflow);
2620 : : else
2621 : 0 : ppParam[i] = pCellArr[i-1];
2622 : : }
2623 : 0 : break;
2624 : : default :
2625 : 0 : SetError(errIllegalParameter);
2626 : 0 : break;
2627 : : }
2628 : : }
2629 [ # # ]: 0 : while ( i-- )
2630 : 0 : Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
2631 : :
2632 [ # # ]: 0 : if (nGlobalError == 0)
2633 : : {
2634 [ # # ]: 0 : if ( pFuncData->GetAsyncType() == NONE )
2635 : : {
2636 [ # # # ]: 0 : switch ( eParamType[0] )
2637 : : {
2638 : : case PTR_DOUBLE :
2639 : : {
2640 : 0 : double nErg = 0.0;
2641 : 0 : ppParam[0] = &nErg;
2642 [ # # ]: 0 : pFuncData->Call(ppParam);
2643 [ # # ]: 0 : PushDouble(nErg);
2644 : : }
2645 : 0 : break;
2646 : : case PTR_STRING :
2647 : : {
2648 [ # # ]: 0 : sal_Char* pcErg = new sal_Char[ADDIN_MAXSTRLEN];
2649 : 0 : ppParam[0] = pcErg;
2650 [ # # ]: 0 : pFuncData->Call(ppParam);
2651 [ # # ][ # # ]: 0 : String aUni( pcErg, osl_getThreadTextEncoding() );
2652 [ # # ]: 0 : PushString( aUni );
2653 [ # # ][ # # ]: 0 : delete[] pcErg;
2654 : : }
2655 : 0 : break;
2656 : : default:
2657 [ # # ]: 0 : PushError( errUnknownState );
2658 : : }
2659 : : }
2660 : : else
2661 : : {
2662 : : // nach dem Laden Asyncs wieder anwerfen
2663 [ # # ]: 0 : if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
2664 : 0 : pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
2665 : : // garantiert identischer Handle bei identischem Aufruf?!?
2666 : : // sonst schei*e ...
2667 : 0 : double nErg = 0.0;
2668 : 0 : ppParam[0] = &nErg;
2669 [ # # ]: 0 : pFuncData->Call(ppParam);
2670 : 0 : sal_uLong nHandle = sal_uLong( nErg );
2671 [ # # ]: 0 : if ( nHandle >= 65536 )
2672 : : {
2673 [ # # ]: 0 : ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2674 [ # # ]: 0 : if ( !pAs )
2675 : : {
2676 [ # # ][ # # ]: 0 : pAs = new ScAddInAsync(nHandle, pFuncData, pDok);
2677 [ # # ]: 0 : pMyFormulaCell->StartListening( *pAs );
2678 : : }
2679 : : else
2680 : : {
2681 : : // falls per cut/copy/paste
2682 [ # # ]: 0 : pMyFormulaCell->StartListening( *pAs );
2683 : : // in anderes Dokument?
2684 [ # # ][ # # ]: 0 : if ( !pAs->HasDocument( pDok ) )
2685 [ # # ]: 0 : pAs->AddDocument( pDok );
2686 : : }
2687 [ # # ]: 0 : if ( pAs->IsValid() )
2688 : : {
2689 [ # # # ]: 0 : switch ( pAs->GetType() )
2690 : : {
2691 : : case PTR_DOUBLE :
2692 [ # # ]: 0 : PushDouble( pAs->GetValue() );
2693 : 0 : break;
2694 : : case PTR_STRING :
2695 [ # # ]: 0 : PushString( pAs->GetString() );
2696 : 0 : break;
2697 : : default:
2698 [ # # ]: 0 : PushError( errUnknownState );
2699 : : }
2700 : : }
2701 : : else
2702 [ # # ]: 0 : PushNA();
2703 : : }
2704 : : else
2705 [ # # ]: 0 : PushNoValue();
2706 : : }
2707 : : }
2708 : :
2709 [ # # ]: 0 : for (i = 0; i < MAXFUNCPARAM; i++)
2710 : : {
2711 [ # # ]: 0 : delete[] pStr[i];
2712 [ # # ]: 0 : delete[] pCellArr[i];
2713 : : }
2714 : : }
2715 : : else
2716 : : {
2717 [ # # ]: 0 : while( nParamCount-- > 0)
2718 : 0 : Pop();
2719 [ # # ]: 0 : PushIllegalParameter();
2720 : : }
2721 : : }
2722 [ # # ][ # # ]: 0 : else if ( ( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).Len() )
[ # # ][ # # ]
[ # # ]
2723 : : {
2724 : : // bLocalFirst=false in FindFunction, cFunc should be the stored
2725 : : // internal name
2726 : :
2727 [ # # ][ # # ]: 0 : ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
[ # # ]
2728 : :
2729 [ # # ][ # # ]: 0 : if ( !aCall.ValidParamCount() )
2730 : 0 : SetError( errIllegalParameter );
2731 : :
2732 [ # # ][ # # ]: 0 : if ( aCall.NeedsCaller() && !GetError() )
[ # # ][ # # ]
2733 : : {
2734 : 0 : SfxObjectShell* pShell = pDok->GetDocumentShell();
2735 [ # # ]: 0 : if (pShell)
2736 [ # # ]: 0 : aCall.SetCallerFromObjectShell( pShell );
2737 : : else
2738 : : {
2739 : : // use temporary model object (without document) to supply options
2740 : : aCall.SetCaller( static_cast<beans::XPropertySet*>(
2741 [ # # ][ # # ]: 0 : new ScDocOptionsObj( pDok->GetDocOptions() ) ) );
[ # # ][ # # ]
[ # # ]
2742 : : }
2743 : : }
2744 : :
2745 : 0 : short nPar = nParamCount;
2746 [ # # ][ # # ]: 0 : while ( nPar > 0 && !GetError() )
[ # # ]
2747 : : {
2748 : 0 : --nPar; // 0 .. (nParamCount-1)
2749 : :
2750 [ # # ]: 0 : ScAddInArgumentType eType = aCall.GetArgType( nPar );
2751 : 0 : sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
2752 : :
2753 : 0 : uno::Any aParam;
2754 [ # # # # : 0 : switch (eType)
# # # # #
# ]
2755 : : {
2756 : : case SC_ADDINARG_INTEGER:
2757 : : {
2758 [ # # ]: 0 : double fVal = GetDouble();
2759 : : double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2760 [ # # ]: 0 : ::rtl::math::approxCeil( fVal );
2761 [ # # ][ # # ]: 0 : if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2762 [ # # ]: 0 : aParam <<= (sal_Int32)fInt;
2763 : : else
2764 : 0 : SetError(errIllegalArgument);
2765 : : }
2766 : 0 : break;
2767 : :
2768 : : case SC_ADDINARG_DOUBLE:
2769 [ # # ][ # # ]: 0 : aParam <<= (double) GetDouble();
2770 : 0 : break;
2771 : :
2772 : : case SC_ADDINARG_STRING:
2773 [ # # ][ # # ]: 0 : aParam <<= rtl::OUString( GetString() );
[ # # ]
2774 : 0 : break;
2775 : :
2776 : : case SC_ADDINARG_INTEGER_ARRAY:
2777 [ # # # # ]: 0 : switch( nStackType )
2778 : : {
2779 : : case svDouble:
2780 : : case svString:
2781 : : case svSingleRef:
2782 : : {
2783 [ # # ]: 0 : double fVal = GetDouble();
2784 : : double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2785 [ # # ]: 0 : ::rtl::math::approxCeil( fVal );
2786 [ # # ][ # # ]: 0 : if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2787 : : {
2788 : 0 : sal_Int32 nIntVal = (long)fInt;
2789 [ # # ]: 0 : uno::Sequence<sal_Int32> aInner( &nIntVal, 1 );
2790 [ # # ]: 0 : uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2791 [ # # ][ # # ]: 0 : aParam <<= aOuter;
[ # # ]
2792 : : }
2793 : : else
2794 : 0 : SetError(errIllegalArgument);
2795 : : }
2796 : 0 : break;
2797 : : case svDoubleRef:
2798 : : {
2799 : 0 : ScRange aRange;
2800 [ # # ]: 0 : PopDoubleRef( aRange );
2801 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
2802 : 0 : SetError(errIllegalParameter);
2803 : : }
2804 : 0 : break;
2805 : : case svMatrix:
2806 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
[ # # ][ # # ]
2807 : 0 : SetError(errIllegalParameter);
2808 : 0 : break;
2809 : : default:
2810 [ # # ]: 0 : PopError();
2811 : 0 : SetError(errIllegalParameter);
2812 : : }
2813 : 0 : break;
2814 : :
2815 : : case SC_ADDINARG_DOUBLE_ARRAY:
2816 [ # # # # ]: 0 : switch( nStackType )
2817 : : {
2818 : : case svDouble:
2819 : : case svString:
2820 : : case svSingleRef:
2821 : : {
2822 [ # # ]: 0 : double fVal = GetDouble();
2823 [ # # ]: 0 : uno::Sequence<double> aInner( &fVal, 1 );
2824 [ # # ]: 0 : uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2825 [ # # ][ # # ]: 0 : aParam <<= aOuter;
[ # # ]
2826 : : }
2827 : 0 : break;
2828 : : case svDoubleRef:
2829 : : {
2830 : 0 : ScRange aRange;
2831 [ # # ]: 0 : PopDoubleRef( aRange );
2832 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
2833 : 0 : SetError(errIllegalParameter);
2834 : : }
2835 : 0 : break;
2836 : : case svMatrix:
2837 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
[ # # ][ # # ]
2838 : 0 : SetError(errIllegalParameter);
2839 : 0 : break;
2840 : : default:
2841 [ # # ]: 0 : PopError();
2842 : 0 : SetError(errIllegalParameter);
2843 : : }
2844 : 0 : break;
2845 : :
2846 : : case SC_ADDINARG_STRING_ARRAY:
2847 [ # # # # ]: 0 : switch( nStackType )
2848 : : {
2849 : : case svDouble:
2850 : : case svString:
2851 : : case svSingleRef:
2852 : : {
2853 [ # # ][ # # ]: 0 : rtl::OUString aString = rtl::OUString( GetString() );
2854 [ # # ]: 0 : uno::Sequence<rtl::OUString> aInner( &aString, 1 );
2855 [ # # ]: 0 : uno::Sequence< uno::Sequence<rtl::OUString> > aOuter( &aInner, 1 );
2856 [ # # ][ # # ]: 0 : aParam <<= aOuter;
[ # # ]
2857 : : }
2858 : 0 : break;
2859 : : case svDoubleRef:
2860 : : {
2861 : 0 : ScRange aRange;
2862 [ # # ]: 0 : PopDoubleRef( aRange );
2863 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
2864 : 0 : SetError(errIllegalParameter);
2865 : : }
2866 : 0 : break;
2867 : : case svMatrix:
2868 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter ))
[ # # ][ # # ]
2869 : 0 : SetError(errIllegalParameter);
2870 : 0 : break;
2871 : : default:
2872 [ # # ]: 0 : PopError();
2873 : 0 : SetError(errIllegalParameter);
2874 : : }
2875 : 0 : break;
2876 : :
2877 : : case SC_ADDINARG_MIXED_ARRAY:
2878 [ # # # # ]: 0 : switch( nStackType )
2879 : : {
2880 : : case svDouble:
2881 : : case svString:
2882 : : case svSingleRef:
2883 : : {
2884 : 0 : uno::Any aElem;
2885 [ # # ]: 0 : if ( nStackType == svDouble )
2886 [ # # ][ # # ]: 0 : aElem <<= (double) GetDouble();
2887 [ # # ]: 0 : else if ( nStackType == svString )
2888 [ # # ][ # # ]: 0 : aElem <<= rtl::OUString( GetString() );
[ # # ]
2889 : : else
2890 : : {
2891 : 0 : ScAddress aAdr;
2892 [ # # ][ # # ]: 0 : if ( PopDoubleRefOrSingleRef( aAdr ) )
2893 : : {
2894 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
2895 [ # # ][ # # ]: 0 : if ( pCell && pCell->HasStringData() )
[ # # ][ # # ]
2896 : : {
2897 [ # # ]: 0 : String aStr;
2898 [ # # ]: 0 : GetCellString( aStr, pCell );
2899 [ # # ][ # # ]: 0 : aElem <<= rtl::OUString( aStr );
[ # # ]
2900 : : }
2901 : : else
2902 [ # # ][ # # ]: 0 : aElem <<= (double) GetCellValue( aAdr, pCell );
2903 : : }
2904 : : }
2905 [ # # ]: 0 : uno::Sequence<uno::Any> aInner( &aElem, 1 );
2906 [ # # ]: 0 : uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2907 [ # # ][ # # ]: 0 : aParam <<= aOuter;
[ # # ]
2908 : : }
2909 : 0 : break;
2910 : : case svDoubleRef:
2911 : : {
2912 : 0 : ScRange aRange;
2913 [ # # ]: 0 : PopDoubleRef( aRange );
2914 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2915 : 0 : SetError(errIllegalParameter);
2916 : : }
2917 : 0 : break;
2918 : : case svMatrix:
2919 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
[ # # ][ # # ]
2920 : 0 : SetError(errIllegalParameter);
2921 : 0 : break;
2922 : : default:
2923 [ # # ]: 0 : PopError();
2924 : 0 : SetError(errIllegalParameter);
2925 : : }
2926 : 0 : break;
2927 : :
2928 : : case SC_ADDINARG_VALUE_OR_ARRAY:
2929 [ # # ]: 0 : if ( IsMissing() )
2930 : 0 : nStackType = svMissing;
2931 [ # # # # : 0 : switch( nStackType )
# # # ]
2932 : : {
2933 : : case svDouble:
2934 [ # # ][ # # ]: 0 : aParam <<= (double) GetDouble();
2935 : 0 : break;
2936 : : case svString:
2937 [ # # ][ # # ]: 0 : aParam <<= rtl::OUString( GetString() );
[ # # ]
2938 : 0 : break;
2939 : : case svSingleRef:
2940 : : {
2941 : 0 : ScAddress aAdr;
2942 [ # # ][ # # ]: 0 : if ( PopDoubleRefOrSingleRef( aAdr ) )
2943 : : {
2944 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
2945 [ # # ][ # # ]: 0 : if ( pCell && pCell->HasStringData() )
[ # # ][ # # ]
2946 : : {
2947 [ # # ]: 0 : String aStr;
2948 [ # # ]: 0 : GetCellString( aStr, pCell );
2949 [ # # ][ # # ]: 0 : aParam <<= rtl::OUString( aStr );
[ # # ]
2950 : : }
2951 : : else
2952 [ # # ][ # # ]: 0 : aParam <<= (double) GetCellValue( aAdr, pCell );
2953 : : }
2954 : : }
2955 : 0 : break;
2956 : : case svDoubleRef:
2957 : : {
2958 : 0 : ScRange aRange;
2959 [ # # ]: 0 : PopDoubleRef( aRange );
2960 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2961 : 0 : SetError(errIllegalParameter);
2962 : : }
2963 : 0 : break;
2964 : : case svMatrix:
2965 [ # # ][ # # ]: 0 : if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
[ # # ][ # # ]
2966 : 0 : SetError(errIllegalParameter);
2967 : 0 : break;
2968 : : case svMissing:
2969 : 0 : Pop();
2970 : 0 : aParam.clear();
2971 : 0 : break;
2972 : : default:
2973 [ # # ]: 0 : PopError();
2974 : 0 : SetError(errIllegalParameter);
2975 : : }
2976 : 0 : break;
2977 : :
2978 : : case SC_ADDINARG_CELLRANGE:
2979 [ # # # ]: 0 : switch( nStackType )
2980 : : {
2981 : : case svSingleRef:
2982 : : {
2983 : 0 : ScAddress aAdr;
2984 [ # # ]: 0 : PopSingleRef( aAdr );
2985 : 0 : ScRange aRange( aAdr );
2986 : : uno::Reference<table::XCellRange> xObj =
2987 [ # # ]: 0 : ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2988 [ # # ]: 0 : if (xObj.is())
2989 [ # # ]: 0 : aParam <<= xObj;
2990 : : else
2991 : 0 : SetError(errIllegalParameter);
2992 : : }
2993 : 0 : break;
2994 : : case svDoubleRef:
2995 : : {
2996 : 0 : ScRange aRange;
2997 [ # # ]: 0 : PopDoubleRef( aRange );
2998 : : uno::Reference<table::XCellRange> xObj =
2999 [ # # ]: 0 : ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
3000 [ # # ]: 0 : if (xObj.is())
3001 [ # # ]: 0 : aParam <<= xObj;
3002 : : else
3003 : 0 : SetError(errIllegalParameter);
3004 : : }
3005 : 0 : break;
3006 : : default:
3007 [ # # ]: 0 : PopError();
3008 : 0 : SetError(errIllegalParameter);
3009 : : }
3010 : 0 : break;
3011 : :
3012 : : default:
3013 [ # # ]: 0 : PopError();
3014 : 0 : SetError(errIllegalParameter);
3015 : : }
3016 [ # # ]: 0 : aCall.SetParam( nPar, aParam );
3017 : 0 : }
3018 : :
3019 [ # # ]: 0 : while (nPar-- > 0)
3020 : 0 : Pop(); // in case of error, remove remaining args
3021 : :
3022 [ # # ]: 0 : if ( !GetError() )
3023 : : {
3024 [ # # ]: 0 : aCall.ExecuteCall();
3025 : :
3026 [ # # ]: 0 : if ( aCall.HasVarRes() ) // handle async functions
3027 : : {
3028 [ # # ]: 0 : if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
3029 : 0 : pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
3030 : :
3031 [ # # ]: 0 : uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3032 [ # # ]: 0 : ScAddInListener* pLis = ScAddInListener::Get( xRes );
3033 [ # # ]: 0 : if ( !pLis )
3034 : : {
3035 [ # # ]: 0 : pLis = ScAddInListener::CreateListener( xRes, pDok );
3036 [ # # ]: 0 : pMyFormulaCell->StartListening( *pLis );
3037 : : }
3038 : : else
3039 : : {
3040 [ # # ]: 0 : pMyFormulaCell->StartListening( *pLis );
3041 [ # # ][ # # ]: 0 : if ( !pLis->HasDocument( pDok ) )
3042 [ # # ]: 0 : pLis->AddDocument( pDok );
3043 : : }
3044 : :
3045 [ # # ]: 0 : aCall.SetResult( pLis->GetResult() ); // use result from async
3046 : : }
3047 : :
3048 [ # # ]: 0 : if ( aCall.GetErrCode() )
3049 [ # # ]: 0 : PushError( aCall.GetErrCode() );
3050 [ # # ][ # # ]: 0 : else if ( aCall.HasMatrix() )
3051 : : {
3052 [ # # ]: 0 : ScMatrixRef xMat = aCall.GetMatrix();
3053 [ # # ][ # # ]: 0 : PushMatrix( xMat );
3054 : : }
3055 [ # # ]: 0 : else if ( aCall.HasString() )
3056 [ # # ][ # # ]: 0 : PushString( aCall.GetString() );
[ # # ]
3057 : : else
3058 [ # # ]: 0 : PushDouble( aCall.GetValue() );
3059 : : }
3060 : : else // error...
3061 [ # # ][ # # ]: 0 : PushError( GetError());
3062 : : }
3063 : : else
3064 : : {
3065 [ # # ]: 0 : while( nParamCount-- > 0)
3066 : 0 : Pop();
3067 [ # # ]: 0 : PushError( errNoAddin );
3068 [ # # ][ # # ]: 0 : }
3069 : 0 : }
3070 : :
3071 : :
3072 : 18 : void ScInterpreter::ScMissing()
3073 : : {
3074 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMissing" );
3075 [ + - ]: 18 : PushTempToken( new FormulaMissingToken );
3076 : 18 : }
3077 : :
3078 : : #ifndef DISABLE_SCRIPTING
3079 : :
3080 : 0 : uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, ScDocument* pDok )
3081 : : {
3082 [ # # ]: 0 : uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3083 [ # # ][ # # ]: 0 : uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
[ # # ]
3084 : 0 : rtl::OUString sCodeName;
3085 [ # # ][ # # ]: 0 : xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) ) >>= sCodeName;
[ # # ]
3086 : : // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3087 : : // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3088 : : // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3089 : : // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3090 : : // create the special document module objects if they don't exist.
3091 [ # # ]: 0 : BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3092 : :
3093 : 0 : uno::Reference< uno::XInterface > xIf;
3094 [ # # ][ # # ]: 0 : if ( pBasMgr && pBasMgr->GetName().Len() )
[ # # ][ # # ]
[ # # # # ]
[ # # ]
3095 : : {
3096 [ # # ]: 0 : String sProj = String( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
3097 [ # # ][ # # ]: 0 : if ( pDok->GetDocumentShell()->GetBasicManager()->GetName().Len() )
[ # # ][ # # ]
3098 [ # # ][ # # ]: 0 : sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
[ # # ][ # # ]
3099 [ # # ][ # # ]: 0 : StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3100 [ # # ]: 0 : if ( pBasic )
3101 : : {
3102 [ # # ][ # # ]: 0 : SbModule* pMod = pBasic->FindModule( sCodeName );
[ # # ]
3103 [ # # ]: 0 : if ( pMod )
3104 [ # # ][ # # ]: 0 : xIf = pMod->GetUnoModule();
3105 [ # # ]: 0 : }
3106 : : }
3107 [ # # ]: 0 : return uno::makeAny( xIf );
3108 : : }
3109 : :
3110 : : bool
3111 : 0 : lcl_setVBARange( ScRange& aRange, ScDocument* pDok, SbxVariable* pPar )
3112 : : {
3113 : 0 : bool bOk = false;
3114 : : try
3115 : : {
3116 : 0 : uno::Reference< uno::XInterface > xVBARange;
3117 [ # # ]: 0 : uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
3118 [ # # ]: 0 : uno::Sequence< uno::Any > aArgs(2);
3119 [ # # ][ # # ]: 0 : aArgs[0] = lcl_getSheetModule( xCellRange, pDok );
3120 [ # # ][ # # ]: 0 : aArgs[1] = uno::Any( xCellRange );
3121 [ # # ][ # # ]: 0 : xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
3122 [ # # ]: 0 : if ( xVBARange.is() )
3123 : : {
3124 [ # # ]: 0 : String sDummy(RTL_CONSTASCII_USTRINGPARAM("A-Range") );
3125 [ # # ][ # # ]: 0 : SbxObjectRef aObj = GetSbUnoObject( sDummy, uno::Any( xVBARange ) );
[ # # ]
3126 [ # # ]: 0 : SetSbUnoObjectDfltPropName( aObj );
3127 [ # # ][ # # ]: 0 : bOk = pPar->PutObject( aObj );
[ # # ]
3128 [ # # ][ # # ]: 0 : }
3129 : : }
3130 : 0 : catch( uno::Exception& )
3131 : : {
3132 : : }
3133 : 0 : return bOk;
3134 : : }
3135 : :
3136 : : #endif
3137 : :
3138 : 0 : void ScInterpreter::ScMacro()
3139 : : {
3140 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMacro" );
3141 : :
3142 : : #ifdef DISABLE_SCRIPTING
3143 : : PushNoValue(); // ohne DocShell kein CallBasic
3144 : : return;
3145 : : #else
3146 [ # # ]: 0 : SbxBase::ResetError();
3147 : :
3148 : 0 : sal_uInt8 nParamCount = GetByte();
3149 [ # # ][ # # ]: 0 : String aMacro( pCur->GetExternal() );
3150 : :
3151 : 0 : SfxObjectShell* pDocSh = pDok->GetDocumentShell();
3152 [ # # ][ # # ]: 0 : if ( !pDocSh || !pDok->CheckMacroWarn() )
[ # # ][ # # ]
3153 : : {
3154 [ # # ]: 0 : PushNoValue(); // ohne DocShell kein CallBasic
3155 : : return;
3156 : : }
3157 : :
3158 : : // keine Sicherheitsabfrage mehr vorneweg (nur CheckMacroWarn), das passiert im CallBasic
3159 : :
3160 : : // Wenn das Dok waehrend eines Basic-Calls geladen wurde,
3161 : : // ist das Sbx-Objekt evtl. nicht angelegt (?)
3162 : : // pDocSh->GetSbxObject();
3163 : :
3164 : : // Funktion ueber den einfachen Namen suchen,
3165 : : // dann aBasicStr, aMacroStr fuer SfxObjectShell::CallBasic zusammenbauen
3166 : :
3167 [ # # ]: 0 : StarBASIC* pRoot = pDocSh->GetBasic();
3168 [ # # ][ # # ]: 0 : SbxVariable* pVar = pRoot->Find( aMacro, SbxCLASS_METHOD );
3169 [ # # ][ # # ]: 0 : if( !pVar || pVar->GetType() == SbxVOID || !pVar->ISA(SbMethod) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
3170 : : {
3171 [ # # ]: 0 : PushError( errNoMacro );
3172 : : return;
3173 : : }
3174 : :
3175 : 0 : bool bVolatileMacro = false;
3176 : 0 : SbMethod* pMethod = (SbMethod*)pVar;
3177 : :
3178 : 0 : SbModule* pModule = pMethod->GetModule();
3179 [ # # ]: 0 : bool bUseVBAObjects = pModule->IsVBACompat();
3180 [ # # ]: 0 : SbxObject* pObject = pModule->GetParent();
3181 : : OSL_ENSURE(pObject->IsA(TYPE(StarBASIC)), "Kein Basic gefunden!");
3182 [ # # ][ # # ]: 0 : String aMacroStr = pObject->GetName();
3183 [ # # ]: 0 : aMacroStr += '.';
3184 [ # # ][ # # ]: 0 : aMacroStr += pModule->GetName();
3185 [ # # ]: 0 : aMacroStr += '.';
3186 [ # # ][ # # ]: 0 : aMacroStr += pMethod->GetName();
3187 [ # # ]: 0 : String aBasicStr;
3188 [ # # ][ # # ]: 0 : if (pObject->GetParent())
3189 [ # # ][ # # ]: 0 : aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
[ # # ]
3190 : : else
3191 [ # # ][ # # ]: 0 : aBasicStr = SFX_APP()->GetName(); // Applikationsbasic
[ # # ]
3192 : :
3193 : : // Parameter-Array zusammenbauen
3194 : :
3195 [ # # ][ # # ]: 0 : SbxArrayRef refPar = new SbxArray;
3196 : 0 : bool bOk = true;
3197 [ # # ][ # # ]: 0 : for( short i = nParamCount; i && bOk ; i-- )
[ # # ]
3198 : : {
3199 [ # # ]: 0 : SbxVariable* pPar = refPar->Get( (sal_uInt16) i );
3200 : 0 : sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
3201 [ # # # # : 0 : switch( nStackType )
# # ]
3202 : : {
3203 : : case svDouble:
3204 [ # # ][ # # ]: 0 : pPar->PutDouble( GetDouble() );
3205 : 0 : break;
3206 : : case svString:
3207 [ # # ][ # # ]: 0 : pPar->PutString( GetString() );
[ # # ]
3208 : 0 : break;
3209 : : case svSingleRef:
3210 : : {
3211 : 0 : ScAddress aAdr;
3212 [ # # ]: 0 : PopSingleRef( aAdr );
3213 [ # # ]: 0 : if ( bUseVBAObjects )
3214 : : {
3215 : 0 : ScRange aRange( aAdr );
3216 [ # # ]: 0 : bOk = lcl_setVBARange( aRange, pDok, pPar );
3217 : : }
3218 : : else
3219 [ # # ]: 0 : bOk = SetSbxVariable( pPar, aAdr );
3220 : : }
3221 : 0 : break;
3222 : : case svDoubleRef:
3223 : : {
3224 : : SCCOL nCol1;
3225 : : SCROW nRow1;
3226 : : SCTAB nTab1;
3227 : : SCCOL nCol2;
3228 : : SCROW nRow2;
3229 : : SCTAB nTab2;
3230 [ # # ]: 0 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3231 [ # # ]: 0 : if( nTab1 != nTab2 )
3232 : : {
3233 : 0 : SetError( errIllegalParameter );
3234 : 0 : bOk = false;
3235 : : }
3236 : : else
3237 : : {
3238 [ # # ]: 0 : if ( bUseVBAObjects )
3239 : : {
3240 : 0 : ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3241 [ # # ]: 0 : bOk = lcl_setVBARange( aRange, pDok, pPar );
3242 : : }
3243 : : else
3244 : : {
3245 [ # # ][ # # ]: 0 : SbxDimArrayRef refArray = new SbxDimArray;
3246 [ # # ]: 0 : refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
3247 [ # # ]: 0 : refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
3248 : 0 : ScAddress aAdr( nCol1, nRow1, nTab1 );
3249 [ # # ][ # # ]: 0 : for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
[ # # ]
3250 : : {
3251 : 0 : aAdr.SetRow( nRow );
3252 : : sal_Int32 nIdx[ 2 ];
3253 : 0 : nIdx[ 0 ] = nRow-nRow1+1;
3254 [ # # ][ # # ]: 0 : for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
[ # # ]
3255 : : {
3256 : 0 : aAdr.SetCol( nCol );
3257 : 0 : nIdx[ 1 ] = nCol-nCol1+1;
3258 [ # # ]: 0 : SbxVariable* p = refArray->Get32( nIdx );
3259 [ # # ]: 0 : bOk = SetSbxVariable( p, aAdr );
3260 : : }
3261 : : }
3262 [ # # ][ # # ]: 0 : pPar->PutObject( refArray );
3263 : : }
3264 : : }
3265 : : }
3266 : 0 : break;
3267 : : case svMatrix:
3268 : : {
3269 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
3270 : : SCSIZE nC, nR;
3271 [ # # ]: 0 : if (pMat)
3272 : : {
3273 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
3274 [ # # ][ # # ]: 0 : SbxDimArrayRef refArray = new SbxDimArray;
3275 [ # # ]: 0 : refArray->AddDim32( 1, static_cast<sal_Int32>(nR) );
3276 [ # # ]: 0 : refArray->AddDim32( 1, static_cast<sal_Int32>(nC) );
3277 [ # # ]: 0 : for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3278 : : {
3279 : : sal_Int32 nIdx[ 2 ];
3280 : 0 : nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3281 [ # # ]: 0 : for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3282 : : {
3283 : 0 : nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3284 [ # # ]: 0 : SbxVariable* p = refArray->Get32( nIdx );
3285 [ # # ][ # # ]: 0 : if (pMat->IsString(nMatCol, nMatRow))
3286 [ # # ][ # # ]: 0 : p->PutString( pMat->GetString(nMatCol, nMatRow) );
3287 : : else
3288 [ # # ][ # # ]: 0 : p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3289 : : }
3290 : : }
3291 [ # # ][ # # ]: 0 : pPar->PutObject( refArray );
3292 : : }
3293 : : else
3294 [ # # ]: 0 : SetError( errIllegalParameter );
3295 : : }
3296 : 0 : break;
3297 : : default:
3298 : 0 : SetError( errIllegalParameter );
3299 : 0 : bOk = false;
3300 : : }
3301 : : }
3302 [ # # ]: 0 : if( bOk )
3303 : : {
3304 [ # # ]: 0 : pDok->LockTable( aPos.Tab() );
3305 [ # # ][ # # ]: 0 : SbxVariableRef refRes = new SbxVariable;
3306 : 0 : pDok->IncMacroInterpretLevel();
3307 [ # # ]: 0 : ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar, refRes );
3308 : 0 : pDok->DecMacroInterpretLevel();
3309 [ # # ]: 0 : pDok->UnlockTable( aPos.Tab() );
3310 : :
3311 [ # # ]: 0 : ScMacroManager* pMacroMgr = pDok->GetMacroManager();
3312 [ # # ]: 0 : if (pMacroMgr)
3313 : : {
3314 [ # # ][ # # ]: 0 : bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
[ # # ]
3315 [ # # ][ # # ]: 0 : pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
[ # # ]
3316 : : }
3317 : :
3318 [ # # ]: 0 : SbxDataType eResType = refRes->GetType();
3319 [ # # ][ # # ]: 0 : if( pVar->GetError() )
3320 : 0 : SetError( errNoValue);
3321 [ # # ]: 0 : if ( eRet != ERRCODE_NONE )
3322 [ # # ]: 0 : PushNoValue();
3323 [ # # ][ # # ]: 0 : else if( eResType >= SbxINTEGER && eResType <= SbxDOUBLE )
3324 [ # # ][ # # ]: 0 : PushDouble( refRes->GetDouble() );
3325 [ # # ]: 0 : else if ( eResType & SbxARRAY )
3326 : : {
3327 [ # # ]: 0 : SbxBase* pElemObj = refRes->GetObject();
3328 [ # # ][ # # ]: 0 : SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
[ # # ][ # # ]
3329 [ # # ]: 0 : short nDim = pDimArray->GetDims();
3330 [ # # ][ # # ]: 0 : if ( 1 <= nDim && nDim <= 2 )
3331 : : {
3332 : : sal_Int32 nCs, nCe, nRs, nRe;
3333 : : SCSIZE nC, nR;
3334 : : SCCOL nColIdx;
3335 : : SCROW nRowIdx;
3336 [ # # ]: 0 : if ( nDim == 1 )
3337 : : { // array( cols ) eine Zeile, mehrere Spalten
3338 [ # # ]: 0 : pDimArray->GetDim32( 1, nCs, nCe );
3339 : 0 : nC = static_cast<SCSIZE>(nCe - nCs + 1);
3340 : 0 : nRs = nRe = 0;
3341 : 0 : nR = 1;
3342 : 0 : nColIdx = 0;
3343 : 0 : nRowIdx = 1;
3344 : : }
3345 : : else
3346 : : { // array( rows, cols )
3347 [ # # ]: 0 : pDimArray->GetDim32( 1, nRs, nRe );
3348 : 0 : nR = static_cast<SCSIZE>(nRe - nRs + 1);
3349 [ # # ]: 0 : pDimArray->GetDim32( 2, nCs, nCe );
3350 : 0 : nC = static_cast<SCSIZE>(nCe - nCs + 1);
3351 : 0 : nColIdx = 1;
3352 : 0 : nRowIdx = 0;
3353 : : }
3354 [ # # ]: 0 : ScMatrixRef pMat = GetNewMat( nC, nR);
3355 [ # # ]: 0 : if ( pMat )
3356 : : {
3357 : : SbxVariable* pV;
3358 : : SbxDataType eType;
3359 [ # # ]: 0 : for ( SCSIZE j=0; j < nR; j++ )
3360 : : {
3361 : : sal_Int32 nIdx[ 2 ];
3362 : : // bei eindimensionalem array( cols ) wird nIdx[1]
3363 : : // von SbxDimArray::Get ignoriert
3364 : 0 : nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3365 [ # # ]: 0 : for ( SCSIZE i=0; i < nC; i++ )
3366 : : {
3367 : 0 : nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3368 [ # # ]: 0 : pV = pDimArray->Get32( nIdx );
3369 [ # # ]: 0 : eType = pV->GetType();
3370 [ # # ][ # # ]: 0 : if ( eType >= SbxINTEGER && eType <= SbxDOUBLE )
3371 [ # # ][ # # ]: 0 : pMat->PutDouble( pV->GetDouble(), i, j );
3372 : : else
3373 [ # # ][ # # ]: 0 : pMat->PutString( pV->GetString(), i, j );
[ # # ]
3374 : : }
3375 : : }
3376 [ # # ]: 0 : PushMatrix( pMat );
3377 : : }
3378 : : else
3379 [ # # ][ # # ]: 0 : PushIllegalArgument();
3380 : : }
3381 : : else
3382 [ # # ]: 0 : PushNoValue();
3383 : : }
3384 : : else
3385 [ # # ][ # # ]: 0 : PushString( refRes->GetString() );
[ # # ]
3386 : : }
3387 : :
3388 [ # # ][ # # ]: 0 : if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3389 [ # # ][ # # ]: 0 : meVolatileType = VOLATILE_MACRO;
[ # # ][ # # ]
[ # # ]
3390 : : #endif
3391 : : }
3392 : :
3393 : : #ifndef DISABLE_SCRIPTING
3394 : :
3395 : 0 : bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3396 : : {
3397 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::SetSbxVariable" );
3398 : 0 : bool bOk = true;
3399 : 0 : ScBaseCell* pCell = pDok->GetCell( rPos );
3400 [ # # ]: 0 : if (pCell)
3401 : : {
3402 : : sal_uInt16 nErr;
3403 : : double nVal;
3404 [ # # # # : 0 : switch( pCell->GetCellType() )
# ]
3405 : : {
3406 : : case CELLTYPE_VALUE :
3407 : 0 : nVal = GetValueCellValue( rPos, (ScValueCell*)pCell );
3408 : 0 : pVar->PutDouble( nVal );
3409 : 0 : break;
3410 : : case CELLTYPE_STRING :
3411 : : {
3412 : 0 : rtl::OUString aVal = ((ScStringCell*)pCell)->GetString();
3413 [ # # ]: 0 : pVar->PutString( aVal );
3414 : 0 : break;
3415 : : }
3416 : : case CELLTYPE_EDIT :
3417 : : {
3418 [ # # ]: 0 : rtl::OUString aVal = ((ScEditCell*) pCell)->GetString();
3419 [ # # ]: 0 : pVar->PutString( aVal );
3420 : 0 : break;
3421 : : }
3422 : : case CELLTYPE_FORMULA :
3423 [ # # ]: 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
3424 [ # # ]: 0 : if( !nErr )
3425 : : {
3426 [ # # ][ # # ]: 0 : if( ((ScFormulaCell*)pCell)->IsValue() )
3427 : : {
3428 [ # # ]: 0 : nVal = ((ScFormulaCell*)pCell)->GetValue();
3429 : 0 : pVar->PutDouble( nVal );
3430 : : }
3431 : : else
3432 : : {
3433 [ # # ][ # # ]: 0 : rtl::OUString aVal = ((ScFormulaCell*)pCell)->GetString();
3434 [ # # ]: 0 : pVar->PutString( aVal );
3435 : : }
3436 : : }
3437 : : else
3438 : 0 : SetError( nErr ), bOk = false;
3439 : 0 : break;
3440 : : default :
3441 : 0 : pVar->PutDouble( 0.0 );
3442 : : }
3443 : : }
3444 : : else
3445 : 0 : pVar->PutDouble( 0.0 );
3446 : 0 : return bOk;
3447 : : }
3448 : :
3449 : : #endif
3450 : :
3451 : : namespace {
3452 : :
3453 : : class FindByPointer : ::std::unary_function<ScInterpreterTableOpParams, bool>
3454 : : {
3455 : : const ScInterpreterTableOpParams* mpTableOp;
3456 : : public:
3457 : 89 : FindByPointer(const ScInterpreterTableOpParams* p) : mpTableOp(p) {}
3458 : 89 : bool operator() (const ScInterpreterTableOpParams& val) const
3459 : : {
3460 : 89 : return &val == mpTableOp;
3461 : : }
3462 : : };
3463 : :
3464 : : }
3465 : :
3466 : 89 : void ScInterpreter::ScTableOp()
3467 : : {
3468 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTableOp" );
3469 : 89 : sal_uInt8 nParamCount = GetByte();
3470 [ - + ][ + + ]: 89 : if (nParamCount != 3 && nParamCount != 5)
3471 : : {
3472 [ # # ]: 0 : PushIllegalParameter();
3473 : 89 : return;
3474 : : }
3475 [ + - ][ + - ]: 89 : ScInterpreterTableOpParams* pTableOp = new ScInterpreterTableOpParams;
3476 [ + + ]: 89 : if (nParamCount == 5)
3477 : : {
3478 [ + - ]: 21 : PopSingleRef( pTableOp->aNew2 );
3479 [ + - ]: 21 : PopSingleRef( pTableOp->aOld2 );
3480 : : }
3481 [ + - ]: 89 : PopSingleRef( pTableOp->aNew1 );
3482 [ + - ]: 89 : PopSingleRef( pTableOp->aOld1 );
3483 [ + - ]: 89 : PopSingleRef( pTableOp->aFormulaPos );
3484 : :
3485 : 89 : pTableOp->bValid = true;
3486 [ + - ]: 89 : pDok->aTableOpList.push_back( pTableOp );
3487 : 89 : pDok->IncInterpreterTableOpLevel();
3488 : :
3489 : 89 : bool bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp);
3490 [ + + ]: 89 : if ( bReuseLastParams )
3491 : : {
3492 [ + - ]: 31 : pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos;
3493 : 31 : pTableOp->bRefresh = true;
3494 [ + - ][ + + ]: 724 : for ( ::std::vector< ScAddress >::const_iterator iBroadcast(
3495 [ + - ]: 31 : pTableOp->aNotifiedFormulaPos.begin() );
3496 : 362 : iBroadcast != pTableOp->aNotifiedFormulaPos.end();
3497 : : ++iBroadcast )
3498 : : { // emulate broadcast and indirectly collect cell pointers
3499 [ + - ]: 331 : ScBaseCell* pCell = pDok->GetCell( *iBroadcast );
3500 [ + - ][ + - ]: 331 : if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
[ + - ]
3501 [ + - ][ + - ]: 331 : ((ScFormulaCell*)pCell)->SetTableOpDirty();
3502 : : }
3503 : : }
3504 : : else
3505 : : { // broadcast and indirectly collect cell pointers and positions
3506 [ + - ]: 58 : pDok->SetTableOpDirty( pTableOp->aOld1 );
3507 [ + + ]: 58 : if ( nParamCount == 5 )
3508 [ + - ]: 2 : pDok->SetTableOpDirty( pTableOp->aOld2 );
3509 : : }
3510 : 89 : pTableOp->bCollectNotifications = false;
3511 : :
3512 [ + - ]: 89 : ScBaseCell* pFCell = pDok->GetCell( pTableOp->aFormulaPos );
3513 [ + - ][ + + ]: 89 : if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
[ + + ]
3514 [ + - ][ + - ]: 55 : ((ScFormulaCell*)pFCell)->SetDirtyVar();
3515 [ + - ][ + + ]: 89 : if ( HasCellValueData( pFCell ) )
3516 [ + - ][ + - ]: 55 : PushDouble( GetCellValue( pTableOp->aFormulaPos, pFCell ));
3517 : : else
3518 : : {
3519 [ + - ]: 34 : String aCellString;
3520 [ + - ]: 34 : GetCellString( aCellString, pFCell );
3521 [ + - ][ + - ]: 34 : PushString( aCellString );
3522 : : }
3523 : :
3524 : : boost::ptr_vector< ScInterpreterTableOpParams >::iterator itr =
3525 [ + - ][ + - ]: 89 : ::std::find_if(pDok->aTableOpList.begin(), pDok->aTableOpList.end(), FindByPointer(pTableOp));
[ + - ]
3526 [ + - ][ + - ]: 89 : if (itr != pDok->aTableOpList.end())
[ + - ]
3527 [ + - ][ + - ]: 89 : pTableOp = pDok->aTableOpList.release(itr).release();
[ + - ]
3528 : :
3529 : : // set dirty again once more to be able to recalculate original
3530 [ + - + - ]: 1926 : for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast(
[ + + ]
3531 [ + - ]: 89 : pTableOp->aNotifiedFormulaCells.begin() );
3532 : 963 : iBroadcast != pTableOp->aNotifiedFormulaCells.end();
3533 : : ++iBroadcast )
3534 : : {
3535 [ + - ][ + - ]: 874 : (*iBroadcast)->SetTableOpDirty();
3536 : : }
3537 : :
3538 : : // save these params for next incarnation
3539 [ + + ]: 89 : if ( !bReuseLastParams )
3540 [ + - ]: 58 : pDok->aLastTableOpParams = *pTableOp;
3541 : :
3542 [ + - ][ + + ]: 89 : if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
[ + + ]
3543 : : {
3544 [ + - ][ + - ]: 55 : ((ScFormulaCell*)pFCell)->SetDirtyVar();
3545 [ + - ][ + - ]: 55 : ((ScFormulaCell*)pFCell)->GetErrCode(); // recalculate original
3546 : : }
3547 : :
3548 : : // Reset all dirty flags so next incarnation does really collect all cell
3549 : : // pointers during notifications and not just non-dirty ones, which may
3550 : : // happen if a formula cell is used by more than one TableOp block.
3551 [ + - + - ]: 1926 : for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast2(
[ + + ]
3552 [ + - ]: 89 : pTableOp->aNotifiedFormulaCells.begin() );
3553 : 963 : iBroadcast2 != pTableOp->aNotifiedFormulaCells.end();
3554 : : ++iBroadcast2 )
3555 : : {
3556 [ + - ]: 874 : (*iBroadcast2)->ResetTableOpDirtyVar();
3557 : : }
3558 [ + - ]: 89 : delete pTableOp;
3559 : :
3560 : 89 : pDok->DecInterpreterTableOpLevel();
3561 : : }
3562 : :
3563 : 0 : void ScInterpreter::ScDBArea()
3564 : : {
3565 : 0 : ScDBData* pDBData = pDok->GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3566 [ # # ]: 0 : if (pDBData)
3567 : : {
3568 : : ScComplexRefData aRefData;
3569 : 0 : aRefData.InitFlags();
3570 : : pDBData->GetArea( (SCTAB&) aRefData.Ref1.nTab,
3571 : : (SCCOL&) aRefData.Ref1.nCol,
3572 : : (SCROW&) aRefData.Ref1.nRow,
3573 : : (SCCOL&) aRefData.Ref2.nCol,
3574 [ # # ]: 0 : (SCROW&) aRefData.Ref2.nRow);
3575 : 0 : aRefData.Ref2.nTab = aRefData.Ref1.nTab;
3576 [ # # ]: 0 : aRefData.CalcRelFromAbs( aPos );
3577 [ # # ][ # # ]: 0 : PushTempToken( new ScDoubleRefToken( aRefData ) );
[ # # ]
3578 : : }
3579 : : else
3580 : 0 : PushError( errNoName);
3581 : 0 : }
3582 : :
3583 : :
3584 : 0 : void ScInterpreter::ScColRowNameAuto()
3585 : : {
3586 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColRowNameAuto" );
3587 [ # # ]: 0 : ScComplexRefData aRefData( static_cast<const ScToken*>(pCur)->GetDoubleRef() );
3588 [ # # ]: 0 : aRefData.CalcAbsIfRel( aPos );
3589 [ # # ]: 0 : if ( aRefData.Valid() )
3590 : : {
3591 : : SCsCOL nStartCol;
3592 : : SCsROW nStartRow;
3593 : : SCsCOL nCol2;
3594 : : SCsROW nRow2;
3595 : : // evtl. Begrenzung durch definierte ColRowNameRanges merken
3596 : 0 : nCol2 = aRefData.Ref2.nCol;
3597 : 0 : nRow2 = aRefData.Ref2.nRow;
3598 : : // DataArea der ersten Zelle
3599 : 0 : nStartCol = aRefData.Ref2.nCol = aRefData.Ref1.nCol;
3600 : 0 : nStartRow = aRefData.Ref2.nRow = aRefData.Ref1.nRow;
3601 : 0 : aRefData.Ref2.nTab = aRefData.Ref1.nTab;
3602 : : pDok->GetDataArea( (SCTAB&) aRefData.Ref1.nTab,
3603 : : (SCCOL&) aRefData.Ref1.nCol,
3604 : : (SCROW&) aRefData.Ref1.nRow,
3605 : : (SCCOL&) aRefData.Ref2.nCol,
3606 : : (SCROW&) aRefData.Ref2.nRow,
3607 [ # # ]: 0 : true, false );
3608 : : // DataArea im Ursprung begrenzen
3609 : 0 : aRefData.Ref1.nCol = nStartCol;
3610 : 0 : aRefData.Ref1.nRow = nStartRow;
3611 : :
3612 : : //! korrespondiert mit ScCompiler::GetToken
3613 [ # # ]: 0 : if ( aRefData.Ref1.IsColRel() )
3614 : : { // ColName
3615 : 0 : aRefData.Ref2.nCol = nStartCol;
3616 : : // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3617 [ # # ]: 0 : if ( aRefData.Ref2.nRow > nRow2 )
3618 : 0 : aRefData.Ref2.nRow = nRow2;
3619 : : SCROW nMyRow;
3620 [ # # ][ # # ]: 0 : if ( aPos.Col() == nStartCol
[ # # ][ # # ]
3621 : 0 : && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aRefData.Ref2.nRow )
3622 : : { // Formel in gleicher Spalte und innerhalb des Range
3623 [ # # ]: 0 : if ( nMyRow == nStartRow )
3624 : : { // direkt unter dem Namen den Rest nehmen
3625 : 0 : nStartRow++;
3626 [ # # ]: 0 : if ( nStartRow > MAXROW )
3627 : 0 : nStartRow = MAXROW;
3628 : 0 : aRefData.Ref1.nRow = nStartRow;
3629 : : }
3630 : : else
3631 : : { // weiter unten vom Namen bis zur Formelzelle
3632 : 0 : aRefData.Ref2.nRow = nMyRow - 1;
3633 : : }
3634 : : }
3635 : : }
3636 : : else
3637 : : { // RowName
3638 : 0 : aRefData.Ref2.nRow = nStartRow;
3639 : : // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3640 [ # # ]: 0 : if ( aRefData.Ref2.nCol > nCol2 )
3641 : 0 : aRefData.Ref2.nCol = nCol2;
3642 : : SCCOL nMyCol;
3643 [ # # ][ # # ]: 0 : if ( aPos.Row() == nStartRow
[ # # ][ # # ]
3644 : 0 : && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aRefData.Ref2.nCol )
3645 : : { // Formel in gleicher Zeile und innerhalb des Range
3646 [ # # ]: 0 : if ( nMyCol == nStartCol )
3647 : : { // direkt neben dem Namen den Rest nehmen
3648 : 0 : nStartCol++;
3649 [ # # ]: 0 : if ( nStartCol > MAXCOL )
3650 : 0 : nStartCol = MAXCOL;
3651 : 0 : aRefData.Ref1.nCol = nStartCol;
3652 : : }
3653 : : else
3654 : : { // weiter rechts vom Namen bis zur Formelzelle
3655 : 0 : aRefData.Ref2.nCol = nMyCol - 1;
3656 : : }
3657 : : }
3658 : : }
3659 [ # # ]: 0 : aRefData.CalcRelFromAbs( aPos );
3660 [ # # ][ # # ]: 0 : PushTempToken( new ScDoubleRefToken( aRefData ) );
[ # # ]
3661 : : }
3662 : : else
3663 [ # # ]: 0 : PushError( errNoRef );
3664 : 0 : }
3665 : :
3666 : : // --- internals ------------------------------------------------------------
3667 : :
3668 : :
3669 : 0 : void ScInterpreter::ScTTT()
3670 : : { // Temporaerer Test-Tanz, zum auspropieren von Funktionen etc.
3671 : 0 : sal_uInt8 nParamCount = GetByte();
3672 : : // do something, nParamCount bei Pops runterzaehlen!
3673 : :
3674 : : // Stack aufraeumen
3675 [ # # ]: 0 : while ( nParamCount-- > 0)
3676 : 0 : Pop();
3677 : 0 : PushError(errNoValue);
3678 : 0 : }
3679 : :
3680 : : // -------------------------------------------------------------------------
3681 : :
3682 : :
3683 : 2619 : ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
3684 : : const ScAddress& rPos, ScTokenArray& r ) :
3685 : : aCode( r ),
3686 : : aPos( rPos ),
3687 : : rArr( r ),
3688 : : pDok( pDoc ),
3689 : : pTokenMatrixMap( NULL ),
3690 : : pMyFormulaCell( pCell ),
3691 [ + - ]: 2619 : pFormatter( pDoc->GetFormatTable() ),
3692 : : mnStringNoValueError( errNoValue),
3693 [ + - ]: 2619 : bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ),
3694 [ + - + + ]: 7857 : meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3695 : : {
3696 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTTT" );
3697 : :
3698 : 2619 : sal_uInt8 cMatFlag = pMyFormulaCell->GetMatrixFlag();
3699 [ - + ][ + + ]: 2619 : bMatrixFormula = ( cMatFlag == MM_FORMULA || cMatFlag == MM_FAKE );
3700 [ + + ]: 2619 : if (!bGlobalStackInUse)
3701 : : {
3702 : 2293 : bGlobalStackInUse = true;
3703 [ + + ]: 2293 : if (!pGlobalStack)
3704 [ + - ]: 16 : pGlobalStack = new ScTokenStack;
3705 : 2293 : pStackObj = pGlobalStack;
3706 : : }
3707 : : else
3708 : : {
3709 [ + - ]: 326 : pStackObj = new ScTokenStack;
3710 : : }
3711 : 2619 : pStack = pStackObj->pPointer;
3712 : 2619 : }
3713 : :
3714 [ + - ][ + - ]: 2619 : ScInterpreter::~ScInterpreter()
3715 : : {
3716 : : // delete pStack;
3717 : :
3718 [ + + ]: 2619 : if ( pStackObj == pGlobalStack )
3719 : 2293 : bGlobalStackInUse = false;
3720 : : else
3721 [ + - ]: 326 : delete pStackObj;
3722 [ + + ]: 2619 : if (pTokenMatrixMap)
3723 [ + - ]: 36 : delete pTokenMatrixMap;
3724 : 2619 : }
3725 : :
3726 : 427 : void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3727 : : {
3728 : 427 : maGlobalConfig = rConfig;
3729 : 427 : }
3730 : :
3731 : 162 : const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3732 : : {
3733 : 162 : return maGlobalConfig;
3734 : : }
3735 : :
3736 : 18 : void ScInterpreter::GlobalExit()
3737 : : {
3738 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GlobalExit" );
3739 : : OSL_ENSURE(!bGlobalStackInUse, "wer benutzt noch den TokenStack?");
3740 : 18 : DELETEZ(pGlobalStack);
3741 : 18 : }
3742 : :
3743 : :
3744 : 2619 : StackVar ScInterpreter::Interpret()
3745 : : {
3746 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Interpret" );
3747 : 2619 : short nRetTypeExpr = NUMBERFORMAT_UNDEFINED;
3748 : 2619 : sal_uLong nRetIndexExpr = 0;
3749 : 2619 : sal_uInt16 nErrorFunction = 0;
3750 : 2619 : sal_uInt16 nErrorFunctionCount = 0;
3751 : : sal_uInt16 nStackBase;
3752 : :
3753 : 2619 : nGlobalError = 0;
3754 : 2619 : nStackBase = sp = maxsp = 0;
3755 : 2619 : nRetFmtType = NUMBERFORMAT_UNDEFINED;
3756 : 2619 : nFuncFmtType = NUMBERFORMAT_UNDEFINED;
3757 : 2619 : nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3758 [ + - ]: 2619 : xResult = NULL;
3759 : 2619 : pJumpMatrix = NULL;
3760 : 2619 : glSubTotal = false;
3761 : 2619 : ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3762 : :
3763 : : // Once upon a time we used to have FP exceptions on, and there was a
3764 : : // Windows printer driver that kept switching off exceptions, so we had to
3765 : : // switch them back on again every time. Who knows if there isn't a driver
3766 : : // that keeps switching exceptions on, now that we run with exceptions off,
3767 : : // so reassure exceptions are really off.
3768 : : SAL_MATH_FPEXCEPTIONS_OFF();
3769 : :
3770 [ + - ]: 2619 : aCode.Reset();
3771 [ + - ][ + + ]: 9938 : while( ( pCur = aCode.Next() ) != NULL
[ + + ][ + + ]
[ + + ]
3772 : 7325 : && (!nGlobalError || nErrorFunction <= nErrorFunctionCount) )
3773 : : {
3774 : 7319 : OpCode eOp = pCur->GetOpCode();
3775 [ + - ]: 7319 : cPar = pCur->GetByte();
3776 [ + + ]: 7319 : if ( eOp == ocPush )
3777 : : {
3778 : : // RPN code push without error
3779 [ + - ]: 4443 : PushWithoutError( (FormulaToken&) *pCur );
3780 : : }
3781 [ + + ][ + + ]: 5824 : else if (pTokenMatrixMap && !(eOp == ocIf || eOp == ocChose) &&
[ + - - +
# # ][ - + ]
3782 [ + + ][ + - ]: 2948 : ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
[ # # ]
3783 [ + - ][ + + ]: 5896 : pTokenMatrixMap->end()) &&
[ + + ][ + + ]
[ + + ][ # #
# # # # #
# ]
3784 : 0 : (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3785 : : {
3786 : : // Path already calculated, reuse result.
3787 [ # # ]: 0 : nStackBase = sp - pCur->GetParamCount();
3788 [ # # ]: 0 : if ( nStackBase > sp )
3789 : 0 : nStackBase = sp; // underflow?!?
3790 : 0 : sp = nStackBase;
3791 [ # # ]: 0 : PushTempToken( (*aTokenMatrixMapIter).second.get());
3792 : : }
3793 : : else
3794 : : {
3795 : : // previous expression determines the current number format
3796 : 2876 : nCurFmtType = nRetTypeExpr;
3797 : 2876 : nCurFmtIndex = nRetIndexExpr;
3798 : : // default function's format, others are set if needed
3799 : 2876 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3800 : 2876 : nFuncFmtIndex = 0;
3801 : :
3802 [ + + ][ - + ]: 2876 : if ( eOp == ocIf || eOp == ocChose )
3803 : 66 : nStackBase = sp; // don't mess around with the jumps
3804 : : else
3805 : : {
3806 : : // Convert parameters to matrix if in array/matrix formula and
3807 : : // parameters of function indicate doing so. Create JumpMatrix
3808 : : // if necessary.
3809 [ + - ][ - + ]: 2810 : if ( MatrixParameterConversion() )
3810 : : {
3811 : 0 : eOp = ocNone; // JumpMatrix created
3812 : 0 : nStackBase = sp;
3813 : : }
3814 : : else
3815 [ + - ]: 2810 : nStackBase = sp - pCur->GetParamCount();
3816 : : }
3817 [ - + ]: 2876 : if ( nStackBase > sp )
3818 : 0 : nStackBase = sp; // underflow?!?
3819 : :
3820 [ + - - - : 2876 : switch( eOp )
+ - + + +
+ - + + -
- + - - +
+ - - - -
+ + - + -
+ + - + +
- - + + -
- - + - +
- - - - -
+ - - - -
- - - - -
+ - - - -
- - - - -
- - + - +
+ - - - -
- + + + +
+ + + + +
+ + + + +
+ + - - -
- - - - -
+ - - - -
- - + - -
- - - - -
- - - - -
- - - - +
- - - - +
+ - - - -
+ - + + -
- - - - -
- - - - -
- - - - -
- - + + +
- - - - -
- - - - -
- + - + -
- - - - -
- - - - +
+ + + + -
- + - - -
- - - - -
- - - - -
- - - - -
- - - - -
- + + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- + - - -
- - - - -
+ - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - -
+ - + - -
- - - - -
- - - - -
- - + + +
+ + - -
- ]
3821 : : {
3822 : : case ocSep:
3823 : : case ocClose: // pushed by the compiler
3824 [ + - ]: 18 : case ocMissing : ScMissing(); break;
3825 [ # # ]: 0 : case ocMacro : ScMacro(); break;
3826 [ # # ]: 0 : case ocDBArea : ScDBArea(); break;
3827 [ # # ]: 0 : case ocColRowNameAuto : ScColRowNameAuto(); break;
3828 [ + - ]: 66 : case ocIf : ScIfJump(); break;
3829 [ # # ]: 0 : case ocChose : ScChoseJump(); break;
3830 [ + - ]: 302 : case ocAdd : ScAdd(); break;
3831 [ + - ]: 53 : case ocSub : ScSub(); break;
3832 [ + - ]: 81 : case ocMul : ScMul(); break;
3833 [ + - ]: 53 : case ocDiv : ScDiv(); break;
3834 [ # # ]: 0 : case ocAmpersand : ScAmpersand(); break;
3835 [ + - ]: 22 : case ocPow : ScPow(); break;
3836 [ + - ]: 72 : case ocEqual : ScEqual(); break;
3837 [ # # ]: 0 : case ocNotEqual : ScNotEqual(); break;
3838 [ # # ]: 0 : case ocLess : ScLess(); break;
3839 [ + - ]: 9 : case ocGreater : ScGreater(); break;
3840 [ # # ]: 0 : case ocLessEqual : ScLessEqual(); break;
3841 [ # # ]: 0 : case ocGreaterEqual : ScGreaterEqual(); break;
3842 [ + - ]: 27 : case ocAnd : ScAnd(); break;
3843 [ + - ]: 39 : case ocOr : ScOr(); break;
3844 [ # # ]: 0 : case ocXor : ScXor(); break;
3845 [ # # ]: 0 : case ocIntersect : ScIntersect(); break;
3846 [ # # ]: 0 : case ocRange : ScRangeFunc(); break;
3847 [ # # ]: 0 : case ocUnion : ScUnionFunc(); break;
3848 [ + - ]: 21 : case ocNot : ScNot(); break;
3849 : : case ocNegSub :
3850 [ + - ]: 133 : case ocNeg : ScNeg(); break;
3851 [ # # ]: 0 : case ocPercentSign : ScPercentSign(); break;
3852 [ + - ]: 30 : case ocPi : ScPi(); break;
3853 [ # # ]: 0 : case ocRandom : ScRandom(); break;
3854 [ + - ]: 27 : case ocTrue : ScTrue(); break;
3855 [ + - ]: 12 : case ocFalse : ScFalse(); break;
3856 [ # # ]: 0 : case ocGetActDate : ScGetActDate(); break;
3857 [ + - ]: 9 : case ocGetActTime : ScGetActTime(); break;
3858 [ + - ]: 36 : case ocNotAvail : PushError( NOTAVAILABLE); break;
3859 [ # # ]: 0 : case ocDeg : ScDeg(); break;
3860 [ # # ]: 0 : case ocRad : ScRad(); break;
3861 [ + - ]: 6 : case ocSin : ScSin(); break;
3862 [ + - ]: 6 : case ocCos : ScCos(); break;
3863 [ # # ]: 0 : case ocTan : ScTan(); break;
3864 [ # # ]: 0 : case ocCot : ScCot(); break;
3865 [ # # ]: 0 : case ocArcSin : ScArcSin(); break;
3866 [ + - ]: 9 : case ocArcCos : ScArcCos(); break;
3867 [ # # ]: 0 : case ocArcTan : ScArcTan(); break;
3868 [ + - ]: 9 : case ocArcCot : ScArcCot(); break;
3869 [ # # ]: 0 : case ocSinHyp : ScSinHyp(); break;
3870 [ # # ]: 0 : case ocCosHyp : ScCosHyp(); break;
3871 [ # # ]: 0 : case ocTanHyp : ScTanHyp(); break;
3872 [ # # ]: 0 : case ocCotHyp : ScCotHyp(); break;
3873 [ # # ]: 0 : case ocArcSinHyp : ScArcSinHyp(); break;
3874 [ + - ]: 6 : case ocArcCosHyp : ScArcCosHyp(); break;
3875 [ # # ]: 0 : case ocArcTanHyp : ScArcTanHyp(); break;
3876 [ # # ]: 0 : case ocArcCotHyp : ScArcCotHyp(); break;
3877 [ # # ]: 0 : case ocCosecant : ScCosecant(); break;
3878 [ # # ]: 0 : case ocSecant : ScSecant(); break;
3879 [ # # ]: 0 : case ocCosecantHyp : ScCosecantHyp(); break;
3880 [ # # ]: 0 : case ocSecantHyp : ScSecantHyp(); break;
3881 [ # # ]: 0 : case ocExp : ScExp(); break;
3882 [ # # ]: 0 : case ocLn : ScLn(); break;
3883 [ # # ]: 0 : case ocLog10 : ScLog10(); break;
3884 [ + - ]: 148 : case ocSqrt : ScSqrt(); break;
3885 [ # # ]: 0 : case ocFact : ScFact(); break;
3886 [ # # ]: 0 : case ocGetYear : ScGetYear(); break;
3887 [ # # ]: 0 : case ocGetMonth : ScGetMonth(); break;
3888 [ # # ]: 0 : case ocGetDay : ScGetDay(); break;
3889 [ # # ]: 0 : case ocGetDayOfWeek : ScGetDayOfWeek(); break;
3890 [ # # ]: 0 : case ocWeek : ScGetWeekOfYear(); break;
3891 [ # # ]: 0 : case ocEasterSunday : ScEasterSunday(); break;
3892 [ # # ]: 0 : case ocGetHour : ScGetHour(); break;
3893 [ # # ]: 0 : case ocGetMin : ScGetMin(); break;
3894 [ # # ]: 0 : case ocGetSec : ScGetSec(); break;
3895 [ # # ]: 0 : case ocPlusMinus : ScPlusMinus(); break;
3896 [ + - ]: 9 : case ocAbs : ScAbs(); break;
3897 [ # # ]: 0 : case ocInt : ScInt(); break;
3898 [ + - ]: 18 : case ocEven : ScEven(); break;
3899 [ + - ]: 18 : case ocOdd : ScOdd(); break;
3900 [ # # ]: 0 : case ocPhi : ScPhi(); break;
3901 [ # # ]: 0 : case ocGauss : ScGauss(); break;
3902 [ # # ]: 0 : case ocStdNormDist : ScStdNormDist(); break;
3903 [ # # ]: 0 : case ocFisher : ScFisher(); break;
3904 [ # # ]: 0 : case ocFisherInv : ScFisherInv(); break;
3905 [ + - ]: 15 : case ocIsEmpty : ScIsEmpty(); break;
3906 [ + - ]: 18 : case ocIsString : ScIsString(); break;
3907 [ + - ]: 9 : case ocIsNonString : ScIsNonString(); break;
3908 [ + - ]: 12 : case ocIsLogical : ScIsLogical(); break;
3909 [ + - ]: 15 : case ocType : ScType(); break;
3910 [ + - ]: 57 : case ocCell : ScCell(); break;
3911 [ + - ]: 24 : case ocIsRef : ScIsRef(); break;
3912 [ + - ]: 15 : case ocIsValue : ScIsValue(); break;
3913 [ + - ]: 9 : case ocIsFormula : ScIsFormula(); break;
3914 [ + - ]: 18 : case ocFormula : ScFormula(); break;
3915 [ + - ]: 18 : case ocIsNA : ScIsNV(); break;
3916 [ + - ]: 12 : case ocIsErr : ScIsErr(); break;
3917 [ + - ]: 18 : case ocIsError : ScIsError(); break;
3918 [ + - ]: 12 : case ocIsEven : ScIsEven(); break;
3919 [ + - ]: 15 : case ocIsOdd : ScIsOdd(); break;
3920 [ + - ]: 180 : case ocN : ScN(); break;
3921 [ # # ]: 0 : case ocGetDateValue : ScGetDateValue(); break;
3922 [ # # ]: 0 : case ocGetTimeValue : ScGetTimeValue(); break;
3923 [ # # ]: 0 : case ocCode : ScCode(); break;
3924 [ # # ]: 0 : case ocTrim : ScTrim(); break;
3925 [ # # ]: 0 : case ocUpper : ScUpper(); break;
3926 [ # # ]: 0 : case ocPropper : ScPropper(); break;
3927 [ # # ]: 0 : case ocLower : ScLower(); break;
3928 [ # # ]: 0 : case ocLen : ScLen(); break;
3929 [ + - ]: 9 : case ocT : ScT(); break;
3930 [ # # ]: 0 : case ocClean : ScClean(); break;
3931 [ # # ]: 0 : case ocValue : ScValue(); break;
3932 [ # # ]: 0 : case ocChar : ScChar(); break;
3933 [ # # ]: 0 : case ocArcTan2 : ScArcTan2(); break;
3934 [ # # ]: 0 : case ocMod : ScMod(); break;
3935 [ # # ]: 0 : case ocPower : ScPower(); break;
3936 [ + - ]: 12 : case ocRound : ScRound(); break;
3937 [ # # ]: 0 : case ocRoundUp : ScRoundUp(); break;
3938 : : case ocTrunc :
3939 [ # # ]: 0 : case ocRoundDown : ScRoundDown(); break;
3940 [ # # ]: 0 : case ocCeil : ScCeil(); break;
3941 [ # # ]: 0 : case ocFloor : ScFloor(); break;
3942 [ # # ]: 0 : case ocSumProduct : ScSumProduct(); break;
3943 [ # # ]: 0 : case ocSumSQ : ScSumSQ(); break;
3944 [ # # ]: 0 : case ocSumX2MY2 : ScSumX2MY2(); break;
3945 [ # # ]: 0 : case ocSumX2DY2 : ScSumX2DY2(); break;
3946 [ # # ]: 0 : case ocSumXMY2 : ScSumXMY2(); break;
3947 [ # # ]: 0 : case ocLog : ScLog(); break;
3948 [ # # ]: 0 : case ocGCD : ScGCD(); break;
3949 [ # # ]: 0 : case ocLCM : ScLCM(); break;
3950 [ # # ]: 0 : case ocGetDate : ScGetDate(); break;
3951 [ # # ]: 0 : case ocGetTime : ScGetTime(); break;
3952 [ # # ]: 0 : case ocGetDiffDate : ScGetDiffDate(); break;
3953 [ # # ]: 0 : case ocGetDiffDate360 : ScGetDiffDate360(); break;
3954 [ + - ]: 270 : case ocGetDateDif : ScGetDateDif(); break;
3955 [ # # ]: 0 : case ocMin : ScMin( false ); break;
3956 [ # # ]: 0 : case ocMinA : ScMin( true ); break;
3957 [ # # ]: 0 : case ocMax : ScMax( false ); break;
3958 [ # # ]: 0 : case ocMaxA : ScMax( true ); break;
3959 [ + - ]: 95 : case ocSum : ScSum(); break;
3960 [ + - ]: 9 : case ocProduct : ScProduct(); break;
3961 [ # # ]: 0 : case ocNPV : ScNPV(); break;
3962 [ # # ]: 0 : case ocIRR : ScIRR(); break;
3963 [ # # ]: 0 : case ocMIRR : ScMIRR(); break;
3964 [ # # ]: 0 : case ocISPMT : ScISPMT(); break;
3965 [ + - ]: 12 : case ocAverage : ScAverage( false ); break;
3966 [ # # ]: 0 : case ocAverageA : ScAverage( true ); break;
3967 [ + - ]: 9 : case ocCount : ScCount(); break;
3968 [ + - ]: 3 : case ocCount2 : ScCount2(); break;
3969 [ # # ]: 0 : case ocVar : ScVar( false ); break;
3970 [ # # ]: 0 : case ocVarA : ScVar( true ); break;
3971 [ # # ]: 0 : case ocVarP : ScVarP( false ); break;
3972 [ # # ]: 0 : case ocVarPA : ScVarP( true ); break;
3973 [ # # ]: 0 : case ocStDev : ScStDev( false ); break;
3974 [ # # ]: 0 : case ocStDevA : ScStDev( true ); break;
3975 [ # # ]: 0 : case ocStDevP : ScStDevP( false ); break;
3976 [ # # ]: 0 : case ocStDevPA : ScStDevP( true ); break;
3977 [ # # ]: 0 : case ocBW : ScBW(); break;
3978 [ # # ]: 0 : case ocDIA : ScDIA(); break;
3979 [ # # ]: 0 : case ocGDA : ScGDA(); break;
3980 [ # # ]: 0 : case ocGDA2 : ScGDA2(); break;
3981 [ # # ]: 0 : case ocVBD : ScVDB(); break;
3982 [ # # ]: 0 : case ocLaufz : ScLaufz(); break;
3983 [ # # ]: 0 : case ocLIA : ScLIA(); break;
3984 [ # # ]: 0 : case ocRMZ : ScRMZ(); break;
3985 [ # # ]: 0 : case ocColumns : ScColumns(); break;
3986 [ # # ]: 0 : case ocRows : ScRows(); break;
3987 [ + - ]: 9 : case ocTables : ScTables(); break;
3988 [ + - ]: 54 : case ocColumn : ScColumn(); break;
3989 [ + - ]: 27 : case ocRow : ScRow(); break;
3990 [ # # ]: 0 : case ocTable : ScTable(); break;
3991 [ # # ]: 0 : case ocZGZ : ScZGZ(); break;
3992 [ # # ]: 0 : case ocZW : ScZW(); break;
3993 [ # # ]: 0 : case ocZZR : ScZZR(); break;
3994 [ # # ]: 0 : case ocZins : ScZins(); break;
3995 [ # # ]: 0 : case ocZinsZ : ScZinsZ(); break;
3996 [ # # ]: 0 : case ocKapz : ScKapz(); break;
3997 [ # # ]: 0 : case ocKumZinsZ : ScKumZinsZ(); break;
3998 [ # # ]: 0 : case ocKumKapZ : ScKumKapZ(); break;
3999 [ # # ]: 0 : case ocEffektiv : ScEffektiv(); break;
4000 [ # # ]: 0 : case ocNominal : ScNominal(); break;
4001 [ + - ]: 7 : case ocSubTotal : ScSubTotal(); break;
4002 [ # # ]: 0 : case ocDBSum : ScDBSum(); break;
4003 [ + - ]: 24 : case ocDBCount : ScDBCount(); break;
4004 [ # # ]: 0 : case ocDBCount2 : ScDBCount2(); break;
4005 [ # # ]: 0 : case ocDBAverage : ScDBAverage(); break;
4006 [ # # ]: 0 : case ocDBGet : ScDBGet(); break;
4007 [ # # ]: 0 : case ocDBMax : ScDBMax(); break;
4008 [ # # ]: 0 : case ocDBMin : ScDBMin(); break;
4009 [ # # ]: 0 : case ocDBProduct : ScDBProduct(); break;
4010 [ # # ]: 0 : case ocDBStdDev : ScDBStdDev(); break;
4011 [ # # ]: 0 : case ocDBStdDevP : ScDBStdDevP(); break;
4012 [ # # ]: 0 : case ocDBVar : ScDBVar(); break;
4013 [ # # ]: 0 : case ocDBVarP : ScDBVarP(); break;
4014 [ + - ]: 102 : case ocIndirect : ScIndirect(); break;
4015 [ + - ]: 12 : case ocAddress : ScAddressFunc(); break;
4016 [ + - ]: 93 : case ocMatch : ScMatch(); break;
4017 [ + - ]: 3 : case ocCountEmptyCells : ScCountEmptyCells(); break;
4018 [ + - ]: 69 : case ocCountIf : ScCountIf(); break;
4019 [ # # ]: 0 : case ocSumIf : ScSumIf(); break;
4020 [ # # ]: 0 : case ocLookup : ScLookup(); break;
4021 [ + - ]: 51 : case ocVLookup : ScVLookup(); break;
4022 [ # # ]: 0 : case ocHLookup : ScHLookup(); break;
4023 [ # # ]: 0 : case ocIndex : ScIndex(); break;
4024 [ # # ]: 0 : case ocMultiArea : ScMultiArea(); break;
4025 [ # # ]: 0 : case ocOffset : ScOffset(); break;
4026 [ # # ]: 0 : case ocAreas : ScAreas(); break;
4027 [ # # ]: 0 : case ocCurrency : ScCurrency(); break;
4028 [ # # ]: 0 : case ocReplace : ScReplace(); break;
4029 [ # # ]: 0 : case ocFixed : ScFixed(); break;
4030 [ # # ]: 0 : case ocFind : ScFind(); break;
4031 [ # # ]: 0 : case ocExact : ScExact(); break;
4032 [ # # ]: 0 : case ocLeft : ScLeft(); break;
4033 [ # # ]: 0 : case ocRight : ScRight(); break;
4034 [ # # ]: 0 : case ocSearch : ScSearch(); break;
4035 [ # # ]: 0 : case ocMid : ScMid(); break;
4036 [ # # ]: 0 : case ocText : ScText(); break;
4037 [ # # ]: 0 : case ocSubstitute : ScSubstitute(); break;
4038 [ # # ]: 0 : case ocRept : ScRept(); break;
4039 [ # # ]: 0 : case ocConcat : ScConcat(); break;
4040 [ # # ]: 0 : case ocMatValue : ScMatValue(); break;
4041 [ # # ]: 0 : case ocMatrixUnit : ScEMat(); break;
4042 [ # # ]: 0 : case ocMatDet : ScMatDet(); break;
4043 [ # # ]: 0 : case ocMatInv : ScMatInv(); break;
4044 [ # # ]: 0 : case ocMatMult : ScMatMult(); break;
4045 [ # # ]: 0 : case ocMatTrans : ScMatTrans(); break;
4046 [ + - ]: 154 : case ocMatRef : ScMatRef(); break;
4047 [ + - ]: 3 : case ocBackSolver : ScBackSolver(); break;
4048 [ # # ]: 0 : case ocB : ScB(); break;
4049 [ # # ]: 0 : case ocNormDist : ScNormDist(); break;
4050 [ # # ]: 0 : case ocExpDist : ScExpDist(); break;
4051 [ # # ]: 0 : case ocBinomDist : ScBinomDist(); break;
4052 [ # # ]: 0 : case ocPoissonDist : ScPoissonDist(); break;
4053 [ # # ]: 0 : case ocKombin : ScKombin(); break;
4054 [ # # ]: 0 : case ocKombin2 : ScKombin2(); break;
4055 [ # # ]: 0 : case ocVariationen : ScVariationen(); break;
4056 [ # # ]: 0 : case ocVariationen2 : ScVariationen2(); break;
4057 [ # # ]: 0 : case ocHypGeomDist : ScHypGeomDist(); break;
4058 [ # # ]: 0 : case ocLogNormDist : ScLogNormDist(); break;
4059 [ # # ]: 0 : case ocTDist : ScTDist(); break;
4060 [ # # ]: 0 : case ocFDist : ScFDist(); break;
4061 [ # # ]: 0 : case ocChiDist : ScChiDist(); break;
4062 [ # # ]: 0 : case ocChiSqDist : ScChiSqDist(); break;
4063 [ # # ]: 0 : case ocStandard : ScStandard(); break;
4064 [ # # ]: 0 : case ocAveDev : ScAveDev(); break;
4065 [ # # ]: 0 : case ocDevSq : ScDevSq(); break;
4066 [ # # ]: 0 : case ocKurt : ScKurt(); break;
4067 [ # # ]: 0 : case ocSchiefe : ScSkew(); break;
4068 [ # # ]: 0 : case ocModalValue : ScModalValue(); break;
4069 [ # # ]: 0 : case ocMedian : ScMedian(); break;
4070 [ # # ]: 0 : case ocGeoMean : ScGeoMean(); break;
4071 [ # # ]: 0 : case ocHarMean : ScHarMean(); break;
4072 [ # # ]: 0 : case ocWeibull : ScWeibull(); break;
4073 [ # # ]: 0 : case ocKritBinom : ScCritBinom(); break;
4074 [ # # ]: 0 : case ocNegBinomVert : ScNegBinomDist(); break;
4075 [ # # ]: 0 : case ocNoName : ScNoName(); break;
4076 [ + - ]: 18 : case ocBad : ScBadName(); break;
4077 [ # # ]: 0 : case ocZTest : ScZTest(); break;
4078 [ # # ]: 0 : case ocTTest : ScTTest(); break;
4079 [ # # ]: 0 : case ocFTest : ScFTest(); break;
4080 [ # # ]: 0 : case ocRank : ScRank(); break;
4081 [ # # ]: 0 : case ocPercentile : ScPercentile(); break;
4082 [ # # ]: 0 : case ocPercentrank : ScPercentrank(); break;
4083 [ # # ]: 0 : case ocLarge : ScLarge(); break;
4084 [ # # ]: 0 : case ocSmall : ScSmall(); break;
4085 [ + - ]: 12 : case ocFrequency : ScFrequency(); break;
4086 [ # # ]: 0 : case ocQuartile : ScQuartile(); break;
4087 [ # # ]: 0 : case ocNormInv : ScNormInv(); break;
4088 [ # # ]: 0 : case ocSNormInv : ScSNormInv(); break;
4089 [ # # ]: 0 : case ocConfidence : ScConfidence(); break;
4090 [ # # ]: 0 : case ocTrimMean : ScTrimMean(); break;
4091 [ # # ]: 0 : case ocProb : ScProbability(); break;
4092 [ # # ]: 0 : case ocCorrel : ScCorrel(); break;
4093 [ # # ]: 0 : case ocCovar : ScCovar(); break;
4094 [ # # ]: 0 : case ocPearson : ScPearson(); break;
4095 [ # # ]: 0 : case ocRSQ : ScRSQ(); break;
4096 [ # # ]: 0 : case ocSTEYX : ScSTEXY(); break;
4097 [ # # ]: 0 : case ocSlope : ScSlope(); break;
4098 [ # # ]: 0 : case ocIntercept : ScIntercept(); break;
4099 [ # # ]: 0 : case ocTrend : ScTrend(); break;
4100 [ # # ]: 0 : case ocGrowth : ScGrowth(); break;
4101 [ # # ]: 0 : case ocRGP : ScRGP(); break;
4102 [ # # ]: 0 : case ocRKP : ScRKP(); break;
4103 [ # # ]: 0 : case ocForecast : ScForecast(); break;
4104 [ # # ]: 0 : case ocGammaLn : ScLogGamma(); break;
4105 [ # # ]: 0 : case ocGamma : ScGamma(); break;
4106 [ # # ]: 0 : case ocGammaDist : ScGammaDist(); break;
4107 [ # # ]: 0 : case ocGammaInv : ScGammaInv(); break;
4108 [ # # ]: 0 : case ocChiTest : ScChiTest(); break;
4109 [ # # ]: 0 : case ocChiInv : ScChiInv(); break;
4110 [ # # ]: 0 : case ocChiSqInv : ScChiSqInv(); break;
4111 [ # # ]: 0 : case ocTInv : ScTInv(); break;
4112 [ # # ]: 0 : case ocFInv : ScFInv(); break;
4113 [ # # ]: 0 : case ocLogInv : ScLogNormInv(); break;
4114 [ # # ]: 0 : case ocBetaDist : ScBetaDist(); break;
4115 [ # # ]: 0 : case ocBetaInv : ScBetaInv(); break;
4116 [ # # ]: 0 : case ocExternal : ScExternal(); break;
4117 [ + - ]: 89 : case ocTableOp : ScTableOp(); break;
4118 : 0 : case ocStop : break;
4119 [ # # ]: 0 : case ocErrorType : ScErrorType(); break;
4120 [ + - ]: 3 : case ocCurrent : ScCurrent(); break;
4121 [ # # ]: 0 : case ocStyle : ScStyle(); break;
4122 [ + - ]: 8 : case ocDde : ScDde(); break;
4123 [ # # ]: 0 : case ocBase : ScBase(); break;
4124 [ # # ]: 0 : case ocDecimal : ScDecimal(); break;
4125 [ # # ]: 0 : case ocConvert : ScConvert(); break;
4126 [ # # ]: 0 : case ocEuroConvert : ScEuroConvert(); break;
4127 [ # # ]: 0 : case ocRoman : ScRoman(); break;
4128 [ # # ]: 0 : case ocArabic : ScArabic(); break;
4129 [ # # ]: 0 : case ocInfo : ScInfo(); break;
4130 [ # # ]: 0 : case ocHyperLink : ScHyperLink(); break;
4131 [ # # ]: 0 : case ocBahtText : ScBahtText(); break;
4132 [ # # ]: 0 : case ocGetPivotData : ScGetPivotData(); break;
4133 [ # # ]: 0 : case ocJis : ScJis(); break;
4134 [ # # ]: 0 : case ocAsc : ScAsc(); break;
4135 [ # # ]: 0 : case ocUnicode : ScUnicode(); break;
4136 [ # # ]: 0 : case ocUnichar : ScUnichar(); break;
4137 [ + - ]: 9 : case ocBitAnd : ScBitAnd(); break;
4138 [ + - ]: 6 : case ocBitOr : ScBitOr(); break;
4139 [ + - ]: 6 : case ocBitXor : ScBitXor(); break;
4140 [ + - ]: 6 : case ocBitRshift : ScBitRshift(); break;
4141 [ + - ]: 6 : case ocBitLshift : ScBitLshift(); break;
4142 [ # # ]: 0 : case ocTTT : ScTTT(); break;
4143 : 0 : case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break;
4144 [ # # ]: 0 : default : PushError( errUnknownOpCode); break;
4145 : : }
4146 : :
4147 : : // If the function signalled that it pushed a subroutine on the
4148 : : // instruction code stack instead of a result, continue with
4149 : : // execution of the subroutine.
4150 [ + + ][ - + ]: 2876 : if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
[ - + ]
4151 : : {
4152 : 0 : Pop();
4153 : 0 : continue; // while( ( pCur = aCode.Next() ) != NULL ...
4154 : : }
4155 : :
4156 [ + - ][ + + ]: 2876 : if (FormulaCompiler::IsOpCodeVolatile(eOp))
4157 : 129 : meVolatileType = VOLATILE;
4158 : :
4159 : : // Remember result matrix in case it could be reused.
4160 [ + + ][ + + ]: 2876 : if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
[ + + ][ + + ]
4161 : : pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
4162 [ + - ][ + - ]: 72 : pStack[sp-1]));
[ + - ]
4163 : :
4164 : : // outer function determines format of an expression
4165 [ + + ]: 2876 : if ( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4166 : : {
4167 : 2743 : nRetTypeExpr = nFuncFmtType;
4168 : : // inherit the format index only for currency formats
4169 : : nRetIndexExpr = ( nFuncFmtType == NUMBERFORMAT_CURRENCY ?
4170 [ - + ]: 2743 : nFuncFmtIndex : 0 );
4171 : : }
4172 : : }
4173 : :
4174 : : // Need a clean stack environment for the JumpMatrix to work.
4175 [ + + ][ + - ]: 7319 : if (nGlobalError && eOp != ocPush && sp > nStackBase + 1)
[ - + ]
4176 : : {
4177 : : // Not all functions pop all parameters in case an error is
4178 : : // generated. Clean up stack. Assumes that every function pushes a
4179 : : // result, may be arbitrary in case of error.
4180 : 0 : const FormulaToken* pLocalResult = pStack[ sp - 1 ];
4181 [ # # ]: 0 : while (sp > nStackBase)
4182 : 0 : Pop();
4183 [ # # ]: 0 : PushTempToken( *pLocalResult );
4184 : : }
4185 : :
4186 : : bool bGotResult;
4187 [ - + ]: 7319 : do
4188 : : {
4189 : 7319 : bGotResult = false;
4190 : 7319 : sal_uInt8 nLevel = 0;
4191 [ + - ]: 7319 : if ( GetStackType( ++nLevel ) == svJumpMatrix )
4192 : : ; // nothing
4193 [ + - ]: 7319 : else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4194 : : ; // nothing
4195 : : else
4196 : 7319 : nLevel = 0;
4197 [ + - ][ - + ]: 7319 : if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
[ # # ][ # # ]
[ - + ]
4198 [ # # ]: 0 : bGotResult = JumpMatrix( nLevel );
4199 : : else
4200 : 7319 : pJumpMatrix = NULL;
4201 : : } while ( bGotResult );
4202 : :
4203 : :
4204 : : // Functions that evaluate an error code and directly set nGlobalError to 0,
4205 : : // usage: switch( OpCode ) { CASE_OCERRFUNC statements; }
4206 : : #define CASE_OCERRFUNC \
4207 : : case ocCount : \
4208 : : case ocCount2 : \
4209 : : case ocErrorType : \
4210 : : case ocIsEmpty : \
4211 : : case ocIsErr : \
4212 : : case ocIsError : \
4213 : : case ocIsFormula : \
4214 : : case ocIsLogical : \
4215 : : case ocIsNA : \
4216 : : case ocIsNonString : \
4217 : : case ocIsRef : \
4218 : : case ocIsString : \
4219 : : case ocIsValue : \
4220 : : case ocN : \
4221 : : case ocType :
4222 : :
4223 [ + + ]: 7319 : switch ( eOp )
4224 : : {
4225 : : CASE_OCERRFUNC
4226 : 357 : ++ nErrorFunction;
4227 : : default:
4228 : : ; // nothing
4229 : : }
4230 [ + + ]: 7319 : if ( nGlobalError )
4231 : : {
4232 [ + - ]: 339 : if ( !nErrorFunctionCount )
4233 : : { // count of errorcode functions in formula
4234 [ + - ][ + - ]: 1310 : for ( FormulaToken* t = rArr.FirstRPN(); t; t = rArr.NextRPN() )
[ + + ]
4235 : : {
4236 [ + + ]: 971 : switch ( t->GetOpCode() )
4237 : : {
4238 : : CASE_OCERRFUNC
4239 : 27 : ++nErrorFunctionCount;
4240 : : default:
4241 : : ; // nothing
4242 : : }
4243 : : }
4244 : : }
4245 [ + + ]: 339 : if ( nErrorFunction >= nErrorFunctionCount )
4246 : 312 : ++nErrorFunction; // that's it, error => terminate
4247 : : }
4248 : : }
4249 : :
4250 : : // End: obtain result
4251 : :
4252 [ + - ]: 2619 : if( sp )
4253 : : {
4254 : 2619 : pCur = pStack[ sp-1 ];
4255 [ + - ]: 2619 : if( pCur->GetOpCode() == ocPush )
4256 : : {
4257 [ + + + + : 2619 : switch( pCur->GetType() )
+ - + + +
- ]
4258 : : {
4259 : : case svEmptyCell:
4260 : : ; // nothing
4261 : 3 : break;
4262 : : case svError:
4263 [ + - ]: 312 : nGlobalError = pCur->GetError();
4264 : 312 : break;
4265 : : case svDouble :
4266 [ + + ]: 1801 : if ( nFuncFmtType == NUMBERFORMAT_UNDEFINED )
4267 : : {
4268 : 15 : nRetTypeExpr = NUMBERFORMAT_NUMBER;
4269 : 15 : nRetIndexExpr = 0;
4270 : : }
4271 : 1801 : break;
4272 : : case svString :
4273 : 142 : nRetTypeExpr = NUMBERFORMAT_TEXT;
4274 : 142 : nRetIndexExpr = 0;
4275 : 142 : break;
4276 : : case svSingleRef :
4277 : : {
4278 : 220 : ScAddress aAdr;
4279 [ + - ]: 220 : PopSingleRef( aAdr );
4280 [ + - ]: 220 : if( !nGlobalError )
4281 : : PushCellResultToken( false, aAdr,
4282 [ + - ]: 220 : &nRetTypeExpr, &nRetIndexExpr);
4283 : : }
4284 : 220 : break;
4285 : : case svRefList :
4286 [ # # ]: 0 : PopError(); // maybe #REF! takes precedence over #VALUE!
4287 [ # # ]: 0 : PushError( errNoValue);
4288 : 0 : break;
4289 : : case svDoubleRef :
4290 : : {
4291 [ + - ]: 10 : if ( bMatrixFormula )
4292 : : { // create matrix for {=A1:A5}
4293 [ + - ]: 10 : PopDoubleRefPushMatrix();
4294 [ + - ]: 10 : ScMatrixRef xMat = PopMatrix();
4295 [ + - ][ + - ]: 10 : QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4296 : : }
4297 : : else
4298 : : {
4299 : 0 : ScRange aRange;
4300 [ # # ]: 0 : PopDoubleRef( aRange );
4301 : 0 : ScAddress aAdr;
4302 [ # # ][ # # ]: 0 : if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr))
[ # # ][ # # ]
4303 : : PushCellResultToken( false, aAdr,
4304 [ # # ]: 0 : &nRetTypeExpr, &nRetIndexExpr);
4305 : : }
4306 : : }
4307 : 10 : break;
4308 : : case svExternalDoubleRef:
4309 : : case svMatrix :
4310 : : {
4311 : 71 : ScMatrixRef xMat;
4312 [ + - ]: 71 : if (pCur->GetType() == svMatrix)
4313 [ + - ][ + - ]: 71 : xMat = PopMatrix();
[ + - ]
4314 : : else
4315 [ # # ]: 0 : PopExternalDoubleRef(xMat);
4316 : :
4317 [ + - ][ + - ]: 71 : QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4318 : : }
4319 : 71 : break;
4320 : : case svExternalSingleRef:
4321 : : {
4322 : 60 : ScExternalRefCache::TokenRef pToken;
4323 [ + - ]: 60 : ScExternalRefCache::CellFormat aFmt;
4324 [ + - ]: 60 : PopExternalSingleRef(pToken, &aFmt);
4325 [ - + ]: 60 : if (nGlobalError)
4326 : : break;
4327 : :
4328 [ + - ]: 60 : PushTempToken(*pToken);
4329 : :
4330 [ + - ]: 60 : if (aFmt.mbIsSet)
4331 : : {
4332 : 60 : nFuncFmtType = aFmt.mnType;
4333 : 60 : nFuncFmtIndex = aFmt.mnIndex;
4334 [ + - ][ + - ]: 60 : }
4335 : : }
4336 : 60 : break;
4337 : : default :
4338 : 2619 : SetError( errUnknownStackVariable);
4339 : : }
4340 : : }
4341 : : else
4342 : 0 : SetError( errUnknownStackVariable);
4343 : : }
4344 : : else
4345 : 0 : SetError( errNoCode);
4346 : :
4347 [ + + ]: 2619 : if( nRetTypeExpr != NUMBERFORMAT_UNDEFINED )
4348 : : {
4349 : 2559 : nRetFmtType = nRetTypeExpr;
4350 : 2559 : nRetFmtIndex = nRetIndexExpr;
4351 : : }
4352 [ + - ]: 60 : else if( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4353 : : {
4354 : 60 : nRetFmtType = nFuncFmtType;
4355 : 60 : nRetFmtIndex = nFuncFmtIndex;
4356 : : }
4357 : : else
4358 : 0 : nRetFmtType = NUMBERFORMAT_NUMBER;
4359 : : // inherit the format index only for currency formats
4360 [ + - ]: 2619 : if ( nRetFmtType != NUMBERFORMAT_CURRENCY )
4361 : 2619 : nRetFmtIndex = 0;
4362 : :
4363 [ + + ][ - + ]: 2619 : if (nGlobalError && GetStackType() != svError )
[ - + ]
4364 [ # # ]: 0 : PushError( nGlobalError);
4365 : :
4366 : : // THE final result.
4367 [ + - ][ + - ]: 2619 : xResult = PopToken();
[ + - ]
4368 [ - + ]: 2619 : if (!xResult)
4369 [ # # ][ # # ]: 0 : xResult = new FormulaErrorToken( errUnknownStackVariable);
[ # # ]
4370 : :
4371 : : // release tokens in expression stack
4372 : 2619 : FormulaToken** p = pStack;
4373 [ + + ]: 7260 : while( maxsp-- )
4374 [ + - ]: 4641 : (*p++)->DecRef();
4375 : :
4376 : 2619 : StackVar eType = xResult->GetType();
4377 [ - + ]: 2619 : if (eType == svMatrix)
4378 : : // Results are immutable in case they would be reused as input for new
4379 : : // interpreters.
4380 [ # # ][ # # ]: 0 : static_cast<ScToken*>(xResult.get())->GetMatrix()->SetImmutable( true);
4381 : 2619 : return eType;
4382 : : }
4383 : :
4384 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|