LibreOffice Module formula (master) 1
token.cxx
Go to the documentation of this file.
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 <algorithm>
22
23#include <string.h>
24#include <limits.h>
25#include <osl/diagnose.h>
26#include <sal/log.hxx>
27
28#include <com/sun/star/sheet/FormulaToken.hpp>
30#include <formula/token.hxx>
33#include <formula/compiler.hxx>
35#include <memory>
36#include <utility>
37
38namespace formula
39{
40 using namespace com::sun::star;
41
42
43// --- helpers --------------------------------------------------------------
44
45static bool lcl_IsReference( OpCode eOp, StackVar eType )
46{
47 return
48 (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
49 || (eOp == ocColRowNameAuto && eType == svDoubleRef)
50 || (eOp == ocColRowName && eType == svSingleRef)
51 || (eOp == ocMatRef && eType == svSingleRef)
52 ;
53}
54
55// --- class FormulaToken --------------------------------------------------------
56
58 eOp(e), eType( eTypeP ), mnRefCnt(0)
59{
60}
61
63 eOp(r.eOp), eType( r.eType ), mnRefCnt(0)
64{
65}
66
68{
69}
70
72{
73 return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
74 eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
75 eOp != ocTableRef &&
76 (GetByte() != 0 // x parameters
77 || (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR) // no parameter
78 || FormulaCompiler::IsOpCodeJumpCommand( eOp ) // @ jump commands
79 || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) // one parameter
80 || (SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR) // x parameters (cByte==0 in
81 // FuncAutoPilot)
82 || eOp == ocMacro || eOp == ocExternal // macros, AddIns
83 || eOp == ocAnd || eOp == ocOr // former binary, now x parameters
84 || (eOp >= ocInternalBegin && eOp <= ocInternalEnd) // internal
85 ));
86}
87
88
90{
91 if ( eOp < SC_OPCODE_STOP_DIV && eOp != ocExternal && eOp != ocMacro &&
94 return 0; // parameters and specials
95 // ocIf... jump commands not for FAP, have cByte then
96//2do: bool parameter whether FAP or not?
97 else if (GetByte())
98 return GetByte(); // all functions, also ocExternal and ocMacro
100 return 2; // binary operators, compiler checked; OR and AND legacy but are functions
102 return 1; // unary operators, compiler checked
104 return 0; // no parameter
106 return 1; // only the condition counts as parameter
107 else
108 return 0; // all the rest, no Parameter, or
109 // if so then it should be in cByte
110}
111
113{
114 bool bRet = false;
115 switch (eType)
116 {
119 case svExternalName:
120 bRet = true;
121 break;
122 default:
123 bRet = false;
124 break;
125 }
126 return bRet;
127}
128
130{
131 switch (eType)
132 {
133 case svSingleRef:
134 case svDoubleRef:
137 return true;
138 default:
139 if (eOp == ocTableRef)
140 return true;
141 }
142
143 return false;
144}
145
147{
148 ParamClass eParam = GetInForceArray();
151}
152
153bool FormulaToken::operator==( const FormulaToken& rToken ) const
154{
155 // don't compare reference count!
156 return eType == rToken.eType && GetOpCode() == rToken.GetOpCode();
157}
158
159
160// --- virtual dummy methods -------------------------------------------------
161
163{
164 // ok to be called for any derived class
165 return 0;
166}
167
169{
170 assert( !"virtual dummy called" );
171}
172
174{
175 // ok to be called for any derived class
177}
178
180{
181 assert( !"virtual dummy called" );
182}
183
185{
186 // This Get is worth an assert.
187 assert( !"virtual dummy called" );
188 return 0.0;
189}
190
192{
193 // This Get is worth an assert.
194 assert( !"virtual dummy called" );
195 static double fVal = 0.0;
196 return fVal;
197}
198
200{
201 SAL_WARN( "formula.core", "FormulaToken::GetDoubleType: virtual dummy called" );
202 return 0;
203}
204
206{
207 assert( !"virtual dummy called" );
208}
209
211
213{
214 SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
215 return INVALID_STRING; // invalid string
216}
217
219{
220 assert( !"virtual dummy called" );
221}
222
223sal_uInt16 FormulaToken::GetIndex() const
224{
225 SAL_WARN( "formula.core", "FormulaToken::GetIndex: virtual dummy called" );
226 return 0;
227}
228
229void FormulaToken::SetIndex( sal_uInt16 )
230{
231 assert( !"virtual dummy called" );
232}
233
234sal_Int16 FormulaToken::GetSheet() const
235{
236 SAL_WARN( "formula.core", "FormulaToken::GetSheet: virtual dummy called" );
237 return -1;
238}
239
240void FormulaToken::SetSheet( sal_Int16 )
241{
242 assert( !"virtual dummy called" );
243}
244
246{
247 // This Get is worth an assert.
248 assert( !"virtual dummy called" );
249 return 0;
250}
251
253{
254 SAL_WARN( "formula.core", "FormulaToken::GetJump: virtual dummy called" );
255 return nullptr;
256}
257
258
259const OUString& FormulaToken::GetExternal() const
260{
261 SAL_WARN( "formula.core", "FormulaToken::GetExternal: virtual dummy called" );
262 static OUString aDummyString;
263 return aDummyString;
264}
265
267{
268 SAL_WARN( "formula.core", "FormulaToken::GetFAPOrigToken: virtual dummy called" );
269 return nullptr;
270}
271
273{
274 SAL_WARN( "formula.core", "FormulaToken::GetError: virtual dummy called" );
275 return FormulaError::NONE;
276}
277
279{
280 assert( !"virtual dummy called" );
281}
282
284{
285 OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
286 return nullptr;
287}
288
290{
291 OSL_FAIL( "FormulaToken::GetSingleRef: virtual dummy called" );
292 return nullptr;
293}
294
296{
297 OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
298 return nullptr;
299}
300
302{
303 OSL_FAIL( "FormulaToken::GetDoubleRef: virtual dummy called" );
304 return nullptr;
305}
306
308{
309 OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
310 return nullptr;
311}
312
314{
315 OSL_FAIL( "FormulaToken::GetSingleRef2: virtual dummy called" );
316 return nullptr;
317}
318
320{
321 OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
322 return nullptr;
323}
324
326{
327 OSL_FAIL( "FormulaToken::GetMatrix: virtual dummy called" );
328 return nullptr;
329}
330
332{
333 OSL_FAIL( "FormulaToken::GetJumpMatrix: virtual dummy called" );
334 return nullptr;
335}
336const std::vector<ScComplexRefData>* FormulaToken::GetRefList() const
337{
338 OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
339 return nullptr;
340}
341
342std::vector<ScComplexRefData>* FormulaToken::GetRefList()
343{
344 OSL_FAIL( "FormulaToken::GetRefList: virtual dummy called" );
345 return nullptr;
346}
347
348bool FormulaToken::TextEqual( const FormulaToken& rToken ) const
349{
350 return *this == rToken;
351}
352
353// real implementations of virtual functions
354
355
359{
360 return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
361 cChar == r.GetChar();
362}
363
364
370{
371 return FormulaToken::operator==( r ) && nByte == r.GetByte() &&
373}
374
375
378{
380}
381
382
383short* FormulaJumpToken::GetJump() const { return pJump.get(); }
387{
388 return FormulaToken::operator==( r ) && pJump[0] == r.GetJump()[0] &&
389 memcmp( pJump.get()+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0 &&
391}
393{
394}
395
396
398 const sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, ExternalReferenceHelper* /*pExtRef*/)
399{
400 bool bError = false;
401 const OpCode eOpCode = static_cast<OpCode>(rToken.OpCode);
402
403 const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
404 switch ( eClass )
405 {
406 case uno::TypeClass_VOID:
407 // empty data -> use AddOpCode (does some special cases)
408 AddOpCode( eOpCode );
409 break;
410 case uno::TypeClass_DOUBLE:
411 // double is only used for "push"
412 if ( eOpCode == ocPush )
413 AddDouble( rToken.Data.get<double>() );
414 else
415 bError = true;
416 break;
417 case uno::TypeClass_LONG:
418 {
419 // long is svIndex, used for name / database area, or "byte" for spaces
420 sal_Int32 nValue = rToken.Data.get<sal_Int32>();
421 if ( eOpCode == ocDBArea )
422 Add( new formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) );
423 else if ( eOpCode == ocTableRef )
424 bError = true; /* TODO: implementation */
425 else if ( eOpCode == ocSpaces )
426 Add( new formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) );
427 else
428 bError = true;
429 }
430 break;
431 case uno::TypeClass_STRING:
432 {
433 OUString aStrVal( rToken.Data.get<OUString>() );
434 if ( eOpCode == ocPush )
435 AddString(rSPool.intern(aStrVal));
436 else if ( eOpCode == ocBad )
437 AddBad( aStrVal );
438 else if ( eOpCode == ocStringXML )
439 AddStringXML( aStrVal );
440 else if ( eOpCode == ocExternal || eOpCode == ocMacro )
441 Add( new formula::FormulaExternalToken( eOpCode, aStrVal ) );
442 else if ( eOpCode == ocWhitespace )
443 {
444 // Simply ignore empty string.
445 // Convention is one character repeated.
446 if (!aStrVal.isEmpty())
447 Add( new formula::FormulaSpaceToken( static_cast<sal_uInt8>(aStrVal.getLength()), aStrVal[0]));
448 }
449 else
450 bError = true; // unexpected string: don't know what to do with it
451 }
452 break;
453 default:
454 bError = true;
455 } // switch ( eClass )
456 return bError;
457}
458
460 const uno::Sequence<sheet::FormulaToken>& rSequence,
462{
463 bool bError = false;
464 const sal_Int32 nCount = rSequence.getLength();
465 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
466 {
467 bool bOneError = AddFormulaToken(rSequence[nPos], rSPool, pExtRef);
468 if (bOneError)
469 {
470 AddOpCode( ocErrName); // add something that indicates an error
471 bError = true;
472 }
473 }
474 return bError;
475}
476
478{
479 if( nRPN )
480 {
481 FormulaToken** p = pRPN;
482 for( sal_uInt16 i = 0; i < nRPN; i++ )
483 {
484 (*p++)->DecRef();
485 }
486 delete [] pRPN;
487 }
488 pRPN = nullptr;
489 nRPN = 0;
490}
491
493{
494 if (!pCode || nLen == 0)
495 return nullptr;
496 return pCode[0];
497}
498
499FormulaToken* FormulaTokenArray::PeekPrev( sal_uInt16 & nIdx ) const
500{
501 if (0 < nIdx && nIdx <= nLen)
502 return pCode[--nIdx];
503 return nullptr;
504}
505
507{
508 if (!pRPN || nRPN == 0)
509 return nullptr;
510 return pRPN[0];
511}
512
514{
515 if (!pRPN || nRPN == 0)
516 return nullptr;
517 return pRPN[nRPN - 1];
518}
519
521{
522 for (auto i: Tokens())
523 {
524 if (i->IsRef())
525 return true;
526 }
527
528 for (auto i: RPNTokens())
529 {
530 if (i->IsRef())
531 return true;
532 }
533
534 return false;
535}
536
538{
539 for (auto i: Tokens())
540 {
541 if (i->IsExternalRef())
542 return true;
543 }
544 return false;
545}
546
548{
549 for (auto i: Tokens())
550 {
551 if (i->GetOpCode() == eOp)
552 return true;
553 }
554 return false;
555}
556
558{
559 for (auto i: RPNTokens())
560 {
561 if (i->GetOpCode() == eOp)
562 return true;
563 }
564 return false;
565}
566
568{
569 for (auto i: Tokens())
570 {
571 if (i->GetType() == svIndex || i->GetOpCode() == ocColRowName )
572 return true;
573 }
574 return false;
575}
576
578{
579 for (auto i: Tokens())
580 {
581 if (rOpCodes.count(i->GetOpCode()) > 0)
582 return true;
583 }
584
585 return false;
586}
587
589 pRPN(nullptr),
590 nLen(0),
591 nRPN(0),
592 nError(FormulaError::NONE),
593 nMode(ScRecalcMode::NORMAL),
594 bHyperLink(false),
595 mbFromRangeName(false),
596 mbShareable(true),
597 mbFinalized(false)
598{
599}
600
602{
603 Assign( rArr );
604}
605
607{
608 Move( std::move(rArr) );
609}
610
612{
614}
615
617{
618 if( nLen && !mbFinalized )
619 {
620 // Add() overallocates, so reallocate to the minimum needed size.
621 std::unique_ptr<FormulaToken*[]> newCode(new FormulaToken*[ nLen ]);
622 std::copy(&pCode[0], &pCode[nLen], newCode.get());
623 pCode = std::move( newCode );
624 mbFinalized = true;
625 }
626}
627
629{
630 nLen = r.nLen;
631 nRPN = r.nRPN;
632 nError = r.nError;
633 nMode = r.nMode;
638 pCode = nullptr;
639 pRPN = nullptr;
640 FormulaToken** pp;
641 if( nLen )
642 {
643 pCode.reset(new FormulaToken*[ nLen ]);
644 pp = pCode.get();
645 memcpy( pp, r.pCode.get(), nLen * sizeof( FormulaToken* ) );
646 for( sal_uInt16 i = 0; i < nLen; i++ )
647 (*pp++)->IncRef();
648 mbFinalized = true;
649 }
650 if( nRPN )
651 {
652 pp = pRPN = new FormulaToken*[ nRPN ];
653 memcpy( pp, r.pRPN, nRPN * sizeof( FormulaToken* ) );
654 for( sal_uInt16 i = 0; i < nRPN; i++ )
655 (*pp++)->IncRef();
656 }
657}
658
660{
661 pCode = std::move(r.pCode);
662 pRPN = r.pRPN;
663 r.pRPN = nullptr;
664 nLen = r.nLen;
665 r.nLen = 0;
666 nRPN = r.nRPN;
667 r.nRPN = 0;
668 nError = r.nError;
669 nMode = r.nMode;
670 bHyperLink = r.bHyperLink;
671 mbFromRangeName = r.mbFromRangeName;
672 mbShareable = r.mbShareable;
673 mbFinalized = r.mbFinalized;
674}
675
677void FormulaTokenArray::Assign( sal_uInt16 nCode, FormulaToken **pTokens )
678{
679 assert( nLen == 0 );
680 assert( pCode == nullptr );
681
682 nLen = nCode;
683 pCode.reset(new FormulaToken*[ nLen ]);
684 mbFinalized = true;
685
686 for( sal_uInt16 i = 0; i < nLen; i++ )
687 {
688 FormulaToken *t = pTokens[ i ];
689 assert( t->GetOpCode() == ocStringXML );
690 pCode[ i ] = t;
691 t->IncRef();
692 }
693}
694
696{
697 if(this == &rArr)
698 return *this;
699
700 Clear();
701 Assign( rArr );
702 return *this;
703}
704
706{
707 Clear();
708 Move( std::move(rArr) );
709 return *this;
710}
711
713{
714 if( nRPN ) DelRPN();
715 if( pCode )
716 {
717 FormulaToken** p = pCode.get();
718 for( sal_uInt16 i = 0; i < nLen; i++ )
719 {
720 (*p++)->DecRef();
721 }
722 pCode.reset();
723 }
724 pRPN = nullptr;
726 nLen = nRPN = 0;
727 bHyperLink = false;
728 mbFromRangeName = false;
729 mbShareable = true;
730 mbFinalized = false;
732}
733
735{
736 // Do nothing.
737}
738
740{
741 if( nRPN )
742 {
743 FormulaToken** p = pRPN;
744 for( sal_uInt16 i = 0; i < nRPN; i++ )
745 {
746 CheckToken( *p[ i ] );
747 }
748 }
749}
750
752{
753 return Add( r.Clone() );
754}
755
757{
758 return nullptr;
759}
760
763{
764 if (nOffset < nLen)
765 {
766 CheckToken(*t);
767 t->IncRef();
768 FormulaToken* p = pCode[nOffset];
769 pCode[nOffset] = t;
770 if (eMode == CODE_AND_RPN && p->GetRef() > 1)
771 {
772 for (sal_uInt16 i=0; i < nRPN; ++i)
773 {
774 if (pRPN[i] == p)
775 {
776 t->IncRef();
777 pRPN[i] = t;
778 p->DecRef();
779 if (p->GetRef() == 1)
780 break; // for
781 }
782 }
783 }
784 p->DecRef(); // may be dead now
785 return t;
786 }
787 else
788 {
789 t->DeleteIfZeroRef();
790 return nullptr;
791 }
792}
793
794sal_uInt16 FormulaTokenArray::RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount )
795{
796 if (nOffset < nLen)
797 {
798 SAL_WARN_IF( nOffset + nCount > nLen, "formula.core",
799 "FormulaTokenArray::RemoveToken - nOffset " << nOffset << " + nCount " << nCount << " > nLen " << nLen);
800 const sal_uInt16 nStop = ::std::min( static_cast<sal_uInt16>(nOffset + nCount), nLen);
801 nCount = nStop - nOffset;
802 for (sal_uInt16 j = nOffset; j < nStop; ++j)
803 {
804 FormulaToken* p = pCode[j];
805 if (p->GetRef() > 1)
806 {
807 for (sal_uInt16 i=0; i < nRPN; ++i)
808 {
809 if (pRPN[i] == p)
810 {
811 // Shift remaining tokens in pRPN down.
812 for (sal_uInt16 x=i+1; x < nRPN; ++x)
813 {
814 pRPN[x-1] = pRPN[x];
815 }
816 --nRPN;
817
818 p->DecRef();
819 if (p->GetRef() == 1)
820 break; // for
821 }
822 }
823 }
824 p->DecRef(); // may be dead now
825 }
826
827 // Shift remaining tokens in pCode down.
828 for (sal_uInt16 x = nStop; x < nLen; ++x)
829 {
830 pCode[x-nCount] = pCode[x];
831 }
832 nLen -= nCount;
833
834 return nCount;
835 }
836 else
837 {
838 SAL_WARN("formula.core","FormulaTokenArray::RemoveToken - nOffset " << nOffset << " >= nLen " << nLen);
839 return 0;
840 }
841}
842
844{
845 assert(!mbFinalized);
846 if (mbFinalized)
847 {
848 t->DeleteIfZeroRef();
849 return nullptr;
850 }
851
852// Allocating an array of size FORMULA_MAXTOKENS is simple, but that results in relatively large
853// allocations that malloc() implementations usually do not handle as efficiently as smaller
854// sizes (not only in terms of memory usage but also speed). Since most token arrays are going
855// to be small, start with a small array and resize only if needed. Eventually Finalize() will
856// reallocate the memory to size exactly matching the requirements.
857 const size_t MAX_FAST_TOKENS = 32;
858 if( !pCode )
859 pCode.reset(new FormulaToken*[ MAX_FAST_TOKENS ]);
860 if( nLen == MAX_FAST_TOKENS )
861 {
863 std::copy(&pCode[0], &pCode[MAX_FAST_TOKENS], tmp);
864 pCode.reset(tmp);
865 }
866 if( nLen < FORMULA_MAXTOKENS - 1 )
867 {
868 CheckToken(*t);
869 pCode[ nLen++ ] = t;
870 t->IncRef();
871 if( t->GetOpCode() == ocArrayClose )
872 return MergeArray();
873 return t;
874 }
875 else
876 {
877 t->DeleteIfZeroRef();
878 if ( nLen == FORMULA_MAXTOKENS - 1 )
879 {
880 t = new FormulaByteToken( ocStop );
881 pCode[ nLen++ ] = t;
882 t->IncRef();
883 }
884 return nullptr;
885 }
886}
887
889{
890 return Add( new FormulaStringToken( rStr ) );
891}
892
894{
895 return Add( new FormulaDoubleToken( fVal ) );
896}
897
899{
900 AddExternal( OUString( pStr ) );
901}
902
904 OpCode eOp /* = ocExternal */ )
905{
906 return Add( new FormulaExternalToken( eOp, rStr ) );
907}
908
910{
911 return Add( new FormulaStringOpToken( ocBad, svl::SharedString( rStr ) ) ); // string not interned
912}
913
915{
916 return Add( new FormulaStringOpToken( ocStringXML, svl::SharedString( rStr ) ) ); // string not interned
917}
918
919
921{
922 const unsigned nExclusive = static_cast<sal_uInt8>(nBits & ScRecalcMode::EMask);
923 if (nExclusive)
924 {
925 unsigned nExBit;
926 if (nExclusive & (nExclusive - 1))
927 {
928 // More than one bit set, use highest priority.
929 for (nExBit = 1; (nExBit & static_cast<sal_uInt8>(ScRecalcMode::EMask)) != 0; nExBit <<= 1)
930 {
931 if (nExclusive & nExBit)
932 break;
933 }
934 }
935 else
936 {
937 // Only one bit is set.
938 nExBit = nExclusive;
939 }
940 // Set exclusive bit if priority is higher than existing.
941 if (nExBit < static_cast<sal_uInt8>(nMode & ScRecalcMode::EMask))
942 SetMaskedRecalcMode( static_cast<ScRecalcMode>(nExBit));
943 }
945}
946
947
949{
950 if ( !pRPN || !nRPN )
951 return false;
952
953 // RPN-Interpreter simulation.
954 // Simply assumes a double as return value of each function.
955 std::unique_ptr<FormulaToken*[]> pStack(new FormulaToken* [nRPN]);
956 FormulaToken* pResult = new FormulaDoubleToken( 0.0 );
957 short sp = 0;
958 for ( auto t: RPNTokens() )
959 {
960 OpCode eOp = t->GetOpCode();
961 sal_uInt8 nParams = t->GetParamCount();
962 switch ( eOp )
963 {
964 case ocAdd :
965 case ocSub :
966 case ocMul :
967 case ocDiv :
968 case ocPow :
969 case ocPower :
970 case ocAmpersand :
971 case ocEqual :
972 case ocNotEqual :
973 case ocLess :
974 case ocGreater :
975 case ocLessEqual :
976 case ocGreaterEqual :
977 {
978 for ( sal_uInt8 k = nParams; k; k-- )
979 {
980 if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
981 {
982 pResult->Delete();
983 return true;
984 }
985 }
986 }
987 break;
988 default:
989 {
990 // added to avoid warnings
991 }
992 }
993 if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() ) )
994 pStack[sp++] = t;
996 { // ignore Jumps, pop previous Result (Condition)
997 if ( sp )
998 --sp;
999 }
1000 else
1001 { // pop parameters, push result
1002 sp = sal::static_int_cast<short>( sp - nParams );
1003 if ( sp < 0 )
1004 {
1005 SAL_WARN("formula.core", "FormulaTokenArray::HasMatrixDoubleRefOps: sp < 0" );
1006 sp = 0;
1007 }
1008 pStack[sp++] = pResult;
1009 }
1010 }
1011 pResult->Delete();
1012
1013 return false;
1014}
1015
1016// --- Formula rewrite of a token array
1017
1019{
1020 switch (eOp)
1021 {
1022 case ocGammaDist:
1023 case ocPoissonDist:
1024 case ocAddress:
1025 case ocLogInv:
1026 case ocLogNormDist:
1027 case ocNormDist:
1028 return true;
1029 case ocMissing:
1030 case ocLog:
1031 return isPODF(); // rewrite only for PODF
1032 case ocDBCount:
1033 case ocDBCount2:
1034 return isODFF(); // rewrite only for ODFF
1035 default:
1036 return false;
1037 }
1038}
1039
1040/*
1041 fdo 81596
1042To be implemented yet:
1043 ocExternal: ?
1044 ocMacro: ?
1045 ocIndex: INDEX() ?
1046*/
1048{
1049 switch (eOp)
1050 {
1051 case ocIf:
1052
1053 case ocExternal:
1054 case ocEuroConvert:
1055 case ocMacro:
1056
1057 case ocRound:
1058 case ocRoundUp:
1059 case ocRoundDown:
1060
1061 case ocIndex:
1062
1063 case ocCeil:
1064 case ocFloor:
1065
1066 case ocGammaDist:
1067 case ocFDist_LT:
1068 case ocPoissonDist:
1069 case ocNormDist:
1070 case ocLogInv:
1071 case ocLogNormDist:
1072 case ocHypGeomDist:
1073
1074 case ocDBCount:
1075 case ocDBCount2:
1076 return true;
1077
1078 default:
1079 return false;
1080 }
1081}
1082
1083namespace {
1084
1085class FormulaMissingContext
1086{
1087 public:
1088 const FormulaToken* mpFunc;
1090
1091 void Clear() { mpFunc = nullptr; mnCurArg = 0; }
1092 inline bool AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const;
1093 bool AddMissingExternal( FormulaTokenArray* pNewArr ) const;
1094 bool AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
1095 void AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const;
1096};
1097
1098}
1099
1100void FormulaMissingContext::AddMoreArgs( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const
1101{
1102 if ( !mpFunc )
1103 return;
1104
1105 switch (rConv.getConvention())
1106 {
1109 {
1110 switch (mpFunc->GetOpCode())
1111 {
1112 case ocGammaDist:
1113 if (mnCurArg == 2)
1114 {
1115 pNewArr->AddOpCode( ocSep );
1116 pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
1117 }
1118 break;
1119 case ocPoissonDist:
1120 if (mnCurArg == 1)
1121 {
1122 pNewArr->AddOpCode( ocSep );
1123 pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
1124 }
1125 break;
1126 case ocNormDist:
1127 if ( mnCurArg == 2 )
1128 {
1129 pNewArr->AddOpCode( ocSep );
1130 pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
1131 }
1132 break;
1133 case ocLogInv:
1134 case ocLogNormDist:
1135 if ( mnCurArg == 0 )
1136 {
1137 pNewArr->AddOpCode( ocSep );
1138 pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
1139 }
1140 if ( mnCurArg <= 1 )
1141 {
1142 pNewArr->AddOpCode( ocSep );
1143 pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
1144 }
1145 break;
1146 case ocLog:
1147 if ( rConv.isPODF() && mnCurArg == 0 )
1148 {
1149 pNewArr->AddOpCode( ocSep );
1150 pNewArr->AddDouble( 10.0 ); // 2nd, basis 10
1151 }
1152 break;
1153 default:
1154 break;
1155 }
1156 }
1157 break;
1159 {
1160 switch (mpFunc->GetOpCode())
1161 {
1162 case ocIf:
1163 if( mnCurArg == 0 )
1164 {
1165 // Excel needs at least two parameters in IF function
1166 pNewArr->AddOpCode( ocSep );
1167 pNewArr->AddOpCode( ocTrue ); // 2nd, true() as function
1168 pNewArr->AddOpCode( ocOpen ); // so the result is of logical type
1169 pNewArr->AddOpCode( ocClose ); // and survives roundtrip
1170 }
1171 break;
1172
1173 case ocEuroConvert:
1174 if ( mnCurArg == 2 )
1175 {
1176 pNewArr->AddOpCode( ocSep );
1177 pNewArr->AddDouble( 0.0 ); // 4th, FullPrecision = false()
1178 }
1179 break;
1180
1181 case ocPoissonDist:
1182 if (mnCurArg == 1)
1183 {
1184 pNewArr->AddOpCode( ocSep );
1185 pNewArr->AddDouble( 1.0 ); // 3rd, Cumulative=true()
1186 }
1187 break;
1188
1189 case ocGammaDist:
1190 case ocFDist_LT:
1191 case ocNormDist:
1192 if (mnCurArg == 2)
1193 {
1194 pNewArr->AddOpCode( ocSep );
1195 pNewArr->AddDouble( 1.0 ); // 4th, Cumulative=true()
1196 }
1197 break;
1198
1199 case ocLogInv:
1200 case ocLogNormDist:
1201 if ( mnCurArg == 0 )
1202 {
1203 pNewArr->AddOpCode( ocSep );
1204 pNewArr->AddDouble( 0.0 ); // 2nd, mean = 0.0
1205 }
1206 if ( mnCurArg <= 1 )
1207 {
1208 pNewArr->AddOpCode( ocSep );
1209 pNewArr->AddDouble( 1.0 ); // 3rd, standard deviation = 1.0
1210 }
1211 break;
1212
1213 case ocHypGeomDist:
1214 if ( mnCurArg == 3 )
1215 {
1216 pNewArr->AddOpCode( ocSep );
1217 pNewArr->AddDouble( 0.0 ); // 5th, Cumulative = false()
1218 }
1219 break;
1220
1221 case ocRound:
1222 case ocRoundUp:
1223 case ocRoundDown:
1224 if( mnCurArg == 0 )
1225 {
1226 // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
1227 pNewArr->AddOpCode( ocSep );
1228 pNewArr->AddDouble( 0.0 ); // 2nd, 0.0
1229 }
1230 break;
1231
1232 default:
1233 break;
1234 }
1235 }
1236 break;
1237 }
1238
1239}
1240
1241inline bool FormulaMissingContext::AddDefaultArg( FormulaTokenArray* pNewArr, int nArg, double f ) const
1242{
1243 if (mnCurArg == nArg)
1244 {
1245 pNewArr->AddDouble( f );
1246 return true;
1247 }
1248 return false;
1249}
1250
1251bool FormulaMissingContext::AddMissingExternal( FormulaTokenArray *pNewArr ) const
1252{
1253 // Only called for PODF, not ODFF. No need to distinguish.
1254
1255 const OUString &rName = mpFunc->GetExternal();
1256
1257 // initial (fast) checks:
1258 sal_Int32 nLength = rName.getLength();
1259 if (!nLength)
1260 return false;
1261
1262 sal_Unicode nLastChar = rName[ nLength - 1];
1263 if ( nLastChar != 't' && nLastChar != 'm' )
1264 return false;
1265
1266 if (rName.equalsIgnoreAsciiCase(
1267 "com.sun.star.sheet.addin.Analysis.getAccrint" ))
1268 {
1269 return AddDefaultArg( pNewArr, 4, 1000.0 );
1270 }
1271 if (rName.equalsIgnoreAsciiCase(
1272 "com.sun.star.sheet.addin.Analysis.getAccrintm" ))
1273 {
1274 return AddDefaultArg( pNewArr, 3, 1000.0 );
1275 }
1276 return false;
1277}
1278
1279bool FormulaMissingContext::AddMissing( FormulaTokenArray *pNewArr, const MissingConvention & rConv ) const
1280{
1281 if ( !mpFunc )
1282 return false;
1283
1284 bool bRet = false;
1285 const OpCode eOp = mpFunc->GetOpCode();
1286
1287 switch (rConv.getConvention())
1288 {
1290 {
1291 // Add for ODFF
1292 switch (eOp)
1293 {
1294 case ocAddress:
1295 return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
1296 default:
1297 break;
1298 }
1299 }
1300 break;
1302 {
1303 // Add for PODF
1304 switch (eOp)
1305 {
1306 case ocAddress:
1307 return AddDefaultArg( pNewArr, 2, 1.0 ); // abs
1308 case ocFixed:
1309 return AddDefaultArg( pNewArr, 1, 2.0 );
1310 case ocBetaDist:
1311 case ocBetaInv:
1312 case ocPMT:
1313 return AddDefaultArg( pNewArr, 3, 0.0 );
1314 case ocIpmt:
1315 case ocPpmt:
1316 return AddDefaultArg( pNewArr, 4, 0.0 );
1317 case ocPV:
1318 case ocFV:
1319 bRet |= AddDefaultArg( pNewArr, 2, 0.0 ); // pmt
1320 bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // [fp]v
1321 break;
1322 case ocRate:
1323 bRet |= AddDefaultArg( pNewArr, 1, 0.0 ); // pmt
1324 bRet |= AddDefaultArg( pNewArr, 3, 0.0 ); // fv
1325 bRet |= AddDefaultArg( pNewArr, 4, 0.0 ); // type
1326 break;
1327 case ocExternal:
1328 return AddMissingExternal( pNewArr );
1329
1330 // --- more complex cases ---
1331
1332 case ocOffset:
1333 // FIXME: rather tough
1334 // if arg 3 (height) omitted, export arg1 (rows)
1335 break;
1336 default:
1337 break;
1338 }
1339 }
1340 break;
1342 {
1343 switch (eOp)
1344 {
1345 case ocExternal:
1346 return AddMissingExternal( pNewArr );
1347 default:
1348 break;
1349 }
1350 }
1351 break;
1352 }
1353
1354 return bRet;
1355}
1356
1358{
1359 for ( auto i: Tokens() )
1360 {
1361 if ( rConv.isRewriteNeeded( i->GetOpCode()))
1362 return true;
1363 }
1364 return false;
1365}
1366
1368{
1369 for ( auto i: Tokens() )
1370 {
1371 if ( MissingConventionOOXML::isRewriteNeeded( i->GetOpCode()))
1372 return true;
1373 }
1374 return false;
1375}
1376
1377
1379{
1380 const size_t nAlloc = 256;
1381 FormulaMissingContext aCtx[ nAlloc ];
1382
1383 /* TODO: with some effort we might be able to merge the two almost
1384 * identical function stacks into one and generalize things, otherwise
1385 * adding yet another "omit argument" would be copypasta. */
1386
1387 int aOpCodeAddressStack[ nAlloc ]; // use of ADDRESS() function
1388 const int nOmitAddressArg = 3; // ADDRESS() 4th parameter A1/R1C1
1389
1390 int aOpCodeDcountStack[ nAlloc ]; // use of DCOUNT()/DCOUNTA() function
1391 const int nOmitDcountArg = 1; // DCOUNT() and DCOUNTA() 2nd parameter DatabaseField if 0
1392
1393 sal_uInt16 nTokens = GetLen() + 1;
1394 FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
1395 int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
1396 int* pOcds = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeDcountStack[0]);
1397 // Never go below 0, never use 0, mpFunc always NULL.
1398 pCtx[0].Clear();
1399 int nFn = 0;
1400 int nOcas = 0;
1401 int nOcds = 0;
1402
1403 FormulaTokenArray *pNewArr = new FormulaTokenArray;
1404 // At least ScRecalcMode::ALWAYS needs to be set.
1405 pNewArr->AddRecalcMode( GetRecalcMode());
1406
1407 FormulaTokenArrayPlainIterator aIter(*this);
1408 for ( FormulaToken *pCur = aIter.First(); pCur; pCur = aIter.Next() )
1409 {
1410 bool bAdd = true;
1411 // Don't write the expression of the new inserted ADDRESS() parameter.
1412 // Do NOT omit the new second parameter of INDIRECT() though. If that
1413 // was done for both, INDIRECT() actually could calculate different and
1414 // valid (but wrong) results with the then changed return value of
1415 // ADDRESS(). Better let it generate an error instead.
1416 for (int i = nOcas; i-- > 0 && bAdd; )
1417 {
1418 if (pCtx[ pOcas[ i ] ].mnCurArg == nOmitAddressArg)
1419 {
1420 // Omit everything except a trailing separator, the leading
1421 // separator is omitted below. The other way around would leave
1422 // an extraneous separator if no parameter followed.
1423 if (pOcas[ i ] != nFn || pCur->GetOpCode() != ocSep)
1424 bAdd = false;
1425 }
1426 }
1427 // Strip the 2nd argument (leaving empty) of DCOUNT() and DCOUNTA() if
1428 // it is 0.
1429 for (int i = nOcds; i-- > 0 && bAdd; )
1430 {
1431 if (pCtx[ pOcds[ i ] ].mnCurArg == nOmitDcountArg)
1432 {
1433 // Omit only a literal 0 value, nothing else.
1434 if (pOcds[ i ] == nFn && pCur->GetOpCode() == ocPush && pCur->GetType() == svDouble &&
1435 pCur->GetDouble() == 0.0)
1436 {
1437 // No other expression, between separators.
1438 FormulaToken* p = aIter.PeekPrevNoSpaces();
1439 if (p && p->GetOpCode() == ocSep)
1440 {
1441 p = aIter.PeekNextNoSpaces();
1442 if (p && p->GetOpCode() == ocSep)
1443 bAdd = false;
1444 }
1445 }
1446 }
1447 }
1448 switch ( pCur->GetOpCode() )
1449 {
1450 case ocOpen:
1451 {
1452 ++nFn; // all following operations on _that_ function
1453 pCtx[ nFn ].mpFunc = aIter.PeekPrevNoSpaces();
1454 pCtx[ nFn ].mnCurArg = 0;
1455 if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
1456 pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
1457 else if ((rConv.isODFF() || rConv.isOOXML()) && pCtx[ nFn ].mpFunc)
1458 {
1459 OpCode eOp = pCtx[ nFn ].mpFunc->GetOpCode();
1460 if (eOp == ocDBCount || eOp == ocDBCount2)
1461 pOcds[ nOcds++ ] = nFn; // entering DCOUNT() or DCOUNTA() if ODFF or OOXML
1462 }
1463 }
1464 break;
1465 case ocClose:
1466 pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
1467 SAL_WARN_IF(nFn <= 0, "formula.core", "FormulaTokenArray::RewriteMissing: underflow");
1468 if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
1469 --nOcas; // leaving ADDRESS()
1470 else if (nOcds > 0 && pOcds[ nOcds-1 ] == nFn)
1471 --nOcds; // leaving DCOUNT() or DCOUNTA()
1472 if (nFn > 0)
1473 --nFn;
1474 break;
1475 case ocSep:
1476 pCtx[ nFn ].mnCurArg++;
1477 // Omit leading separator of ADDRESS() parameter.
1478 if (nOcas && pOcas[ nOcas-1 ] == nFn && pCtx[ nFn ].mnCurArg == nOmitAddressArg)
1479 {
1480 bAdd = false;
1481 }
1482 break;
1483 case ocMissing:
1484 if ( bAdd )
1485 bAdd = !pCtx[ nFn ].AddMissing( pNewArr, rConv );
1486 break;
1487 default:
1488 break;
1489 }
1490 if (bAdd)
1491 {
1492 OpCode eOp = pCur->GetOpCode();
1493 if ( ( eOp == ocCeil || eOp == ocFloor ||
1494 ( eOp == ocLogNormDist && pCur->GetByte() == 4 ) ) &&
1496 {
1497 switch ( eOp )
1498 {
1499 case ocCeil :
1500 eOp = ocCeil_Math;
1501 break;
1502 case ocFloor :
1503 eOp = ocFloor_Math;
1504 break;
1505 case ocLogNormDist :
1506 eOp = ocLogNormDist_MS;
1507 break;
1508 default :
1509 eOp = ocNone;
1510 break;
1511 }
1512 FormulaToken *pToken = new FormulaToken( svByte, eOp );
1513 pNewArr->Add( pToken );
1514 }
1515 else if ( eOp == ocHypGeomDist &&
1517 {
1519 pNewArr->Add( pToken );
1520 }
1521 else
1522 pNewArr->AddToken( *pCur );
1523 }
1524 }
1525
1526 if (pOcds != &aOpCodeDcountStack[0])
1527 delete [] pOcds;
1528 if (pOcas != &aOpCodeAddressStack[0])
1529 delete [] pOcas;
1530 if (pCtx != &aCtx[0])
1531 delete [] pCtx;
1532
1533 return pNewArr;
1534}
1535
1536namespace {
1537inline bool isWhitespace( OpCode eOp ) { return eOp == ocSpaces || eOp == ocWhitespace; }
1538}
1539
1541{
1542 if ( !pCode || nLen <= 0 )
1543 return false;
1544
1545 // ignore trailing spaces
1546 sal_uInt16 i = nLen - 1;
1547 while (i > 0 && isWhitespace( pCode[i]->GetOpCode()))
1548 {
1549 --i;
1550 }
1551 if (i > 0 || !isWhitespace( pCode[i]->GetOpCode()))
1552 {
1553 OpCode eOp = pCode[i]->GetOpCode();
1554 if ( (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP ) ||
1555 (SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP ) ||
1556 eOp == SC_OPCODE_OPEN || eOp == SC_OPCODE_SEP )
1557 {
1558 return true;
1559 }
1560 }
1561 return false;
1562}
1564{
1565 FormulaToken* pRet = nullptr;
1566 switch ( eOp )
1567 {
1568 case ocOpen:
1569 case ocClose:
1570 case ocSep:
1571 case ocArrayOpen:
1572 case ocArrayClose:
1573 case ocArrayRowSep:
1574 case ocArrayColSep:
1575 pRet = new FormulaToken( svSep,eOp );
1576 break;
1577 case ocIf:
1578 case ocIfError:
1579 case ocIfNA:
1580 case ocChoose:
1581 {
1582 short nJump[FORMULA_MAXJUMPCOUNT + 1];
1583 if ( eOp == ocIf )
1584 nJump[ 0 ] = 3;
1585 else if ( eOp == ocChoose )
1586 nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
1587 else
1588 nJump[ 0 ] = 2;
1589 pRet = new FormulaJumpToken( eOp, nJump );
1590 }
1591 break;
1592 default:
1593 pRet = new FormulaByteToken( eOp, 0, ParamClass::Unknown );
1594 break;
1595 }
1596 return Add( pRet );
1597}
1598
1600{
1601 for (auto i: Tokens())
1602 {
1603 switch (i->GetType())
1604 {
1605 case svString:
1606 i->SetString( rPool.intern( i->GetString().getString()));
1607 break;
1608 default:
1609 ; // nothing
1610 }
1611 }
1612}
1613
1614
1615/*----------------------------------------------------------------------*/
1616
1617FormulaTokenIterator::Item::Item(const FormulaTokenArray* pArray, short pc, short stop) :
1618 pArr(pArray), nPC(pc), nStop(stop)
1619{
1620}
1621
1623 : maStack{ FormulaTokenIterator::Item(&rArr, -1, SHRT_MAX) }
1624{
1625}
1626
1628{
1629}
1630
1632{
1633 FormulaTokenIterator::Item item(pArr, -1, SHRT_MAX);
1634
1635 maStack.push_back(item);
1636}
1637
1639{
1640 maStack.pop_back();
1641}
1642
1644{
1645 while( maStack.size() > 1 )
1646 maStack.pop_back();
1647
1648 maStack.back().nPC = -1;
1649}
1650
1652{
1653 if( mpFTA->GetArray() )
1654 {
1655 while ( mnIndex < mpFTA->GetLen() )
1656 {
1657 FormulaToken* t = mpFTA->GetArray()[ mnIndex++ ];
1658 if( t->GetType() == svIndex )
1659 return t;
1660 }
1661 }
1662 return nullptr;
1663}
1664
1666{
1667 const FormulaToken* t = GetNonEndOfPathToken( ++maStack.back().nPC );
1668 if( !t && maStack.size() > 1 )
1669 {
1670 Pop();
1671 t = Next();
1672 }
1673 return t;
1674}
1675
1677{
1678 const FormulaToken* t = nullptr;
1679 short nIdx = maStack.back().nPC;
1680 for (;;)
1681 {
1682 t = GetNonEndOfPathToken( ++nIdx);
1683 if (t == nullptr || t->GetOpCode() != ocPush)
1684 break; // ignore operands
1685 }
1686 if (!t && maStack.size() > 1)
1687 {
1688 FormulaTokenIterator::Item aHere = maStack.back();
1689 maStack.pop_back();
1690 t = PeekNextOperator();
1691 maStack.push_back(aHere);
1692 }
1693 return t;
1694}
1695
1697
1698void FormulaTokenIterator::Jump( short nStart, short nNext, short nStop )
1699{
1700 maStack.back().nPC = nNext;
1701 if( nStart != nNext )
1702 {
1703 Push( maStack.back().pArr );
1704 maStack.back().nPC = nStart;
1705 maStack.back().nStop = nStop;
1706 }
1707}
1708
1710{
1711 maStack.clear();
1712 Push( &rArr );
1713}
1714
1716{
1718
1719 if (nIdx < cur.pArr->GetCodeLen() && nIdx < cur.nStop)
1720 {
1721 const FormulaToken* t = cur.pArr->GetCode()[ nIdx ];
1722 // such an OpCode ends an IF() or CHOOSE() path
1723 return (t->GetOpCode() == ocSep || t->GetOpCode() == ocClose) ? nullptr : t;
1724 }
1725 return nullptr;
1726}
1727
1729{
1730 return GetNonEndOfPathToken( maStack.back().nPC + 1) == nullptr;
1731}
1732
1734{
1735 while( mnIndex < mpFTA->GetLen() )
1736 {
1737 FormulaToken* t = mpFTA->GetArray()[ mnIndex++ ];
1738 switch( t->GetType() )
1739 {
1740 case svSingleRef:
1741 case svDoubleRef:
1744 return t;
1745 default:
1746 {
1747 // added to avoid warnings
1748 }
1749 }
1750 }
1751 return nullptr;
1752}
1753
1755{
1756 while( mnIndex < mpFTA->GetLen() )
1757 {
1758 FormulaToken* t = mpFTA->GetArray()[ mnIndex++ ];
1759 if ( t->GetOpCode() == ocColRowName )
1760 return t;
1761 }
1762 return nullptr;
1763}
1764
1766{
1767 while( mnIndex < mpFTA->GetCodeLen() )
1768 {
1769 FormulaToken* t = mpFTA->GetCode()[ mnIndex++ ];
1770 switch( t->GetType() )
1771 {
1772 case svSingleRef:
1773 case svDoubleRef:
1776 return t;
1777 default:
1778 {
1779 // added to avoid warnings
1780 }
1781 }
1782 }
1783 return nullptr;
1784}
1785
1787{
1788 if( !mpFTA->GetArray() )
1789 return nullptr;
1790
1791 while ( mnIndex < mpFTA->GetLen() )
1792 {
1793 FormulaToken* t = mpFTA->GetArray()[ mnIndex++ ];
1794 switch( t->GetType() )
1795 {
1796 case svSingleRef:
1797 case svDoubleRef:
1798 case svIndex:
1801 case svExternalName:
1802 return t;
1803 default:
1804 {
1805 // added to avoid warnings
1806 }
1807 }
1808 }
1809 return nullptr;
1810}
1811
1813{
1814 if( mpFTA->GetArray() && mnIndex < mpFTA->GetLen() )
1815 return mpFTA->GetArray()[ mnIndex++ ];
1816 else
1817 return nullptr;
1818}
1819
1821{
1822 if( mpFTA->GetArray() )
1823 {
1824 while ((mnIndex < mpFTA->GetLen()) && isWhitespace( mpFTA->GetArray()[ mnIndex ]->GetOpCode()))
1825 ++mnIndex;
1826 if( mnIndex < mpFTA->GetLen() )
1827 return mpFTA->GetArray()[ mnIndex++ ];
1828 }
1829 return nullptr;
1830}
1831
1833{
1834 if( mpFTA->GetCode() && mnIndex < mpFTA->GetCodeLen() )
1835 return mpFTA->GetCode()[ mnIndex++ ];
1836 else
1837 return nullptr;
1838}
1839
1841{
1842 if( mpFTA->GetCode() && mnIndex )
1843 return mpFTA->GetCode()[ --mnIndex ];
1844 else
1845 return nullptr;
1846}
1847
1849{
1850 if( mpFTA->GetArray() && mnIndex < mpFTA->GetLen() )
1851 return mpFTA->GetArray()[ mnIndex ];
1852 else
1853 return nullptr;
1854}
1855
1857{
1858 if( mpFTA->GetArray() && mnIndex < mpFTA->GetLen() )
1859 {
1860 sal_uInt16 j = mnIndex;
1861 while (j < mpFTA->GetLen() && isWhitespace( mpFTA->GetArray()[j]->GetOpCode()))
1862 j++;
1863 if ( j < mpFTA->GetLen() )
1864 return mpFTA->GetArray()[ j ];
1865 else
1866 return nullptr;
1867 }
1868 else
1869 return nullptr;
1870}
1871
1873{
1874 if( mpFTA->GetArray() && mnIndex > 1 )
1875 {
1876 sal_uInt16 j = mnIndex - 2;
1877 while (isWhitespace( mpFTA->GetArray()[j]->GetOpCode()) && j > 0 )
1878 j--;
1879 if (j > 0 || !isWhitespace( mpFTA->GetArray()[j]->GetOpCode()))
1880 return mpFTA->GetArray()[ j ];
1881 else
1882 return nullptr;
1883 }
1884 else
1885 return nullptr;
1886}
1887
1888void FormulaTokenArrayPlainIterator::AfterRemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount )
1889{
1890 const sal_uInt16 nStop = std::min( static_cast<sal_uInt16>(nOffset + nCount), mpFTA->GetLen());
1891
1892 if (mnIndex >= nOffset)
1893 {
1894 if (mnIndex < nStop)
1895 mnIndex = nOffset + 1;
1896 else
1897 mnIndex -= nStop - nOffset;
1898 }
1899}
1900
1901// real implementations of virtual functions
1902
1903
1904double FormulaDoubleToken::GetDouble() const { return fDouble; }
1906
1908{
1909 // This is a plain double value without type information, don't emit a
1910 // warning via FormulaToken::GetDoubleType().
1911 return 0;
1912}
1913
1915{
1916 return FormulaToken::operator==( r ) && fDouble == r.GetDouble();
1917}
1918
1920{
1921 return mnType;
1922}
1923
1925{
1926 mnType = nType;
1927}
1928
1930{
1932}
1933
1935 FormulaToken( svString ), maString(std::move( r ))
1936{
1937}
1938
1940 FormulaToken( r ), maString( r.maString ) {}
1941
1943{
1944 return new FormulaStringToken(*this);
1945}
1946
1948{
1949 return maString;
1950}
1951
1953{
1954 maString = rStr;
1955}
1956
1958{
1959 return FormulaToken::operator==( r ) && maString == r.GetString();
1960}
1961
1963 FormulaByteToken( e, 0, svString, ParamClass::Unknown ), maString(std::move( r )) {}
1964
1966 FormulaByteToken( r ), maString( r.maString ) {}
1967
1969{
1970 return new FormulaStringOpToken(*this);
1971}
1972
1974{
1975 return maString;
1976}
1977
1979{
1980 maString = rStr;
1981}
1982
1984{
1985 return FormulaByteToken::operator==( r ) && maString == r.GetString();
1986}
1987
1988sal_uInt16 FormulaIndexToken::GetIndex() const { return nIndex; }
1989void FormulaIndexToken::SetIndex( sal_uInt16 n ) { nIndex = n; }
1990sal_Int16 FormulaIndexToken::GetSheet() const { return mnSheet; }
1991void FormulaIndexToken::SetSheet( sal_Int16 n ) { mnSheet = n; }
1993{
1994 return FormulaToken::operator==( r ) && nIndex == r.GetIndex() &&
1995 mnSheet == r.GetSheet();
1996}
1997const OUString& FormulaExternalToken::GetExternal() const { return aExternal; }
1999{
2001}
2002
2003
2007{
2008 return FormulaToken::operator==( r ) &&
2009 nError == static_cast< const FormulaErrorToken & >(r).GetError();
2010}
2011double FormulaMissingToken::GetDouble() const { return 0.0; }
2012
2014{
2016}
2017
2019{
2020 return FormulaToken::operator==( r );
2021}
2022
2023
2025{
2026 return FormulaToken::operator==( r );
2027}
2028
2029
2030} // formula
2031
2032
2033/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define FORMULA_MAXJUMPCOUNT
#define FORMULA_MAXTOKENS
XPropertyListType t
virtual void SetInForceArray(ParamClass c) override
Definition: token.cxx:368
virtual void SetByte(sal_uInt8 n) override
Definition: token.cxx:366
ParamClass eInForceArray
Definition: token.hxx:253
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:369
virtual ParamClass GetInForceArray() const override
Definition: token.cxx:367
virtual sal_uInt8 GetByte() const override
Dummy methods to avoid switches and casts where possible, the real token classes have to override the...
Definition: token.cxx:365
static bool IsOpCodeJumpCommand(OpCode eOp)
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:1914
virtual double GetDouble() const override
Definition: token.cxx:1904
virtual sal_Int16 GetDoubleType() const override
always returns 0 for "not typed"
Definition: token.cxx:1907
virtual double & GetDoubleAsReference() override
Definition: token.cxx:1905
virtual FormulaError GetError() const override
Definition: token.cxx:2004
virtual void SetError(FormulaError nErr) override
Definition: token.cxx:2005
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:2006
virtual const OUString & GetExternal() const override
Definition: token.cxx:1997
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:1998
virtual FormulaToken * GetFAPOrigToken() const override
Definition: token.cxx:376
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:377
FormulaTokenRef pOrigToken
Definition: token.hxx:286
virtual void SetIndex(sal_uInt16 n) override
Definition: token.cxx:1989
virtual sal_uInt16 GetIndex() const override
Definition: token.cxx:1988
virtual sal_Int16 GetSheet() const override
Definition: token.cxx:1990
virtual void SetSheet(sal_Int16 n) override
Definition: token.cxx:1991
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:1992
virtual void SetInForceArray(ParamClass c) override
Definition: token.cxx:385
virtual ParamClass GetInForceArray() const override
Definition: token.cxx:384
virtual bool operator==(const formula::FormulaToken &rToken) const override
Definition: token.cxx:386
ParamClass eInForceArray
Definition: token.hxx:424
virtual ~FormulaJumpToken() override
Definition: token.cxx:392
virtual short * GetJump() const override
Definition: token.cxx:383
std::unique_ptr< short[]> pJump
Definition: token.hxx:423
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:2013
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:2018
virtual double GetDouble() const override
Definition: token.cxx:2011
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:358
virtual sal_uInt8 GetByte() const override
Dummy methods to avoid switches and casts where possible, the real token classes have to override the...
Definition: token.cxx:356
virtual sal_Unicode GetChar() const override
Definition: token.cxx:357
Identical to FormulaStringToken, but with explicit OpCode instead of implicit ocPush,...
Definition: token.hxx:353
svl::SharedString maString
Definition: token.hxx:354
virtual FormulaToken * Clone() const override
Definition: token.cxx:1968
FormulaStringOpToken(OpCode e, svl::SharedString r)
Definition: token.cxx:1962
virtual void SetString(const svl::SharedString &rStr) override
Definition: token.cxx:1978
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:1973
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:1983
svl::SharedString maString
Definition: token.hxx:338
virtual const svl::SharedString & GetString() const override
Definition: token.cxx:1947
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:1957
FormulaStringToken(svl::SharedString r)
Definition: token.cxx:1934
virtual void SetString(const svl::SharedString &rStr) override
Definition: token.cxx:1952
virtual FormulaToken * Clone() const override
Definition: token.cxx:1942
const FormulaTokenArray * mpFTA
Definition: tokenarray.hxx:602
FormulaToken * PeekPrevNoSpaces() const
Definition: token.cxx:1872
FormulaToken * PeekNextNoSpaces() const
Only after Reset/First/Next/Last/Prev!
Definition: token.cxx:1856
void AfterRemoveToken(sal_uInt16 nOffset, sal_uInt16 nCount)
Definition: token.cxx:1888
void Move(FormulaTokenArray &&)
Definition: token.cxx:659
bool HasNameOrColRowName() const
Token of type svIndex or opcode ocColRowName.
Definition: token.cxx:567
virtual FormulaToken * MergeArray()
ocStringXML with OUString, temporary during import
Definition: token.cxx:756
void Assign(const FormulaTokenArray &)
Definition: token.cxx:628
bool HasReferences() const
Definition: token.cxx:520
FormulaToken * PeekPrev(sal_uInt16 &nIdx) const
Peek at nIdx-1 if not out of bounds, decrements nIdx if successful. Returns NULL if not.
Definition: token.cxx:499
FormulaToken * AddToken(const FormulaToken &)
Clones the token and then adds the clone to the pCode array.
Definition: token.cxx:751
bool HasMatrixDoubleRefOps() const
Operators +,-,*,/,^,&,=,<>,<,>,<=,>= with DoubleRef in Formula?
Definition: token.cxx:948
bool NeedsOoxmlRewrite()
Determines if this formula needs any changes to convert it to OOXML.
Definition: token.cxx:1367
sal_uInt16 GetLen() const
Definition: tokenarray.hxx:387
bool MayReferenceFollow()
Determines if this formula may be followed by a reference.
Definition: token.cxx:1540
void CheckAllRPNTokens()
Call CheckToken() for all RPN tokens.
Definition: token.cxx:739
void AddRecalcMode(ScRecalcMode nBits)
Bits aren't set directly but validated and handled according to priority if more than one exclusive b...
Definition: token.cxx:920
FormulaTokenArray * RewriteMissing(const MissingConvention &rConv)
Rewrites to Plain Old Formula or OOXML, substituting missing parameters.
Definition: token.cxx:1378
virtual void CheckToken(const FormulaToken &t)
Do some checking based on the individual tokens.
Definition: token.cxx:734
virtual ~FormulaTokenArray()
Definition: token.cxx:611
void Finalize()
The array has its final used size and no more token can be added.
Definition: token.cxx:616
FormulaToken * Add(FormulaToken *)
Also used by the compiler. The token MUST had been allocated with new!
Definition: token.cxx:843
void SetCombinedBitsRecalcMode(ScRecalcMode nBits)
Definition: tokenarray.hxx:396
FormulaTokenArrayStandardRange Tokens() const
Definition: tokenarray.hxx:370
bool HasOpCodes(const unordered_opcode_set &rOpCodes) const
Check if the token array contains any of specified opcode tokens.
Definition: token.cxx:577
virtual FormulaToken * AddOpCode(OpCode e)
Definition: token.cxx:1563
FormulaToken ** GetArray() const
Definition: tokenarray.hxx:368
FormulaToken * AddDouble(double fVal)
Definition: token.cxx:893
bool NeedsPodfRewrite(const MissingConventionODF &rConv)
Determines if this formula needs any changes to convert it to something previous versions of OOo coul...
Definition: token.cxx:1357
FormulaToken * ReplaceToken(sal_uInt16 nOffset, FormulaToken *, ReplaceMode eMode)
Also used by the compiler.
Definition: token.cxx:761
FormulaToken * FirstToken() const
Definition: token.cxx:492
virtual void Clear()
Definition: token.cxx:712
void AddExternal(const sal_Unicode *pStr)
Definition: token.cxx:898
void ReinternStrings(svl::SharedStringPool &rPool)
Re-intern SharedString in case the SharedStringPool differs.
Definition: token.cxx:1599
bool HasExternalRef() const
Definition: token.cxx:537
@ CODE_AND_RPN
replacement in pCode and pRPN
Definition: tokenarray.hxx:260
FormulaTokenArray & operator=(const FormulaTokenArray &)
Assignment with incrementing references of FormulaToken entries (not copied!)
Definition: token.cxx:695
FormulaTokenArrayStandardRange RPNTokens() const
Definition: tokenarray.hxx:377
FormulaToken ** GetCode() const
Definition: tokenarray.hxx:375
bool Fill(const css::uno::Sequence< css::sheet::FormulaToken > &rSequence, svl::SharedStringPool &rSPool, ExternalReferenceHelper *pExtRef)
fill the array with the tokens from the sequence.
Definition: token.cxx:459
sal_uInt16 RemoveToken(sal_uInt16 nOffset, sal_uInt16 nCount)
Remove a sequence of tokens from pCode array, and pRPN array if the tokens are referenced there.
Definition: token.cxx:794
bool HasOpCodeRPN(OpCode) const
Definition: token.cxx:557
FormulaToken * FirstRPNToken() const
Definition: token.cxx:506
virtual bool AddFormulaToken(const css::sheet::FormulaToken &rToken, svl::SharedStringPool &rSPool, ExternalReferenceHelper *pExtRef)
Adds the single token to array.
Definition: token.cxx:397
FormulaToken * LastRPNToken() const
Definition: token.cxx:513
FormulaToken * AddString(const svl::SharedString &rStr)
Definition: token.cxx:888
void SetMaskedRecalcMode(ScRecalcMode nBits)
Exclusive bits already set in nMode are zero'ed, nBits may contain combined bits, but only one exclus...
Definition: tokenarray.hxx:404
FormulaToken * AddStringXML(const OUString &rStr)
ocBad with OUString
Definition: token.cxx:914
bool HasOpCode(OpCode) const
Definition: token.cxx:547
ScRecalcMode GetRecalcMode() const
Definition: tokenarray.hxx:394
FormulaToken * AddBad(const OUString &rStr)
Definition: token.cxx:909
std::unique_ptr< FormulaToken *[]> pCode
Definition: tokenarray.hxx:237
void ReInit(const FormulaTokenArray &)
Reconstruct the iterator afresh from a token array.
Definition: token.cxx:1709
const FormulaToken * Next()
Definition: token.cxx:1665
void Jump(short nStart, short nNext, short nStop=SHRT_MAX)
Jump or subroutine call.
Definition: token.cxx:1698
const FormulaToken * GetNonEndOfPathToken(short nIdx) const
Definition: token.cxx:1715
void Push(const FormulaTokenArray *)
Definition: token.cxx:1631
std::vector< Item > maStack
Definition: tokenarray.hxx:546
FormulaTokenIterator(const FormulaTokenArray &)
Definition: token.cxx:1622
const FormulaToken * PeekNextOperator()
Definition: token.cxx:1676
virtual FormulaToken * GetFAPOrigToken() const
Definition: token.cxx:266
virtual const ScSingleRefData * GetSingleRef() const
Definition: token.cxx:283
bool IsFunction() const
Definition: token.cxx:71
bool IsInForceArray() const
Definition: token.cxx:146
virtual void SetError(FormulaError)
Definition: token.cxx:278
bool IsRef() const
Definition: token.cxx:129
virtual sal_uInt8 GetByte() const
Dummy methods to avoid switches and casts where possible, the real token classes have to override the...
Definition: token.cxx:162
virtual const ScSingleRefData * GetSingleRef2() const
Definition: token.cxx:307
virtual sal_uInt16 GetIndex() const
Definition: token.cxx:223
virtual void SetString(const svl::SharedString &rStr)
Definition: token.cxx:218
virtual ParamClass GetInForceArray() const
Definition: token.cxx:173
virtual ~FormulaToken()
Definition: token.cxx:67
virtual void SetSheet(sal_Int16 n)
Definition: token.cxx:240
virtual sal_Int16 GetSheet() const
Definition: token.cxx:234
virtual const OUString & GetExternal() const
Definition: token.cxx:259
OpCode GetOpCode() const
Definition: token.hxx:158
virtual void SetDoubleType(sal_Int16 nType)
Definition: token.cxx:205
virtual bool operator==(const FormulaToken &rToken) const
Definition: token.cxx:153
virtual const std::vector< ScComplexRefData > * GetRefList() const
Definition: token.cxx:336
virtual FormulaToken * Clone() const
Definition: token.hxx:210
virtual sal_Unicode GetChar() const
Definition: token.cxx:245
virtual void SetByte(sal_uInt8 n)
Definition: token.cxx:168
virtual const ScComplexRefData * GetDoubleRef() const
Definition: token.cxx:295
virtual const svl::SharedString & GetString() const
Definition: token.cxx:212
virtual const ScMatrix * GetMatrix() const
Definition: token.cxx:319
virtual void SetInForceArray(ParamClass c)
Definition: token.cxx:179
virtual short * GetJump() const
Definition: token.cxx:252
bool IsExternalRef() const
Definition: token.cxx:112
virtual double GetDouble() const
Definition: token.cxx:184
virtual double & GetDoubleAsReference()
Definition: token.cxx:191
const StackVar eType
Definition: token.hxx:126
virtual void SetIndex(sal_uInt16 n)
Definition: token.cxx:229
sal_uInt8 GetParamCount() const
Definition: token.cxx:89
virtual FormulaError GetError() const
Definition: token.cxx:272
virtual sal_Int16 GetDoubleType() const
Definition: token.cxx:199
virtual bool TextEqual(const formula::FormulaToken &rToken) const
Definition: token.cxx:348
FormulaToken(StackVar eTypeP, OpCode e=ocPush)
Definition: token.cxx:57
virtual ScJumpMatrix * GetJumpMatrix() const
Definition: token.cxx:331
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:1929
virtual void SetDoubleType(sal_Int16 nType) override
Definition: token.cxx:1924
sal_Int16 mnType
Can hold, for example, a value of SvNumFormatType, or by contract any other classification.
Definition: token.hxx:319
virtual sal_Int16 GetDoubleType() const override
always returns 0 for "not typed"
Definition: token.cxx:1919
virtual bool operator==(const FormulaToken &rToken) const override
Definition: token.cxx:2024
bool isRewriteNeeded(OpCode eOp) const
Definition: token.cxx:1018
static bool isRewriteNeeded(OpCode eOp)
Definition: token.cxx:1047
Convention getConvention() const
Definition: tokenarray.hxx:91
SharedString intern(const OUString &rStr)
static const SharedString & getEmptyString()
#define SC_OPCODE_STOP_BIN_OP
Definition: compiler.hxx:95
#define SC_OPCODE_SEP
Definition: compiler.hxx:38
#define SC_OPCODE_STOP_1_PAR
Definition: compiler.hxx:210
#define SC_OPCODE_START_2_PAR
Definition: compiler.hxx:213
#define SC_OPCODE_STOP_UN_OP
Definition: compiler.hxx:102
#define SC_OPCODE_START_UN_OP
Definition: compiler.hxx:100
#define SC_OPCODE_STOP_2_PAR
Definition: compiler.hxx:513
#define SC_OPCODE_STOP_NO_PAR
Definition: compiler.hxx:117
#define SC_OPCODE_STOP_DIV
Definition: compiler.hxx:62
#define SC_OPCODE_OPEN
Definition: compiler.hxx:36
#define SC_OPCODE_START_1_PAR
Definition: compiler.hxx:120
#define SC_OPCODE_START_NO_PAR
Definition: compiler.hxx:107
#define SC_OPCODE_START_BIN_OP
Definition: compiler.hxx:77
int nCount
OUString maString
float x
NORMAL
FormulaError
Definition: errorcodes.hxx:32
DocumentType eType
sal_Int16 nValue
Mode eMode
void * p
sal_Int64 n
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
bool isWhitespace(sal_Unicode c)
def stop(arg=None)
void Clear(EHistoryType eHistory)
NONE
@ ReferenceOrRefArray
Like Reference but the function accepts also a list of references (ocUnion svRefList) as one argument...
Definition: paramclass.hxx:45
@ ForceArray
Area reference must be converted to array in any case, and must also be propagated to subsequent oper...
Definition: paramclass.hxx:56
@ ReferenceOrForceArray
Area reference is not converted to array, but ForceArray must be propagated to subsequent operators a...
Definition: paramclass.hxx:63
@ ForceArrayReturn
A function return forces the caller into array mode for this one call, making it behave like it had F...
Definition: paramclass.hxx:75
std::unordered_set< OpCode, std::hash< std::underlying_type< OpCode >::type > > unordered_opcode_set
Definition: tokenarray.hxx:117
StackVar
Definition: token.hxx:49
@ svIndex
Definition: token.hxx:56
@ svExternalDoubleRef
Definition: token.hxx:74
@ svExternalName
Definition: token.hxx:75
@ svDouble
Definition: token.hxx:51
@ svSep
Definition: token.hxx:80
@ svDoubleRef
Definition: token.hxx:54
@ svExternalSingleRef
Definition: token.hxx:73
@ svString
Definition: token.hxx:52
@ svMatrix
Definition: token.hxx:55
@ svByte
Definition: token.hxx:50
@ svSingleRef
Definition: token.hxx:53
static bool lcl_IsReference(OpCode eOp, StackVar eType)
Definition: token.cxx:45
const svl::SharedString INVALID_STRING
Definition: token.cxx:210
int i
OpCode
Definition: opcode.hxx:29
@ ocArrayOpen
Definition: opcode.hxx:47
@ ocInternalBegin
Definition: opcode.hxx:508
@ ocDiv
Definition: opcode.hxx:84
@ ocTableRef
Definition: opcode.hxx:66
@ ocDBCount
Definition: opcode.hxx:295
@ ocHypGeomDist
Definition: opcode.hxx:359
@ ocRoundUp
Definition: opcode.hxx:213
@ ocAmpersand
Definition: opcode.hxx:85
@ ocStringXML
Definition: opcode.hxx:54
@ ocIndex
Definition: opcode.hxx:322
@ ocLessEqual
Definition: opcode.hxx:91
@ ocNone
Definition: opcode.hxx:515
@ ocOr
Definition: opcode.hxx:94
@ ocNotEqual
Definition: opcode.hxx:88
@ ocAddress
Definition: opcode.hxx:308
@ ocClose
Definition: opcode.hxx:43
@ ocPMT
Definition: opcode.hxx:271
@ ocColRowName
Definition: opcode.hxx:68
@ ocBetaInv
Definition: opcode.hxx:462
@ ocFloor
Definition: opcode.hxx:208
@ ocHypGeomDist_MS
Definition: opcode.hxx:360
@ ocNormDist
Definition: opcode.hxx:251
@ ocFV
Definition: opcode.hxx:277
@ ocRound
Definition: opcode.hxx:212
@ ocArrayRowSep
Definition: opcode.hxx:49
@ ocFDist_LT
Definition: opcode.hxx:368
@ ocPpmt
Definition: opcode.hxx:281
@ ocMacro
Definition: opcode.hxx:67
@ ocOffset
Definition: opcode.hxx:321
@ ocFixed
Definition: opcode.hxx:327
@ ocIfNA
Definition: opcode.hxx:39
@ ocBetaDist
Definition: opcode.hxx:461
@ ocPow
Definition: opcode.hxx:86
@ ocAdd
Definition: opcode.hxx:81
@ ocStop
Definition: opcode.hxx:33
@ ocCeil_Math
Definition: opcode.hxx:207
@ ocFloor_Math
Definition: opcode.hxx:210
@ ocErrName
Definition: opcode.hxx:77
@ ocEqual
Definition: opcode.hxx:87
@ ocIpmt
Definition: opcode.hxx:280
@ ocOpen
Definition: opcode.hxx:42
@ ocSub
Definition: opcode.hxx:82
@ ocInternalEnd
Definition: opcode.hxx:511
@ ocGreater
Definition: opcode.hxx:90
@ ocCeil
Definition: opcode.hxx:203
@ ocColRowNameAuto
Definition: opcode.hxx:69
@ ocTrue
Definition: opcode.hxx:104
@ ocExternal
Definition: opcode.hxx:34
@ ocSpaces
Definition: opcode.hxx:55
@ ocAnd
Definition: opcode.hxx:93
@ ocPercentSign
Definition: opcode.hxx:71
@ ocLogNormDist_MS
Definition: opcode.hxx:362
@ ocSep
Definition: opcode.hxx:46
@ ocMissing
Definition: opcode.hxx:52
@ ocDBCount2
Definition: opcode.hxx:296
@ ocPush
Definition: opcode.hxx:31
@ ocGreaterEqual
Definition: opcode.hxx:92
@ ocBad
Definition: opcode.hxx:53
@ ocDBArea
Definition: opcode.hxx:65
@ ocRate
Definition: opcode.hxx:279
@ ocIfError
Definition: opcode.hxx:38
@ ocPower
Definition: opcode.hxx:217
@ ocWhitespace
Definition: opcode.hxx:56
@ ocRoundDown
Definition: opcode.hxx:214
@ ocMatRef
Definition: opcode.hxx:57
@ ocLess
Definition: opcode.hxx:89
@ ocPoissonDist
Definition: opcode.hxx:258
@ ocLogInv
Definition: opcode.hxx:458
@ ocArrayClose
Definition: opcode.hxx:48
@ ocEuroConvert
Definition: opcode.hxx:498
@ ocArrayColSep
Definition: opcode.hxx:50
@ ocMul
Definition: opcode.hxx:83
@ ocPV
Definition: opcode.hxx:264
@ ocChoose
Definition: opcode.hxx:40
@ ocIf
Definition: opcode.hxx:37
@ ocGammaDist
Definition: opcode.hxx:446
@ ocLog
Definition: opcode.hxx:216
@ ocLogNormDist
Definition: opcode.hxx:361
@ ocName
Definition: opcode.hxx:35
QPRO_FUNC_TYPE nType
Item(const FormulaTokenArray *arr, short pc, short stop)
Definition: token.cxx:1617
const FormulaTokenArray * pArr
Definition: tokenarray.hxx:539
tools::Long GetLen(const Point &rPnt)
const FormulaToken * mpFunc
Definition: token.cxx:1088
int mnCurArg
Definition: token.cxx:1089
ScRecalcMode
Definition: tokenarray.hxx:60
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
sal_Int32 nLength