xref: /aoo4110/main/formula/source/core/api/token.cxx (revision b1cdbd2c)
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