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