Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <cstddef>
22 : #include <cstdio>
23 :
24 : #include <string.h>
25 : #include <limits.h>
26 : #include <tools/debug.hxx>
27 :
28 : #include "formula/token.hxx"
29 : #include "formula/tokenarray.hxx"
30 : #include "formula/FormulaCompiler.hxx"
31 : #include <formula/compiler.hrc>
32 :
33 : namespace formula
34 : {
35 : using namespace com::sun::star;
36 : // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
37 : // SubCode via FormulaTokenIterator Push/Pop moeglich
38 33 : IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator )
39 :
40 : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
41 :
42 : // Need a lot of FormulaDoubleToken
43 18983 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaDoubleToken )
44 : // Need a lot of FormulaByteToken
45 30890 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaByteToken )
46 : // Need several FormulaStringToken
47 6188 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaStringToken )
48 :
49 :
50 : // --- helpers --------------------------------------------------------------
51 :
52 0 : inline bool lcl_IsReference( OpCode eOp, StackVar eType )
53 : {
54 : return
55 0 : (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
56 0 : || (eOp == ocColRowNameAuto && eType == svDoubleRef)
57 0 : || (eOp == ocColRowName && eType == svSingleRef)
58 0 : || (eOp == ocMatRef && eType == svSingleRef)
59 : ;
60 : }
61 :
62 : // --- class FormulaToken --------------------------------------------------------
63 87984 : FormulaToken::~FormulaToken()
64 : {
65 87984 : }
66 :
67 0 : bool FormulaToken::Is3DRef() const
68 : {
69 0 : return false;
70 : }
71 :
72 0 : bool FormulaToken::IsFunction() const
73 : {
74 0 : return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
75 0 : eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
76 0 : (GetByte() != 0 // x parameters
77 0 : || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) // no parameter
78 0 : || (ocIf == eOp || ocIfError == eOp || ocIfNA == eOp || ocChose == eOp ) // @ jump commands
79 0 : || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) // one parameter
80 0 : || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) // x parameters (cByte==0 in
81 : // FuncAutoPilot)
82 0 : || eOp == ocMacro || eOp == ocExternal // macros, AddIns
83 0 : || eOp == ocAnd || eOp == ocOr // former binary, now x parameters
84 0 : || eOp == ocNot || eOp == ocNeg // unary but function
85 0 : || (eOp >= ocInternalBegin && eOp <= ocInternalEnd) // internal
86 0 : ));
87 : }
88 :
89 :
90 27909 : sal_uInt8 FormulaToken::GetParamCount() const
91 : {
92 40270 : if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
93 37053 : eOp != ocIf && eOp != ocIfError && eOp != ocIfNA && eOp != ocChose &&
94 12341 : eOp != ocPercentSign )
95 12341 : return 0; // parameters and specials
96 : // ocIf, ocIfError, ocIfNA and ocChose not for FAP, have cByte then
97 : //2do: bool parameter whether FAP or not?
98 15568 : else if ( GetByte() )
99 5069 : return GetByte(); // all functions, also ocExternal and ocMacro
100 10499 : else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
101 10346 : return 2; // binary
102 153 : else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
103 73 : || eOp == ocPercentSign)
104 80 : return 1; // unary
105 73 : else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
106 44 : return 0; // no parameter
107 29 : else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
108 0 : return 1; // one parameter
109 29 : else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose )
110 20 : return 1; // only the condition counts as parameter
111 : else
112 9 : return 0; // all the rest, no Parameter, or
113 : // if so then it should be in cByte
114 : }
115 :
116 62347 : bool FormulaToken::IsExternalRef() const
117 : {
118 62347 : bool bRet = false;
119 62347 : switch (eType)
120 : {
121 : case svExternalSingleRef:
122 : case svExternalDoubleRef:
123 : case svExternalName:
124 41 : bRet = true;
125 41 : break;
126 : default:
127 62306 : bRet = false;
128 62306 : break;
129 : }
130 62347 : return bRet;
131 : }
132 :
133 48 : bool FormulaToken::operator==( const FormulaToken& rToken ) const
134 : {
135 : // don't compare reference count!
136 48 : return eType == rToken.eType && GetOpCode() == rToken.GetOpCode();
137 : }
138 :
139 :
140 : // --- virtual dummy methods -------------------------------------------------
141 :
142 10166 : sal_uInt8 FormulaToken::GetByte() const
143 : {
144 : // ok to be called for any derived class
145 10166 : return 0;
146 : }
147 :
148 0 : void FormulaToken::SetByte( sal_uInt8 )
149 : {
150 : SAL_WARN( "formula.core", "FormulaToken::SetByte: virtual dummy called" );
151 0 : }
152 :
153 300 : bool FormulaToken::HasForceArray() const
154 : {
155 : // ok to be called for any derived class
156 300 : return false;
157 : }
158 :
159 0 : void FormulaToken::SetForceArray( bool )
160 : {
161 : SAL_WARN( "formula.core", "FormulaToken::SetForceArray: virtual dummy called" );
162 0 : }
163 :
164 0 : double FormulaToken::GetDouble() const
165 : {
166 : SAL_WARN( "formula.core", "FormulaToken::GetDouble: virtual dummy called" );
167 0 : return 0.0;
168 : }
169 :
170 0 : double & FormulaToken::GetDoubleAsReference()
171 : {
172 : SAL_WARN( "formula.core", "FormulaToken::GetDouble: virtual dummy called" );
173 : static double fVal = 0.0;
174 0 : return fVal;
175 : }
176 :
177 0 : const String& FormulaToken::GetString() const
178 : {
179 : SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
180 0 : static String aDummyString;
181 0 : return aDummyString;
182 : }
183 :
184 0 : sal_uInt16 FormulaToken::GetIndex() const
185 : {
186 : SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" );
187 0 : return 0;
188 : }
189 :
190 0 : void FormulaToken::SetIndex( sal_uInt16 )
191 : {
192 : SAL_WARN( "formula.core", "FormulaToken::SetIndex: virtual dummy called" );
193 0 : }
194 :
195 0 : bool FormulaToken::IsGlobal() const
196 : {
197 : SAL_WARN( "formula.core", "FormulaToken::IsGlobal: virtual dummy called" );
198 0 : return true;
199 : }
200 :
201 0 : void FormulaToken::SetGlobal( bool )
202 : {
203 : SAL_WARN( "formula.core", "FormulaToken::SetGlobal: virtual dummy called" );
204 0 : }
205 :
206 0 : short* FormulaToken::GetJump() const
207 : {
208 : SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" );
209 0 : return NULL;
210 : }
211 :
212 :
213 0 : const String& FormulaToken::GetExternal() const
214 : {
215 : SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" );
216 0 : static String aDummyString;
217 0 : return aDummyString;
218 : }
219 :
220 0 : FormulaToken* FormulaToken::GetFAPOrigToken() const
221 : {
222 : SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" );
223 0 : return NULL;
224 : }
225 :
226 0 : sal_uInt16 FormulaToken::GetError() const
227 : {
228 : SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" );
229 0 : return 0;
230 : }
231 :
232 0 : void FormulaToken::SetError( sal_uInt16 )
233 : {
234 : SAL_WARN( "formula.core", "FormulaToken::SetError: virtual dummy called" );
235 0 : }
236 :
237 2 : bool FormulaToken::TextEqual( const FormulaToken& rToken ) const
238 : {
239 2 : return *this == rToken;
240 : }
241 : // ==========================================================================
242 : // real implementations of virtual functions
243 : // --------------------------------------------------------------------------
244 :
245 :
246 27106 : sal_uInt8 FormulaByteToken::GetByte() const { return nByte; }
247 3715 : void FormulaByteToken::SetByte( sal_uInt8 n ) { nByte = n; }
248 17273 : bool FormulaByteToken::HasForceArray() const { return bHasForceArray; }
249 0 : void FormulaByteToken::SetForceArray( bool b ) { bHasForceArray = b; }
250 24 : bool FormulaByteToken::operator==( const FormulaToken& r ) const
251 : {
252 48 : return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
253 48 : bHasForceArray == r.HasForceArray();
254 : }
255 :
256 :
257 0 : FormulaToken* FormulaFAPToken::GetFAPOrigToken() const { return pOrigToken.get(); }
258 0 : bool FormulaFAPToken::operator==( const FormulaToken& r ) const
259 : {
260 0 : return FormulaByteToken::operator==( r ) && pOrigToken == r.GetFAPOrigToken();
261 : }
262 196 : short* FormulaJumpToken::GetJump() const { return pJump; }
263 0 : bool FormulaJumpToken::operator==( const FormulaToken& r ) const
264 : {
265 0 : return FormulaToken::operator==( r ) && pJump[0] == r.GetJump()[0] &&
266 0 : memcmp( pJump+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0;
267 : }
268 111 : FormulaJumpToken::~FormulaJumpToken()
269 : {
270 37 : delete [] pJump;
271 74 : }
272 :
273 :
274 118 : bool FormulaTokenArray::AddFormulaToken(const sheet::FormulaToken& _aToken,ExternalReferenceHelper* /*_pRef*/)
275 : {
276 118 : bool bError = false;
277 118 : const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode); //! assuming equal values for the moment
278 :
279 118 : const uno::TypeClass eClass = _aToken.Data.getValueTypeClass();
280 118 : switch ( eClass )
281 : {
282 : case uno::TypeClass_VOID:
283 : // empty data -> use AddOpCode (does some special cases)
284 32 : AddOpCode( eOpCode );
285 32 : break;
286 : case uno::TypeClass_DOUBLE:
287 : // double is only used for "push"
288 17 : if ( eOpCode == ocPush )
289 17 : AddDouble( _aToken.Data.get<double>() );
290 : else
291 0 : bError = true;
292 17 : break;
293 : case uno::TypeClass_LONG:
294 : {
295 : // long is svIndex, used for name / database area, or "byte" for spaces
296 2 : sal_Int32 nValue = _aToken.Data.get<sal_Int32>();
297 2 : if ( eOpCode == ocDBArea )
298 0 : AddToken( formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) );
299 2 : else if ( eOpCode == ocSpaces )
300 2 : AddToken( formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) );
301 : else
302 0 : bError = true;
303 : }
304 2 : break;
305 : case uno::TypeClass_STRING:
306 : {
307 2 : String aStrVal( _aToken.Data.get<OUString>() );
308 2 : if ( eOpCode == ocPush )
309 0 : AddString( aStrVal );
310 2 : else if ( eOpCode == ocBad )
311 2 : AddBad( aStrVal );
312 0 : else if ( eOpCode == ocStringXML )
313 0 : AddStringXML( aStrVal );
314 0 : else if ( eOpCode == ocExternal || eOpCode == ocMacro )
315 0 : AddToken( formula::FormulaExternalToken( eOpCode, aStrVal ) );
316 : else
317 0 : bError = true; // unexpected string: don't know what to do with it
318 : }
319 2 : break;
320 : default:
321 65 : bError = true;
322 : } // switch ( eClass )
323 118 : return bError;
324 : }
325 81 : bool FormulaTokenArray::Fill(const uno::Sequence< sheet::FormulaToken >& _aSequence,ExternalReferenceHelper* _pRef)
326 : {
327 81 : bool bError = false;
328 81 : const sal_Int32 nCount = _aSequence.getLength();
329 199 : for (sal_Int32 nPos=0; nPos<nCount; nPos++)
330 : {
331 118 : bool bOneError = AddFormulaToken( _aSequence[nPos] ,_pRef);
332 118 : if (bOneError)
333 : {
334 0 : AddOpCode( ocErrName); // add something that indicates an error
335 0 : bError = true;
336 : }
337 : }
338 81 : return bError;
339 : }
340 2297 : FormulaToken* FormulaTokenArray::GetNextReference()
341 : {
342 5449 : while( nIndex < nLen )
343 : {
344 2312 : FormulaToken* t = pCode[ nIndex++ ];
345 2312 : switch( t->GetType() )
346 : {
347 : case svSingleRef:
348 : case svDoubleRef:
349 : case svExternalSingleRef:
350 : case svExternalDoubleRef:
351 1457 : return t;
352 : default:
353 : {
354 : // added to avoid warnings
355 : }
356 : }
357 : }
358 840 : return NULL;
359 : }
360 :
361 54 : FormulaToken* FormulaTokenArray::GetNextColRowName()
362 : {
363 244 : while( nIndex < nLen )
364 : {
365 136 : FormulaToken* t = pCode[ nIndex++ ];
366 136 : if ( t->GetOpCode() == ocColRowName )
367 0 : return t;
368 : }
369 54 : return NULL;
370 : }
371 :
372 13590 : FormulaToken* FormulaTokenArray::GetNextReferenceRPN()
373 : {
374 42603 : while( nIndex < nRPN )
375 : {
376 24157 : FormulaToken* t = pRPN[ nIndex++ ];
377 24157 : switch( t->GetType() )
378 : {
379 : case svSingleRef:
380 : case svDoubleRef:
381 : case svExternalSingleRef:
382 : case svExternalDoubleRef:
383 8734 : return t;
384 : default:
385 : {
386 : // added to avoid warnings
387 : }
388 : }
389 : }
390 4856 : return NULL;
391 : }
392 :
393 1593 : FormulaToken* FormulaTokenArray::GetNextReferenceOrName()
394 : {
395 1593 : if( pCode )
396 : {
397 5805 : while ( nIndex < nLen )
398 : {
399 3404 : FormulaToken* t = pCode[ nIndex++ ];
400 3404 : switch( t->GetType() )
401 : {
402 : case svSingleRef:
403 : case svDoubleRef:
404 : case svIndex:
405 : case svExternalSingleRef:
406 : case svExternalDoubleRef:
407 : case svExternalName:
408 719 : return t;
409 : default:
410 : {
411 : // added to avoid warnings
412 : }
413 : }
414 : }
415 : }
416 874 : return NULL;
417 : }
418 :
419 797 : FormulaToken* FormulaTokenArray::GetNextName()
420 : {
421 797 : if( pCode )
422 : {
423 4542 : while ( nIndex < nLen )
424 : {
425 3030 : FormulaToken* t = pCode[ nIndex++ ];
426 3030 : if( t->GetType() == svIndex )
427 16 : return t;
428 : }
429 : } // if( pCode )
430 781 : return NULL;
431 : }
432 :
433 24 : FormulaToken* FormulaTokenArray::GetNextOpCodeRPN( OpCode eOp )
434 : {
435 48 : while( nIndex < nRPN )
436 : {
437 0 : FormulaToken* t = pRPN[ nIndex++ ];
438 0 : if ( t->GetOpCode() == eOp )
439 0 : return t;
440 : }
441 24 : return NULL;
442 : }
443 :
444 46261 : FormulaToken* FormulaTokenArray::Next()
445 : {
446 46261 : if( pCode && nIndex < nLen )
447 40600 : return pCode[ nIndex++ ];
448 : else
449 5661 : return NULL;
450 : }
451 :
452 0 : FormulaToken* FormulaTokenArray::NextNoSpaces()
453 : {
454 0 : if( pCode )
455 : {
456 0 : while( (nIndex < nLen) && (pCode[ nIndex ]->GetOpCode() == ocSpaces) )
457 0 : ++nIndex;
458 0 : if( nIndex < nLen )
459 0 : return pCode[ nIndex++ ];
460 : }
461 0 : return NULL;
462 : }
463 :
464 692 : FormulaToken* FormulaTokenArray::NextRPN()
465 : {
466 692 : if( pRPN && nIndex < nRPN )
467 499 : return pRPN[ nIndex++ ];
468 : else
469 193 : return NULL;
470 : }
471 :
472 0 : FormulaToken* FormulaTokenArray::PrevRPN()
473 : {
474 0 : if( pRPN && nIndex )
475 0 : return pRPN[ --nIndex ];
476 : else
477 0 : return NULL;
478 : }
479 :
480 10545 : void FormulaTokenArray::DelRPN()
481 : {
482 10545 : if( nRPN )
483 : {
484 5109 : FormulaToken** p = pRPN;
485 29220 : for( sal_uInt16 i = 0; i < nRPN; i++ )
486 : {
487 24111 : (*p++)->DecRef();
488 : }
489 5109 : delete [] pRPN;
490 : }
491 10545 : pRPN = NULL;
492 10545 : nRPN = nIndex = 0;
493 10545 : }
494 :
495 0 : FormulaToken* FormulaTokenArray::PeekPrev( sal_uInt16 & nIdx )
496 : {
497 0 : if (0 < nIdx && nIdx <= nLen)
498 0 : return pCode[--nIdx];
499 0 : return NULL;
500 : }
501 :
502 0 : FormulaToken* FormulaTokenArray::PeekNext()
503 : {
504 0 : if( pCode && nIndex < nLen )
505 0 : return pCode[ nIndex ];
506 : else
507 0 : return NULL;
508 : }
509 :
510 182 : FormulaToken* FormulaTokenArray::PeekNextNoSpaces()
511 : {
512 182 : if( pCode && nIndex < nLen )
513 : {
514 28 : sal_uInt16 j = nIndex;
515 56 : while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
516 0 : j++;
517 28 : if ( j < nLen )
518 28 : return pCode[ j ];
519 : else
520 0 : return NULL;
521 : }
522 : else
523 154 : return NULL;
524 : }
525 :
526 182 : FormulaToken* FormulaTokenArray::PeekPrevNoSpaces()
527 : {
528 182 : if( pCode && nIndex > 1 )
529 : {
530 25 : sal_uInt16 j = nIndex - 2;
531 50 : while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
532 0 : j--;
533 25 : if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
534 25 : return pCode[ j ];
535 : else
536 0 : return NULL;
537 : }
538 : else
539 157 : return NULL;
540 : }
541 :
542 0 : bool FormulaTokenArray::HasExternalRef() const
543 : {
544 0 : for ( sal_uInt16 j=0; j < nLen; j++ )
545 : {
546 0 : if (pCode[j]->IsExternalRef())
547 0 : return true;
548 : }
549 0 : return false;
550 : }
551 :
552 5112 : bool FormulaTokenArray::HasOpCode( OpCode eOp ) const
553 : {
554 42050 : for ( sal_uInt16 j=0; j < nLen; j++ )
555 : {
556 36939 : if ( pCode[j]->GetOpCode() == eOp )
557 1 : return true;
558 : }
559 5111 : return false;
560 : }
561 :
562 395 : bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp ) const
563 : {
564 1421 : for ( sal_uInt16 j=0; j < nRPN; j++ )
565 : {
566 1026 : if ( pRPN[j]->GetOpCode() == eOp )
567 0 : return true;
568 : }
569 395 : return false;
570 : }
571 :
572 0 : bool FormulaTokenArray::HasNameOrColRowName() const
573 : {
574 0 : for ( sal_uInt16 j=0; j < nLen; j++ )
575 : {
576 0 : if( pCode[j]->GetType() == svIndex || pCode[j]->GetOpCode() == ocColRowName )
577 0 : return true;
578 : }
579 0 : return false;
580 : }
581 :
582 :
583 5770 : FormulaTokenArray::FormulaTokenArray() :
584 : pCode(NULL),
585 : pRPN(NULL),
586 : nLen(0),
587 : nRPN(0),
588 : nIndex(0),
589 : nError(0),
590 : nRefs(0),
591 : nMode(RECALCMODE_NORMAL),
592 5770 : bHyperLink(false)
593 : {
594 5770 : }
595 :
596 7485 : FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray& rArr )
597 : {
598 7485 : Assign( rArr );
599 7485 : }
600 :
601 12796 : FormulaTokenArray::~FormulaTokenArray()
602 : {
603 12796 : Clear();
604 12796 : }
605 :
606 7485 : void FormulaTokenArray::Assign( const FormulaTokenArray& r )
607 : {
608 7485 : nLen = r.nLen;
609 7485 : nRPN = r.nRPN;
610 7485 : nIndex = r.nIndex;
611 7485 : nError = r.nError;
612 7485 : nRefs = r.nRefs;
613 7485 : nMode = r.nMode;
614 7485 : bHyperLink = r.bHyperLink;
615 7485 : pCode = NULL;
616 7485 : pRPN = NULL;
617 : FormulaToken** pp;
618 7485 : if( nLen )
619 : {
620 7474 : pp = pCode = new FormulaToken*[ nLen ];
621 7474 : memcpy( pp, r.pCode, nLen * sizeof( FormulaToken* ) );
622 46061 : for( sal_uInt16 i = 0; i < nLen; i++ )
623 38587 : (*pp++)->IncRef();
624 : }
625 7485 : if( nRPN )
626 : {
627 0 : pp = pRPN = new FormulaToken*[ nRPN ];
628 0 : memcpy( pp, r.pRPN, nRPN * sizeof( FormulaToken* ) );
629 0 : for( sal_uInt16 i = 0; i < nRPN; i++ )
630 0 : (*pp++)->IncRef();
631 : }
632 7485 : }
633 :
634 0 : FormulaTokenArray& FormulaTokenArray::operator=( const FormulaTokenArray& rArr )
635 : {
636 0 : Clear();
637 0 : Assign( rArr );
638 0 : return *this;
639 : }
640 :
641 0 : FormulaTokenArray* FormulaTokenArray::Clone() const
642 : {
643 0 : FormulaTokenArray* p = new FormulaTokenArray;
644 0 : p->nLen = nLen;
645 0 : p->nRPN = nRPN;
646 0 : p->nRefs = nRefs;
647 0 : p->nMode = nMode;
648 0 : p->nError = nError;
649 0 : p->bHyperLink = bHyperLink;
650 : FormulaToken** pp;
651 0 : if( nLen )
652 : {
653 0 : pp = p->pCode = new FormulaToken*[ nLen ];
654 0 : memcpy( pp, pCode, nLen * sizeof( FormulaToken* ) );
655 0 : for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
656 : {
657 0 : *pp = (*pp)->Clone();
658 0 : (*pp)->IncRef();
659 : }
660 : }
661 0 : if( nRPN )
662 : {
663 0 : pp = p->pRPN = new FormulaToken*[ nRPN ];
664 0 : memcpy( pp, pRPN, nRPN * sizeof( FormulaToken* ) );
665 0 : for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
666 : {
667 0 : FormulaToken* t = *pp;
668 0 : if( t->GetRef() > 1 )
669 : {
670 0 : FormulaToken** p2 = pCode;
671 0 : sal_uInt16 nIdx = 0xFFFF;
672 0 : for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
673 : {
674 0 : if( *p2 == t )
675 : {
676 0 : nIdx = j; break;
677 : }
678 : }
679 0 : if( nIdx == 0xFFFF )
680 0 : *pp = t->Clone();
681 : else
682 0 : *pp = p->pCode[ nIdx ];
683 : }
684 : else
685 0 : *pp = t->Clone();
686 0 : (*pp)->IncRef();
687 : }
688 : }
689 0 : return p;
690 : }
691 :
692 15846 : void FormulaTokenArray::Clear()
693 : {
694 15846 : if( nRPN ) DelRPN();
695 15846 : if( pCode )
696 : {
697 15273 : FormulaToken** p = pCode;
698 94255 : for( sal_uInt16 i = 0; i < nLen; i++ )
699 : {
700 78982 : (*p++)->DecRef();
701 : }
702 15273 : delete [] pCode;
703 : }
704 15846 : pCode = NULL; pRPN = NULL;
705 15846 : nError = nLen = nIndex = nRPN = nRefs = 0;
706 15846 : bHyperLink = false;
707 15846 : ClearRecalcMode();
708 15846 : }
709 :
710 0 : void FormulaTokenArray::CheckToken( const FormulaToken& /*r*/ )
711 : {
712 : // Do nothing.
713 0 : }
714 :
715 27 : FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r )
716 : {
717 27 : return Add( r.Clone() );
718 : }
719 :
720 0 : FormulaToken* FormulaTokenArray::MergeArray( )
721 : {
722 0 : return NULL;
723 : }
724 :
725 37800 : FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
726 : {
727 37800 : if( !pCode )
728 6665 : pCode = new FormulaToken*[ FORMULA_MAXTOKENS ];
729 37800 : if( nLen < FORMULA_MAXTOKENS - 1 )
730 : {
731 37800 : CheckToken(*t);
732 37800 : pCode[ nLen++ ] = t;
733 75600 : if( t->GetOpCode() == ocPush
734 37800 : && ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
735 9606 : nRefs++;
736 37800 : t->IncRef();
737 37800 : if( t->GetOpCode() == ocArrayClose )
738 5 : return MergeArray();
739 37795 : return t;
740 : }
741 : else
742 : {
743 0 : t->Delete();
744 0 : if ( nLen == FORMULA_MAXTOKENS - 1 )
745 : {
746 0 : t = new FormulaByteToken( ocStop );
747 0 : pCode[ nLen++ ] = t;
748 0 : t->IncRef();
749 : }
750 0 : return NULL;
751 : }
752 : }
753 :
754 0 : FormulaToken* FormulaTokenArray::AddString( const sal_Unicode* pStr )
755 : {
756 0 : return AddString( OUString( pStr ) );
757 : }
758 :
759 2694 : FormulaToken* FormulaTokenArray::AddString( const String& rStr )
760 : {
761 2694 : return Add( new FormulaStringToken( rStr ) );
762 : }
763 :
764 1120 : FormulaToken* FormulaTokenArray::AddDouble( double fVal )
765 : {
766 1120 : return Add( new FormulaDoubleToken( fVal ) );
767 : }
768 :
769 0 : FormulaToken* FormulaTokenArray::AddExternal( const sal_Unicode* pStr )
770 : {
771 0 : return AddExternal( OUString( pStr ) );
772 : }
773 :
774 1 : FormulaToken* FormulaTokenArray::AddExternal( const String& rStr,
775 : OpCode eOp /* = ocExternal */ )
776 : {
777 1 : return Add( new FormulaExternalToken( eOp, rStr ) );
778 : }
779 :
780 2 : FormulaToken* FormulaTokenArray::AddBad( const String& rStr )
781 : {
782 2 : return Add( new FormulaStringOpToken( ocBad, rStr ) );
783 : }
784 :
785 445 : FormulaToken* FormulaTokenArray::AddStringXML( const String& rStr )
786 : {
787 445 : return Add( new FormulaStringOpToken( ocStringXML, rStr ) );
788 : }
789 :
790 :
791 :
792 65 : void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
793 : {
794 : //! Reihenfolge ist wichtig
795 65 : if ( nBits & RECALCMODE_ALWAYS )
796 0 : SetExclusiveRecalcModeAlways();
797 65 : else if ( !IsRecalcModeAlways() )
798 : {
799 65 : if ( nBits & RECALCMODE_ONLOAD )
800 45 : SetExclusiveRecalcModeOnLoad();
801 20 : else if ( nBits & RECALCMODE_ONLOAD_ONCE && !IsRecalcModeOnLoad() )
802 0 : SetExclusiveRecalcModeOnLoadOnce();
803 : }
804 65 : SetCombinedBitsRecalcMode( nBits );
805 65 : }
806 :
807 :
808 0 : bool FormulaTokenArray::HasMatrixDoubleRefOps()
809 : {
810 0 : if ( pRPN && nRPN )
811 : {
812 : // RPN-Interpreter Simulation
813 : // als Ergebnis jeder Funktion wird einfach ein Double angenommen
814 0 : FormulaToken** pStack = new FormulaToken* [nRPN];
815 0 : FormulaToken* pResult = new FormulaDoubleToken( 0.0 );
816 0 : short sp = 0;
817 0 : for ( sal_uInt16 j = 0; j < nRPN; j++ )
818 : {
819 0 : FormulaToken* t = pRPN[j];
820 0 : OpCode eOp = t->GetOpCode();
821 0 : sal_uInt8 nParams = t->GetParamCount();
822 0 : switch ( eOp )
823 : {
824 : case ocAdd :
825 : case ocSub :
826 : case ocMul :
827 : case ocDiv :
828 : case ocPow :
829 : case ocPower :
830 : case ocAmpersand :
831 : case ocEqual :
832 : case ocNotEqual :
833 : case ocLess :
834 : case ocGreater :
835 : case ocLessEqual :
836 : case ocGreaterEqual :
837 : {
838 0 : for ( sal_uInt8 k = nParams; k; k-- )
839 : {
840 0 : if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
841 : {
842 0 : pResult->Delete();
843 0 : delete [] pStack;
844 0 : return true;
845 : }
846 : }
847 : }
848 0 : break;
849 : default:
850 : {
851 : // added to avoid warnings
852 : }
853 : }
854 0 : if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() ) )
855 0 : pStack[sp++] = t;
856 0 : else if ( eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose )
857 : { // ignore Jumps, pop previous Result (Condition)
858 0 : if ( sp )
859 0 : --sp;
860 : }
861 : else
862 : { // pop parameters, push result
863 0 : sp = sal::static_int_cast<short>( sp - nParams );
864 0 : if ( sp < 0 )
865 : {
866 : OSL_FAIL( "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
867 0 : sp = 0;
868 : }
869 0 : pStack[sp++] = pResult;
870 : }
871 : }
872 0 : pResult->Delete();
873 0 : delete [] pStack;
874 : }
875 :
876 0 : return false;
877 : }
878 :
879 :
880 :
881 : // --- POF (plain old formula) rewrite of a token array ---------------------
882 :
883 599 : inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
884 : {
885 599 : switch (eOp)
886 : {
887 : case ocGammaDist:
888 : case ocPoissonDist:
889 : case ocAddress:
890 : case ocLogNormDist:
891 : case ocNormDist:
892 0 : return true;
893 : case ocMissing:
894 : case ocLog:
895 0 : return !isODFF(); // rewrite only for PODF
896 : default:
897 599 : return false;
898 : }
899 : }
900 :
901 : class FormulaMissingContext
902 : {
903 : public:
904 : const FormulaToken* mpFunc;
905 : int mnCurArg;
906 :
907 0 : void Clear() { mpFunc = NULL; mnCurArg = 0; }
908 : inline bool AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const;
909 : bool AddMissingExternal( FormulaTokenArray* pNewArr ) const;
910 : bool AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
911 : void AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
912 : };
913 :
914 0 : void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const
915 : {
916 0 : if ( !mpFunc )
917 0 : return;
918 :
919 0 : switch (mpFunc->GetOpCode())
920 : {
921 : case ocGammaDist:
922 0 : if (mnCurArg == 2)
923 : {
924 0 : pNewArr->AddOpCode( ocSep );
925 0 : pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
926 : }
927 0 : break;
928 : case ocPoissonDist:
929 0 : if (mnCurArg == 1)
930 : {
931 0 : pNewArr->AddOpCode( ocSep );
932 0 : pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
933 : }
934 0 : break;
935 : case ocNormDist:
936 0 : if ( mnCurArg == 2 )
937 : {
938 0 : pNewArr->AddOpCode( ocSep );
939 0 : pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
940 : }
941 0 : break;
942 : case ocLogNormDist:
943 0 : if ( mnCurArg == 0 )
944 : {
945 0 : pNewArr->AddOpCode( ocSep );
946 0 : pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
947 : }
948 0 : if ( mnCurArg <= 1 )
949 : {
950 0 : pNewArr->AddOpCode( ocSep );
951 0 : pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
952 : }
953 0 : break;
954 : case ocLog:
955 0 : if ( !rConv.isODFF() && mnCurArg == 0 )
956 : {
957 0 : pNewArr->AddOpCode( ocSep );
958 0 : pNewArr->AddDouble( 10.0 ); // 2nd, basis 10
959 : }
960 0 : break;
961 : default:
962 0 : break;
963 : }
964 : }
965 :
966 0 : inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
967 : {
968 0 : if (mnCurArg == nArg)
969 : {
970 0 : pNewArr->AddDouble( f );
971 0 : return true;
972 : }
973 0 : return false;
974 : }
975 :
976 0 : bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray *pNewArr ) const
977 : {
978 : // Only called for PODF, not ODFF. No need to distinguish.
979 :
980 0 : const String &rName = mpFunc->GetExternal();
981 :
982 : // initial (fast) check:
983 0 : sal_Unicode nLastChar = rName.GetChar( rName.Len() - 1);
984 0 : if ( nLastChar != 't' && nLastChar != 'm' )
985 0 : return false;
986 :
987 0 : if (rName.EqualsIgnoreCaseAscii(
988 0 : "com.sun.star.sheet.addin.Analysis.getAccrint" ))
989 : {
990 0 : return AddDefaultArg( pNewArr, 4, 1000.0 );
991 : }
992 0 : if (rName.EqualsIgnoreCaseAscii(
993 0 : "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
994 : {
995 0 : return AddDefaultArg( pNewArr, 3, 1000.0 );
996 : }
997 0 : return false;
998 : }
999 :
1000 0 : bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const
1001 : {
1002 0 : if ( !mpFunc )
1003 0 : return false;
1004 :
1005 0 : bool bRet = false;
1006 0 : const OpCode eOp = mpFunc->GetOpCode();
1007 :
1008 : // Add for both, PODF and ODFF
1009 0 : switch (eOp)
1010 : {
1011 : case ocAddress:
1012 0 : return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
1013 : default:
1014 0 : break;
1015 : }
1016 :
1017 0 : if (rConv.isODFF())
1018 : {
1019 : // Add for ODFF
1020 : }
1021 : else
1022 : {
1023 : // Add for PODF
1024 0 : switch (eOp)
1025 : {
1026 : case ocFixed:
1027 0 : return AddDefaultArg( pNewArr, 1, 2.0 );
1028 : case ocBetaDist:
1029 : case ocBetaInv:
1030 : case ocRMZ: // PMT
1031 0 : return AddDefaultArg( pNewArr, 3, 0.0 );
1032 : case ocZinsZ: // IPMT
1033 : case ocKapz: // PPMT
1034 0 : return AddDefaultArg( pNewArr, 4, 0.0 );
1035 : case ocBW: // PV
1036 : case ocZW: // FV
1037 0 : bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
1038 0 : bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
1039 0 : break;
1040 : case ocZins: // RATE
1041 0 : bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
1042 0 : bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
1043 0 : bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
1044 0 : break;
1045 : case ocExternal:
1046 0 : return AddMissingExternal( pNewArr );
1047 :
1048 : // --- more complex cases ---
1049 :
1050 : case ocOffset:
1051 : // FIXME: rather tough.
1052 : // if arg 3 (height) ommitted, export arg1 (rows)
1053 0 : break;
1054 : default:
1055 0 : break;
1056 : }
1057 : }
1058 :
1059 0 : return bRet;
1060 : }
1061 :
1062 209 : bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
1063 : {
1064 808 : for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
1065 : {
1066 599 : if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
1067 0 : return true;
1068 : }
1069 209 : return false;
1070 : }
1071 :
1072 :
1073 0 : FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvention & rConv )
1074 : {
1075 0 : const size_t nAlloc = 256;
1076 : FormulaMissingContext aCtx[ nAlloc ];
1077 : int aOpCodeAddressStack[ nAlloc ]; // use of ADDRESS() function
1078 0 : const int nOmitAddressArg = 3; // ADDRESS() 4th parameter A1/R1C1
1079 0 : sal_uInt16 nTokens = GetLen() + 1;
1080 0 : FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
1081 0 : int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
1082 : // Never go below 0, never use 0, mpFunc always NULL.
1083 0 : pCtx[0].Clear();
1084 0 : int nFn = 0;
1085 0 : int nOcas = 0;
1086 :
1087 0 : FormulaTokenArray *pNewArr = new FormulaTokenArray;
1088 : // At least RECALCMODE_ALWAYS needs to be set.
1089 0 : pNewArr->AddRecalcMode( GetRecalcMode());
1090 :
1091 0 : for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
1092 : {
1093 0 : bool bAdd = true;
1094 : // Don't write the expression of the new inserted ADDRESS() parameter.
1095 : // Do NOT omit the new second parameter of INDIRECT() though. If that
1096 : // was done for both, INDIRECT() actually could calculate different and
1097 : // valid (but wrong) results with the then changed return value of
1098 : // ADDRESS(). Better let it generate an error instead.
1099 0 : for (int i = nOcas; i-- > 0 && bAdd; )
1100 : {
1101 0 : if (pCtx[ pOcas[ i ] ].mnCurArg == nOmitAddressArg)
1102 : {
1103 : // Omit erverything except a trailing separator, the leading
1104 : // separator is omitted below. The other way around would leave
1105 : // an extraneous separator if no parameter followed.
1106 0 : if (!(pOcas[ i ] == nFn && pCur->GetOpCode() == ocSep))
1107 0 : bAdd = false;
1108 : }
1109 : }
1110 0 : switch ( pCur->GetOpCode() )
1111 : {
1112 : case ocOpen:
1113 0 : ++nFn; // all following operations on _that_ function
1114 0 : pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
1115 0 : pCtx[ nFn ].mnCurArg = 0;
1116 0 : if (pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress && !rConv.isODFF())
1117 0 : pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
1118 0 : break;
1119 : case ocClose:
1120 0 : pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
1121 : DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissingToPof: underflow");
1122 0 : if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
1123 0 : --nOcas; // leaving ADDRESS()
1124 0 : if (nFn > 0)
1125 0 : --nFn;
1126 0 : break;
1127 : case ocSep:
1128 0 : pCtx[ nFn ].mnCurArg++;
1129 : // Omit leading separator of ADDRESS() parameter.
1130 0 : if (nOcas && pOcas[ nOcas-1 ] == nFn && pCtx[ nFn ].mnCurArg == nOmitAddressArg)
1131 : {
1132 0 : bAdd = false;
1133 : }
1134 0 : break;
1135 : case ocMissing:
1136 0 : if (bAdd)
1137 0 : bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
1138 0 : break;
1139 : default:
1140 0 : break;
1141 : }
1142 0 : if (bAdd)
1143 0 : pNewArr->AddToken( *pCur );
1144 : }
1145 :
1146 0 : if (pOcas != &aOpCodeAddressStack[0])
1147 0 : delete [] pOcas;
1148 0 : if (pCtx != &aCtx[0])
1149 0 : delete [] pCtx;
1150 :
1151 0 : return pNewArr;
1152 : }
1153 :
1154 0 : bool FormulaTokenArray::MayReferenceFollow()
1155 : {
1156 0 : if ( pCode && nLen > 0 )
1157 : {
1158 : // ignore trailing spaces
1159 0 : sal_uInt16 i = nLen - 1;
1160 0 : while ( i > 0 && pCode[i]->GetOpCode() == SC_OPCODE_SPACES )
1161 : {
1162 0 : --i;
1163 : }
1164 0 : if ( i > 0 || pCode[i]->GetOpCode() != SC_OPCODE_SPACES )
1165 : {
1166 0 : OpCode eOp = pCode[i]->GetOpCode();
1167 0 : if ( (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) ||
1168 0 : (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP ) ||
1169 0 : eOp == SC_OPCODE_OPEN || eOp == SC_OPCODE_SEP )
1170 : {
1171 0 : return true;
1172 : }
1173 : }
1174 : }
1175 0 : return false;
1176 : }
1177 0 : FormulaToken* FormulaTokenArray::AddOpCode( OpCode eOp )
1178 : {
1179 0 : FormulaToken* pRet = NULL;
1180 0 : switch ( eOp )
1181 : {
1182 : case ocOpen:
1183 : case ocClose:
1184 : case ocSep:
1185 : case ocArrayOpen:
1186 : case ocArrayClose:
1187 : case ocArrayRowSep:
1188 : case ocArrayColSep:
1189 0 : pRet = new FormulaToken( svSep,eOp );
1190 0 : break;
1191 : case ocIf:
1192 : case ocIfError:
1193 : case ocIfNA:
1194 : case ocChose:
1195 : {
1196 : short nJump[FORMULA_MAXJUMPCOUNT + 1];
1197 0 : if ( eOp == ocIf )
1198 0 : nJump[ 0 ] = 3;
1199 0 : else if ( eOp == ocChose )
1200 0 : nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
1201 : else
1202 0 : nJump[ 0 ] = 2;
1203 0 : pRet = new FormulaJumpToken( eOp, (short*)nJump );
1204 : }
1205 0 : break;
1206 : default:
1207 0 : pRet = new FormulaByteToken( eOp, 0, false );
1208 0 : break;
1209 : }
1210 0 : return AddToken( *pRet );
1211 : }
1212 :
1213 :
1214 : /*----------------------------------------------------------------------*/
1215 :
1216 4634 : FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray& rArr )
1217 : {
1218 4634 : pCur = NULL;
1219 4634 : Push( &rArr );
1220 4634 : }
1221 :
1222 4634 : FormulaTokenIterator::~FormulaTokenIterator()
1223 : {
1224 13902 : while( pCur )
1225 4634 : Pop();
1226 4634 : }
1227 :
1228 4655 : void FormulaTokenIterator::Push( const FormulaTokenArray* pArr )
1229 : {
1230 4655 : ImpTokenIterator* p = new ImpTokenIterator;
1231 4655 : p->pArr = pArr;
1232 4655 : p->nPC = -1;
1233 4655 : p->nStop = SHRT_MAX;
1234 4655 : p->pNext = pCur;
1235 4655 : pCur = p;
1236 4655 : }
1237 :
1238 4655 : void FormulaTokenIterator::Pop()
1239 : {
1240 4655 : ImpTokenIterator* p = pCur;
1241 4655 : if( p )
1242 : {
1243 4655 : pCur = p->pNext;
1244 4655 : delete p;
1245 : }
1246 4655 : }
1247 :
1248 4634 : void FormulaTokenIterator::Reset()
1249 : {
1250 9268 : while( pCur->pNext )
1251 0 : Pop();
1252 4634 : pCur->nPC = -1;
1253 4634 : }
1254 :
1255 21259 : const FormulaToken* FormulaTokenIterator::Next()
1256 : {
1257 21259 : const FormulaToken* t = GetNonEndOfPathToken( ++pCur->nPC );
1258 21259 : if( !t && pCur->pNext )
1259 : {
1260 20 : Pop();
1261 20 : t = Next();
1262 : }
1263 21259 : return t;
1264 : }
1265 :
1266 0 : const FormulaToken* FormulaTokenIterator::PeekNextOperator()
1267 : {
1268 0 : const FormulaToken* t = NULL;
1269 0 : short nIdx = pCur->nPC;
1270 0 : while (!t && ((t = GetNonEndOfPathToken( ++nIdx)) != NULL))
1271 : {
1272 0 : if (t->GetOpCode() == ocPush)
1273 0 : t = NULL; // ignore operands
1274 : }
1275 0 : if (!t && pCur->pNext)
1276 : {
1277 0 : ImpTokenIterator* pHere = pCur;
1278 0 : pCur = pCur->pNext;
1279 0 : t = PeekNextOperator();
1280 0 : pCur = pHere;
1281 : }
1282 0 : return t;
1283 : }
1284 :
1285 : //! The nPC counts after a Push() are -1
1286 :
1287 32 : void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
1288 : {
1289 32 : pCur->nPC = nNext;
1290 32 : if( nStart != nNext )
1291 : {
1292 21 : Push( pCur->pArr );
1293 21 : pCur->nPC = nStart;
1294 21 : pCur->nStop = nStop;
1295 : }
1296 32 : }
1297 :
1298 21260 : const FormulaToken* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx ) const
1299 : {
1300 21260 : if (nIdx < pCur->pArr->nRPN && nIdx < pCur->nStop)
1301 : {
1302 16628 : const FormulaToken* t = pCur->pArr->pRPN[ nIdx ];
1303 : // such an OpCode ends an IF() or CHOOSE() path
1304 16628 : return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? NULL : t;
1305 : }
1306 4632 : return NULL;
1307 : }
1308 :
1309 1 : bool FormulaTokenIterator::IsEndOfPath() const
1310 : {
1311 1 : return GetNonEndOfPathToken( pCur->nPC + 1) == NULL;
1312 : }
1313 :
1314 : // -----------------------------------------------------------------------------
1315 : // ==========================================================================
1316 : // real implementations of virtual functions
1317 : // --------------------------------------------------------------------------
1318 :
1319 11334 : double FormulaDoubleToken::GetDouble() const { return fDouble; }
1320 0 : double & FormulaDoubleToken::GetDoubleAsReference() { return fDouble; }
1321 0 : bool FormulaDoubleToken::operator==( const FormulaToken& r ) const
1322 : {
1323 0 : return FormulaToken::operator==( r ) && fDouble == r.GetDouble();
1324 : }
1325 :
1326 :
1327 2149 : const String& FormulaStringToken::GetString() const { return aString; }
1328 0 : bool FormulaStringToken::operator==( const FormulaToken& r ) const
1329 : {
1330 0 : return FormulaToken::operator==( r ) && aString == r.GetString();
1331 : }
1332 :
1333 :
1334 451 : const String& FormulaStringOpToken::GetString() const { return aString; }
1335 22 : bool FormulaStringOpToken::operator==( const FormulaToken& r ) const
1336 : {
1337 22 : return FormulaByteToken::operator==( r ) && aString == r.GetString();
1338 : }
1339 :
1340 242 : sal_uInt16 FormulaIndexToken::GetIndex() const { return nIndex; }
1341 10 : void FormulaIndexToken::SetIndex( sal_uInt16 n ) { nIndex = n; }
1342 229 : bool FormulaIndexToken::IsGlobal() const { return mbGlobal; }
1343 10 : void FormulaIndexToken::SetGlobal( bool b ) { mbGlobal = b; }
1344 0 : bool FormulaIndexToken::operator==( const FormulaToken& r ) const
1345 : {
1346 0 : return FormulaToken::operator==( r ) && nIndex == r.GetIndex() &&
1347 0 : mbGlobal == r.IsGlobal();
1348 : }
1349 0 : const String& FormulaExternalToken::GetExternal() const { return aExternal; }
1350 0 : sal_uInt8 FormulaExternalToken::GetByte() const { return nByte; }
1351 1 : void FormulaExternalToken::SetByte( sal_uInt8 n ) { nByte = n; }
1352 0 : bool FormulaExternalToken::operator==( const FormulaToken& r ) const
1353 : {
1354 0 : return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
1355 0 : aExternal == r.GetExternal();
1356 : }
1357 :
1358 :
1359 601 : sal_uInt16 FormulaErrorToken::GetError() const { return nError; }
1360 0 : void FormulaErrorToken::SetError( sal_uInt16 nErr ) { nError = nErr; }
1361 0 : bool FormulaErrorToken::operator==( const FormulaToken& r ) const
1362 : {
1363 0 : return FormulaToken::operator==( r ) &&
1364 0 : nError == static_cast< const FormulaErrorToken & >(r).GetError();
1365 : }
1366 0 : double FormulaMissingToken::GetDouble() const { return 0.0; }
1367 0 : const String& FormulaMissingToken::GetString() const
1368 : {
1369 0 : static String aDummyString;
1370 0 : return aDummyString;
1371 : }
1372 0 : bool FormulaMissingToken::operator==( const FormulaToken& r ) const
1373 : {
1374 0 : return FormulaToken::operator==( r );
1375 : }
1376 :
1377 :
1378 0 : FormulaSubroutineToken::FormulaSubroutineToken( const FormulaSubroutineToken& r ) :
1379 : FormulaToken( r ),
1380 0 : mpArray( r.mpArray->Clone())
1381 : {
1382 0 : }
1383 0 : FormulaSubroutineToken::~FormulaSubroutineToken()
1384 : {
1385 0 : delete mpArray;
1386 0 : }
1387 0 : bool FormulaSubroutineToken::operator==( const FormulaToken& r ) const
1388 : {
1389 : // Arrays don't equal..
1390 0 : return FormulaToken::operator==( r ) &&
1391 0 : (mpArray == static_cast<const FormulaSubroutineToken&>(r).mpArray);
1392 : }
1393 :
1394 :
1395 0 : bool FormulaUnknownToken::operator==( const FormulaToken& r ) const
1396 : {
1397 0 : return FormulaToken::operator==( r );
1398 : }
1399 :
1400 : // -----------------------------------------------------------------------------
1401 99 : } // formula
1402 : // -----------------------------------------------------------------------------
1403 :
1404 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|