Bug Summary

File:home/maarten/src/libreoffice/core/formula/source/core/api/token.cxx
Warning:line 760, column 29
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name token.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D FORMULA_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/formula/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/formula/source/core/api/token.cxx

/home/maarten/src/libreoffice/core/formula/source/core/api/token.cxx

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

/home/maarten/src/libreoffice/core/include/formula/token.hxx

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#ifndef INCLUDED_FORMULA_TOKEN_HXX
21#define INCLUDED_FORMULA_TOKEN_HXX
22
23#include <sal/config.h>
24
25#include <cstring>
26#include <memory>
27#include <vector>
28
29#include <formula/formuladllapi.h>
30#include <formula/opcode.hxx>
31#include <formula/types.hxx>
32#include <formula/paramclass.hxx>
33#include <osl/interlck.h>
34#include <rtl/ustring.hxx>
35#include <sal/types.h>
36#include <svl/sharedstring.hxx>
37
38class ScJumpMatrix;
39class ScMatrix;
40struct ScComplexRefData;
41struct ScSingleRefData;
42enum class FormulaError : sal_uInt16;
43
44namespace formula
45{
46
47enum StackVar : sal_uInt8
48{
49 svByte,
50 svDouble,
51 svString,
52 svSingleRef,
53 svDoubleRef,
54 svMatrix,
55 svIndex,
56 svJump,
57 svExternal, // Byte + String
58 svFAP, // FormulaAutoPilot only, ever exported
59 svJumpMatrix,
60 svRefList, // ocUnion result
61 svEmptyCell, // Result is an empty cell, e.g. in LOOKUP()
62
63 svMatrixCell, // Result is a matrix with bells and
64 // whistles as needed for _the_ matrix
65 // formula result.
66
67 svHybridCell, // A temporary condition of a formula
68 // cell during import, having a double
69 // and/or string result and a formula
70 // string to be compiled.
71
72 svExternalSingleRef,
73 svExternalDoubleRef,
74 svExternalName,
75 svSingleVectorRef,
76 svDoubleVectorRef,
77 svError, // error token
78 svMissing, // 0 or ""
79 svSep, // separator, ocSep, ocOpen, ocClose
80 svUnknown // unknown StackType
81};
82
83// Only to be used for debugging output. No guarantee of stability of the
84// return value.
85
86// Turn this into an operator<< when StackVar becomes a scoped enum
87
88inline std::string StackVarEnumToString(StackVar const e)
89{
90 switch (e)
91 {
92 case svByte: return "Byte";
93 case svDouble: return "Double";
94 case svString: return "String";
95 case svSingleRef: return "SingleRef";
96 case svDoubleRef: return "DoubleRef";
97 case svMatrix: return "Matrix";
98 case svIndex: return "Index";
99 case svJump: return "Jump";
100 case svExternal: return "External";
101 case svFAP: return "FAP";
102 case svJumpMatrix: return "JumpMatrix";
103 case svRefList: return "RefList";
104 case svEmptyCell: return "EmptyCell";
105 case svMatrixCell: return "MatrixCell";
106 case svHybridCell: return "HybridCell";
107 case svExternalSingleRef: return "ExternalSingleRef";
108 case svExternalDoubleRef: return "ExternalDoubleRef";
109 case svExternalName: return "ExternalName";
110 case svSingleVectorRef: return "SingleVectorRef";
111 case svDoubleVectorRef: return "DoubleVectorRef";
112 case svError: return "Error";
113 case svMissing: return "Missing";
114 case svSep: return "Sep";
115 case svUnknown: return "Unknown";
116 }
117 std::ostringstream os;
118 os << static_cast<int>(e);
119 return os.str();
120}
121
122class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaToken
123{
124 OpCode eOp;
125 const StackVar eType; // type of data
126 mutable oslInterlockedCount mnRefCnt; // reference count
127
128 FormulaToken& operator=( const FormulaToken& ) = delete;
129public:
130 FormulaToken( StackVar eTypeP,OpCode e = ocPush );
131 FormulaToken( const FormulaToken& r );
132
133 virtual ~FormulaToken();
134
135 void Delete() { delete this; }
20
Memory is released
136 void DeleteIfZeroRef() { if (mnRefCnt == 0) delete this; }
137 StackVar GetType() const { return eType; }
138 bool IsFunction() const; // pure functions, no operators
139
140 bool IsExternalRef() const;
141 bool IsRef() const;
142
143 sal_uInt8 GetParamCount() const;
144
145 void IncRef() const
146 {
147 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
148 }
149
150 void DecRef() const
151 {
152 if (!osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1))
17
Assuming the condition is true
18
Taking true branch
153 const_cast<FormulaToken*>(this)->Delete();
19
Calling 'FormulaToken::Delete'
21
Returning; memory was released
154 }
155
156 oslInterlockedCount GetRef() const { return mnRefCnt; }
157 OpCode GetOpCode() const { return eOp; }
158
159 bool IsInForceArray() const;
160
161 /**
162 Dummy methods to avoid switches and casts where possible,
163 the real token classes have to override the appropriate method[s].
164 The only methods valid anytime if not overridden are:
165
166 - GetByte() since this represents the count of parameters to a function
167 which of course is 0 on non-functions. FormulaByteToken and ScExternal do
168 override it.
169
170 - GetInForceArray() since also this is only used for operators and
171 functions and is ParamClass::Unknown for other tokens.
172
173 Any other non-overridden method pops up an assertion.
174 */
175
176 virtual sal_uInt8 GetByte() const;
177 virtual void SetByte( sal_uInt8 n );
178 virtual ParamClass GetInForceArray() const;
179 virtual void SetInForceArray( ParamClass c );
180 virtual double GetDouble() const;
181 virtual double& GetDoubleAsReference();
182 virtual sal_Int16 GetDoubleType() const;
183 virtual void SetDoubleType( sal_Int16 nType );
184 virtual svl::SharedString GetString() const;
185 virtual void SetString( const svl::SharedString& rStr );
186 virtual sal_uInt16 GetIndex() const;
187 virtual void SetIndex( sal_uInt16 n );
188 virtual sal_Int16 GetSheet() const;
189 virtual void SetSheet( sal_Int16 n );
190 virtual short* GetJump() const;
191 virtual const OUString& GetExternal() const;
192 virtual FormulaToken* GetFAPOrigToken() const;
193 virtual FormulaError GetError() const;
194 virtual void SetError( FormulaError );
195
196 virtual const ScSingleRefData* GetSingleRef() const;
197 virtual ScSingleRefData* GetSingleRef();
198 virtual const ScComplexRefData* GetDoubleRef() const;
199 virtual ScComplexRefData* GetDoubleRef();
200 virtual const ScSingleRefData* GetSingleRef2() const;
201 virtual ScSingleRefData* GetSingleRef2();
202 virtual const ScMatrix* GetMatrix() const;
203 virtual ScMatrix* GetMatrix();
204 virtual ScJumpMatrix* GetJumpMatrix() const;
205 virtual const std::vector<ScComplexRefData>* GetRefList() const;
206 virtual std::vector<ScComplexRefData>* GetRefList();
207
208 virtual FormulaToken* Clone() const { return new FormulaToken(*this); }
209
210 virtual bool TextEqual( const formula::FormulaToken& rToken ) const;
211 virtual bool operator==( const FormulaToken& rToken ) const;
212
213 /** This is dirty and only the compiler should use it! */
214 struct PrivateAccess { friend class FormulaCompiler; private: PrivateAccess() { } };
215 void NewOpCode( OpCode e, const PrivateAccess& ) { eOp = e; }
216};
217
218inline void intrusive_ptr_add_ref(const FormulaToken* p)
219{
220 p->IncRef();
221}
222
223inline void intrusive_ptr_release(const FormulaToken* p)
224{
225 p->DecRef();
226}
227
228class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaByteToken : public FormulaToken
229{
230private:
231 sal_uInt8 nByte;
232 ParamClass eInForceArray;
233protected:
234 FormulaByteToken( OpCode e, sal_uInt8 n, StackVar v, ParamClass c ) :
235 FormulaToken( v,e ), nByte( n ),
236 eInForceArray( c ) {}
237public:
238 FormulaByteToken( OpCode e, sal_uInt8 n, ParamClass c ) :
239 FormulaToken( svByte,e ), nByte( n ),
240 eInForceArray( c ) {}
241 FormulaByteToken( OpCode e, sal_uInt8 n ) :
242 FormulaToken( svByte,e ), nByte( n ),
243 eInForceArray( ParamClass::Unknown ) {}
244 FormulaByteToken( OpCode e ) :
245 FormulaToken( svByte,e ), nByte( 0 ),
246 eInForceArray( ParamClass::Unknown ) {}
247 FormulaByteToken( const FormulaByteToken& r ) :
248 FormulaToken( r ), nByte( r.nByte ),
249 eInForceArray( r.eInForceArray ) {}
250
251 virtual FormulaToken* Clone() const override { return new FormulaByteToken(*this); }
252 virtual sal_uInt8 GetByte() const override;
253 virtual void SetByte( sal_uInt8 n ) override;
254 virtual ParamClass GetInForceArray() const override;
255 virtual void SetInForceArray( ParamClass c ) override;
256 virtual bool operator==( const FormulaToken& rToken ) const override;
257};
258
259
260// A special token for the FormulaAutoPilot only. Keeps a reference pointer of
261// the token of which it was created for comparison.
262class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaFAPToken final : public FormulaByteToken
263{
264private:
265 FormulaTokenRef pOrigToken;
266public:
267 FormulaFAPToken( OpCode e, sal_uInt8 n, FormulaToken* p ) :
268 FormulaByteToken( e, n, svFAP, ParamClass::Unknown ),
269 pOrigToken( p ) {}
270 FormulaFAPToken( const FormulaFAPToken& r ) :
271 FormulaByteToken( r ), pOrigToken( r.pOrigToken ) {}
272
273 virtual FormulaToken* Clone() const override { return new FormulaFAPToken(*this); }
274 virtual FormulaToken* GetFAPOrigToken() const override;
275 virtual bool operator==( const FormulaToken& rToken ) const override;
276};
277
278class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaDoubleToken : public FormulaToken
279{
280private:
281 double fDouble;
282public:
283 FormulaDoubleToken( double f ) :
284 FormulaToken( svDouble ), fDouble( f ) {}
285 FormulaDoubleToken( const FormulaDoubleToken& r ) :
286 FormulaToken( r ), fDouble( r.fDouble ) {}
287
288 virtual FormulaToken* Clone() const override { return new FormulaDoubleToken(*this); }
289 virtual double GetDouble() const override;
290 virtual double& GetDoubleAsReference() override;
291 virtual sal_Int16 GetDoubleType() const override; ///< always returns 0 for "not typed"
292 virtual bool operator==( const FormulaToken& rToken ) const override;
293};
294
295class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaTypedDoubleToken final : public FormulaDoubleToken
296{
297private:
298 sal_Int16 mnType; /**< Can hold, for example, a value
299 of SvNumFormatType, or by
300 contract any other
301 classification. */
302public:
303 FormulaTypedDoubleToken( double f, sal_Int16 nType ) :
304 FormulaDoubleToken( f ), mnType( nType ) {}
305 FormulaTypedDoubleToken( const FormulaTypedDoubleToken& r ) :
306 FormulaDoubleToken( r ), mnType( r.mnType ) {}
307
308 virtual FormulaToken* Clone() const override { return new FormulaTypedDoubleToken(*this); }
309 virtual sal_Int16 GetDoubleType() const override;
310 virtual void SetDoubleType( sal_Int16 nType ) override;
311 virtual bool operator==( const FormulaToken& rToken ) const override;
312};
313
314
315class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaStringToken final : public FormulaToken
316{
317 svl::SharedString maString;
318public:
319 FormulaStringToken( const svl::SharedString& r );
320 FormulaStringToken( const FormulaStringToken& r );
321
322 virtual FormulaToken* Clone() const override;
323 virtual svl::SharedString GetString() const override;
324 virtual void SetString( const svl::SharedString& rStr ) override;
325 virtual bool operator==( const FormulaToken& rToken ) const override;
326};
327
328
329/** Identical to FormulaStringToken, but with explicit OpCode instead of implicit
330 ocPush, and an optional sal_uInt8 for ocBad tokens. */
331class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaStringOpToken final : public FormulaByteToken
332{
333 svl::SharedString maString;
334public:
335 FormulaStringOpToken( OpCode e, const svl::SharedString& r );
336 FormulaStringOpToken( const FormulaStringOpToken& r );
337
338 virtual FormulaToken* Clone() const override;
339 virtual svl::SharedString GetString() const override;
340 virtual void SetString( const svl::SharedString& rStr ) override;
341 virtual bool operator==( const FormulaToken& rToken ) const override;
342};
343
344class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaIndexToken final : public FormulaToken
345{
346private:
347 sal_uInt16 nIndex;
348 sal_Int16 mnSheet;
349public:
350 FormulaIndexToken( OpCode e, sal_uInt16 n, sal_Int16 nSheet = -1 ) :
351 FormulaToken( svIndex, e ), nIndex( n ), mnSheet( nSheet ) {}
352 FormulaIndexToken( const FormulaIndexToken& r ) :
353 FormulaToken( r ), nIndex( r.nIndex ), mnSheet( r.mnSheet ) {}
354
355 virtual FormulaToken* Clone() const override { return new FormulaIndexToken(*this); }
356 virtual sal_uInt16 GetIndex() const override;
357 virtual void SetIndex( sal_uInt16 n ) override;
358 virtual sal_Int16 GetSheet() const override;
359 virtual void SetSheet( sal_Int16 n ) override;
360 virtual bool operator==( const FormulaToken& rToken ) const override;
361};
362
363
364class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaExternalToken final : public FormulaToken
365{
366private:
367 OUString aExternal;
368 sal_uInt8 nByte;
369public:
370 FormulaExternalToken( OpCode e, sal_uInt8 n, const OUString& r ) :
371 FormulaToken( svExternal, e ), aExternal( r ),
372 nByte( n ) {}
373 FormulaExternalToken( OpCode e, const OUString& r ) :
374 FormulaToken(svExternal, e ), aExternal( r ),
375 nByte( 0 ) {}
376 FormulaExternalToken( const FormulaExternalToken& r ) :
377 FormulaToken( r ), aExternal( r.aExternal ),
378 nByte( r.nByte ) {}
379
380 virtual FormulaToken* Clone() const override { return new FormulaExternalToken(*this); }
381 virtual const OUString& GetExternal() const override;
382 virtual sal_uInt8 GetByte() const override;
383 virtual void SetByte( sal_uInt8 n ) override;
384 virtual bool operator==( const FormulaToken& rToken ) const override;
385};
386
387
388class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaMissingToken final : public FormulaToken
389{
390public:
391 FormulaMissingToken() :
392 FormulaToken( svMissing,ocMissing ) {}
393 FormulaMissingToken( const FormulaMissingToken& r ) :
394 FormulaToken( r ) {}
395
396 virtual FormulaToken* Clone() const override { return new FormulaMissingToken(*this); }
397 virtual double GetDouble() const override;
398 virtual svl::SharedString GetString() const override;
399 virtual bool operator==( const FormulaToken& rToken ) const override;
400};
401
402class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaJumpToken final : public FormulaToken
403{
404private:
405 std::unique_ptr<short[]>
406 pJump;
407 ParamClass eInForceArray;
408public:
409 FormulaJumpToken( OpCode e, short const * p ) :
410 FormulaToken( formula::svJump , e),
411 eInForceArray( ParamClass::Unknown)
412 {
413 pJump.reset( new short[ p[0] + 1 ] );
414 memcpy( pJump.get(), p, (p[0] + 1) * sizeof(short) );
415 }
416 FormulaJumpToken( const FormulaJumpToken& r ) :
417 FormulaToken( r ),
418 eInForceArray( r.eInForceArray)
419 {
420 pJump.reset( new short[ r.pJump[0] + 1 ] );
421 memcpy( pJump.get(), r.pJump.get(), (r.pJump[0] + 1) * sizeof(short) );
422 }
423 virtual ~FormulaJumpToken() override;
424 virtual short* GetJump() const override;
425 virtual bool operator==( const formula::FormulaToken& rToken ) const override;
426 virtual FormulaToken* Clone() const override { return new FormulaJumpToken(*this); }
427 virtual ParamClass GetInForceArray() const override;
428 virtual void SetInForceArray( ParamClass c ) override;
429};
430
431
432class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaUnknownToken final : public FormulaToken
433{
434public:
435 FormulaUnknownToken( OpCode e ) :
436 FormulaToken( svUnknown, e ) {}
437 FormulaUnknownToken( const FormulaUnknownToken& r ) :
438 FormulaToken( r ) {}
439
440 virtual FormulaToken* Clone() const override { return new FormulaUnknownToken(*this); }
441 virtual bool operator==( const FormulaToken& rToken ) const override;
442};
443
444
445class FORMULA_DLLPUBLIC__attribute__ ((visibility("default"))) FormulaErrorToken final : public FormulaToken
446{
447 FormulaError nError;
448public:
449 FormulaErrorToken( FormulaError nErr ) :
450 FormulaToken( svError ), nError( nErr) {}
451 FormulaErrorToken( const FormulaErrorToken& r ) :
452 FormulaToken( r ), nError( r.nError) {}
453
454 virtual FormulaToken* Clone() const override { return new FormulaErrorToken(*this); }
455 virtual FormulaError GetError() const override;
456 virtual void SetError( FormulaError nErr ) override;
457 virtual bool operator==( const FormulaToken& rToken ) const override;
458};
459
460
461} // formula
462
463
464#endif
465
466/* vim:set shiftwidth=4 softtabstop=4 expandtab: */