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 : #define MAXJUMPCOUNT 32 /* maximum number of jumps (ocChose) */
33 :
34 : namespace formula
35 : {
36 : using namespace com::sun::star;
37 : // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
38 : // SubCode via FormulaTokenIterator Push/Pop moeglich
39 38 : IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator )
40 :
41 : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
42 :
43 : // Need a lot of FormulaDoubleToken
44 29910 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaDoubleToken )
45 : // Need a lot of FormulaByteToken
46 50214 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaByteToken )
47 : // Need several FormulaStringToken
48 11406 : IMPL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaStringToken )
49 :
50 :
51 : // --- helpers --------------------------------------------------------------
52 :
53 0 : inline bool lcl_IsReference( OpCode eOp, StackVar eType )
54 : {
55 : return
56 : (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
57 : || (eOp == ocColRowNameAuto && eType == svDoubleRef)
58 : || (eOp == ocColRowName && eType == svSingleRef)
59 0 : || (eOp == ocMatRef && eType == svSingleRef)
60 : ;
61 : }
62 :
63 : // --- class FormulaToken --------------------------------------------------------
64 113714 : FormulaToken::~FormulaToken()
65 : {
66 113714 : }
67 :
68 0 : bool FormulaToken::Is3DRef() const
69 : {
70 0 : return false;
71 : }
72 :
73 0 : bool FormulaToken::IsFunction() const
74 : {
75 : return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
76 : eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
77 0 : (GetByte() != 0 // x parameters
78 : || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) // no parameter
79 : || (ocIf == eOp || ocChose == eOp ) // @ jump commands
80 : || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) // one parameter
81 : || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) // x parameters (cByte==0 in
82 : // FuncAutoPilot)
83 : || eOp == ocMacro || eOp == ocExternal // macros, AddIns
84 : || eOp == ocAnd || eOp == ocOr // former binary, now x parameters
85 : || eOp == ocNot || eOp == ocNeg // unary but function
86 : || (eOp >= ocInternalBegin && eOp <= ocInternalEnd) // internal
87 0 : ));
88 : }
89 :
90 :
91 11714 : sal_uInt8 FormulaToken::GetParamCount() const
92 : {
93 11714 : if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
94 : eOp != ocIf && eOp != ocChose && eOp != ocPercentSign )
95 106 : return 0; // parameters and specials
96 : // ocIf and ocChose not for FAP, have cByte then
97 : //2do: bool parameter whether FAP or not?
98 11608 : else if ( GetByte() )
99 2284 : return GetByte(); // all functions, also ocExternal and ocMacro
100 9324 : else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
101 9158 : return 2; // binary
102 166 : else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
103 : || eOp == ocPercentSign)
104 94 : return 1; // unary
105 72 : else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
106 62 : return 0; // no parameter
107 10 : else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
108 0 : return 1; // one parameter
109 10 : else if ( eOp == ocIf || eOp == ocChose )
110 0 : return 1; // only the condition counts as parameter
111 : else
112 10 : return 0; // all the rest, no Parameter, or
113 : // if so then it should be in cByte
114 : }
115 :
116 68284 : bool FormulaToken::IsExternalRef() const
117 : {
118 68284 : bool bRet = false;
119 68284 : switch (eType)
120 : {
121 : case svExternalSingleRef:
122 : case svExternalDoubleRef:
123 : case svExternalName:
124 82 : bRet = true;
125 82 : break;
126 : default:
127 68202 : bRet = false;
128 68202 : break;
129 : }
130 68284 : return bRet;
131 : }
132 :
133 56 : bool FormulaToken::operator==( const FormulaToken& rToken ) const
134 : {
135 : // don't compare reference count!
136 56 : return eType == rToken.eType && GetOpCode() == rToken.GetOpCode();
137 : }
138 :
139 :
140 : // --- virtual dummy methods -------------------------------------------------
141 :
142 16156 : sal_uInt8 FormulaToken::GetByte() const
143 : {
144 : // ok to be called for any derived class
145 16156 : 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 328 : bool FormulaToken::HasForceArray() const
154 : {
155 : // ok to be called for any derived class
156 328 : 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 4 : bool FormulaToken::TextEqual( const FormulaToken& rToken ) const
238 : {
239 4 : return *this == rToken;
240 : }
241 : // ==========================================================================
242 : // real implementations of virtual functions
243 : // --------------------------------------------------------------------------
244 :
245 :
246 25514 : sal_uInt8 FormulaByteToken::GetByte() const { return nByte; }
247 7100 : void FormulaByteToken::SetByte( sal_uInt8 n ) { nByte = n; }
248 32332 : bool FormulaByteToken::HasForceArray() const { return bHasForceArray; }
249 0 : void FormulaByteToken::SetForceArray( bool b ) { bHasForceArray = b; }
250 48 : bool FormulaByteToken::operator==( const FormulaToken& r ) const
251 : {
252 96 : return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
253 96 : 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 200 : 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 78 : FormulaJumpToken::~FormulaJumpToken()
269 : {
270 26 : delete [] pJump;
271 52 : }
272 :
273 :
274 250 : bool FormulaTokenArray::AddFormulaToken(const sheet::FormulaToken& _aToken,ExternalReferenceHelper* /*_pRef*/)
275 : {
276 250 : bool bError = false;
277 250 : const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode); //! assuming equal values for the moment
278 :
279 250 : const uno::TypeClass eClass = _aToken.Data.getValueTypeClass();
280 250 : switch ( eClass )
281 : {
282 : case uno::TypeClass_VOID:
283 : // empty data -> use AddOpCode (does some special cases)
284 90 : AddOpCode( eOpCode );
285 90 : break;
286 : case uno::TypeClass_DOUBLE:
287 : // double is only used for "push"
288 60 : if ( eOpCode == ocPush )
289 60 : AddDouble( _aToken.Data.get<double>() );
290 : else
291 0 : bError = true;
292 60 : break;
293 : case uno::TypeClass_LONG:
294 : {
295 : // long is svIndex, used for name / database area, or "byte" for spaces
296 4 : sal_Int32 nValue = _aToken.Data.get<sal_Int32>();
297 4 : if ( eOpCode == ocDBArea )
298 0 : AddToken( formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) );
299 4 : else if ( eOpCode == ocSpaces )
300 4 : AddToken( formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) );
301 : else
302 0 : bError = true;
303 : }
304 4 : break;
305 : case uno::TypeClass_STRING:
306 : {
307 6 : String aStrVal( _aToken.Data.get<rtl::OUString>() );
308 6 : if ( eOpCode == ocPush )
309 0 : AddString( aStrVal );
310 6 : else if ( eOpCode == ocBad )
311 6 : 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 6 : break;
320 : default:
321 90 : bError = true;
322 : } // switch ( eClass )
323 250 : return bError;
324 : }
325 152 : bool FormulaTokenArray::Fill(const uno::Sequence< sheet::FormulaToken >& _aSequence,ExternalReferenceHelper* _pRef)
326 : {
327 152 : bool bError = false;
328 152 : const sal_Int32 nCount = _aSequence.getLength();
329 402 : for (sal_Int32 nPos=0; nPos<nCount; nPos++)
330 : {
331 250 : bool bOneError = AddFormulaToken( _aSequence[nPos] ,_pRef);
332 250 : if (bOneError)
333 : {
334 0 : AddOpCode( ocErrName); // add something that indicates an error
335 0 : bError = true;
336 : }
337 : }
338 152 : return bError;
339 : }
340 2724 : FormulaToken* FormulaTokenArray::GetNextReference()
341 : {
342 6884 : while( nIndex < nLen )
343 : {
344 3288 : FormulaToken* t = pCode[ nIndex++ ];
345 3288 : switch( t->GetType() )
346 : {
347 : case svSingleRef:
348 : case svDoubleRef:
349 : case svExternalSingleRef:
350 : case svExternalDoubleRef:
351 1852 : return t;
352 : default:
353 : {
354 : // added to avoid warnings
355 : }
356 : }
357 : }
358 872 : return NULL;
359 : }
360 :
361 76 : FormulaToken* FormulaTokenArray::GetNextColRowName()
362 : {
363 304 : while( nIndex < nLen )
364 : {
365 152 : FormulaToken* t = pCode[ nIndex++ ];
366 152 : if ( t->GetOpCode() == ocColRowName )
367 0 : return t;
368 : }
369 76 : return NULL;
370 : }
371 :
372 22434 : FormulaToken* FormulaTokenArray::GetNextReferenceRPN()
373 : {
374 72148 : while( nIndex < nRPN )
375 : {
376 42904 : FormulaToken* t = pRPN[ nIndex++ ];
377 42904 : switch( t->GetType() )
378 : {
379 : case svSingleRef:
380 : case svDoubleRef:
381 : case svExternalSingleRef:
382 : case svExternalDoubleRef:
383 15624 : return t;
384 : default:
385 : {
386 : // added to avoid warnings
387 : }
388 : }
389 : }
390 6810 : return NULL;
391 : }
392 :
393 530 : FormulaToken* FormulaTokenArray::GetNextReferenceOrName()
394 : {
395 530 : if( pCode )
396 : {
397 1332 : while ( nIndex < nLen )
398 : {
399 600 : FormulaToken* t = pCode[ nIndex++ ];
400 600 : switch( t->GetType() )
401 : {
402 : case svSingleRef:
403 : case svDoubleRef:
404 : case svIndex:
405 : case svExternalSingleRef:
406 : case svExternalDoubleRef:
407 : case svExternalName:
408 328 : return t;
409 : default:
410 : {
411 : // added to avoid warnings
412 : }
413 : }
414 : }
415 : }
416 202 : return NULL;
417 : }
418 :
419 122 : FormulaToken* FormulaTokenArray::GetNextName()
420 : {
421 122 : if( pCode )
422 : {
423 394 : while ( nIndex < nLen )
424 : {
425 190 : FormulaToken* t = pCode[ nIndex++ ];
426 190 : if( t->GetType() == svIndex )
427 40 : return t;
428 : }
429 : } // if( pCode )
430 82 : return NULL;
431 : }
432 :
433 0 : FormulaToken* FormulaTokenArray::GetNextOpCodeRPN( OpCode eOp )
434 : {
435 0 : while( nIndex < nRPN )
436 : {
437 0 : FormulaToken* t = pRPN[ nIndex++ ];
438 0 : if ( t->GetOpCode() == eOp )
439 0 : return t;
440 : }
441 0 : return NULL;
442 : }
443 :
444 75650 : FormulaToken* FormulaTokenArray::Next()
445 : {
446 75650 : if( pCode && nIndex < nLen )
447 68212 : return pCode[ nIndex++ ];
448 : else
449 7438 : 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 590 : FormulaToken* FormulaTokenArray::NextRPN()
465 : {
466 590 : if( pRPN && nIndex < nRPN )
467 448 : return pRPN[ nIndex++ ];
468 : else
469 142 : 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 13910 : void FormulaTokenArray::DelRPN()
481 : {
482 13910 : if( nRPN )
483 : {
484 6146 : FormulaToken** p = pRPN;
485 46592 : for( sal_uInt16 i = 0; i < nRPN; i++ )
486 : {
487 40446 : (*p++)->DecRef();
488 : }
489 6146 : delete [] pRPN;
490 : }
491 13910 : pRPN = NULL;
492 13910 : nRPN = nIndex = 0;
493 13910 : }
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 318 : FormulaToken* FormulaTokenArray::PeekNextNoSpaces()
511 : {
512 318 : if( pCode && nIndex < nLen )
513 : {
514 56 : sal_uInt16 j = nIndex;
515 112 : while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
516 0 : j++;
517 56 : if ( j < nLen )
518 56 : return pCode[ j ];
519 : else
520 0 : return NULL;
521 : }
522 : else
523 262 : return NULL;
524 : }
525 :
526 318 : FormulaToken* FormulaTokenArray::PeekPrevNoSpaces()
527 : {
528 318 : if( pCode && nIndex > 1 )
529 : {
530 50 : sal_uInt16 j = nIndex - 2;
531 100 : while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
532 0 : j--;
533 50 : if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
534 50 : return pCode[ j ];
535 : else
536 0 : return NULL;
537 : }
538 : else
539 268 : 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 6042 : bool FormulaTokenArray::HasOpCode( OpCode eOp ) const
553 : {
554 70036 : for ( sal_uInt16 j=0; j < nLen; j++ )
555 : {
556 63996 : if ( pCode[j]->GetOpCode() == eOp )
557 2 : return true;
558 : }
559 6040 : return false;
560 : }
561 :
562 734 : bool FormulaTokenArray::HasOpCodeRPN( OpCode eOp ) const
563 : {
564 2700 : for ( sal_uInt16 j=0; j < nRPN; j++ )
565 : {
566 1966 : if ( pRPN[j]->GetOpCode() == eOp )
567 0 : return true;
568 : }
569 734 : 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 4342 : FormulaTokenArray::FormulaTokenArray()
584 : {
585 4342 : pCode = NULL; pRPN = NULL;
586 4342 : nError = nLen = nIndex = nRPN = nRefs = 0;
587 4342 : bHyperLink = false;
588 4342 : ClearRecalcMode();
589 4342 : }
590 :
591 7704 : FormulaTokenArray::FormulaTokenArray( const FormulaTokenArray& rArr )
592 : {
593 7704 : Assign( rArr );
594 7704 : }
595 :
596 11576 : FormulaTokenArray::~FormulaTokenArray()
597 : {
598 11576 : Clear();
599 11576 : }
600 :
601 7704 : void FormulaTokenArray::Assign( const FormulaTokenArray& r )
602 : {
603 7704 : nLen = r.nLen;
604 7704 : nRPN = r.nRPN;
605 7704 : nIndex = r.nIndex;
606 7704 : nError = r.nError;
607 7704 : nRefs = r.nRefs;
608 7704 : nMode = r.nMode;
609 7704 : bHyperLink = r.bHyperLink;
610 7704 : pCode = NULL;
611 7704 : pRPN = NULL;
612 : FormulaToken** pp;
613 7704 : if( nLen )
614 : {
615 7682 : pp = pCode = new FormulaToken*[ nLen ];
616 7682 : memcpy( pp, r.pCode, nLen * sizeof( FormulaToken* ) );
617 74178 : for( sal_uInt16 i = 0; i < nLen; i++ )
618 66496 : (*pp++)->IncRef();
619 : }
620 7704 : if( nRPN )
621 : {
622 0 : pp = pRPN = new FormulaToken*[ nRPN ];
623 0 : memcpy( pp, r.pRPN, nRPN * sizeof( FormulaToken* ) );
624 0 : for( sal_uInt16 i = 0; i < nRPN; i++ )
625 0 : (*pp++)->IncRef();
626 : }
627 7704 : }
628 :
629 0 : FormulaTokenArray& FormulaTokenArray::operator=( const FormulaTokenArray& rArr )
630 : {
631 0 : Clear();
632 0 : Assign( rArr );
633 0 : return *this;
634 : }
635 :
636 0 : FormulaTokenArray* FormulaTokenArray::Clone() const
637 : {
638 0 : FormulaTokenArray* p = new FormulaTokenArray;
639 0 : p->nLen = nLen;
640 0 : p->nRPN = nRPN;
641 0 : p->nRefs = nRefs;
642 0 : p->nMode = nMode;
643 0 : p->nError = nError;
644 0 : p->bHyperLink = bHyperLink;
645 : FormulaToken** pp;
646 0 : if( nLen )
647 : {
648 0 : pp = p->pCode = new FormulaToken*[ nLen ];
649 0 : memcpy( pp, pCode, nLen * sizeof( FormulaToken* ) );
650 0 : for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
651 : {
652 0 : *pp = (*pp)->Clone();
653 0 : (*pp)->IncRef();
654 : }
655 : }
656 0 : if( nRPN )
657 : {
658 0 : pp = p->pRPN = new FormulaToken*[ nRPN ];
659 0 : memcpy( pp, pRPN, nRPN * sizeof( FormulaToken* ) );
660 0 : for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
661 : {
662 0 : FormulaToken* t = *pp;
663 0 : if( t->GetRef() > 1 )
664 : {
665 0 : FormulaToken** p2 = pCode;
666 0 : sal_uInt16 nIdx = 0xFFFF;
667 0 : for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
668 : {
669 0 : if( *p2 == t )
670 : {
671 0 : nIdx = j; break;
672 : }
673 : }
674 0 : if( nIdx == 0xFFFF )
675 0 : *pp = t->Clone();
676 : else
677 0 : *pp = p->pCode[ nIdx ];
678 : }
679 : else
680 0 : *pp = t->Clone();
681 0 : (*pp)->IncRef();
682 : }
683 : }
684 0 : return p;
685 : }
686 :
687 17444 : void FormulaTokenArray::Clear()
688 : {
689 17444 : if( nRPN ) DelRPN();
690 17444 : if( pCode )
691 : {
692 16564 : FormulaToken** p = pCode;
693 151044 : for( sal_uInt16 i = 0; i < nLen; i++ )
694 : {
695 134480 : (*p++)->DecRef();
696 : }
697 16564 : delete [] pCode;
698 : }
699 17444 : pCode = NULL; pRPN = NULL;
700 17444 : nError = nLen = nIndex = nRPN = nRefs = 0;
701 17444 : bHyperLink = false;
702 17444 : ClearRecalcMode();
703 17444 : }
704 :
705 18 : FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r )
706 : {
707 18 : return Add( r.Clone() );
708 : }
709 :
710 0 : FormulaToken* FormulaTokenArray::MergeArray( )
711 : {
712 0 : return NULL;
713 : }
714 :
715 66762 : FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
716 : {
717 66762 : if( !pCode )
718 7916 : pCode = new FormulaToken*[ MAXCODE ];
719 66762 : if( nLen < MAXCODE-1 )
720 : {
721 66762 : pCode[ nLen++ ] = t;
722 103426 : if( t->GetOpCode() == ocPush
723 36664 : && ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
724 14390 : nRefs++;
725 66762 : t->IncRef();
726 66762 : if( t->GetOpCode() == ocArrayClose )
727 10 : return MergeArray();
728 66752 : return t;
729 : }
730 : else
731 : {
732 0 : t->Delete();
733 0 : if ( nLen == MAXCODE-1 )
734 : {
735 0 : t = new FormulaByteToken( ocStop );
736 0 : pCode[ nLen++ ] = t;
737 0 : t->IncRef();
738 : }
739 0 : return NULL;
740 : }
741 : }
742 :
743 0 : FormulaToken* FormulaTokenArray::AddString( const sal_Unicode* pStr )
744 : {
745 0 : return AddString( rtl::OUString( pStr ) );
746 : }
747 :
748 5380 : FormulaToken* FormulaTokenArray::AddString( const String& rStr )
749 : {
750 5380 : return Add( new FormulaStringToken( rStr ) );
751 : }
752 :
753 2262 : FormulaToken* FormulaTokenArray::AddDouble( double fVal )
754 : {
755 2262 : return Add( new FormulaDoubleToken( fVal ) );
756 : }
757 :
758 0 : FormulaToken* FormulaTokenArray::AddExternal( const sal_Unicode* pStr )
759 : {
760 0 : return AddExternal( rtl::OUString( pStr ) );
761 : }
762 :
763 2 : FormulaToken* FormulaTokenArray::AddExternal( const String& rStr,
764 : OpCode eOp /* = ocExternal */ )
765 : {
766 2 : return Add( new FormulaExternalToken( eOp, rStr ) );
767 : }
768 :
769 6 : FormulaToken* FormulaTokenArray::AddBad( const String& rStr )
770 : {
771 6 : return Add( new FormulaStringOpToken( ocBad, rStr ) );
772 : }
773 :
774 810 : FormulaToken* FormulaTokenArray::AddStringXML( const String& rStr )
775 : {
776 810 : return Add( new FormulaStringOpToken( ocStringXML, rStr ) );
777 : }
778 :
779 :
780 :
781 40 : void FormulaTokenArray::AddRecalcMode( ScRecalcMode nBits )
782 : {
783 : //! Reihenfolge ist wichtig
784 40 : if ( nBits & RECALCMODE_ALWAYS )
785 0 : SetRecalcModeAlways();
786 40 : else if ( !IsRecalcModeAlways() )
787 : {
788 40 : if ( nBits & RECALCMODE_ONLOAD )
789 0 : SetRecalcModeOnLoad();
790 40 : else if ( nBits & RECALCMODE_ONLOAD_ONCE && !IsRecalcModeOnLoad() )
791 0 : SetRecalcModeOnLoadOnce();
792 : }
793 40 : SetCombinedBitsRecalcMode( nBits );
794 40 : }
795 :
796 :
797 0 : bool FormulaTokenArray::HasMatrixDoubleRefOps()
798 : {
799 0 : if ( pRPN && nRPN )
800 : {
801 : // RPN-Interpreter Simulation
802 : // als Ergebnis jeder Funktion wird einfach ein Double angenommen
803 0 : FormulaToken** pStack = new FormulaToken* [nRPN];
804 0 : FormulaToken* pResult = new FormulaDoubleToken( 0.0 );
805 0 : short sp = 0;
806 0 : for ( sal_uInt16 j = 0; j < nRPN; j++ )
807 : {
808 0 : FormulaToken* t = pRPN[j];
809 0 : OpCode eOp = t->GetOpCode();
810 0 : sal_uInt8 nParams = t->GetParamCount();
811 0 : switch ( eOp )
812 : {
813 : case ocAdd :
814 : case ocSub :
815 : case ocMul :
816 : case ocDiv :
817 : case ocPow :
818 : case ocPower :
819 : case ocAmpersand :
820 : case ocEqual :
821 : case ocNotEqual :
822 : case ocLess :
823 : case ocGreater :
824 : case ocLessEqual :
825 : case ocGreaterEqual :
826 : {
827 0 : for ( sal_uInt8 k = nParams; k; k-- )
828 : {
829 0 : if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
830 : {
831 0 : pResult->Delete();
832 0 : delete [] pStack;
833 0 : return true;
834 : }
835 : }
836 : }
837 0 : break;
838 : default:
839 : {
840 : // added to avoid warnings
841 : }
842 : }
843 0 : if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() ) )
844 0 : pStack[sp++] = t;
845 0 : else if ( eOp == ocIf || eOp == ocChose )
846 : { // Jumps ignorieren, vorheriges Result (Condition) poppen
847 0 : if ( sp )
848 0 : --sp;
849 : }
850 : else
851 : { // pop parameters, push result
852 0 : sp = sal::static_int_cast<short>( sp - nParams );
853 0 : if ( sp < 0 )
854 : {
855 : OSL_FAIL( "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
856 0 : sp = 0;
857 : }
858 0 : pStack[sp++] = pResult;
859 : }
860 : }
861 0 : pResult->Delete();
862 0 : delete [] pStack;
863 : }
864 :
865 0 : return false;
866 : }
867 :
868 :
869 :
870 : // --- POF (plain old formula) rewrite of a token array ---------------------
871 :
872 90 : inline bool MissingConvention::isRewriteNeeded( OpCode eOp ) const
873 : {
874 90 : switch (eOp)
875 : {
876 : case ocGammaDist:
877 : case ocPoissonDist:
878 : case ocAddress:
879 : case ocLogNormDist:
880 : case ocNormDist:
881 0 : return true;
882 : case ocMissing:
883 : case ocLog:
884 0 : return !isODFF(); // rewrite only for PODF
885 : default:
886 90 : return false;
887 : }
888 : }
889 :
890 : class FormulaMissingContext
891 : {
892 : public:
893 : const FormulaToken* mpFunc;
894 : int mnCurArg;
895 :
896 0 : void Clear() { mpFunc = NULL; mnCurArg = 0; }
897 : inline bool AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const;
898 : bool AddMissingExternal( FormulaTokenArray* pNewArr ) const;
899 : bool AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
900 : void AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
901 : };
902 :
903 0 : void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const
904 : {
905 0 : if ( !mpFunc )
906 0 : return;
907 :
908 0 : switch (mpFunc->GetOpCode())
909 : {
910 : case ocGammaDist:
911 0 : if (mnCurArg == 2)
912 : {
913 0 : pNewArr->AddOpCode( ocSep );
914 0 : pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
915 : }
916 0 : break;
917 : case ocPoissonDist:
918 0 : if (mnCurArg == 1)
919 : {
920 0 : pNewArr->AddOpCode( ocSep );
921 0 : pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
922 : }
923 0 : break;
924 : case ocNormDist:
925 0 : if ( mnCurArg == 2 )
926 : {
927 0 : pNewArr->AddOpCode( ocSep );
928 0 : pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
929 : }
930 0 : break;
931 : case ocLogNormDist:
932 0 : if ( mnCurArg == 0 )
933 : {
934 0 : pNewArr->AddOpCode( ocSep );
935 0 : pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
936 : }
937 0 : if ( mnCurArg <= 1 )
938 : {
939 0 : pNewArr->AddOpCode( ocSep );
940 0 : pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
941 : }
942 0 : break;
943 : case ocLog:
944 0 : if ( !rConv.isODFF() && mnCurArg == 0 )
945 : {
946 0 : pNewArr->AddOpCode( ocSep );
947 0 : pNewArr->AddDouble( 10.0 ); // 2nd, basis 10
948 : }
949 0 : break;
950 : default:
951 0 : break;
952 : }
953 : }
954 :
955 0 : inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
956 : {
957 0 : if (mnCurArg == nArg)
958 : {
959 0 : pNewArr->AddDouble( f );
960 0 : return true;
961 : }
962 0 : return false;
963 : }
964 :
965 0 : bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray *pNewArr ) const
966 : {
967 : // Only called for PODF, not ODFF. No need to distinguish.
968 :
969 0 : const String &rName = mpFunc->GetExternal();
970 :
971 : // initial (fast) check:
972 0 : sal_Unicode nLastChar = rName.GetChar( rName.Len() - 1);
973 0 : if ( nLastChar != 't' && nLastChar != 'm' )
974 0 : return false;
975 :
976 0 : if (rName.EqualsIgnoreCaseAscii(
977 0 : "com.sun.star.sheet.addin.Analysis.getAccrint" ))
978 : {
979 0 : return AddDefaultArg( pNewArr, 4, 1000.0 );
980 : }
981 0 : if (rName.EqualsIgnoreCaseAscii(
982 0 : "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
983 : {
984 0 : return AddDefaultArg( pNewArr, 3, 1000.0 );
985 : }
986 0 : return false;
987 : }
988 :
989 0 : bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const
990 : {
991 0 : if ( !mpFunc )
992 0 : return false;
993 :
994 0 : bool bRet = false;
995 0 : const OpCode eOp = mpFunc->GetOpCode();
996 :
997 : // Add for both, PODF and ODFF
998 0 : switch (eOp)
999 : {
1000 : case ocAddress:
1001 0 : return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
1002 : default:
1003 0 : break;
1004 : }
1005 :
1006 0 : if (rConv.isODFF())
1007 : {
1008 : // Add for ODFF
1009 : }
1010 : else
1011 : {
1012 : // Add for PODF
1013 0 : switch (eOp)
1014 : {
1015 : case ocFixed:
1016 0 : return AddDefaultArg( pNewArr, 1, 2.0 );
1017 : case ocBetaDist:
1018 : case ocBetaInv:
1019 : case ocRMZ: // PMT
1020 0 : return AddDefaultArg( pNewArr, 3, 0.0 );
1021 : case ocZinsZ: // IPMT
1022 : case ocKapz: // PPMT
1023 0 : return AddDefaultArg( pNewArr, 4, 0.0 );
1024 : case ocBW: // PV
1025 : case ocZW: // FV
1026 0 : bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
1027 0 : bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
1028 0 : break;
1029 : case ocZins: // RATE
1030 0 : bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
1031 0 : bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
1032 0 : bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
1033 0 : break;
1034 : case ocExternal:
1035 0 : return AddMissingExternal( pNewArr );
1036 :
1037 : // --- more complex cases ---
1038 :
1039 : case ocOffset:
1040 : // FIXME: rather tough.
1041 : // if arg 3 (height) ommitted, export arg1 (rows)
1042 0 : break;
1043 : default:
1044 0 : break;
1045 : }
1046 : }
1047 :
1048 0 : return bRet;
1049 : }
1050 :
1051 82 : bool FormulaTokenArray::NeedsPofRewrite( const MissingConvention & rConv )
1052 : {
1053 172 : for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
1054 : {
1055 90 : if ( rConv.isRewriteNeeded( pCur->GetOpCode()))
1056 0 : return true;
1057 : }
1058 82 : return false;
1059 : }
1060 :
1061 :
1062 0 : FormulaTokenArray * FormulaTokenArray::RewriteMissingToPof( const MissingConvention & rConv )
1063 : {
1064 0 : const size_t nAlloc = 256;
1065 : FormulaMissingContext aCtx[ nAlloc ];
1066 : int aOpCodeAddressStack[ nAlloc ]; // use of ADDRESS() function
1067 0 : const int nOmitAddressArg = 3; // ADDRESS() 4th parameter A1/R1C1
1068 0 : sal_uInt16 nTokens = GetLen() + 1;
1069 0 : FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
1070 0 : int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
1071 : // Never go below 0, never use 0, mpFunc always NULL.
1072 0 : pCtx[0].Clear();
1073 0 : int nFn = 0;
1074 0 : int nOcas = 0;
1075 :
1076 0 : FormulaTokenArray *pNewArr = new FormulaTokenArray;
1077 : // At least RECALCMODE_ALWAYS needs to be set.
1078 0 : pNewArr->AddRecalcMode( GetRecalcMode());
1079 :
1080 0 : for ( FormulaToken *pCur = First(); pCur; pCur = Next() )
1081 : {
1082 0 : bool bAdd = true;
1083 : // Don't write the expression of the new inserted ADDRESS() parameter.
1084 : // Do NOT omit the new second parameter of INDIRECT() though. If that
1085 : // was done for both, INDIRECT() actually could calculate different and
1086 : // valid (but wrong) results with the then changed return value of
1087 : // ADDRESS(). Better let it generate an error instead.
1088 0 : for (int i = nOcas; i-- > 0 && bAdd; )
1089 : {
1090 0 : if (pCtx[ pOcas[ i ] ].mnCurArg == nOmitAddressArg)
1091 : {
1092 : // Omit erverything except a trailing separator, the leading
1093 : // separator is omitted below. The other way around would leave
1094 : // an extraneous separator if no parameter followed.
1095 0 : if (!(pOcas[ i ] == nFn && pCur->GetOpCode() == ocSep))
1096 0 : bAdd = false;
1097 : }
1098 : }
1099 0 : switch ( pCur->GetOpCode() )
1100 : {
1101 : case ocOpen:
1102 0 : ++nFn; // all following operations on _that_ function
1103 0 : pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
1104 0 : pCtx[ nFn ].mnCurArg = 0;
1105 0 : if (pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress && !rConv.isODFF())
1106 0 : pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
1107 0 : break;
1108 : case ocClose:
1109 0 : pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
1110 : DBG_ASSERT( nFn > 0, "FormulaTokenArray::RewriteMissingToPof: underflow");
1111 0 : if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
1112 0 : --nOcas; // leaving ADDRESS()
1113 0 : if (nFn > 0)
1114 0 : --nFn;
1115 0 : break;
1116 : case ocSep:
1117 0 : pCtx[ nFn ].mnCurArg++;
1118 : // Omit leading separator of ADDRESS() parameter.
1119 0 : if (nOcas && pOcas[ nOcas-1 ] == nFn && pCtx[ nFn ].mnCurArg == nOmitAddressArg)
1120 : {
1121 0 : bAdd = false;
1122 : }
1123 0 : break;
1124 : case ocMissing:
1125 0 : if (bAdd)
1126 0 : bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
1127 0 : break;
1128 : default:
1129 0 : break;
1130 : }
1131 0 : if (bAdd)
1132 0 : pNewArr->AddToken( *pCur );
1133 : }
1134 :
1135 0 : if (pOcas != &aOpCodeAddressStack[0])
1136 0 : delete [] pOcas;
1137 0 : if (pCtx != &aCtx[0])
1138 0 : delete [] pCtx;
1139 :
1140 0 : return pNewArr;
1141 : }
1142 :
1143 0 : bool FormulaTokenArray::MayReferenceFollow()
1144 : {
1145 0 : if ( pCode && nLen > 0 )
1146 : {
1147 : // ignore trailing spaces
1148 0 : sal_uInt16 i = nLen - 1;
1149 0 : while ( i > 0 && pCode[i]->GetOpCode() == SC_OPCODE_SPACES )
1150 : {
1151 0 : --i;
1152 : }
1153 0 : if ( i > 0 || pCode[i]->GetOpCode() != SC_OPCODE_SPACES )
1154 : {
1155 0 : OpCode eOp = pCode[i]->GetOpCode();
1156 0 : if ( (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) ||
1157 : (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP ) ||
1158 : eOp == SC_OPCODE_OPEN || eOp == SC_OPCODE_SEP )
1159 : {
1160 0 : return true;
1161 : }
1162 : }
1163 : }
1164 0 : return false;
1165 : }
1166 0 : FormulaToken* FormulaTokenArray::AddOpCode( OpCode eOp )
1167 : {
1168 0 : FormulaToken* pRet = NULL;
1169 0 : switch ( eOp )
1170 : {
1171 : case ocOpen:
1172 : case ocClose:
1173 : case ocSep:
1174 : case ocArrayOpen:
1175 : case ocArrayClose:
1176 : case ocArrayRowSep:
1177 : case ocArrayColSep:
1178 0 : pRet = new FormulaToken( svSep,eOp );
1179 0 : break;
1180 : case ocIf:
1181 : case ocChose:
1182 : {
1183 : short nJump[MAXJUMPCOUNT + 1];
1184 0 : nJump[ 0 ] = ocIf == eOp ? 3 : MAXJUMPCOUNT+1;
1185 0 : pRet = new FormulaJumpToken( eOp, (short*)nJump );
1186 : }
1187 0 : break;
1188 : default:
1189 0 : pRet = new FormulaByteToken( eOp, 0, false );
1190 0 : break;
1191 : }
1192 0 : return AddToken( *pRet );
1193 : }
1194 :
1195 :
1196 : /*----------------------------------------------------------------------*/
1197 :
1198 6046 : FormulaTokenIterator::FormulaTokenIterator( const FormulaTokenArray& rArr )
1199 : {
1200 6046 : pCur = NULL;
1201 6046 : Push( &rArr );
1202 6046 : }
1203 :
1204 6046 : FormulaTokenIterator::~FormulaTokenIterator()
1205 : {
1206 18138 : while( pCur )
1207 6046 : Pop();
1208 6046 : }
1209 :
1210 6064 : void FormulaTokenIterator::Push( const FormulaTokenArray* pArr )
1211 : {
1212 6064 : ImpTokenIterator* p = new ImpTokenIterator;
1213 6064 : p->pArr = pArr;
1214 6064 : p->nPC = -1;
1215 6064 : p->nStop = SHRT_MAX;
1216 6064 : p->pNext = pCur;
1217 6064 : pCur = p;
1218 6064 : }
1219 :
1220 6064 : void FormulaTokenIterator::Pop()
1221 : {
1222 6064 : ImpTokenIterator* p = pCur;
1223 6064 : if( p )
1224 : {
1225 6064 : pCur = p->pNext;
1226 6064 : delete p;
1227 : }
1228 6064 : }
1229 :
1230 6046 : void FormulaTokenIterator::Reset()
1231 : {
1232 12092 : while( pCur->pNext )
1233 0 : Pop();
1234 6046 : pCur->nPC = -1;
1235 6046 : }
1236 :
1237 33790 : const FormulaToken* FormulaTokenIterator::Next()
1238 : {
1239 33790 : const FormulaToken* t = GetNonEndOfPathToken( ++pCur->nPC );
1240 33790 : if( !t && pCur->pNext )
1241 : {
1242 18 : Pop();
1243 18 : t = Next();
1244 : }
1245 33790 : return t;
1246 : }
1247 :
1248 0 : const FormulaToken* FormulaTokenIterator::PeekNextOperator()
1249 : {
1250 0 : const FormulaToken* t = NULL;
1251 0 : short nIdx = pCur->nPC;
1252 0 : while (!t && ((t = GetNonEndOfPathToken( ++nIdx)) != NULL))
1253 : {
1254 0 : if (t->GetOpCode() == ocPush)
1255 0 : t = NULL; // ignore operands
1256 : }
1257 0 : if (!t && pCur->pNext)
1258 : {
1259 0 : ImpTokenIterator* pHere = pCur;
1260 0 : pCur = pCur->pNext;
1261 0 : t = PeekNextOperator();
1262 0 : pCur = pHere;
1263 : }
1264 0 : return t;
1265 : }
1266 :
1267 : //! The nPC counts after a Push() are -1
1268 :
1269 24 : void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
1270 : {
1271 24 : pCur->nPC = nNext;
1272 24 : if( nStart != nNext )
1273 : {
1274 18 : Push( pCur->pArr );
1275 18 : pCur->nPC = nStart;
1276 18 : pCur->nStop = nStop;
1277 : }
1278 24 : }
1279 :
1280 33790 : const FormulaToken* FormulaTokenIterator::GetNonEndOfPathToken( short nIdx ) const
1281 : {
1282 33790 : if (nIdx < pCur->pArr->nRPN && nIdx < pCur->nStop)
1283 : {
1284 27748 : const FormulaToken* t = pCur->pArr->pRPN[ nIdx ];
1285 : // such an OpCode ends an IF() or CHOOSE() path
1286 27748 : return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? NULL : t;
1287 : }
1288 6042 : return NULL;
1289 : }
1290 :
1291 0 : bool FormulaTokenIterator::IsEndOfPath() const
1292 : {
1293 0 : return GetNonEndOfPathToken( pCur->nPC + 1) == NULL;
1294 : }
1295 :
1296 : // -----------------------------------------------------------------------------
1297 : // ==========================================================================
1298 : // real implementations of virtual functions
1299 : // --------------------------------------------------------------------------
1300 :
1301 15174 : double FormulaDoubleToken::GetDouble() const { return fDouble; }
1302 0 : double & FormulaDoubleToken::GetDoubleAsReference() { return fDouble; }
1303 0 : bool FormulaDoubleToken::operator==( const FormulaToken& r ) const
1304 : {
1305 0 : return FormulaToken::operator==( r ) && fDouble == r.GetDouble();
1306 : }
1307 :
1308 :
1309 342 : const String& FormulaStringToken::GetString() const { return aString; }
1310 0 : bool FormulaStringToken::operator==( const FormulaToken& r ) const
1311 : {
1312 0 : return FormulaToken::operator==( r ) && aString == r.GetString();
1313 : }
1314 :
1315 :
1316 820 : const String& FormulaStringOpToken::GetString() const { return aString; }
1317 44 : bool FormulaStringOpToken::operator==( const FormulaToken& r ) const
1318 : {
1319 44 : return FormulaByteToken::operator==( r ) && aString == r.GetString();
1320 : }
1321 :
1322 454 : sal_uInt16 FormulaIndexToken::GetIndex() const { return nIndex; }
1323 28 : void FormulaIndexToken::SetIndex( sal_uInt16 n ) { nIndex = n; }
1324 420 : bool FormulaIndexToken::IsGlobal() const { return mbGlobal; }
1325 28 : void FormulaIndexToken::SetGlobal( bool b ) { mbGlobal = b; }
1326 0 : bool FormulaIndexToken::operator==( const FormulaToken& r ) const
1327 : {
1328 0 : return FormulaToken::operator==( r ) && nIndex == r.GetIndex() &&
1329 0 : mbGlobal == r.IsGlobal();
1330 : }
1331 0 : const String& FormulaExternalToken::GetExternal() const { return aExternal; }
1332 0 : sal_uInt8 FormulaExternalToken::GetByte() const { return nByte; }
1333 2 : void FormulaExternalToken::SetByte( sal_uInt8 n ) { nByte = n; }
1334 0 : bool FormulaExternalToken::operator==( const FormulaToken& r ) const
1335 : {
1336 0 : return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
1337 0 : aExternal == r.GetExternal();
1338 : }
1339 :
1340 :
1341 386 : sal_uInt16 FormulaErrorToken::GetError() const { return nError; }
1342 0 : void FormulaErrorToken::SetError( sal_uInt16 nErr ) { nError = nErr; }
1343 0 : bool FormulaErrorToken::operator==( const FormulaToken& r ) const
1344 : {
1345 0 : return FormulaToken::operator==( r ) &&
1346 0 : nError == static_cast< const FormulaErrorToken & >(r).GetError();
1347 : }
1348 0 : double FormulaMissingToken::GetDouble() const { return 0.0; }
1349 0 : const String& FormulaMissingToken::GetString() const
1350 : {
1351 0 : static String aDummyString;
1352 0 : return aDummyString;
1353 : }
1354 0 : bool FormulaMissingToken::operator==( const FormulaToken& r ) const
1355 : {
1356 0 : return FormulaToken::operator==( r );
1357 : }
1358 :
1359 :
1360 0 : FormulaSubroutineToken::FormulaSubroutineToken( const FormulaSubroutineToken& r ) :
1361 : FormulaToken( r ),
1362 0 : mpArray( r.mpArray->Clone())
1363 : {
1364 0 : }
1365 0 : FormulaSubroutineToken::~FormulaSubroutineToken()
1366 : {
1367 0 : delete mpArray;
1368 0 : }
1369 0 : bool FormulaSubroutineToken::operator==( const FormulaToken& r ) const
1370 : {
1371 : // Arrays don't equal..
1372 0 : return FormulaToken::operator==( r ) &&
1373 0 : (mpArray == static_cast<const FormulaSubroutineToken&>(r).mpArray);
1374 : }
1375 :
1376 :
1377 0 : bool FormulaUnknownToken::operator==( const FormulaToken& r ) const
1378 : {
1379 0 : return FormulaToken::operator==( r );
1380 : }
1381 :
1382 : // -----------------------------------------------------------------------------
1383 114 : } // formula
1384 : // -----------------------------------------------------------------------------
1385 :
1386 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|