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