Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : // XXX xelink.hxx MUST be included before xeformula.hxx because of the
31 : : // redifinition of the CREATE_OUSTRING() macro, which is in oox/helper.hxx
32 : : // (indirectly included via xelink.hxx) and ../inc/ftools.hxx (indirectly
33 : : // included via xeformula.hxx) that does an undef first. Ugly.
34 : : #include "xelink.hxx"
35 : : #include "xeformula.hxx"
36 : :
37 : : #include <list>
38 : : #include <map>
39 : : #include <memory>
40 : : #include "addincol.hxx"
41 : : #include "compiler.hxx"
42 : : #include "document.hxx"
43 : : #include "externalrefmgr.hxx"
44 : : #include "rangelst.hxx"
45 : : #include "token.hxx"
46 : : #include "tokenarray.hxx"
47 : : #include "xehelper.hxx"
48 : : #include "xename.hxx"
49 : : #include "xestream.hxx"
50 : :
51 : : using namespace ::formula;
52 : :
53 : : // External reference log =====================================================
54 : :
55 : 0 : XclExpRefLogEntry::XclExpRefLogEntry() :
56 : : mpUrl( 0 ),
57 : : mpFirstTab( 0 ),
58 : : mpLastTab( 0 ),
59 : : mnFirstXclTab( EXC_TAB_DELETED ),
60 : 0 : mnLastXclTab( EXC_TAB_DELETED )
61 : : {
62 : 0 : }
63 : :
64 : : // Formula compiler ===========================================================
65 : :
66 : : namespace {
67 : :
68 : : /** Wrapper structure for a processed Calc formula token with additional
69 : : settings (whitespaces). */
70 : : struct XclExpScToken
71 : : {
72 : : const FormulaToken* mpScToken; /// Currently processed Calc token.
73 : : sal_uInt8 mnSpaces; /// Number of spaces before the Calc token.
74 : :
75 : 0 : inline explicit XclExpScToken() : mpScToken( 0 ), mnSpaces( 0 ) {}
76 : 0 : inline bool Is() const { return mpScToken != 0; }
77 [ # # ]: 0 : inline StackVar GetType() const { return mpScToken ? mpScToken->GetType() : static_cast< StackVar >( svUnknown ); }
78 [ # # ]: 0 : inline OpCode GetOpCode() const { return mpScToken ? mpScToken->GetOpCode() : static_cast< OpCode >( ocNone ); }
79 : : };
80 : :
81 : : // ----------------------------------------------------------------------------
82 : :
83 : : /** Effective token class conversion types. */
84 : : enum XclExpClassConv
85 : : {
86 : : EXC_CLASSCONV_ORG, /// Keep original class of the token.
87 : : EXC_CLASSCONV_VAL, /// Convert ARR tokens to VAL class (REF remains uncahnged).
88 : : EXC_CLASSCONV_ARR /// Convert VAL tokens to ARR class (REF remains uncahnged).
89 : : };
90 : :
91 : : // ----------------------------------------------------------------------------
92 : :
93 : : /** Token class conversion and position of a token in the token array. */
94 : : struct XclExpTokenConvInfo
95 : : {
96 : : sal_uInt16 mnTokPos; /// Position of the token in the token array.
97 : : XclFuncParamConv meConv; /// Token class conversion type.
98 : : bool mbValType; /// Data type (false = REFTYPE, true = VALTYPE).
99 : : };
100 : :
101 : : /** Vector of token position and conversion for all operands of an operator,
102 : : or for all parameters of a function. */
103 : 0 : struct XclExpOperandList : public ::std::vector< XclExpTokenConvInfo >
104 : : {
105 [ # # ]: 0 : inline explicit XclExpOperandList() { reserve( 2 ); }
106 : : void AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType );
107 : : };
108 : :
109 : 0 : void XclExpOperandList::AppendOperand( sal_uInt16 nTokPos, XclFuncParamConv eConv, bool bValType )
110 : : {
111 : 0 : resize( size() + 1 );
112 : 0 : XclExpTokenConvInfo& rConvInfo = back();
113 : 0 : rConvInfo.mnTokPos = nTokPos;
114 : 0 : rConvInfo.meConv = eConv;
115 : 0 : rConvInfo.mbValType = bValType;
116 : 0 : }
117 : :
118 : : typedef boost::shared_ptr< XclExpOperandList > XclExpOperandListRef;
119 : : typedef ::std::vector< XclExpOperandListRef > XclExpOperandListVector;
120 : :
121 : : // ----------------------------------------------------------------------------
122 : :
123 : : /** Encapsulates all data needed for a call to an external function (macro, add-in). */
124 : 0 : struct XclExpExtFuncData
125 : : {
126 : : String maFuncName; /// Name of the function.
127 : : bool mbVBasic; /// True = Visual Basic macro call.
128 : : bool mbHidden; /// True = Create hidden defined name.
129 : :
130 : 0 : inline explicit XclExpExtFuncData() : mbVBasic( false ), mbHidden( false ) {}
131 : : void Set( const String& rFuncName, bool bVBasic, bool bHidden );
132 : : };
133 : :
134 : 0 : void XclExpExtFuncData::Set( const String& rFuncName, bool bVBasic, bool bHidden )
135 : : {
136 : 0 : maFuncName = rFuncName;
137 : 0 : mbVBasic = bVBasic;
138 : 0 : mbHidden = bHidden;
139 : 0 : }
140 : :
141 : : // ----------------------------------------------------------------------------
142 : :
143 : : /** Encapsulates all data needed to process an entire function. */
144 [ # # ][ # # ]: 0 : class XclExpFuncData
145 : : {
146 : : public:
147 : : explicit XclExpFuncData(
148 : : const XclExpScToken& rTokData,
149 : : const XclFunctionInfo& rFuncInfo,
150 : : const XclExpExtFuncData& rExtFuncData );
151 : :
152 : 0 : inline const FormulaToken& GetScToken() const { return *mrTokData.mpScToken; }
153 : 0 : inline OpCode GetOpCode() const { return mrFuncInfo.meOpCode; }
154 : 0 : inline sal_uInt16 GetXclFuncIdx() const { return mrFuncInfo.mnXclFunc; }
155 : 0 : inline bool IsVolatile() const { return mrFuncInfo.IsVolatile(); }
156 : 0 : inline bool IsFixedParamCount() const { return mrFuncInfo.IsFixedParamCount(); }
157 : 0 : inline bool IsMacroFunc() const { return mrFuncInfo.IsMacroFunc(); }
158 : 0 : inline sal_uInt8 GetSpaces() const { return mrTokData.mnSpaces; }
159 : 0 : inline const XclExpExtFuncData& GetExtFuncData() const { return maExtFuncData; }
160 : 0 : inline sal_uInt8 GetReturnClass() const { return mrFuncInfo.mnRetClass; }
161 : :
162 : : const XclFuncParamInfo& GetParamInfo() const;
163 : : bool IsCalcOnlyParam() const;
164 : : bool IsExcelOnlyParam() const;
165 : : void IncParamInfoIdx();
166 : :
167 : 0 : inline sal_uInt8 GetMinParamCount() const { return mrFuncInfo.mnMinParamCount; }
168 : 0 : inline sal_uInt8 GetMaxParamCount() const { return mrFuncInfo.mnMaxParamCount; }
169 : 0 : inline sal_uInt8 GetParamCount() const { return static_cast< sal_uInt8 >( mxOperands->size() ); }
170 : : void FinishParam( sal_uInt16 nTokPos );
171 : 0 : inline XclExpOperandListRef GetOperandList() const { return mxOperands; }
172 : :
173 : 0 : inline ScfUInt16Vec& GetAttrPosVec() { return maAttrPosVec; }
174 : 0 : inline void AppendAttrPos( sal_uInt16 nPos ) { maAttrPosVec.push_back( nPos ); }
175 : :
176 : : private:
177 : : ScfUInt16Vec maAttrPosVec; /// Token array positions of tAttr tokens.
178 : : const XclExpScToken& mrTokData; /// Data about processed function name token.
179 : : const XclFunctionInfo& mrFuncInfo; /// Constant data about processed function.
180 : : XclExpExtFuncData maExtFuncData; /// Data for external functions (macro, add-in).
181 : : XclExpOperandListRef mxOperands; /// Class conversion and position of all parameters.
182 : : const XclFuncParamInfo* mpParamInfo; /// Information for current parameter.
183 : : };
184 : :
185 : 0 : XclExpFuncData::XclExpFuncData( const XclExpScToken& rTokData,
186 : : const XclFunctionInfo& rFuncInfo, const XclExpExtFuncData& rExtFuncData ) :
187 : : mrTokData( rTokData ),
188 : : mrFuncInfo( rFuncInfo ),
189 : : maExtFuncData( rExtFuncData ),
190 [ # # ]: 0 : mxOperands( new XclExpOperandList ),
191 [ # # ][ # # ]: 0 : mpParamInfo( rFuncInfo.mpParamInfos )
[ # # ]
192 : : {
193 : : OSL_ENSURE( mrTokData.mpScToken, "XclExpFuncData::XclExpFuncData - missing core token" );
194 : : // set name of an add-in function
195 [ # # ][ # # ]: 0 : if( (maExtFuncData.maFuncName.Len() == 0) && dynamic_cast< const FormulaExternalToken* >( mrTokData.mpScToken ) )
[ # # ][ # # ]
196 [ # # ][ # # ]: 0 : maExtFuncData.Set( GetScToken().GetExternal(), true, false );
197 : 0 : }
198 : :
199 : 0 : const XclFuncParamInfo& XclExpFuncData::GetParamInfo() const
200 : : {
201 : : static const XclFuncParamInfo saInvalidInfo = { EXC_PARAM_NONE, EXC_PARAMCONV_ORG, false };
202 [ # # ]: 0 : return mpParamInfo ? *mpParamInfo : saInvalidInfo;
203 : : }
204 : :
205 : 0 : bool XclExpFuncData::IsCalcOnlyParam() const
206 : : {
207 [ # # ][ # # ]: 0 : return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_CALCONLY);
208 : : }
209 : :
210 : 0 : bool XclExpFuncData::IsExcelOnlyParam() const
211 : : {
212 [ # # ][ # # ]: 0 : return mpParamInfo && (mpParamInfo->meValid == EXC_PARAM_EXCELONLY);
213 : : }
214 : :
215 : 0 : void XclExpFuncData::IncParamInfoIdx()
216 : : {
217 [ # # ]: 0 : if( mpParamInfo )
218 : : {
219 : : // move pointer to next entry, if something explicit follows
220 [ # # ][ # # ]: 0 : if( (static_cast<size_t>(mpParamInfo - mrFuncInfo.mpParamInfos + 1) < EXC_FUNCINFO_PARAMINFO_COUNT) && (mpParamInfo[ 1 ].meValid != EXC_PARAM_NONE) )
221 : 0 : ++mpParamInfo;
222 : : // if last parameter type is 'Excel-only' or 'Calc-only', do not repeat it
223 [ # # ][ # # ]: 0 : else if( IsExcelOnlyParam() || IsCalcOnlyParam() )
[ # # ]
224 : 0 : mpParamInfo = 0;
225 : : // otherwise: repeat last parameter class
226 : : }
227 : 0 : }
228 : :
229 : 0 : void XclExpFuncData::FinishParam( sal_uInt16 nTokPos )
230 : : {
231 : : // write token class conversion info for this parameter
232 : 0 : const XclFuncParamInfo& rParamInfo = GetParamInfo();
233 : 0 : mxOperands->AppendOperand( nTokPos, rParamInfo.meConv, rParamInfo.mbValType );
234 : : // move to next parameter info structure
235 : 0 : IncParamInfoIdx();
236 : 0 : }
237 : :
238 : : // compiler configuration -----------------------------------------------------
239 : :
240 : : /** Type of token class handling. */
241 : : enum XclExpFmlaClassType
242 : : {
243 : : EXC_CLASSTYPE_CELL, /// Cell formula, shared formula.
244 : : EXC_CLASSTYPE_ARRAY, /// Array formula, conditional formatting, data validation.
245 : : EXC_CLASSTYPE_NAME /// Defined name, range list.
246 : : };
247 : :
248 : : /** Configuration data of the formula compiler. */
249 : : struct XclExpCompConfig
250 : : {
251 : : XclFormulaType meType; /// Type of the formula to be created.
252 : : XclExpFmlaClassType meClassType; /// Token class handling type.
253 : : bool mbLocalLinkMgr; /// True = local (per-sheet) link manager, false = global.
254 : : bool mbFromCell; /// True = Any kind of cell formula (cell, array, shared).
255 : : bool mb3DRefOnly; /// True = Only 3D references allowed (e.g. names).
256 : : bool mbAllowArrays; /// True = Allow inline arrays.
257 : : };
258 : :
259 : : /** The table containing configuration data for all formula types. */
260 : : static const XclExpCompConfig spConfigTable[] =
261 : : {
262 : : // formula type token class type lclLM inCell 3dOnly allowArray
263 : : { EXC_FMLATYPE_CELL, EXC_CLASSTYPE_CELL, true, true, false, true },
264 : : { EXC_FMLATYPE_SHARED, EXC_CLASSTYPE_CELL, true, true, false, true },
265 : : { EXC_FMLATYPE_MATRIX, EXC_CLASSTYPE_ARRAY, true, true, false, true },
266 : : { EXC_FMLATYPE_CONDFMT, EXC_CLASSTYPE_ARRAY, true, false, false, false },
267 : : { EXC_FMLATYPE_DATAVAL, EXC_CLASSTYPE_ARRAY, true, false, false, false },
268 : : { EXC_FMLATYPE_NAME, EXC_CLASSTYPE_NAME, false, false, true, true },
269 : : { EXC_FMLATYPE_CHART, EXC_CLASSTYPE_NAME, true, false, true, true },
270 : : { EXC_FMLATYPE_CONTROL, EXC_CLASSTYPE_NAME, true, false, false, false },
271 : : { EXC_FMLATYPE_WQUERY, EXC_CLASSTYPE_NAME, true, false, true, false },
272 : : { EXC_FMLATYPE_LISTVAL, EXC_CLASSTYPE_NAME, true, false, false, false }
273 : : };
274 : :
275 : : // ----------------------------------------------------------------------------
276 : :
277 : : /** Working data of the formula compiler. Used to push onto a stack for recursive calls. */
278 : 0 : struct XclExpCompData
279 : : {
280 : : typedef boost::shared_ptr< ScTokenArray > ScTokenArrayRef;
281 : :
282 : : const XclExpCompConfig& mrCfg; /// Configuration for current formula type.
283 : : ScTokenArrayRef mxOwnScTokArr; /// Own clone of a Calc token array.
284 : : XclTokenArrayIterator maTokArrIt; /// Iterator in Calc token array.
285 : : XclExpLinkManager* mpLinkMgr; /// Link manager for current context (local/global).
286 : : XclExpRefLog* mpRefLog; /// Log for external references.
287 : : const ScAddress* mpScBasePos; /// Current cell position of the formula.
288 : :
289 : : ScfUInt8Vec maTokVec; /// Byte vector containing token data.
290 : : ScfUInt8Vec maExtDataVec; /// Byte vector containing extended data (arrays, stacked NLRs).
291 : : XclExpOperandListVector maOpListVec; /// Formula structure, maps operators to their operands.
292 : : ScfUInt16Vec maOpPosStack; /// Stack with positions of operand tokens waiting for an operator.
293 : : bool mbStopAtSep; /// True = Stop subexpression creation at an ocSep token.
294 : : bool mbVolatile; /// True = Formula contains volatile function.
295 : : bool mbOk; /// Current state of the compiler.
296 : :
297 : : explicit XclExpCompData( const XclExpCompConfig* pCfg );
298 : : };
299 : :
300 : 0 : XclExpCompData::XclExpCompData( const XclExpCompConfig* pCfg ) :
301 : : mrCfg( pCfg ? *pCfg : spConfigTable[ 0 ] ),
302 : : mpLinkMgr( 0 ),
303 : : mpRefLog( 0 ),
304 : : mpScBasePos( 0 ),
305 : : mbStopAtSep( false ),
306 : : mbVolatile( false ),
307 [ # # ][ # # ]: 0 : mbOk( pCfg != 0 )
[ # # ][ # # ]
[ # # ][ # # ]
308 : : {
309 : : OSL_ENSURE( pCfg, "XclExpFmlaCompImpl::Init - unknown formula type" );
310 : 0 : }
311 : :
312 : : } // namespace
313 : :
314 : : // ----------------------------------------------------------------------------
315 : :
316 : : /** Implementation class of the export formula compiler. */
317 [ # # ][ # # ]: 0 : class XclExpFmlaCompImpl : protected XclExpRoot, protected XclTokenArrayHelper
318 : : {
319 : : public:
320 : : explicit XclExpFmlaCompImpl( const XclExpRoot& rRoot );
321 : :
322 : : /** Creates an Excel token array from the passed Calc token array. */
323 : : XclTokenArrayRef CreateFormula(
324 : : XclFormulaType eType, const ScTokenArray& rScTokArr,
325 : : const ScAddress* pScBasePos = 0, XclExpRefLog* pRefLog = 0 );
326 : : /** Creates a single error token containing the passed error code. */
327 : : XclTokenArrayRef CreateErrorFormula( sal_uInt8 nErrCode );
328 : : /** Creates a single token for a special cell reference. */
329 : : XclTokenArrayRef CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos );
330 : : /** Creates a single tNameXR token for a reference to an external name. */
331 : : XclTokenArrayRef CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName );
332 : :
333 : : /** Returns true, if the passed formula type allows 3D references only. */
334 : : bool Is3DRefOnly( XclFormulaType eType ) const;
335 : :
336 : : // ------------------------------------------------------------------------
337 : : private:
338 : : const XclExpCompConfig* GetConfigForType( XclFormulaType eType ) const;
339 : 0 : inline sal_uInt16 GetSize() const { return static_cast< sal_uInt16 >( mxData->maTokVec.size() ); }
340 : :
341 : : void Init( XclFormulaType eType );
342 : : void Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
343 : : const ScAddress* pScBasePos, XclExpRefLog* pRefLog );
344 : :
345 : : void RecalcTokenClasses();
346 : : void RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo, XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass );
347 : :
348 : : void FinalizeFormula();
349 : : XclTokenArrayRef CreateTokenArray();
350 : :
351 : : // compiler ---------------------------------------------------------------
352 : : // XclExpScToken: pass-by-value and return-by-value is intended
353 : :
354 : : const FormulaToken* GetNextRawToken();
355 : : const FormulaToken* PeekNextRawToken( bool bSkipSpaces ) const;
356 : :
357 : : bool GetNextToken( XclExpScToken& rTokData );
358 : : XclExpScToken GetNextToken();
359 : :
360 : : XclExpScToken Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep );
361 : : XclExpScToken SkipExpression( XclExpScToken aTokData, bool bStopAtSep );
362 : :
363 : : XclExpScToken OrTerm( XclExpScToken aTokData, bool bInParentheses );
364 : : XclExpScToken AndTerm( XclExpScToken aTokData, bool bInParentheses );
365 : : XclExpScToken CompareTerm( XclExpScToken aTokData, bool bInParentheses );
366 : : XclExpScToken ConcatTerm( XclExpScToken aTokData, bool bInParentheses );
367 : : XclExpScToken AddSubTerm( XclExpScToken aTokData, bool bInParentheses );
368 : : XclExpScToken MulDivTerm( XclExpScToken aTokData, bool bInParentheses );
369 : : XclExpScToken PowTerm( XclExpScToken aTokData, bool bInParentheses );
370 : : XclExpScToken UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses );
371 : : XclExpScToken UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses );
372 : : XclExpScToken ListTerm( XclExpScToken aTokData, bool bInParentheses );
373 : : XclExpScToken IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp );
374 : : XclExpScToken RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp );
375 : : XclExpScToken Factor( XclExpScToken aTokData );
376 : :
377 : : // formula structure ------------------------------------------------------
378 : :
379 : : void ProcessDouble( const XclExpScToken& rTokData );
380 : : void ProcessString( const XclExpScToken& rTokData );
381 : : void ProcessMissing( const XclExpScToken& rTokData );
382 : : void ProcessBad( const XclExpScToken& rTokData );
383 : : void ProcessParentheses( const XclExpScToken& rTokData );
384 : : void ProcessBoolean( const XclExpScToken& rTokData );
385 : : void ProcessDdeLink( const XclExpScToken& rTokData );
386 : : void ProcessExternal( const XclExpScToken& rTokData );
387 : : void ProcessMatrix( const XclExpScToken& rTokData );
388 : :
389 : : void ProcessFunction( const XclExpScToken& rTokData );
390 : : void PrepareFunction( XclExpFuncData& rFuncData );
391 : : void FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces );
392 : : void FinishIfFunction( XclExpFuncData& rFuncData );
393 : : void FinishChooseFunction( XclExpFuncData& rFuncData );
394 : :
395 : : XclExpScToken ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData );
396 : : void PrepareParam( XclExpFuncData& rFuncData );
397 : : void FinishParam( XclExpFuncData& rFuncData );
398 : : void AppendDefaultParam( XclExpFuncData& rFuncData );
399 : : void AppendTrailingParam( XclExpFuncData& rFuncData );
400 : :
401 : : // reference handling -----------------------------------------------------
402 : :
403 : : SCTAB GetScTab( const ScSingleRefData& rRefData ) const;
404 : : bool IsRef2D( const ScSingleRefData& rRefData ) const;
405 : : bool IsRef2D( const ScComplexRefData& rRefData ) const;
406 : :
407 : : void ConvertRefData( ScSingleRefData& rRefData, XclAddress& rXclPos,
408 : : bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const;
409 : : void ConvertRefData( ScComplexRefData& rRefData, XclRange& rXclRange,
410 : : bool bNatLangRef ) const;
411 : :
412 : : XclExpRefLogEntry* GetNewRefLogEntry();
413 : : void ProcessCellRef( const XclExpScToken& rTokData );
414 : : void ProcessRangeRef( const XclExpScToken& rTokData );
415 : : void ProcessExternalCellRef( const XclExpScToken& rTokData );
416 : : void ProcessExternalRangeRef( const XclExpScToken& rTokData );
417 : : void ProcessDefinedName( const XclExpScToken& rTokData );
418 : : void ProcessExternalName( const XclExpScToken& rTokData );
419 : :
420 : : // token vector -----------------------------------------------------------
421 : :
422 : : void PushOperandPos( sal_uInt16 nTokPos );
423 : : void PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands );
424 : : sal_uInt16 PopOperandPos();
425 : :
426 : : void Append( sal_uInt8 nData );
427 : : void Append( sal_uInt8 nData, size_t nCount );
428 : : void Append( sal_uInt16 nData );
429 : : void Append( sal_uInt32 nData );
430 : : void Append( double fData );
431 : : void Append( const String& rString );
432 : :
433 : : void AppendAddress( const XclAddress& rXclPos );
434 : : void AppendRange( const XclRange& rXclRange );
435 : :
436 : : void AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount );
437 : :
438 : : void AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
439 : : void AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces = 0 );
440 : : void AppendNumToken( double fValue, sal_uInt8 nSpaces = 0 );
441 : : void AppendBoolToken( bool bValue, sal_uInt8 nSpaces = 0 );
442 : : void AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces = 0 );
443 : : void AppendMissingToken( sal_uInt8 nSpaces = 0 );
444 : : void AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces = 0 );
445 : : void AppendMissingNameToken( const String& rName, sal_uInt8 nSpaces = 0 );
446 : : void AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces = 0 );
447 : : void AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
448 : : void AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
449 : : void AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces = 0 );
450 : :
451 : : void AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces = 0 );
452 : : void AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces = 0 );
453 : : void AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces = 0 );
454 : : void AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount );
455 : : void AppendFuncToken( const XclExpFuncData& rFuncData );
456 : :
457 : : void AppendParenToken( sal_uInt8 nOpenSpaces = 0, sal_uInt8 nCloseSpaces = 0 );
458 : : void AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType );
459 : :
460 : : void InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize );
461 : : void Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset );
462 : :
463 : : void UpdateAttrGoto( sal_uInt16 nAttrPos );
464 : :
465 : : bool IsSpaceToken( sal_uInt16 nPos ) const;
466 : : void RemoveTrailingParen();
467 : :
468 : : void AppendExt( sal_uInt8 nData );
469 : : void AppendExt( sal_uInt8 nData, size_t nCount );
470 : : void AppendExt( sal_uInt16 nData );
471 : : void AppendExt( double fData );
472 : : void AppendExt( const String& rString );
473 : :
474 : : // ------------------------------------------------------------------------
475 : : private:
476 : : typedef ::std::map< XclFormulaType, XclExpCompConfig > XclExpCompConfigMap;
477 : : typedef boost::shared_ptr< XclExpCompData > XclExpCompDataRef;
478 : : typedef ::std::vector< XclExpCompDataRef > XclExpCompDataVector;
479 : :
480 : : XclExpCompConfigMap maCfgMap; /// Compiler configuration map for all formula types.
481 : : XclFunctionProvider maFuncProv; /// Excel function data provider.
482 : : XclExpCompDataRef mxData; /// Working data for current formula.
483 : : XclExpCompDataVector maDataStack; /// Stack for working data, when compiler is called recursively.
484 : : const XclBiff meBiff; /// Cached BIFF version to save GetBiff() calls.
485 : : const SCsCOL mnMaxAbsCol; /// Maximum column index.
486 : : const SCsROW mnMaxAbsRow; /// Maximum row index.
487 : : const SCsCOL mnMaxScCol; /// Maximum column index in Calc itself.
488 : : const SCsROW mnMaxScRow; /// Maximum row index in Calc itself.
489 : : const sal_uInt16 mnMaxColMask; /// Mask to delete invalid bits in column fields.
490 : : const sal_uInt32 mnMaxRowMask; /// Mask to delete invalid bits in row fields.
491 : : };
492 : :
493 : : // ----------------------------------------------------------------------------
494 : :
495 : 0 : XclExpFmlaCompImpl::XclExpFmlaCompImpl( const XclExpRoot& rRoot ) :
496 : : XclExpRoot( rRoot ),
497 : : maFuncProv( rRoot ),
498 : 0 : meBiff( rRoot.GetBiff() ),
499 : 0 : mnMaxAbsCol( static_cast< SCsCOL >( rRoot.GetXclMaxPos().Col() ) ),
500 : 0 : mnMaxAbsRow( static_cast< SCsROW >( rRoot.GetXclMaxPos().Row() ) ),
501 : 0 : mnMaxScCol( static_cast< SCsCOL >( rRoot.GetScMaxPos().Col() ) ),
502 : 0 : mnMaxScRow( static_cast< SCsROW >( rRoot.GetScMaxPos().Row() ) ),
503 : 0 : mnMaxColMask( static_cast< sal_uInt16 >( rRoot.GetXclMaxPos().Col() ) ),
504 [ # # ][ # # ]: 0 : mnMaxRowMask( static_cast< sal_uInt32 >( rRoot.GetXclMaxPos().Row() ) )
[ # # ][ # # ]
505 : : {
506 : : // build the configuration map
507 [ # # ]: 0 : for( const XclExpCompConfig* pEntry = spConfigTable; pEntry != STATIC_TABLE_END( spConfigTable ); ++pEntry )
508 [ # # ]: 0 : maCfgMap[ pEntry->meType ] = *pEntry;
509 : 0 : }
510 : :
511 : 0 : XclTokenArrayRef XclExpFmlaCompImpl::CreateFormula( XclFormulaType eType,
512 : : const ScTokenArray& rScTokArr, const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
513 : : {
514 : : // initialize the compiler
515 : 0 : Init( eType, rScTokArr, pScBasePos, pRefLog );
516 : :
517 : : // start compilation, if initialization didn't fail
518 [ # # ]: 0 : if( mxData->mbOk )
519 : : {
520 [ # # ]: 0 : XclExpScToken aTokData( GetNextToken() );
521 : 0 : sal_uInt16 nScError = rScTokArr.GetCodeError();
522 [ # # ][ # # ]: 0 : if( (nScError != 0) && (!aTokData.Is() || (aTokData.GetOpCode() == ocStop)) )
[ # # ][ # # ]
523 : : {
524 : : // #i50253# convert simple ocStop token to error code formula (e.g. =#VALUE!)
525 [ # # ][ # # ]: 0 : AppendErrorToken( XclTools::GetXclErrorCode( nScError ), aTokData.mnSpaces );
526 : : }
527 [ # # ]: 0 : else if( aTokData.Is() )
528 : : {
529 [ # # ]: 0 : aTokData = Expression( aTokData, false, false );
530 : : }
531 : : else
532 : : {
533 : : OSL_FAIL( "XclExpFmlaCompImpl::CreateFormula - empty token array" );
534 : 0 : mxData->mbOk = false;
535 : : }
536 : :
537 [ # # ]: 0 : if( mxData->mbOk )
538 : : {
539 : : // #i44907# auto-generated SUBTOTAL formula cells have trailing ocStop token
540 [ # # ][ # # ]: 0 : mxData->mbOk = !aTokData.Is() || (aTokData.GetOpCode() == ocStop);
541 : : OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::CreateFormula - unknown garbage behind formula" );
542 : : }
543 : : }
544 : :
545 : : // finalize (add tAttrVolatile token, calculate all token classes)
546 : 0 : RecalcTokenClasses();
547 : 0 : FinalizeFormula();
548 : :
549 : : // leave recursive call, create and return the final token array
550 : 0 : return CreateTokenArray();
551 : : }
552 : :
553 : 0 : XclTokenArrayRef XclExpFmlaCompImpl::CreateErrorFormula( sal_uInt8 nErrCode )
554 : : {
555 : 0 : Init( EXC_FMLATYPE_NAME );
556 : 0 : AppendErrorToken( nErrCode );
557 : 0 : return CreateTokenArray();
558 : : }
559 : :
560 : 0 : XclTokenArrayRef XclExpFmlaCompImpl::CreateSpecialRefFormula( sal_uInt8 nTokenId, const XclAddress& rXclPos )
561 : : {
562 : 0 : Init( EXC_FMLATYPE_NAME );
563 : 0 : AppendOperandTokenId( nTokenId );
564 : 0 : Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
565 : 0 : Append( rXclPos.mnCol ); // do not use AppendAddress(), we always need 16-bit column here
566 : 0 : return CreateTokenArray();
567 : : }
568 : :
569 : 0 : XclTokenArrayRef XclExpFmlaCompImpl::CreateNameXFormula( sal_uInt16 nExtSheet, sal_uInt16 nExtName )
570 : : {
571 : 0 : Init( EXC_FMLATYPE_NAME );
572 : 0 : AppendNameXToken( nExtSheet, nExtName );
573 : 0 : return CreateTokenArray();
574 : : }
575 : :
576 : 0 : bool XclExpFmlaCompImpl::Is3DRefOnly( XclFormulaType eType ) const
577 : : {
578 : 0 : const XclExpCompConfig* pCfg = GetConfigForType( eType );
579 [ # # ][ # # ]: 0 : return pCfg && pCfg->mb3DRefOnly;
580 : : }
581 : :
582 : : // private --------------------------------------------------------------------
583 : :
584 : 0 : const XclExpCompConfig* XclExpFmlaCompImpl::GetConfigForType( XclFormulaType eType ) const
585 : : {
586 [ # # ]: 0 : XclExpCompConfigMap::const_iterator aIt = maCfgMap.find( eType );
587 : : OSL_ENSURE( aIt != maCfgMap.end(), "XclExpFmlaCompImpl::GetConfigForType - unknown formula type" );
588 [ # # ]: 0 : return (aIt == maCfgMap.end()) ? 0 : &aIt->second;
589 : : }
590 : :
591 : 0 : void XclExpFmlaCompImpl::Init( XclFormulaType eType )
592 : : {
593 : : // compiler invoked recursively? - store old working data
594 [ # # ]: 0 : if( mxData.get() )
595 : 0 : maDataStack.push_back( mxData );
596 : : // new compiler working data structure
597 [ # # ]: 0 : mxData.reset( new XclExpCompData( GetConfigForType( eType ) ) );
598 : 0 : }
599 : :
600 : 0 : void XclExpFmlaCompImpl::Init( XclFormulaType eType, const ScTokenArray& rScTokArr,
601 : : const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
602 : : {
603 : : // common initialization
604 : 0 : Init( eType );
605 : :
606 : : // special initialization
607 [ # # # ]: 0 : if( mxData->mbOk ) switch( mxData->mrCfg.meType )
[ # # ]
608 : : {
609 : : case EXC_FMLATYPE_CELL:
610 : : case EXC_FMLATYPE_MATRIX:
611 : : case EXC_FMLATYPE_CHART:
612 : 0 : mxData->mbOk = pScBasePos != 0;
613 : : OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
614 : 0 : mxData->mpScBasePos = pScBasePos;
615 : 0 : break;
616 : : case EXC_FMLATYPE_SHARED:
617 : 0 : mxData->mbOk = pScBasePos != 0;
618 : : OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::Init - missing cell address" );
619 : : // clone the passed token array, convert references relative to current cell position
620 : 0 : mxData->mxOwnScTokArr.reset( rScTokArr.Clone() );
621 : 0 : ScCompiler::MoveRelWrap( *mxData->mxOwnScTokArr, GetDocPtr(), *pScBasePos, MAXCOL, MAXROW );
622 : : // don't remember pScBasePos in mxData->mpScBasePos, shared formulas use real relative refs
623 : 0 : break;
624 : : default:;
625 : : }
626 : :
627 [ # # ]: 0 : if( mxData->mbOk )
628 : : {
629 : : // link manager to be used
630 [ # # ]: 0 : mxData->mpLinkMgr = mxData->mrCfg.mbLocalLinkMgr ? &GetLocalLinkManager() : &GetGlobalLinkManager();
631 : :
632 : : // token array iterator (use cloned token array if present)
633 [ # # ]: 0 : mxData->maTokArrIt.Init( mxData->mxOwnScTokArr ? *mxData->mxOwnScTokArr : rScTokArr, false );
634 : 0 : mxData->mpRefLog = pRefLog;
635 : : }
636 : 0 : }
637 : :
638 : 0 : void XclExpFmlaCompImpl::RecalcTokenClasses()
639 : : {
640 [ # # ]: 0 : if( mxData->mbOk )
641 : : {
642 : 0 : mxData->mbOk = mxData->maOpPosStack.size() == 1;
643 : : OSL_ENSURE( mxData->mbOk, "XclExpFmlaCompImpl::RecalcTokenClasses - position of root token expected on stack" );
644 [ # # ]: 0 : if( mxData->mbOk )
645 : : {
646 : : /* Cell and array formulas start with VAL conversion and VALTYPE
647 : : parameter type, defined names start with ARR conversion and
648 : : REFTYPE parameter type for the root token. */
649 [ # # ]: 0 : XclExpOperandList aOperands;
650 : 0 : bool bNameFmla = mxData->mrCfg.meClassType == EXC_CLASSTYPE_NAME;
651 [ # # ]: 0 : XclFuncParamConv eParamConv = bNameFmla ? EXC_PARAMCONV_ARR : EXC_PARAMCONV_VAL;
652 [ # # ]: 0 : XclExpClassConv eClassConv = bNameFmla ? EXC_CLASSCONV_ARR : EXC_CLASSCONV_VAL;
653 [ # # ]: 0 : XclExpTokenConvInfo aConvInfo = { PopOperandPos(), eParamConv, !bNameFmla };
654 [ # # ]: 0 : RecalcTokenClass( aConvInfo, eParamConv, eClassConv, bNameFmla );
655 : : }
656 : :
657 : : // clear operand vectors (calls to the expensive InsertZeros() may follow)
658 : 0 : mxData->maOpListVec.clear();
659 : 0 : mxData->maOpPosStack.clear();
660 : : }
661 : 0 : }
662 : :
663 : 0 : void XclExpFmlaCompImpl::RecalcTokenClass( const XclExpTokenConvInfo& rConvInfo,
664 : : XclFuncParamConv ePrevConv, XclExpClassConv ePrevClassConv, bool bWasRefClass )
665 : : {
666 : : OSL_ENSURE( rConvInfo.mnTokPos < GetSize(), "XclExpFmlaCompImpl::RecalcTokenClass - invalid token position" );
667 : 0 : sal_uInt8& rnTokenId = mxData->maTokVec[ rConvInfo.mnTokPos ];
668 : 0 : sal_uInt8 nTokClass = GetTokenClass( rnTokenId );
669 : :
670 : : // REF tokens in VALTYPE parameters behave like VAL tokens
671 [ # # ][ # # ]: 0 : if( rConvInfo.mbValType && (nTokClass == EXC_TOKCLASS_REF) )
672 : 0 : ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_VAL );
673 : :
674 : : // replace RPO conversion of operator with parent conversion
675 [ # # ]: 0 : XclFuncParamConv eConv = (rConvInfo.meConv == EXC_PARAMCONV_RPO) ? ePrevConv : rConvInfo.meConv;
676 : :
677 : : // find the effective token class conversion to be performed for this token
678 : 0 : XclExpClassConv eClassConv = EXC_CLASSCONV_ORG;
679 [ # # # # : 0 : switch( eConv )
# # # ]
680 : : {
681 : : case EXC_PARAMCONV_ORG:
682 : : // conversion is forced independent of parent conversion
683 : 0 : eClassConv = EXC_CLASSCONV_ORG;
684 : 0 : break;
685 : : case EXC_PARAMCONV_VAL:
686 : : // conversion is forced independent of parent conversion
687 : 0 : eClassConv = EXC_CLASSCONV_VAL;
688 : 0 : break;
689 : : case EXC_PARAMCONV_ARR:
690 : : // conversion is forced independent of parent conversion
691 : 0 : eClassConv = EXC_CLASSCONV_ARR;
692 : 0 : break;
693 : : case EXC_PARAMCONV_RPT:
694 [ # # # # : 0 : switch( ePrevConv )
# ]
695 : : {
696 : : case EXC_PARAMCONV_ORG:
697 : : case EXC_PARAMCONV_VAL:
698 : : case EXC_PARAMCONV_ARR:
699 : : /* If parent token has REF class (REF token in REFTYPE
700 : : function parameter), then RPT does not repeat the
701 : : previous explicit ORG or ARR conversion, but always
702 : : falls back to VAL conversion. */
703 [ # # ]: 0 : eClassConv = bWasRefClass ? EXC_CLASSCONV_VAL : ePrevClassConv;
704 : 0 : break;
705 : : case EXC_PARAMCONV_RPT:
706 : : // nested RPT repeats the previous effective conversion
707 : 0 : eClassConv = ePrevClassConv;
708 : 0 : break;
709 : : case EXC_PARAMCONV_RPX:
710 : : /* If parent token has REF class (REF token in REFTYPE
711 : : function parameter), then RPX repeats the previous
712 : : effective conversion (wich will be either ORG or ARR,
713 : : but never VAL), otherwise falls back to ORG conversion. */
714 [ # # ]: 0 : eClassConv = bWasRefClass ? ePrevClassConv : EXC_CLASSCONV_ORG;
715 : 0 : break;
716 : : case EXC_PARAMCONV_RPO: // does not occur
717 : 0 : break;
718 : : }
719 : 0 : break;
720 : : case EXC_PARAMCONV_RPX:
721 : : /* If current token still has REF class, set previous effective
722 : : conversion as current conversion. This will not have an effect
723 : : on the REF token but is needed for RPT parameters of this
724 : : function that want to repeat this conversion type. If current
725 : : token is VAL or ARR class, the previous ARR conversion will be
726 : : repeated on the token, but VAL conversion will not. */
727 : : eClassConv = ((nTokClass == EXC_TOKCLASS_REF) || (ePrevClassConv == EXC_CLASSCONV_ARR)) ?
728 [ # # ][ # # ]: 0 : ePrevClassConv : EXC_CLASSCONV_ORG;
729 : 0 : break;
730 : : case EXC_PARAMCONV_RPO: // does not occur (see above)
731 : 0 : break;
732 : : }
733 : :
734 : : // do the token class conversion
735 [ # # # # ]: 0 : switch( eClassConv )
736 : : {
737 : : case EXC_CLASSCONV_ORG:
738 : : /* Cell formulas: leave the current token class. Cell formulas
739 : : are the only type of formulas where all tokens can keep
740 : : their original token class.
741 : : Array and defined name formulas: convert VAL to ARR. */
742 [ # # ][ # # ]: 0 : if( (mxData->mrCfg.meClassType != EXC_CLASSTYPE_CELL) && (nTokClass == EXC_TOKCLASS_VAL) )
[ # # ]
743 : 0 : ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_ARR );
744 : 0 : break;
745 : : case EXC_CLASSCONV_VAL:
746 : : // convert ARR to VAL
747 [ # # ]: 0 : if( nTokClass == EXC_TOKCLASS_ARR )
748 : 0 : ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_VAL );
749 : 0 : break;
750 : : case EXC_CLASSCONV_ARR:
751 : : // convert VAL to ARR
752 [ # # ]: 0 : if( nTokClass == EXC_TOKCLASS_VAL )
753 : 0 : ChangeTokenClass( rnTokenId, nTokClass = EXC_TOKCLASS_ARR );
754 : 0 : break;
755 : : }
756 : :
757 : : // do conversion for nested operands, if token is an operator or function
758 [ # # ]: 0 : if( rConvInfo.mnTokPos < mxData->maOpListVec.size() )
759 [ # # ]: 0 : if( const XclExpOperandList* pOperands = mxData->maOpListVec[ rConvInfo.mnTokPos ].get() )
760 [ # # ][ # # ]: 0 : for( XclExpOperandList::const_iterator aIt = pOperands->begin(), aEnd = pOperands->end(); aIt != aEnd; ++aIt )
761 [ # # ]: 0 : RecalcTokenClass( *aIt, eConv, eClassConv, nTokClass == EXC_TOKCLASS_REF );
762 : 0 : }
763 : :
764 : 0 : void XclExpFmlaCompImpl::FinalizeFormula()
765 : : {
766 [ # # ]: 0 : if( mxData->mbOk )
767 : : {
768 : : // Volatile? Add a tAttrVolatile token at the beginning of the token array.
769 [ # # ]: 0 : if( mxData->mbVolatile )
770 : : {
771 : : // tAttrSpace token can be extended with volatile flag
772 [ # # ]: 0 : if( !IsSpaceToken( 0 ) )
773 : : {
774 : 0 : InsertZeros( 0, 4 );
775 : 0 : mxData->maTokVec[ 0 ] = EXC_TOKID_ATTR;
776 : : }
777 : 0 : mxData->maTokVec[ 1 ] |= EXC_TOK_ATTR_VOLATILE;
778 : : }
779 : :
780 : : // Token array too long? -> error
781 : 0 : mxData->mbOk = mxData->maTokVec.size() <= EXC_TOKARR_MAXLEN;
782 : : }
783 : :
784 [ # # ]: 0 : if( !mxData->mbOk )
785 : : {
786 : : // Any unrecoverable error? -> Create a =#NA formula.
787 : 0 : mxData->maTokVec.clear();
788 : 0 : mxData->maExtDataVec.clear();
789 : 0 : mxData->mbVolatile = false;
790 : 0 : AppendErrorToken( EXC_ERR_NA );
791 : : }
792 : 0 : }
793 : :
794 : 0 : XclTokenArrayRef XclExpFmlaCompImpl::CreateTokenArray()
795 : : {
796 : : // create the Excel token array from working data before resetting mxData
797 : : OSL_ENSURE( mxData->mrCfg.mbAllowArrays || mxData->maExtDataVec.empty(), "XclExpFmlaCompImpl::CreateTokenArray - unexpected extended data" );
798 [ # # ]: 0 : if( !mxData->mrCfg.mbAllowArrays )
799 : 0 : mxData->maExtDataVec.clear();
800 [ # # ][ # # ]: 0 : XclTokenArrayRef xTokArr( new XclTokenArray( mxData->maTokVec, mxData->maExtDataVec, mxData->mbVolatile ) );
[ # # ]
801 [ # # ]: 0 : mxData.reset();
802 : :
803 : : // compiler invoked recursively? - restore old working data
804 [ # # ]: 0 : if( !maDataStack.empty() )
805 : : {
806 [ # # ][ # # ]: 0 : mxData = maDataStack.back();
807 [ # # ]: 0 : maDataStack.pop_back();
808 : : }
809 : :
810 : 0 : return xTokArr;
811 : : }
812 : :
813 : : // compiler -------------------------------------------------------------------
814 : :
815 : 0 : const FormulaToken* XclExpFmlaCompImpl::GetNextRawToken()
816 : : {
817 : 0 : const FormulaToken* pScToken = mxData->maTokArrIt.Get();
818 : 0 : ++mxData->maTokArrIt;
819 : 0 : return pScToken;
820 : : }
821 : :
822 : 0 : const FormulaToken* XclExpFmlaCompImpl::PeekNextRawToken( bool bSkipSpaces ) const
823 : : {
824 : : /* Returns pointer to next raw token in the token array. The token array
825 : : iterator already points to the next token (A call to GetNextToken()
826 : : always increases the iterator), so this function just returns the token
827 : : the iterator points to. To skip space tokens, a copy of the iterator is
828 : : created and set to the passed skip-spaces mode. If spaces have to be
829 : : skipped, and the iterator currently points to a space token, the
830 : : constructor will move it to the next non-space token. */
831 [ # # ]: 0 : XclTokenArrayIterator aTempIt( mxData->maTokArrIt, bSkipSpaces );
832 : 0 : return aTempIt.Get();
833 : : }
834 : :
835 : 0 : bool XclExpFmlaCompImpl::GetNextToken( XclExpScToken& rTokData )
836 : : {
837 : 0 : rTokData.mpScToken = GetNextRawToken();
838 [ # # ]: 0 : rTokData.mnSpaces = (rTokData.GetOpCode() == ocSpaces) ? rTokData.mpScToken->GetByte() : 0;
839 [ # # ]: 0 : while( rTokData.GetOpCode() == ocSpaces )
840 : 0 : rTokData.mpScToken = GetNextRawToken();
841 : 0 : return rTokData.Is();
842 : : }
843 : :
844 : 0 : XclExpScToken XclExpFmlaCompImpl::GetNextToken()
845 : : {
846 : 0 : XclExpScToken aTokData;
847 : 0 : GetNextToken( aTokData );
848 : 0 : return aTokData;
849 : : }
850 : :
851 : : namespace {
852 : :
853 : : /** Returns the Excel token ID of a comparison operator or EXC_TOKID_NONE. */
854 : 0 : inline sal_uInt8 lclGetCompareTokenId( OpCode eOpCode )
855 : : {
856 [ # # # # : 0 : switch( eOpCode )
# # # ]
857 : : {
858 : 0 : case ocLess: return EXC_TOKID_LT;
859 : 0 : case ocLessEqual: return EXC_TOKID_LE;
860 : 0 : case ocEqual: return EXC_TOKID_EQ;
861 : 0 : case ocGreaterEqual: return EXC_TOKID_GE;
862 : 0 : case ocGreater: return EXC_TOKID_GT;
863 : 0 : case ocNotEqual: return EXC_TOKID_NE;
864 : : default:;
865 : : }
866 : 0 : return EXC_TOKID_NONE;
867 : : }
868 : :
869 : : /** Returns the Excel token ID of a string concatenation operator or EXC_TOKID_NONE. */
870 : 0 : inline sal_uInt8 lclGetConcatTokenId( OpCode eOpCode )
871 : : {
872 [ # # ]: 0 : return (eOpCode == ocAmpersand) ? EXC_TOKID_CONCAT : EXC_TOKID_NONE;
873 : : }
874 : :
875 : : /** Returns the Excel token ID of an addition/subtraction operator or EXC_TOKID_NONE. */
876 : 0 : inline sal_uInt8 lclGetAddSubTokenId( OpCode eOpCode )
877 : : {
878 [ # # # ]: 0 : switch( eOpCode )
879 : : {
880 : 0 : case ocAdd: return EXC_TOKID_ADD;
881 : 0 : case ocSub: return EXC_TOKID_SUB;
882 : : default:;
883 : : }
884 : 0 : return EXC_TOKID_NONE;
885 : : }
886 : :
887 : : /** Returns the Excel token ID of a multiplication/division operator or EXC_TOKID_NONE. */
888 : 0 : inline sal_uInt8 lclGetMulDivTokenId( OpCode eOpCode )
889 : : {
890 [ # # # ]: 0 : switch( eOpCode )
891 : : {
892 : 0 : case ocMul: return EXC_TOKID_MUL;
893 : 0 : case ocDiv: return EXC_TOKID_DIV;
894 : : default:;
895 : : }
896 : 0 : return EXC_TOKID_NONE;
897 : : }
898 : :
899 : : /** Returns the Excel token ID of a power operator or EXC_TOKID_NONE. */
900 : 0 : inline sal_uInt8 lclGetPowTokenId( OpCode eOpCode )
901 : : {
902 [ # # ]: 0 : return (eOpCode == ocPow) ? EXC_TOKID_POWER : EXC_TOKID_NONE;
903 : : }
904 : :
905 : : /** Returns the Excel token ID of a trailing unary operator or EXC_TOKID_NONE. */
906 : 0 : inline sal_uInt8 lclGetUnaryPostTokenId( OpCode eOpCode )
907 : : {
908 [ # # ]: 0 : return (eOpCode == ocPercentSign) ? EXC_TOKID_PERCENT : EXC_TOKID_NONE;
909 : : }
910 : :
911 : : /** Returns the Excel token ID of a leading unary operator or EXC_TOKID_NONE. */
912 : 0 : inline sal_uInt8 lclGetUnaryPreTokenId( OpCode eOpCode )
913 : : {
914 [ # # # # ]: 0 : switch( eOpCode )
915 : : {
916 : 0 : case ocAdd: return EXC_TOKID_UPLUS; // +(1)
917 : 0 : case ocNeg: return EXC_TOKID_UMINUS; // NEG(1)
918 : 0 : case ocNegSub: return EXC_TOKID_UMINUS; // -(1)
919 : : default:;
920 : : }
921 : 0 : return EXC_TOKID_NONE;
922 : : }
923 : :
924 : : /** Returns the Excel token ID of a reference list operator or EXC_TOKID_NONE. */
925 : 0 : inline sal_uInt8 lclGetListTokenId( OpCode eOpCode, bool bStopAtSep )
926 : : {
927 [ # # ][ # # ]: 0 : return ((eOpCode == ocUnion) || (!bStopAtSep && (eOpCode == ocSep))) ? EXC_TOKID_LIST : EXC_TOKID_NONE;
[ # # ]
928 : : }
929 : :
930 : : /** Returns the Excel token ID of a reference intersection operator or EXC_TOKID_NONE. */
931 : 0 : inline sal_uInt8 lclGetIntersectTokenId( OpCode eOpCode )
932 : : {
933 [ # # ]: 0 : return (eOpCode == ocIntersect) ? EXC_TOKID_ISECT : EXC_TOKID_NONE;
934 : : }
935 : :
936 : : /** Returns the Excel token ID of a reference range operator or EXC_TOKID_NONE. */
937 : 0 : inline sal_uInt8 lclGetRangeTokenId( OpCode eOpCode )
938 : : {
939 [ # # ]: 0 : return (eOpCode == ocRange) ? EXC_TOKID_RANGE : EXC_TOKID_NONE;
940 : : }
941 : :
942 : : } // namespace
943 : :
944 : 0 : XclExpScToken XclExpFmlaCompImpl::Expression( XclExpScToken aTokData, bool bInParentheses, bool bStopAtSep )
945 : : {
946 [ # # ][ # # ]: 0 : if( mxData->mbOk && aTokData.Is() )
[ # # ]
947 : : {
948 : : // remember old stop-at-ocSep mode, restored below
949 : 0 : bool bOldStopAtSep = mxData->mbStopAtSep;
950 : 0 : mxData->mbStopAtSep = bStopAtSep;
951 : : // start compilation of the subexpression
952 : 0 : aTokData = OrTerm( aTokData, bInParentheses );
953 : : // restore old stop-at-ocSep mode
954 : 0 : mxData->mbStopAtSep = bOldStopAtSep;
955 : : }
956 : 0 : return aTokData;
957 : : }
958 : :
959 : 0 : XclExpScToken XclExpFmlaCompImpl::SkipExpression( XclExpScToken aTokData, bool bStopAtSep )
960 : : {
961 [ # # ][ # # ]: 0 : while( mxData->mbOk && aTokData.Is() && (aTokData.GetOpCode() != ocClose) && (!bStopAtSep || (aTokData.GetOpCode() != ocSep)) )
[ # # ][ # # ]
[ # # ][ # # ]
962 : : {
963 [ # # ]: 0 : if( aTokData.GetOpCode() == ocOpen )
964 : : {
965 : 0 : aTokData = SkipExpression( GetNextToken(), false );
966 [ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = aTokData.GetOpCode() == ocClose;
967 : : }
968 : 0 : aTokData = GetNextToken();
969 : : }
970 : 0 : return aTokData;
971 : : }
972 : :
973 : 0 : XclExpScToken XclExpFmlaCompImpl::OrTerm( XclExpScToken aTokData, bool bInParentheses )
974 : : {
975 : 0 : aTokData = AndTerm( aTokData, bInParentheses );
976 : 0 : sal_uInt8 nParamCount = 1;
977 [ # # ][ # # ]: 0 : while( mxData->mbOk && (aTokData.GetOpCode() == ocOr) )
[ # # ]
978 : : {
979 : 0 : RemoveTrailingParen();
980 : 0 : aTokData = AndTerm( GetNextToken(), bInParentheses );
981 : 0 : RemoveTrailingParen();
982 : 0 : ++nParamCount;
983 [ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
984 : : }
985 [ # # ][ # # ]: 0 : if( mxData->mbOk && (nParamCount > 1) )
[ # # ]
986 : 0 : AppendLogicalOperatorToken( EXC_FUNCID_OR, nParamCount );
987 : 0 : return aTokData;
988 : : }
989 : :
990 : 0 : XclExpScToken XclExpFmlaCompImpl::AndTerm( XclExpScToken aTokData, bool bInParentheses )
991 : : {
992 : 0 : aTokData = CompareTerm( aTokData, bInParentheses );
993 : 0 : sal_uInt8 nParamCount = 1;
994 [ # # ][ # # ]: 0 : while( mxData->mbOk && (aTokData.GetOpCode() == ocAnd) )
[ # # ]
995 : : {
996 : 0 : RemoveTrailingParen();
997 : 0 : aTokData = CompareTerm( GetNextToken(), bInParentheses );
998 : 0 : RemoveTrailingParen();
999 : 0 : ++nParamCount;
1000 [ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = nParamCount <= EXC_FUNC_MAXPARAM;
1001 : : }
1002 [ # # ][ # # ]: 0 : if( mxData->mbOk && (nParamCount > 1) )
[ # # ]
1003 : 0 : AppendLogicalOperatorToken( EXC_FUNCID_AND, nParamCount );
1004 : 0 : return aTokData;
1005 : : }
1006 : :
1007 : 0 : XclExpScToken XclExpFmlaCompImpl::CompareTerm( XclExpScToken aTokData, bool bInParentheses )
1008 : : {
1009 : 0 : aTokData = ConcatTerm( aTokData, bInParentheses );
1010 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1011 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetCompareTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1012 : : {
1013 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1014 : 0 : aTokData = ConcatTerm( GetNextToken(), bInParentheses );
1015 : 0 : AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1016 : : }
1017 : 0 : return aTokData;
1018 : : }
1019 : :
1020 : 0 : XclExpScToken XclExpFmlaCompImpl::ConcatTerm( XclExpScToken aTokData, bool bInParentheses )
1021 : : {
1022 : 0 : aTokData = AddSubTerm( aTokData, bInParentheses );
1023 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1024 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetConcatTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1025 : : {
1026 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1027 : 0 : aTokData = AddSubTerm( GetNextToken(), bInParentheses );
1028 : 0 : AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1029 : : }
1030 : 0 : return aTokData;
1031 : : }
1032 : :
1033 : 0 : XclExpScToken XclExpFmlaCompImpl::AddSubTerm( XclExpScToken aTokData, bool bInParentheses )
1034 : : {
1035 : 0 : aTokData = MulDivTerm( aTokData, bInParentheses );
1036 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1037 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetAddSubTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1038 : : {
1039 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1040 : 0 : aTokData = MulDivTerm( GetNextToken(), bInParentheses );
1041 : 0 : AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1042 : : }
1043 : 0 : return aTokData;
1044 : : }
1045 : :
1046 : 0 : XclExpScToken XclExpFmlaCompImpl::MulDivTerm( XclExpScToken aTokData, bool bInParentheses )
1047 : : {
1048 : 0 : aTokData = PowTerm( aTokData, bInParentheses );
1049 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1050 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetMulDivTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1051 : : {
1052 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1053 : 0 : aTokData = PowTerm( GetNextToken(), bInParentheses );
1054 : 0 : AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1055 : : }
1056 : 0 : return aTokData;
1057 : : }
1058 : :
1059 : 0 : XclExpScToken XclExpFmlaCompImpl::PowTerm( XclExpScToken aTokData, bool bInParentheses )
1060 : : {
1061 : 0 : aTokData = UnaryPostTerm( aTokData, bInParentheses );
1062 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1063 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetPowTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1064 : : {
1065 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1066 : 0 : aTokData = UnaryPostTerm( GetNextToken(), bInParentheses );
1067 : 0 : AppendBinaryOperatorToken( nOpTokenId, true, nSpaces );
1068 : : }
1069 : 0 : return aTokData;
1070 : : }
1071 : :
1072 : 0 : XclExpScToken XclExpFmlaCompImpl::UnaryPostTerm( XclExpScToken aTokData, bool bInParentheses )
1073 : : {
1074 : 0 : aTokData = UnaryPreTerm( aTokData, bInParentheses );
1075 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1076 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetUnaryPostTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1077 : : {
1078 : 0 : AppendUnaryOperatorToken( nOpTokenId, aTokData.mnSpaces );
1079 : 0 : GetNextToken( aTokData );
1080 : : }
1081 : 0 : return aTokData;
1082 : : }
1083 : :
1084 : 0 : XclExpScToken XclExpFmlaCompImpl::UnaryPreTerm( XclExpScToken aTokData, bool bInParentheses )
1085 : : {
1086 [ # # ]: 0 : sal_uInt8 nOpTokenId = mxData->mbOk ? lclGetUnaryPreTokenId( aTokData.GetOpCode() ) : EXC_TOKID_NONE;
1087 [ # # ]: 0 : if( nOpTokenId != EXC_TOKID_NONE )
1088 : : {
1089 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1090 : 0 : aTokData = UnaryPreTerm( GetNextToken(), bInParentheses );
1091 : 0 : AppendUnaryOperatorToken( nOpTokenId, nSpaces );
1092 : : }
1093 : : else
1094 : : {
1095 : 0 : aTokData = ListTerm( aTokData, bInParentheses );
1096 : : }
1097 : 0 : return aTokData;
1098 : : }
1099 : :
1100 : 0 : XclExpScToken XclExpFmlaCompImpl::ListTerm( XclExpScToken aTokData, bool bInParentheses )
1101 : : {
1102 [ # # ]: 0 : sal_uInt16 nSubExprPos = GetSize();
1103 : 0 : bool bHasAnyRefOp = false;
1104 : 0 : bool bHasListOp = false;
1105 [ # # ]: 0 : aTokData = IntersectTerm( aTokData, bHasAnyRefOp );
1106 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1107 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetListTokenId( aTokData.GetOpCode(), mxData->mbStopAtSep )) != EXC_TOKID_NONE) )
[ # # ]
1108 : : {
1109 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1110 [ # # ][ # # ]: 0 : aTokData = IntersectTerm( GetNextToken(), bHasAnyRefOp );
1111 [ # # ]: 0 : AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1112 : 0 : bHasAnyRefOp = bHasListOp = true;
1113 : : }
1114 [ # # ]: 0 : if( bHasAnyRefOp )
1115 : : {
1116 : : // add a tMemFunc token enclosing the entire reference subexpression
1117 [ # # ]: 0 : sal_uInt16 nSubExprSize = GetSize() - nSubExprPos;
1118 [ # # ]: 0 : InsertZeros( nSubExprPos, 3 );
1119 [ # # ]: 0 : mxData->maTokVec[ nSubExprPos ] = GetTokenId( EXC_TOKID_MEMFUNC, EXC_TOKCLASS_REF );
1120 [ # # ]: 0 : Overwrite( nSubExprPos + 1, nSubExprSize );
1121 : : // update the operand/operator stack (set the list expression as operand of the tMemFunc)
1122 [ # # ][ # # ]: 0 : XclExpOperandListRef xOperands( new XclExpOperandList );
[ # # ]
1123 [ # # ][ # # ]: 0 : xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_VAL, false );
1124 [ # # ][ # # ]: 0 : PushOperatorPos( nSubExprPos, xOperands );
1125 : : }
1126 : : // #i86439# enclose list operator into parentheses, e.g. Calc's =AREAS(A1~A2) to Excel's =AREAS((A1;A2))
1127 [ # # ][ # # ]: 0 : if( bHasListOp && !bInParentheses )
1128 [ # # ]: 0 : AppendParenToken();
1129 : 0 : return aTokData;
1130 : : }
1131 : :
1132 : 0 : XclExpScToken XclExpFmlaCompImpl::IntersectTerm( XclExpScToken aTokData, bool& rbHasRefOp )
1133 : : {
1134 : 0 : aTokData = RangeTerm( aTokData, rbHasRefOp );
1135 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1136 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetIntersectTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1137 : : {
1138 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1139 : 0 : aTokData = RangeTerm( GetNextToken(), rbHasRefOp );
1140 : 0 : AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1141 : 0 : rbHasRefOp = true;
1142 : : }
1143 : 0 : return aTokData;
1144 : : }
1145 : :
1146 : 0 : XclExpScToken XclExpFmlaCompImpl::RangeTerm( XclExpScToken aTokData, bool& rbHasRefOp )
1147 : : {
1148 : 0 : aTokData = Factor( aTokData );
1149 : 0 : sal_uInt8 nOpTokenId = EXC_TOKID_NONE;
1150 [ # # ][ # # ]: 0 : while( mxData->mbOk && ((nOpTokenId = lclGetRangeTokenId( aTokData.GetOpCode() )) != EXC_TOKID_NONE) )
[ # # ]
1151 : : {
1152 : 0 : sal_uInt8 nSpaces = aTokData.mnSpaces;
1153 : 0 : aTokData = Factor( GetNextToken() );
1154 : 0 : AppendBinaryOperatorToken( nOpTokenId, false, nSpaces );
1155 : 0 : rbHasRefOp = true;
1156 : : }
1157 : 0 : return aTokData;
1158 : : }
1159 : :
1160 : 0 : XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData )
1161 : : {
1162 [ # # ][ # # ]: 0 : if( !mxData->mbOk || !aTokData.Is() ) return XclExpScToken();
[ # # ]
1163 : :
1164 [ # # # # : 0 : switch( aTokData.GetType() )
# # # # #
# # ]
1165 : : {
1166 : 0 : case svUnknown: mxData->mbOk = false; break;
1167 : 0 : case svDouble: ProcessDouble( aTokData ); break;
1168 : 0 : case svString: ProcessString( aTokData ); break;
1169 : 0 : case svSingleRef: ProcessCellRef( aTokData ); break;
1170 : 0 : case svDoubleRef: ProcessRangeRef( aTokData ); break;
1171 : 0 : case svExternalSingleRef: ProcessExternalCellRef( aTokData ); break;
1172 : 0 : case svExternalDoubleRef: ProcessExternalRangeRef( aTokData ); break;
1173 : 0 : case svExternalName: ProcessExternalName( aTokData ); break;
1174 : 0 : case svMatrix: ProcessMatrix( aTokData ); break;
1175 : 0 : case svExternal: ProcessExternal( aTokData ); break;
1176 : :
1177 [ # # # # : 0 : default: switch( aTokData.GetOpCode() )
# # # # ]
1178 : : {
1179 : 0 : case ocNone: /* do nothing */ break;
1180 : 0 : case ocMissing: ProcessMissing( aTokData ); break;
1181 : 0 : case ocBad: ProcessBad( aTokData ); break;
1182 : 0 : case ocOpen: ProcessParentheses( aTokData ); break;
1183 : 0 : case ocName: ProcessDefinedName( aTokData ); break;
1184 : : case ocFalse:
1185 : 0 : case ocTrue: ProcessBoolean( aTokData ); break;
1186 : 0 : case ocDde: ProcessDdeLink( aTokData ); break;
1187 : 0 : default: ProcessFunction( aTokData );
1188 : : }
1189 : : }
1190 : :
1191 : 0 : return GetNextToken();
1192 : : }
1193 : :
1194 : : // formula structure ----------------------------------------------------------
1195 : :
1196 : 0 : void XclExpFmlaCompImpl::ProcessDouble( const XclExpScToken& rTokData )
1197 : : {
1198 [ # # ]: 0 : double fValue = rTokData.mpScToken->GetDouble();
1199 : : double fInt;
1200 : 0 : double fFrac = modf( fValue, &fInt );
1201 [ # # ][ # # ]: 0 : if( (fFrac == 0.0) && (0.0 <= fInt) && (fInt <= 65535.0) )
[ # # ]
1202 [ # # ]: 0 : AppendIntToken( static_cast< sal_uInt16 >( fInt ), rTokData.mnSpaces );
1203 : : else
1204 [ # # ]: 0 : AppendNumToken( fValue, rTokData.mnSpaces );
1205 : 0 : }
1206 : :
1207 : 0 : void XclExpFmlaCompImpl::ProcessString( const XclExpScToken& rTokData )
1208 : : {
1209 : 0 : AppendOperandTokenId( EXC_TOKID_STR, rTokData.mnSpaces );
1210 : 0 : Append( rTokData.mpScToken->GetString() );
1211 : 0 : }
1212 : :
1213 : 0 : void XclExpFmlaCompImpl::ProcessMissing( const XclExpScToken& rTokData )
1214 : : {
1215 : 0 : AppendMissingToken( rTokData.mnSpaces );
1216 : 0 : }
1217 : :
1218 : 0 : void XclExpFmlaCompImpl::ProcessBad( const XclExpScToken& rTokData )
1219 : : {
1220 : 0 : AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1221 : 0 : }
1222 : :
1223 : 0 : void XclExpFmlaCompImpl::ProcessParentheses( const XclExpScToken& rTokData )
1224 : : {
1225 [ # # ][ # # ]: 0 : XclExpScToken aTokData = Expression( GetNextToken(), true, false );
1226 : 0 : mxData->mbOk = aTokData.GetOpCode() == ocClose;
1227 [ # # ]: 0 : AppendParenToken( rTokData.mnSpaces, aTokData.mnSpaces );
1228 : 0 : }
1229 : :
1230 : 0 : void XclExpFmlaCompImpl::ProcessBoolean( const XclExpScToken& rTokData )
1231 : : {
1232 : 0 : mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
1233 [ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
1234 [ # # ]: 0 : if( mxData->mbOk )
1235 : 0 : AppendBoolToken( rTokData.GetOpCode() == ocTrue, rTokData.mnSpaces );
1236 : 0 : }
1237 : :
1238 : : namespace {
1239 : :
1240 : 0 : inline bool lclGetTokenString( String& rString, const XclExpScToken& rTokData )
1241 : : {
1242 [ # # ][ # # ]: 0 : bool bIsStr = (rTokData.GetType() == svString) && (rTokData.GetOpCode() == ocPush);
1243 [ # # ]: 0 : if( bIsStr )
1244 : 0 : rString = rTokData.mpScToken->GetString();
1245 : 0 : return bIsStr;
1246 : : }
1247 : :
1248 : : } // namespace
1249 : :
1250 : 0 : void XclExpFmlaCompImpl::ProcessDdeLink( const XclExpScToken& rTokData )
1251 : : {
1252 [ # # ][ # # ]: 0 : String aApplic, aTopic, aItem;
[ # # ]
1253 : :
1254 [ # # ]: 0 : mxData->mbOk = GetNextToken().GetOpCode() == ocOpen;
1255 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aApplic, GetNextToken() );
[ # # ]
1256 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
1257 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aTopic, GetNextToken() );
[ # # ]
1258 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocSep;
1259 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = lclGetTokenString( aItem, GetNextToken() );
[ # # ]
1260 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = GetNextToken().GetOpCode() == ocClose;
1261 [ # # ][ # # ]: 0 : if( mxData->mbOk ) mxData->mbOk = aApplic.Len() && aTopic.Len() && aItem.Len();
[ # # ][ # # ]
1262 [ # # ]: 0 : if( mxData->mbOk )
1263 : : {
1264 : : sal_uInt16 nExtSheet, nExtName;
1265 [ # # ][ # # ]: 0 : if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertDde( nExtSheet, nExtName, aApplic, aTopic, aItem ) )
[ # # ][ # # ]
1266 [ # # ]: 0 : AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
1267 : : else
1268 [ # # ]: 0 : AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1269 [ # # ][ # # ]: 0 : }
[ # # ]
1270 : 0 : }
1271 : :
1272 : 0 : void XclExpFmlaCompImpl::ProcessExternal( const XclExpScToken& rTokData )
1273 : : {
1274 : : /* #i47228# Excel import generates svExternal/ocMacro tokens for invalid
1275 : : names and for external/invalid function calls. This function looks for
1276 : : the next token in the token array. If it is an opening parenthesis, the
1277 : : token is processed as external function call, otherwise as undefined name. */
1278 : 0 : const FormulaToken* pNextScToken = PeekNextRawToken( true );
1279 [ # # ][ # # ]: 0 : if( !pNextScToken || (pNextScToken->GetOpCode() != ocOpen) )
[ # # ]
1280 : 0 : AppendMissingNameToken( rTokData.mpScToken->GetExternal(), rTokData.mnSpaces );
1281 : : else
1282 : 0 : ProcessFunction( rTokData );
1283 : 0 : }
1284 : :
1285 : 0 : void XclExpFmlaCompImpl::ProcessMatrix( const XclExpScToken& rTokData )
1286 : : {
1287 : 0 : const ScMatrix* pMatrix = static_cast< const ScToken* >( rTokData.mpScToken )->GetMatrix();
1288 [ # # ][ # # ]: 0 : if( pMatrix && mxData->mrCfg.mbAllowArrays )
[ # # ]
1289 : : {
1290 : : SCSIZE nScCols, nScRows;
1291 [ # # ]: 0 : pMatrix->GetDimensions( nScCols, nScRows );
1292 : : OSL_ENSURE( (nScCols > 0) && (nScRows > 0), "XclExpFmlaCompImpl::ProcessMatrix - invalid matrix size" );
1293 [ # # ]: 0 : sal_uInt16 nCols = ::limit_cast< sal_uInt16 >( nScCols, 0, 256 );
1294 [ # # ]: 0 : sal_uInt16 nRows = ::limit_cast< sal_uInt16 >( nScRows, 0, 1024 );
1295 : :
1296 : : // create the tArray token
1297 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( EXC_TOKID_ARRAY, EXC_TOKCLASS_ARR ), rTokData.mnSpaces );
1298 [ # # ][ # # ]: 0 : Append( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
1299 [ # # ][ # # ]: 0 : Append( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
1300 [ # # ]: 0 : Append( static_cast< sal_uInt32 >( 0 ) );
1301 : :
1302 : : // create the extended data containing the array values
1303 [ # # ][ # # ]: 0 : AppendExt( static_cast< sal_uInt8 >( (meBiff == EXC_BIFF8) ? (nCols - 1) : nCols ) );
1304 [ # # ][ # # ]: 0 : AppendExt( static_cast< sal_uInt16 >( (meBiff == EXC_BIFF8) ? (nRows - 1) : nRows ) );
1305 [ # # ]: 0 : for( SCSIZE nScRow = 0; nScRow < nScRows; ++nScRow )
1306 : : {
1307 [ # # ]: 0 : for( SCSIZE nScCol = 0; nScCol < nScCols; ++nScCol )
1308 : : {
1309 [ # # ]: 0 : ScMatrixValue nMatVal = pMatrix->Get( nScCol, nScRow );
1310 [ # # ]: 0 : if( ScMatrix::IsValueType( nMatVal.nType ) ) // value, boolean, or error
1311 : : {
1312 [ # # ]: 0 : if( ScMatrix::IsBooleanType( nMatVal.nType ) )
1313 : : {
1314 [ # # ]: 0 : AppendExt( EXC_CACHEDVAL_BOOL );
1315 [ # # ][ # # ]: 0 : AppendExt( static_cast< sal_uInt8 >( nMatVal.GetBoolean() ? 1 : 0 ) );
1316 [ # # ]: 0 : AppendExt( 0, 7 );
1317 : : }
1318 [ # # ]: 0 : else if( sal_uInt16 nErr = nMatVal.GetError() )
1319 : : {
1320 [ # # ]: 0 : AppendExt( EXC_CACHEDVAL_ERROR );
1321 [ # # ][ # # ]: 0 : AppendExt( XclTools::GetXclErrorCode( nErr ) );
1322 [ # # ]: 0 : AppendExt( 0, 7 );
1323 : : }
1324 : : else
1325 : : {
1326 [ # # ]: 0 : AppendExt( EXC_CACHEDVAL_DOUBLE );
1327 [ # # ]: 0 : AppendExt( nMatVal.fVal );
1328 : : }
1329 : : }
1330 : : else // string or empty
1331 : : {
1332 [ # # ]: 0 : const String& rStr = nMatVal.GetString();
1333 [ # # ]: 0 : if( rStr.Len() == 0 )
1334 : : {
1335 [ # # ]: 0 : AppendExt( EXC_CACHEDVAL_EMPTY );
1336 [ # # ]: 0 : AppendExt( 0, 8 );
1337 : : }
1338 : : else
1339 : : {
1340 [ # # ]: 0 : AppendExt( EXC_CACHEDVAL_STRING );
1341 [ # # ]: 0 : AppendExt( rStr );
1342 [ # # ]: 0 : }
1343 : : }
1344 : 0 : }
1345 : : }
1346 : : }
1347 : : else
1348 : : {
1349 : : // array in places that do not allow it (cond fmts, data validation)
1350 : 0 : AppendErrorToken( EXC_ERR_NA, rTokData.mnSpaces );
1351 : : }
1352 : 0 : }
1353 : :
1354 : 0 : void XclExpFmlaCompImpl::ProcessFunction( const XclExpScToken& rTokData )
1355 : : {
1356 : 0 : OpCode eOpCode = rTokData.GetOpCode();
1357 [ # # ]: 0 : const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( eOpCode );
1358 : :
1359 [ # # ]: 0 : XclExpExtFuncData aExtFuncData;
1360 : :
1361 : : // no exportable function found - try to create an external macro call
1362 [ # # ][ # # ]: 0 : if( !pFuncInfo && (eOpCode >= SC_OPCODE_START_NO_PAR) )
1363 : : {
1364 [ # # ]: 0 : const String& rFuncName = ScCompiler::GetNativeSymbol( eOpCode );
1365 [ # # ]: 0 : if( rFuncName.Len() )
1366 : : {
1367 [ # # ]: 0 : aExtFuncData.Set( rFuncName, true, false );
1368 [ # # ]: 0 : pFuncInfo = maFuncProv.GetFuncInfoFromOpCode( ocMacro );
1369 : : }
1370 : : }
1371 : :
1372 : 0 : mxData->mbOk = pFuncInfo != 0;
1373 [ # # ]: 0 : if( !mxData->mbOk ) return;
1374 : :
1375 : : // functions simulated by a macro call in file format
1376 [ # # ]: 0 : if( pFuncInfo->IsMacroFunc() )
1377 [ # # ][ # # ]: 0 : aExtFuncData.Set( pFuncInfo->GetMacroFuncName(), false, true );
[ # # ]
1378 : :
1379 [ # # ]: 0 : XclExpFuncData aFuncData( rTokData, *pFuncInfo, aExtFuncData );
1380 : 0 : XclExpScToken aTokData;
1381 : :
1382 : : // preparations for special functions, before function processing starts
1383 [ # # ]: 0 : PrepareFunction( aFuncData );
1384 : :
1385 : : enum { STATE_START, STATE_OPEN, STATE_PARAM, STATE_SEP, STATE_CLOSE, STATE_END }
1386 : 0 : eState = STATE_START;
1387 [ # # # # : 0 : while( eState != STATE_END ) switch( eState )
# # ][ # # ]
1388 : : {
1389 : : case STATE_START:
1390 [ # # ][ # # ]: 0 : mxData->mbOk = GetNextToken( aTokData ) && (aTokData.GetOpCode() == ocOpen);
[ # # ]
1391 [ # # ]: 0 : eState = mxData->mbOk ? STATE_OPEN : STATE_END;
1392 : 0 : break;
1393 : : case STATE_OPEN:
1394 [ # # ]: 0 : mxData->mbOk = GetNextToken( aTokData );
1395 [ # # ][ # # ]: 0 : eState = mxData->mbOk ? ((aTokData.GetOpCode() == ocClose) ? STATE_CLOSE : STATE_PARAM) : STATE_END;
1396 : 0 : break;
1397 : : case STATE_PARAM:
1398 [ # # ]: 0 : aTokData = ProcessParam( aTokData, aFuncData );
1399 [ # # # ]: 0 : switch( aTokData.GetOpCode() )
1400 : : {
1401 : 0 : case ocSep: eState = STATE_SEP; break;
1402 : 0 : case ocClose: eState = STATE_CLOSE; break;
1403 : 0 : default: mxData->mbOk = false;
1404 : : }
1405 [ # # ]: 0 : if( !mxData->mbOk ) eState = STATE_END;
1406 : 0 : break;
1407 : : case STATE_SEP:
1408 [ # # ][ # # ]: 0 : mxData->mbOk = (aFuncData.GetParamCount() < EXC_FUNC_MAXPARAM) && GetNextToken( aTokData );
[ # # ][ # # ]
1409 [ # # ]: 0 : eState = mxData->mbOk ? STATE_PARAM : STATE_END;
1410 : 0 : break;
1411 : : case STATE_CLOSE:
1412 [ # # ]: 0 : FinishFunction( aFuncData, aTokData.mnSpaces );
1413 : 0 : eState = STATE_END;
1414 : 0 : break;
1415 : : default:;
1416 [ # # ][ # # ]: 0 : }
[ # # ]
1417 : : }
1418 : :
1419 : 0 : void XclExpFmlaCompImpl::PrepareFunction( XclExpFuncData& rFuncData )
1420 : : {
1421 [ # # # ]: 0 : switch( rFuncData.GetOpCode() )
1422 : : {
1423 : : case ocCosecant: // simulate CSC(x) by (1/SIN(x))
1424 : : case ocSecant: // simulate SEC(x) by (1/COS(x))
1425 : : case ocCot: // simulate COT(x) by (1/TAN(x))
1426 : : case ocCosecantHyp: // simulate CSCH(x) by (1/SINH(x))
1427 : : case ocSecantHyp: // simulate SECH(x) by (1/COSH(x))
1428 : : case ocCotHyp: // simulate COTH(x) by (1/TANH(x))
1429 : 0 : AppendIntToken( 1 );
1430 : 0 : break;
1431 : : case ocArcCot: // simulate ACOT(x) by (PI/2-ATAN(x))
1432 : 0 : AppendNumToken( F_PI2 );
1433 : 0 : break;
1434 : : default:;
1435 : : }
1436 : 0 : }
1437 : :
1438 : 0 : void XclExpFmlaCompImpl::FinishFunction( XclExpFuncData& rFuncData, sal_uInt8 nCloseSpaces )
1439 : : {
1440 : : // append missing parameters required in Excel, may modify param count
1441 : 0 : AppendTrailingParam( rFuncData );
1442 : :
1443 : : // check if parameter count fits into the limits of the function
1444 : 0 : sal_uInt8 nParamCount = rFuncData.GetParamCount();
1445 [ # # ][ # # ]: 0 : if( (rFuncData.GetMinParamCount() <= nParamCount) && (nParamCount <= rFuncData.GetMaxParamCount()) )
[ # # ]
1446 : : {
1447 : : // first put the tAttrSpace tokens, they must not be included in tAttrGoto handling
1448 : 0 : AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_CLOSE, nCloseSpaces );
1449 : 0 : AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, rFuncData.GetSpaces() );
1450 : :
1451 : : // add tAttrGoto tokens for IF or CHOOSE functions
1452 [ # # ]: 0 : switch( rFuncData.GetOpCode() )
1453 : : {
1454 : : case ocIf:
1455 : : case ocChose:
1456 : 0 : AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
1457 : 0 : break;
1458 : : default:;
1459 : : }
1460 : :
1461 : : // put the tFunc or tFuncVar token (or another special token, e.g. tAttrSum)
1462 : 0 : AppendFuncToken( rFuncData );
1463 : :
1464 : : // update volatile flag - is set if at least one used function is volatile
1465 : 0 : mxData->mbVolatile |= rFuncData.IsVolatile();
1466 : :
1467 : : // update jump tokens for specific functions, add additional tokens
1468 [ # # # # : 0 : switch( rFuncData.GetOpCode() )
# ]
1469 : : {
1470 : : case ocIf:
1471 : 0 : FinishIfFunction( rFuncData );
1472 : 0 : break;
1473 : : case ocChose:
1474 : 0 : FinishChooseFunction( rFuncData );
1475 : 0 : break;
1476 : :
1477 : : case ocCosecant: // simulate CSC(x) by (1/SIN(x))
1478 : : case ocSecant: // simulate SEC(x) by (1/COS(x))
1479 : : case ocCot: // simulate COT(x) by (1/TAN(x))
1480 : : case ocCosecantHyp: // simulate CSCH(x) by (1/SINH(x))
1481 : : case ocSecantHyp: // simulate SECH(x) by (1/COSH(x))
1482 : : case ocCotHyp: // simulate COTH(x) by (1/TANH(x))
1483 : 0 : AppendBinaryOperatorToken( EXC_TOKID_DIV, true );
1484 : 0 : AppendParenToken();
1485 : 0 : break;
1486 : : case ocArcCot: // simulate ACOT(x) by (PI/2-ATAN(x))
1487 : 0 : AppendBinaryOperatorToken( EXC_TOKID_SUB, true );
1488 : 0 : AppendParenToken();
1489 : 0 : break;
1490 : :
1491 : : default:;
1492 : : }
1493 : : }
1494 : : else
1495 : 0 : mxData->mbOk = false;
1496 : 0 : }
1497 : :
1498 : 0 : void XclExpFmlaCompImpl::FinishIfFunction( XclExpFuncData& rFuncData )
1499 : : {
1500 : 0 : sal_uInt16 nParamCount = rFuncData.GetParamCount();
1501 : : OSL_ENSURE( (nParamCount == 2) || (nParamCount == 3), "XclExpFmlaCompImpl::FinishIfFunction - wrong parameter count" );
1502 : 0 : const ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
1503 : : OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishIfFunction - wrong number of tAttr tokens" );
1504 : : // update tAttrIf token following the condition parameter
1505 : 0 : Overwrite( rAttrPos[ 0 ] + 2, static_cast< sal_uInt16 >( rAttrPos[ 1 ] - rAttrPos[ 0 ] ) );
1506 : : // update the tAttrGoto tokens following true and false parameters
1507 : 0 : UpdateAttrGoto( rAttrPos[ 1 ] );
1508 [ # # ]: 0 : if( nParamCount == 3 )
1509 : 0 : UpdateAttrGoto( rAttrPos[ 2 ] );
1510 : 0 : }
1511 : :
1512 : 0 : void XclExpFmlaCompImpl::FinishChooseFunction( XclExpFuncData& rFuncData )
1513 : : {
1514 : 0 : sal_uInt16 nParamCount = rFuncData.GetParamCount();
1515 : 0 : ScfUInt16Vec& rAttrPos = rFuncData.GetAttrPosVec();
1516 : : OSL_ENSURE( nParamCount == rAttrPos.size(), "XclExpFmlaCompImpl::FinishChooseFunction - wrong number of tAttr tokens" );
1517 : : // number of choices is parameter count minus 1
1518 : 0 : sal_uInt16 nChoices = nParamCount - 1;
1519 : : // tAttrChoose token contains number of choices
1520 : 0 : Overwrite( rAttrPos[ 0 ] + 2, nChoices );
1521 : : // cache position of the jump table (follows number of choices in tAttrChoose token)
1522 : 0 : sal_uInt16 nJumpArrPos = rAttrPos[ 0 ] + 4;
1523 : : // size of jump table: number of choices, plus 1 for error position
1524 : 0 : sal_uInt16 nJumpArrSize = 2 * (nChoices + 1);
1525 : : // insert the jump table into the tAttrChoose token
1526 : 0 : InsertZeros( nJumpArrPos, nJumpArrSize );
1527 : : // update positions of tAttrGoto tokens after jump table insertion
1528 : : sal_uInt16 nIdx;
1529 [ # # ]: 0 : for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1530 : 0 : rAttrPos[ nIdx ] = rAttrPos[ nIdx ] + nJumpArrSize;
1531 : : // update the tAttrGoto tokens (they contain a value one-less to real distance)
1532 [ # # ]: 0 : for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1533 : 0 : UpdateAttrGoto( rAttrPos[ nIdx ] );
1534 : : // update the distances in the jump table
1535 : 0 : Overwrite( nJumpArrPos, nJumpArrSize );
1536 [ # # ]: 0 : for( nIdx = 1; nIdx < nParamCount; ++nIdx )
1537 : 0 : Overwrite( nJumpArrPos + 2 * nIdx, static_cast< sal_uInt16 >( rAttrPos[ nIdx ] + 4 - nJumpArrPos ) );
1538 : 0 : }
1539 : :
1540 : 0 : XclExpScToken XclExpFmlaCompImpl::ProcessParam( XclExpScToken aTokData, XclExpFuncData& rFuncData )
1541 : : {
1542 [ # # ]: 0 : if( rFuncData.IsCalcOnlyParam() )
1543 : : {
1544 : : // skip Calc-only parameter, stop at next ocClose or ocSep
1545 : 0 : aTokData = SkipExpression( aTokData, true );
1546 : 0 : rFuncData.IncParamInfoIdx();
1547 : : }
1548 : : else
1549 : : {
1550 : : // insert Excel-only parameters, modifies param count and class in rFuncData
1551 [ # # ]: 0 : while( rFuncData.IsExcelOnlyParam() )
1552 : 0 : AppendDefaultParam( rFuncData );
1553 : :
1554 : : // process the parameter, stop at next ocClose or ocSep
1555 : 0 : PrepareParam( rFuncData );
1556 : : /* #i37355# insert tMissArg token for missing parameters --
1557 : : Excel import filter adds ocMissing token (handled in Factor()),
1558 : : but Calc itself does not do this if a new formula is entered. */
1559 [ # # ]: 0 : switch( aTokData.GetOpCode() )
1560 : : {
1561 : : case ocSep:
1562 : 0 : case ocClose: AppendMissingToken(); break; // empty parameter
1563 : 0 : default: aTokData = Expression( aTokData, false, true );
1564 : : }
1565 : : // finalize the parameter and add special tokens, e.g. for IF or CHOOSE parameters
1566 [ # # ]: 0 : if( mxData->mbOk ) FinishParam( rFuncData );
1567 : : }
1568 : 0 : return aTokData;
1569 : : }
1570 : :
1571 : 0 : void XclExpFmlaCompImpl::PrepareParam( XclExpFuncData& rFuncData )
1572 : : {
1573 : : // index of this parameter is equal to number of already finished parameters
1574 : 0 : sal_uInt8 nParamIdx = rFuncData.GetParamCount();
1575 : :
1576 [ # # # # ]: 0 : switch( rFuncData.GetOpCode() )
1577 : : {
1578 : : case ocIf:
1579 [ # # # ]: 0 : switch( nParamIdx )
1580 : : {
1581 : : // add a tAttrIf token before true-parameter (second parameter)
1582 : 0 : case 1: AppendJumpToken( rFuncData, EXC_TOK_ATTR_IF ); break;
1583 : : // add a tAttrGoto token before false-parameter (third parameter)
1584 : 0 : case 2: AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO ); break;
1585 : : }
1586 : 0 : break;
1587 : :
1588 : : case ocChose:
1589 [ # # # ]: 0 : switch( nParamIdx )
1590 : : {
1591 : : // do nothing for first parameter
1592 : 0 : case 0: break;
1593 : : // add a tAttrChoose token before first value parameter (second parameter)
1594 : 0 : case 1: AppendJumpToken( rFuncData, EXC_TOK_ATTR_CHOOSE ); break;
1595 : : // add a tAttrGoto token before other value parameters
1596 : 0 : default: AppendJumpToken( rFuncData, EXC_TOK_ATTR_GOTO );
1597 : : }
1598 : 0 : break;
1599 : :
1600 : : case ocArcCotHyp: // simulate ACOTH(x) by ATANH(1/(x))
1601 [ # # ]: 0 : if( nParamIdx == 0 )
1602 : 0 : AppendIntToken( 1 );
1603 : 0 : break;
1604 : : default:;
1605 : : }
1606 : 0 : }
1607 : :
1608 : 0 : void XclExpFmlaCompImpl::FinishParam( XclExpFuncData& rFuncData )
1609 : : {
1610 : : // increase parameter count, update operand stack
1611 : 0 : rFuncData.FinishParam( PopOperandPos() );
1612 : :
1613 : : // append more tokens for parameters of some special functions
1614 : 0 : sal_uInt8 nParamIdx = rFuncData.GetParamCount() - 1;
1615 [ # # ]: 0 : switch( rFuncData.GetOpCode() )
1616 : : {
1617 : : case ocArcCotHyp: // simulate ACOTH(x) by ATANH(1/(x))
1618 [ # # ]: 0 : if( nParamIdx == 0 )
1619 : : {
1620 : 0 : AppendParenToken();
1621 : 0 : AppendBinaryOperatorToken( EXC_TOKID_DIV, true );
1622 : : }
1623 : 0 : break;
1624 : : default:;
1625 : : }
1626 : 0 : }
1627 : :
1628 : 0 : void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData )
1629 : : {
1630 : : // prepare parameters of some special functions
1631 : 0 : PrepareParam( rFuncData );
1632 : :
1633 [ # # # # ]: 0 : switch( rFuncData.GetOpCode() )
1634 : : {
1635 : : case ocExternal:
1636 : 0 : AppendAddInCallToken( rFuncData.GetExtFuncData() );
1637 : 0 : break;
1638 : : case ocEuroConvert:
1639 : 0 : AppendEuroToolCallToken( rFuncData.GetExtFuncData() );
1640 : 0 : break;
1641 : : case ocMacro:
1642 : 0 : AppendMacroCallToken( rFuncData.GetExtFuncData() );
1643 : 0 : break;
1644 : : default:
1645 : : {
1646 : : OSL_ENSURE( rFuncData.IsMacroFunc(), "XclExpFmlaCompImpl::AppendDefaultParam - unknown opcode" );
1647 [ # # ]: 0 : if( rFuncData.IsMacroFunc() )
1648 : 0 : AppendMacroCallToken( rFuncData.GetExtFuncData() );
1649 : : else
1650 : 0 : AppendMissingToken(); // to keep parameter count valid
1651 : : }
1652 : : }
1653 : :
1654 : : // update parameter count, add special parameter tokens
1655 : 0 : FinishParam( rFuncData );
1656 : 0 : }
1657 : :
1658 : 0 : void XclExpFmlaCompImpl::AppendTrailingParam( XclExpFuncData& rFuncData )
1659 : : {
1660 : 0 : sal_uInt8 nParamCount = rFuncData.GetParamCount();
1661 [ # # # # : 0 : switch( rFuncData.GetOpCode() )
# # # #
# ]
1662 : : {
1663 : : case ocIf:
1664 [ # # ]: 0 : if( nParamCount == 1 )
1665 : : {
1666 : : // Excel needs at least two parameters in IF function
1667 : 0 : PrepareParam( rFuncData );
1668 : 0 : AppendBoolToken( true );
1669 : 0 : FinishParam( rFuncData );
1670 : : }
1671 : 0 : break;
1672 : :
1673 : : case ocRound:
1674 : : case ocRoundUp:
1675 : : case ocRoundDown:
1676 [ # # ]: 0 : if( nParamCount == 1 )
1677 : : {
1678 : : // ROUND, ROUNDUP, ROUNDDOWN functions are fixed to 2 parameters in Excel
1679 : 0 : PrepareParam( rFuncData );
1680 : 0 : AppendIntToken( 0 );
1681 : 0 : FinishParam( rFuncData );
1682 : : }
1683 : 0 : break;
1684 : :
1685 : : case ocIndex:
1686 [ # # ]: 0 : if( nParamCount == 1 )
1687 : : {
1688 : : // INDEX function needs at least 2 parameters in Excel
1689 : 0 : PrepareParam( rFuncData );
1690 : 0 : AppendMissingToken();
1691 : 0 : FinishParam( rFuncData );
1692 : : }
1693 : 0 : break;
1694 : :
1695 : : case ocExternal:
1696 : : case ocMacro:
1697 : : // external or macro call without parameters needs the external name reference
1698 [ # # ]: 0 : if( nParamCount == 0 )
1699 : 0 : AppendDefaultParam( rFuncData );
1700 : 0 : break;
1701 : :
1702 : : case ocGammaDist:
1703 [ # # ]: 0 : if( nParamCount == 3 )
1704 : : {
1705 : : // GAMMADIST function needs 4 parameters in Excel
1706 : 0 : PrepareParam( rFuncData );
1707 : 0 : AppendIntToken( 1 );
1708 : 0 : FinishParam( rFuncData );
1709 : : }
1710 : 0 : break;
1711 : :
1712 : : case ocPoissonDist:
1713 [ # # ]: 0 : if( nParamCount == 2 )
1714 : : {
1715 : : // POISSON function needs 3 parameters in Excel
1716 : 0 : PrepareParam( rFuncData );
1717 : 0 : AppendIntToken( 1 );
1718 : 0 : FinishParam( rFuncData );
1719 : : }
1720 : 0 : break;
1721 : :
1722 : : case ocNormDist:
1723 [ # # ]: 0 : if( nParamCount == 3 )
1724 : : {
1725 : : // NORMDIST function needs 4 parameters in Excel
1726 : 0 : PrepareParam( rFuncData );
1727 : 0 : AppendBoolToken( true );
1728 : 0 : FinishParam( rFuncData );
1729 : : }
1730 : 0 : break;
1731 : :
1732 : : case ocLogNormDist:
1733 [ # # # ]: 0 : switch( nParamCount )
1734 : : {
1735 : : // LOGNORMDIST function needs 3 parameters in Excel
1736 : : case 1:
1737 : 0 : PrepareParam( rFuncData );
1738 : 0 : AppendIntToken( 0 );
1739 : 0 : FinishParam( rFuncData );
1740 : : // do not break, add next default parameter
1741 : : case 2:
1742 : 0 : PrepareParam( rFuncData );
1743 : 0 : AppendIntToken( 1 );
1744 : 0 : FinishParam( rFuncData );
1745 : 0 : break;
1746 : : default:;
1747 : : }
1748 : :
1749 : 0 : break;
1750 : :
1751 : : default:
1752 : : // #i108420# function without parameters stored as macro call needs the external name reference
1753 [ # # ][ # # ]: 0 : if( (nParamCount == 0) && rFuncData.IsMacroFunc() )
[ # # ]
1754 : 0 : AppendDefaultParam( rFuncData );
1755 : :
1756 : : }
1757 : 0 : }
1758 : :
1759 : : // reference handling ---------------------------------------------------------
1760 : :
1761 : : namespace {
1762 : :
1763 : 0 : inline bool lclIsRefRel2D( const ScSingleRefData& rRefData )
1764 : : {
1765 [ # # ][ # # ]: 0 : return rRefData.IsColRel() || rRefData.IsRowRel();
1766 : : }
1767 : :
1768 : 0 : inline bool lclIsRefDel2D( const ScSingleRefData& rRefData )
1769 : : {
1770 [ # # ][ # # ]: 0 : return rRefData.IsColDeleted() || rRefData.IsRowDeleted();
1771 : : }
1772 : :
1773 : 0 : inline bool lclIsRefRel2D( const ScComplexRefData& rRefData )
1774 : : {
1775 [ # # ][ # # ]: 0 : return lclIsRefRel2D( rRefData.Ref1 ) || lclIsRefRel2D( rRefData.Ref2 );
1776 : : }
1777 : :
1778 : 0 : inline bool lclIsRefDel2D( const ScComplexRefData& rRefData )
1779 : : {
1780 [ # # ][ # # ]: 0 : return lclIsRefDel2D( rRefData.Ref1 ) || lclIsRefDel2D( rRefData.Ref2 );
1781 : : }
1782 : :
1783 : : } // namespace
1784 : :
1785 : 0 : SCTAB XclExpFmlaCompImpl::GetScTab( const ScSingleRefData& rRefData ) const
1786 : : {
1787 [ # # ][ # # ]: 0 : bool bInvTab = rRefData.IsTabDeleted() || (!mxData->mpScBasePos && IsInGlobals() && rRefData.IsTabRel());
[ # # ][ # # ]
1788 [ # # ]: 0 : return bInvTab ? SCTAB_INVALID : static_cast< SCTAB >( rRefData.nTab );
1789 : : }
1790 : :
1791 : 0 : bool XclExpFmlaCompImpl::IsRef2D( const ScSingleRefData& rRefData ) const
1792 : : {
1793 : : /* rRefData.IsFlag3D() determines if sheet name is always visible, even on
1794 : : the own sheet. If 3D references are allowed, the passed reference does
1795 : : not count as 2D reference. */
1796 : 0 : return (!mxData->mpLinkMgr || !rRefData.IsFlag3D()) && !rRefData.IsTabDeleted() &&
1797 [ # # ][ # # ]: 0 : (rRefData.IsTabRel() ? (rRefData.nRelTab == 0) : (static_cast< SCTAB >( rRefData.nTab ) == GetCurrScTab()));
[ # # ][ # #
# # # # ]
1798 : : }
1799 : :
1800 : 0 : bool XclExpFmlaCompImpl::IsRef2D( const ScComplexRefData& rRefData ) const
1801 : : {
1802 [ # # ][ # # ]: 0 : return IsRef2D( rRefData.Ref1 ) && IsRef2D( rRefData.Ref2 );
1803 : : }
1804 : :
1805 : 0 : void XclExpFmlaCompImpl::ConvertRefData(
1806 : : ScSingleRefData& rRefData, XclAddress& rXclPos,
1807 : : bool bNatLangRef, bool bTruncMaxCol, bool bTruncMaxRow ) const
1808 : : {
1809 [ # # ]: 0 : if( mxData->mpScBasePos )
1810 : : {
1811 : : // *** reference position exists (cell, matrix) - convert to absolute ***
1812 : 0 : rRefData.CalcAbsIfRel( *mxData->mpScBasePos );
1813 : :
1814 : : // convert column index
1815 : 0 : SCsCOL& rnScCol = rRefData.nCol;
1816 [ # # ][ # # ]: 0 : if( bTruncMaxCol && (rnScCol == mnMaxScCol) )
1817 : 0 : rnScCol = mnMaxAbsCol;
1818 [ # # ][ # # ]: 0 : else if( (rnScCol < 0) || (rnScCol > mnMaxAbsCol) )
1819 : 0 : rRefData.SetColDeleted( sal_True );
1820 : 0 : rXclPos.mnCol = static_cast< sal_uInt16 >( rnScCol ) & mnMaxColMask;
1821 : :
1822 : : // convert row index
1823 : 0 : SCsROW& rnScRow = rRefData.nRow;
1824 [ # # ][ # # ]: 0 : if( bTruncMaxRow && (rnScRow == mnMaxScRow) )
1825 : 0 : rnScRow = mnMaxAbsRow;
1826 [ # # ][ # # ]: 0 : else if( (rnScRow < 0) || (rnScRow > mnMaxAbsRow) )
1827 : 0 : rRefData.SetRowDeleted( sal_True );
1828 : 0 : rXclPos.mnRow = static_cast< sal_uInt32 >( rnScRow ) & mnMaxRowMask;
1829 : : }
1830 : : else
1831 : : {
1832 : : // *** no reference position (shared, names, condfmt) - use relative values ***
1833 : :
1834 : : // convert column index (2-step-cast ScsCOL->sal_Int16->sal_uInt16 to get all bits correctly)
1835 [ # # ]: 0 : sal_Int16 nXclRelCol = static_cast< sal_Int16 >( rRefData.IsColRel() ? rRefData.nRelCol : rRefData.nCol );
1836 : 0 : rXclPos.mnCol = static_cast< sal_uInt16 >( nXclRelCol ) & mnMaxColMask;
1837 : :
1838 : : // convert row index (2-step-cast ScsROW->sal_Int16->sal_uInt16 to get all bits correctly)
1839 [ # # ]: 0 : sal_Int16 nXclRelRow = static_cast< sal_Int32 >( rRefData.IsRowRel() ? rRefData.nRelRow : rRefData.nRow );
1840 : 0 : rXclPos.mnRow = static_cast< sal_uInt32 >( nXclRelRow ) & mnMaxRowMask;
1841 : :
1842 : : // resolve relative tab index if possible
1843 [ # # ][ # # ]: 0 : if( rRefData.IsTabRel() && !IsInGlobals() && (GetCurrScTab() < GetDoc().GetTableCount()) )
[ # # ][ # # ]
1844 : 0 : rRefData.nTab = static_cast< SCsTAB >( GetCurrScTab() + rRefData.nRelTab );
1845 : : }
1846 : :
1847 : : // flags for relative column and row
1848 [ # # ]: 0 : if( bNatLangRef )
1849 : : {
1850 : : OSL_ENSURE( meBiff == EXC_BIFF8, "XclExpFmlaCompImpl::ConvertRefData - NLRs only for BIFF8" );
1851 : : // Calc does not support absolute reference mode in natural language references
1852 : 0 : ::set_flag( rXclPos.mnCol, EXC_TOK_NLR_REL );
1853 : : }
1854 : : else
1855 : : {
1856 : 0 : sal_uInt16 rnRelRow = rXclPos.mnRow;
1857 [ # # ]: 0 : sal_uInt16& rnRelField = (meBiff <= EXC_BIFF5) ? rnRelRow : rXclPos.mnCol;
1858 : 0 : ::set_flag( rnRelField, EXC_TOK_REF_COLREL, rRefData.IsColRel() );
1859 : 0 : ::set_flag( rnRelField, EXC_TOK_REF_ROWREL, rRefData.IsRowRel() );
1860 : : }
1861 : 0 : }
1862 : :
1863 : 0 : void XclExpFmlaCompImpl::ConvertRefData(
1864 : : ScComplexRefData& rRefData, XclRange& rXclRange, bool bNatLangRef ) const
1865 : : {
1866 : : // convert start and end of the range
1867 : 0 : ConvertRefData( rRefData.Ref1, rXclRange.maFirst, bNatLangRef, false, false );
1868 [ # # ][ # # ]: 0 : bool bTruncMaxCol = !rRefData.Ref1.IsColDeleted() && (rRefData.Ref1.nCol == 0);
1869 [ # # ][ # # ]: 0 : bool bTruncMaxRow = !rRefData.Ref1.IsRowDeleted() && (rRefData.Ref1.nRow == 0);
1870 : 0 : ConvertRefData( rRefData.Ref2, rXclRange.maLast, bNatLangRef, bTruncMaxCol, bTruncMaxRow );
1871 : 0 : }
1872 : :
1873 : 0 : XclExpRefLogEntry* XclExpFmlaCompImpl::GetNewRefLogEntry()
1874 : : {
1875 [ # # ]: 0 : if( mxData->mpRefLog )
1876 : : {
1877 : 0 : mxData->mpRefLog->resize( mxData->mpRefLog->size() + 1 );
1878 : 0 : return &mxData->mpRefLog->back();
1879 : : }
1880 : 0 : return 0;
1881 : : }
1882 : :
1883 : 0 : void XclExpFmlaCompImpl::ProcessCellRef( const XclExpScToken& rTokData )
1884 : : {
1885 : : // get the Excel address components, adjust internal data in aRefData
1886 [ # # ][ # # ]: 0 : bool bNatLangRef = (meBiff == EXC_BIFF8) && mxData->mpScBasePos && (rTokData.GetOpCode() == ocColRowName);
[ # # ]
1887 [ # # ]: 0 : ScSingleRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetSingleRef();
1888 : 0 : XclAddress aXclPos( ScAddress::UNINITIALIZED );
1889 [ # # ]: 0 : ConvertRefData( aRefData, aXclPos, bNatLangRef, false, false );
1890 : :
1891 [ # # ]: 0 : if( bNatLangRef )
1892 : : {
1893 : : OSL_ENSURE( aRefData.IsColRel() != aRefData.IsRowRel(),
1894 : : "XclExpFmlaCompImpl::ProcessCellRef - broken natural language reference" );
1895 : : // create tNlr token for natural language reference
1896 [ # # ]: 0 : sal_uInt8 nSubId = aRefData.IsColRel() ? EXC_TOK_NLR_COLV : EXC_TOK_NLR_ROWV;
1897 [ # # ]: 0 : AppendOperandTokenId( EXC_TOKID_NLR, rTokData.mnSpaces );
1898 [ # # ]: 0 : Append( nSubId );
1899 [ # # ]: 0 : AppendAddress( aXclPos );
1900 : : }
1901 : : else
1902 : : {
1903 : : // store external cell contents in CRN records
1904 [ # # ][ # # ]: 0 : if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
[ # # ][ # # ]
1905 [ # # ]: 0 : mxData->mpLinkMgr->StoreCell( aRefData );
1906 : :
1907 : : // create the tRef, tRefErr, tRefN, tRef3d, or tRefErr3d token
1908 [ # # ][ # # ]: 0 : if( !mxData->mrCfg.mb3DRefOnly && IsRef2D( aRefData ) )
[ # # ][ # # ]
1909 : : {
1910 : : // 2D reference (not in defined names, but allowed in range lists)
1911 : 0 : sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_REFN :
1912 [ # # ]: 0 : (lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR : EXC_TOKID_REF);
[ # # # # ]
1913 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1914 [ # # ]: 0 : AppendAddress( aXclPos );
1915 : : }
1916 [ # # ]: 0 : else if( mxData->mpLinkMgr ) // 3D reference
1917 : : {
1918 : : // 1-based EXTERNSHEET index and 0-based Excel sheet index
1919 : : sal_uInt16 nExtSheet, nXclTab;
1920 [ # # ][ # # ]: 0 : mxData->mpLinkMgr->FindExtSheet( nExtSheet, nXclTab, GetScTab( aRefData ), GetNewRefLogEntry() );
[ # # ]
1921 : : // write the token
1922 [ # # ]: 0 : sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
1923 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1924 [ # # ]: 0 : Append( nExtSheet );
1925 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
1926 : : {
1927 [ # # ]: 0 : Append( 0, 8 );
1928 [ # # ]: 0 : Append( nXclTab );
1929 [ # # ]: 0 : Append( nXclTab );
1930 : : }
1931 [ # # ]: 0 : AppendAddress( aXclPos );
1932 : : }
1933 : : else
1934 : : {
1935 : : // 3D ref in cond. format, or 2D ref in name
1936 [ # # ]: 0 : AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
1937 : : }
1938 : : }
1939 : 0 : }
1940 : :
1941 : 0 : void XclExpFmlaCompImpl::ProcessRangeRef( const XclExpScToken& rTokData )
1942 : : {
1943 : : // get the Excel address components, adjust internal data in aRefData
1944 [ # # ]: 0 : ScComplexRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetDoubleRef();
1945 : 0 : XclRange aXclRange( ScAddress::UNINITIALIZED );
1946 [ # # ]: 0 : ConvertRefData( aRefData, aXclRange, false );
1947 : :
1948 : : // store external cell contents in CRN records
1949 [ # # ][ # # ]: 0 : if( mxData->mrCfg.mbFromCell && mxData->mpLinkMgr && mxData->mpScBasePos )
[ # # ][ # # ]
1950 [ # # ]: 0 : mxData->mpLinkMgr->StoreCellRange( aRefData );
1951 : :
1952 : : // create the tArea, tAreaErr, tAreaN, tArea3d, or tAreaErr3d token
1953 [ # # ][ # # ]: 0 : if( !mxData->mrCfg.mb3DRefOnly && IsRef2D( aRefData ) )
[ # # ][ # # ]
1954 : : {
1955 : : // 2D reference (not in name formulas, but allowed in range lists)
1956 : 0 : sal_uInt8 nBaseId = (!mxData->mpScBasePos && lclIsRefRel2D( aRefData )) ? EXC_TOKID_AREAN :
1957 [ # # ]: 0 : (lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR : EXC_TOKID_AREA);
[ # # # # ]
1958 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1959 [ # # ]: 0 : AppendRange( aXclRange );
1960 : : }
1961 [ # # ]: 0 : else if( mxData->mpLinkMgr ) // 3D reference
1962 : : {
1963 : : // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
1964 : : sal_uInt16 nExtSheet, nFirstXclTab, nLastXclTab;
1965 : 0 : mxData->mpLinkMgr->FindExtSheet( nExtSheet, nFirstXclTab, nLastXclTab,
1966 [ # # ][ # # ]: 0 : GetScTab( aRefData.Ref1 ), GetScTab( aRefData.Ref2 ), GetNewRefLogEntry() );
[ # # # # ]
1967 : : // write the token
1968 [ # # ]: 0 : sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
1969 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
1970 [ # # ]: 0 : Append( nExtSheet );
1971 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
1972 : : {
1973 [ # # ]: 0 : Append( 0, 8 );
1974 [ # # ]: 0 : Append( nFirstXclTab );
1975 [ # # ]: 0 : Append( nLastXclTab );
1976 : : }
1977 [ # # ]: 0 : AppendRange( aXclRange );
1978 : : }
1979 : : else
1980 : : {
1981 : : // 3D ref in cond. format, or 2D ref in name
1982 [ # # ]: 0 : AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
1983 : : }
1984 : 0 : }
1985 : :
1986 : 0 : void XclExpFmlaCompImpl::ProcessExternalCellRef( const XclExpScToken& rTokData )
1987 : : {
1988 [ # # ]: 0 : if( mxData->mpLinkMgr )
1989 : : {
1990 : : // get the Excel address components, adjust internal data in aRefData
1991 [ # # ]: 0 : ScSingleRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetSingleRef();
1992 : 0 : XclAddress aXclPos( ScAddress::UNINITIALIZED );
1993 [ # # ]: 0 : ConvertRefData( aRefData, aXclPos, false, false, false );
1994 : :
1995 : : // store external cell contents in CRN records
1996 [ # # ]: 0 : sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
1997 [ # # ]: 0 : const String& rTabName = rTokData.mpScToken->GetString();
1998 [ # # ][ # # ]: 0 : if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
[ # # ]
1999 [ # # ]: 0 : mxData->mpLinkMgr->StoreCell( nFileId, rTabName, aRefData );
2000 : :
2001 : : // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2002 : : sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
2003 [ # # ][ # # ]: 0 : mxData->mpLinkMgr->FindExtSheet( nFileId, rTabName, 1, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
2004 : : // write the token
2005 [ # # ]: 0 : sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_REFERR3D : EXC_TOKID_REF3D;
2006 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2007 [ # # ]: 0 : Append( nExtSheet );
2008 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
2009 : : {
2010 [ # # ]: 0 : Append( 0, 8 );
2011 [ # # ]: 0 : Append( nFirstSBTab );
2012 [ # # ]: 0 : Append( nLastSBTab );
2013 : : }
2014 [ # # ]: 0 : AppendAddress( aXclPos );
2015 : : }
2016 : : else
2017 : : {
2018 : 0 : AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2019 : : }
2020 : 0 : }
2021 : :
2022 : 0 : void XclExpFmlaCompImpl::ProcessExternalRangeRef( const XclExpScToken& rTokData )
2023 : : {
2024 [ # # ]: 0 : if( mxData->mpLinkMgr )
2025 : : {
2026 : : // get the Excel address components, adjust internal data in aRefData
2027 [ # # ]: 0 : ScComplexRefData aRefData = static_cast< const ScToken* >( rTokData.mpScToken )->GetDoubleRef();
2028 : 0 : XclRange aXclRange( ScAddress::UNINITIALIZED );
2029 [ # # ]: 0 : ConvertRefData( aRefData, aXclRange, false );
2030 : :
2031 : : // store external cell contents in CRN records
2032 [ # # ]: 0 : sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2033 [ # # ]: 0 : const String& rTabName = rTokData.mpScToken->GetString();
2034 [ # # ][ # # ]: 0 : if( mxData->mrCfg.mbFromCell && mxData->mpScBasePos )
[ # # ]
2035 [ # # ]: 0 : mxData->mpLinkMgr->StoreCellRange( nFileId, rTabName, aRefData );
2036 : :
2037 : : // 1-based EXTERNSHEET index and 0-based Excel sheet indexes
2038 : : sal_uInt16 nExtSheet, nFirstSBTab, nLastSBTab;
2039 : 0 : sal_uInt16 nTabSpan = static_cast< sal_uInt16 >( aRefData.Ref2.nTab - aRefData.Ref1.nTab + 1 );
2040 [ # # ][ # # ]: 0 : mxData->mpLinkMgr->FindExtSheet( nFileId, rTabName, nTabSpan, nExtSheet, nFirstSBTab, nLastSBTab, GetNewRefLogEntry() );
2041 : : // write the token
2042 [ # # ]: 0 : sal_uInt8 nBaseId = lclIsRefDel2D( aRefData ) ? EXC_TOKID_AREAERR3D : EXC_TOKID_AREA3D;
2043 [ # # ]: 0 : AppendOperandTokenId( GetTokenId( nBaseId, EXC_TOKCLASS_REF ), rTokData.mnSpaces );
2044 [ # # ]: 0 : Append( nExtSheet );
2045 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
2046 : : {
2047 [ # # ]: 0 : Append( 0, 8 );
2048 [ # # ]: 0 : Append( nFirstSBTab );
2049 [ # # ]: 0 : Append( nLastSBTab );
2050 : : }
2051 [ # # ]: 0 : AppendRange( aXclRange );
2052 : : }
2053 : : else
2054 : : {
2055 : 0 : AppendErrorToken( EXC_ERR_REF, rTokData.mnSpaces );
2056 : : }
2057 : 0 : }
2058 : :
2059 : 0 : void XclExpFmlaCompImpl::ProcessDefinedName( const XclExpScToken& rTokData )
2060 : : {
2061 : 0 : SCTAB nTab = SCTAB_GLOBAL;
2062 : 0 : bool bGlobal = rTokData.mpScToken->IsGlobal();
2063 [ # # ][ # # ]: 0 : if (!bGlobal && mxData->mpScBasePos)
[ # # ]
2064 : 0 : nTab = mxData->mpScBasePos->Tab();
2065 : :
2066 : 0 : XclExpNameManager& rNameMgr = GetNameManager();
2067 : 0 : sal_uInt16 nNameIdx = rNameMgr.InsertName(nTab, rTokData.mpScToken->GetIndex());
2068 [ # # ]: 0 : if( nNameIdx != 0 )
2069 : : {
2070 : : // global names always with tName token, local names dependent on config
2071 : 0 : SCTAB nScTab = rNameMgr.GetScTab( nNameIdx );
2072 [ # # ][ # # ]: 0 : if( (nScTab == SCTAB_GLOBAL) || (!mxData->mrCfg.mb3DRefOnly && (nScTab == GetCurrScTab())) )
[ # # ][ # # ]
2073 : : {
2074 : 0 : AppendNameToken( nNameIdx, rTokData.mnSpaces );
2075 : : }
2076 [ # # ]: 0 : else if( mxData->mpLinkMgr )
2077 : : {
2078 : : // use the same special EXTERNNAME to refer to any local name
2079 : 0 : sal_uInt16 nExtSheet = mxData->mpLinkMgr->FindExtSheet( EXC_EXTSH_OWNDOC );
2080 : 0 : AppendNameXToken( nExtSheet, nNameIdx, rTokData.mnSpaces );
2081 : : }
2082 : : else
2083 : 0 : AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2084 : : // volatile names (containing volatile functions)
2085 : 0 : mxData->mbVolatile |= rNameMgr.IsVolatile( nNameIdx );
2086 : : }
2087 : : else
2088 : 0 : AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2089 : 0 : }
2090 : :
2091 : 0 : void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData )
2092 : : {
2093 [ # # ]: 0 : if( mxData->mpLinkMgr )
2094 : : {
2095 [ # # ]: 0 : ScExternalRefManager& rExtRefMgr = *GetDoc().GetExternalRefManager();
2096 [ # # ]: 0 : sal_uInt16 nFileId = rTokData.mpScToken->GetIndex();
2097 [ # # ]: 0 : const String& rName = rTokData.mpScToken->GetString();
2098 [ # # ][ # # ]: 0 : ScExternalRefCache::TokenArrayRef xArray = rExtRefMgr.getRangeNameTokens( nFileId, rName );
2099 [ # # ]: 0 : if( xArray.get() )
2100 : : {
2101 : : // store external cell contents in CRN records
2102 [ # # ]: 0 : if( mxData->mpScBasePos )
2103 : : {
2104 [ # # ][ # # ]: 0 : for( FormulaToken* pScToken = xArray->First(); pScToken; pScToken = xArray->Next() )
[ # # ]
2105 : : {
2106 [ # # ][ # # ]: 0 : if( pScToken->IsExternalRef() )
2107 : : {
2108 [ # # # ]: 0 : switch( pScToken->GetType() )
2109 : : {
2110 : : case svExternalSingleRef:
2111 : : {
2112 [ # # ]: 0 : ScSingleRefData aRefData = static_cast< ScToken* >( pScToken )->GetSingleRef();
2113 [ # # ]: 0 : aRefData.CalcAbsIfRel( *mxData->mpScBasePos );
2114 [ # # ][ # # ]: 0 : mxData->mpLinkMgr->StoreCell( nFileId, pScToken->GetString(), aRefData );
2115 : : }
2116 : 0 : break;
2117 : : case svExternalDoubleRef:
2118 : : {
2119 [ # # ]: 0 : ScComplexRefData aRefData = static_cast< ScToken* >( pScToken )->GetDoubleRef();
2120 [ # # ]: 0 : aRefData.CalcAbsIfRel( *mxData->mpScBasePos );
2121 [ # # ][ # # ]: 0 : mxData->mpLinkMgr->StoreCellRange( nFileId, pScToken->GetString(), aRefData );
2122 : : }
2123 : : default:
2124 : : ; // nothing, avoid compiler warning
2125 : : }
2126 : : }
2127 : : }
2128 : : }
2129 : :
2130 : : // insert the new external name and create the tNameX token
2131 : 0 : sal_uInt16 nExtSheet = 0, nExtName = 0;
2132 [ # # ]: 0 : const ::rtl::OUString* pFile = rExtRefMgr.getExternalFileName( nFileId );
2133 [ # # ][ # # ]: 0 : if( pFile && mxData->mpLinkMgr->InsertExtName( nExtSheet, nExtName, *pFile, rName, xArray ) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
2134 : : {
2135 [ # # ]: 0 : AppendNameXToken( nExtSheet, nExtName, rTokData.mnSpaces );
2136 : 0 : return;
2137 : : }
2138 [ # # ][ # # ]: 0 : }
2139 : : }
2140 : :
2141 : : // on any error: create a #NAME? error
2142 : 0 : AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces );
2143 : : }
2144 : :
2145 : : // token vector ---------------------------------------------------------------
2146 : :
2147 : 0 : void XclExpFmlaCompImpl::PushOperandPos( sal_uInt16 nTokPos )
2148 : : {
2149 : 0 : mxData->maOpPosStack.push_back( nTokPos );
2150 : 0 : }
2151 : :
2152 : 0 : void XclExpFmlaCompImpl::PushOperatorPos( sal_uInt16 nTokPos, const XclExpOperandListRef& rxOperands )
2153 : : {
2154 : 0 : PushOperandPos( nTokPos );
2155 : : OSL_ENSURE( rxOperands.get(), "XclExpFmlaCompImpl::AppendOperatorTokenId - missing operand list" );
2156 [ # # ]: 0 : if( mxData->maOpListVec.size() <= nTokPos )
2157 [ # # ]: 0 : mxData->maOpListVec.resize( nTokPos + 1, XclExpOperandListRef() );
2158 : 0 : mxData->maOpListVec[ nTokPos ] = rxOperands;
2159 : 0 : }
2160 : :
2161 : 0 : sal_uInt16 XclExpFmlaCompImpl::PopOperandPos()
2162 : : {
2163 : : OSL_ENSURE( !mxData->mbOk || !mxData->maOpPosStack.empty(), "XclExpFmlaCompImpl::PopOperandPos - token stack broken" );
2164 : 0 : mxData->mbOk &= !mxData->maOpPosStack.empty();
2165 [ # # ]: 0 : if( mxData->mbOk )
2166 : : {
2167 : 0 : sal_uInt16 nTokPos = mxData->maOpPosStack.back();
2168 : 0 : mxData->maOpPosStack.pop_back();
2169 : 0 : return nTokPos;
2170 : : }
2171 : 0 : return 0;
2172 : : }
2173 : :
2174 : : namespace {
2175 : :
2176 : 0 : inline void lclAppend( ScfUInt8Vec& orVector, sal_uInt16 nData )
2177 : : {
2178 : 0 : orVector.resize( orVector.size() + 2 );
2179 [ # # ][ # # ]: 0 : ShortToSVBT16( nData, &*(orVector.end() - 2) );
2180 : 0 : }
2181 : :
2182 : 0 : inline void lclAppend( ScfUInt8Vec& orVector, sal_uInt32 nData )
2183 : : {
2184 : 0 : orVector.resize( orVector.size() + 4 );
2185 [ # # ][ # # ]: 0 : UInt32ToSVBT32( nData, &*(orVector.end() - 4) );
2186 : 0 : }
2187 : :
2188 : 0 : inline void lclAppend( ScfUInt8Vec& orVector, double fData )
2189 : : {
2190 : 0 : orVector.resize( orVector.size() + 8 );
2191 [ # # ][ # # ]: 0 : DoubleToSVBT64( fData, &*(orVector.end() - 8) );
2192 : 0 : }
2193 : :
2194 : 0 : inline void lclAppend( ScfUInt8Vec& orVector, const XclExpRoot& rRoot, const String& rString, XclStrFlags nStrFlags )
2195 : : {
2196 [ # # ]: 0 : XclExpStringRef xXclStr = XclExpStringHelper::CreateString( rRoot, rString, nStrFlags, EXC_TOK_STR_MAXLEN );
2197 : 0 : size_t nSize = orVector.size();
2198 [ # # ][ # # ]: 0 : orVector.resize( nSize + xXclStr->GetSize() );
2199 [ # # ][ # # ]: 0 : xXclStr->WriteToMem( &orVector[ nSize ] );
[ # # ]
2200 : 0 : }
2201 : :
2202 : : } // namespace
2203 : :
2204 : 0 : void XclExpFmlaCompImpl::Append( sal_uInt8 nData )
2205 : : {
2206 : 0 : mxData->maTokVec.push_back( nData );
2207 : 0 : }
2208 : :
2209 : 0 : void XclExpFmlaCompImpl::Append( sal_uInt8 nData, size_t nCount )
2210 : : {
2211 : 0 : mxData->maTokVec.resize( mxData->maTokVec.size() + nCount, nData );
2212 : 0 : }
2213 : :
2214 : 0 : void XclExpFmlaCompImpl::Append( sal_uInt16 nData )
2215 : : {
2216 : 0 : lclAppend( mxData->maTokVec, nData );
2217 : 0 : }
2218 : :
2219 : 0 : void XclExpFmlaCompImpl::Append( sal_uInt32 nData )
2220 : : {
2221 : 0 : lclAppend( mxData->maTokVec, nData );
2222 : 0 : }
2223 : :
2224 : 0 : void XclExpFmlaCompImpl::Append( double fData )
2225 : : {
2226 : 0 : lclAppend( mxData->maTokVec, fData );
2227 : 0 : }
2228 : :
2229 : 0 : void XclExpFmlaCompImpl::Append( const String& rString )
2230 : : {
2231 : 0 : lclAppend( mxData->maTokVec, GetRoot(), rString, EXC_STR_8BITLENGTH );
2232 : 0 : }
2233 : :
2234 : 0 : void XclExpFmlaCompImpl::AppendAddress( const XclAddress& rXclPos )
2235 : : {
2236 : 0 : Append( static_cast<sal_uInt16>(rXclPos.mnRow) );
2237 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
2238 : 0 : Append( static_cast< sal_uInt8 >( rXclPos.mnCol ) );
2239 : : else
2240 : 0 : Append( rXclPos.mnCol );
2241 : 0 : }
2242 : :
2243 : 0 : void XclExpFmlaCompImpl::AppendRange( const XclRange& rXclRange )
2244 : : {
2245 : 0 : Append( static_cast<sal_uInt16>(rXclRange.maFirst.mnRow) );
2246 : 0 : Append( static_cast<sal_uInt16>(rXclRange.maLast.mnRow) );
2247 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
2248 : : {
2249 : 0 : Append( static_cast< sal_uInt8 >( rXclRange.maFirst.mnCol ) );
2250 : 0 : Append( static_cast< sal_uInt8 >( rXclRange.maLast.mnCol ) );
2251 : : }
2252 : : else
2253 : : {
2254 : 0 : Append( rXclRange.maFirst.mnCol );
2255 : 0 : Append( rXclRange.maLast.mnCol );
2256 : : }
2257 : 0 : }
2258 : :
2259 : 0 : void XclExpFmlaCompImpl::AppendSpaceToken( sal_uInt8 nType, sal_uInt8 nCount )
2260 : : {
2261 [ # # ]: 0 : if( nCount > 0 )
2262 : : {
2263 : 0 : Append( EXC_TOKID_ATTR );
2264 : 0 : Append( EXC_TOK_ATTR_SPACE );
2265 : 0 : Append( nType );
2266 : 0 : Append( nCount );
2267 : : }
2268 : 0 : }
2269 : :
2270 : 0 : void XclExpFmlaCompImpl::AppendOperandTokenId( sal_uInt8 nTokenId, sal_uInt8 nSpaces )
2271 : : {
2272 : 0 : AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, nSpaces );
2273 : 0 : PushOperandPos( GetSize() );
2274 : 0 : Append( nTokenId );
2275 : 0 : }
2276 : :
2277 : 0 : void XclExpFmlaCompImpl::AppendIntToken( sal_uInt16 nValue, sal_uInt8 nSpaces )
2278 : : {
2279 : 0 : AppendOperandTokenId( EXC_TOKID_INT, nSpaces );
2280 : 0 : Append( nValue );
2281 : 0 : }
2282 : :
2283 : 0 : void XclExpFmlaCompImpl::AppendNumToken( double fValue, sal_uInt8 nSpaces )
2284 : : {
2285 : 0 : AppendOperandTokenId( EXC_TOKID_NUM, nSpaces );
2286 : 0 : Append( fValue );
2287 : 0 : }
2288 : :
2289 : 0 : void XclExpFmlaCompImpl::AppendBoolToken( bool bValue, sal_uInt8 nSpaces )
2290 : : {
2291 : 0 : AppendOperandTokenId( EXC_TOKID_BOOL, nSpaces );
2292 [ # # ]: 0 : Append( bValue ? EXC_TOK_BOOL_TRUE : EXC_TOK_BOOL_FALSE );
2293 : 0 : }
2294 : :
2295 : 0 : void XclExpFmlaCompImpl::AppendErrorToken( sal_uInt8 nErrCode, sal_uInt8 nSpaces )
2296 : : {
2297 : 0 : AppendOperandTokenId( EXC_TOKID_ERR, nSpaces );
2298 : 0 : Append( nErrCode );
2299 : 0 : }
2300 : :
2301 : 0 : void XclExpFmlaCompImpl::AppendMissingToken( sal_uInt8 nSpaces )
2302 : : {
2303 : 0 : AppendOperandTokenId( EXC_TOKID_MISSARG, nSpaces );
2304 : 0 : }
2305 : :
2306 : 0 : void XclExpFmlaCompImpl::AppendNameToken( sal_uInt16 nNameIdx, sal_uInt8 nSpaces )
2307 : : {
2308 [ # # ]: 0 : if( nNameIdx > 0 )
2309 : : {
2310 : 0 : AppendOperandTokenId( GetTokenId( EXC_TOKID_NAME, EXC_TOKCLASS_REF ), nSpaces );
2311 : 0 : Append( nNameIdx );
2312 [ # # ]: 0 : Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
2313 : : }
2314 : : else
2315 : 0 : AppendErrorToken( EXC_ERR_NAME );
2316 : 0 : }
2317 : :
2318 : 0 : void XclExpFmlaCompImpl::AppendMissingNameToken( const String& rName, sal_uInt8 nSpaces )
2319 : : {
2320 : 0 : sal_uInt16 nNameIdx = GetNameManager().InsertRawName( rName );
2321 : 0 : AppendNameToken( nNameIdx, nSpaces );
2322 : 0 : }
2323 : :
2324 : 0 : void XclExpFmlaCompImpl::AppendNameXToken( sal_uInt16 nExtSheet, sal_uInt16 nExtName, sal_uInt8 nSpaces )
2325 : : {
2326 : 0 : AppendOperandTokenId( GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ), nSpaces );
2327 : 0 : Append( nExtSheet );
2328 [ # # ]: 0 : if( meBiff <= EXC_BIFF5 )
2329 : 0 : Append( 0, 8 );
2330 : 0 : Append( nExtName );
2331 [ # # ]: 0 : Append( 0, (meBiff <= EXC_BIFF5) ? 12 : 2 );
2332 : 0 : }
2333 : :
2334 : 0 : void XclExpFmlaCompImpl::AppendMacroCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
2335 : : {
2336 : 0 : sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rExtFuncData.maFuncName, rExtFuncData.mbVBasic, true, rExtFuncData.mbHidden );
2337 : 0 : AppendNameToken( nNameIdx, nSpaces );
2338 : 0 : }
2339 : :
2340 : 0 : void XclExpFmlaCompImpl::AppendAddInCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
2341 : : {
2342 : 0 : ::rtl::OUString aXclFuncName;
2343 [ # # ][ # # ]: 0 : if( mxData->mpLinkMgr && ScGlobal::GetAddInCollection()->GetExcelName( rExtFuncData.maFuncName, GetUILanguage(), aXclFuncName ) )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ]
2344 : : {
2345 : : sal_uInt16 nExtSheet, nExtName;
2346 [ # # ][ # # ]: 0 : if( mxData->mpLinkMgr->InsertAddIn( nExtSheet, nExtName, aXclFuncName ) )
[ # # ][ # # ]
2347 : : {
2348 [ # # ]: 0 : AppendNameXToken( nExtSheet, nExtName, nSpaces );
2349 : 0 : return;
2350 : : }
2351 : : }
2352 [ # # ][ # # ]: 0 : AppendMacroCallToken( rExtFuncData, nSpaces );
2353 : : }
2354 : :
2355 : 0 : void XclExpFmlaCompImpl::AppendEuroToolCallToken( const XclExpExtFuncData& rExtFuncData, sal_uInt8 nSpaces )
2356 : : {
2357 : : sal_uInt16 nExtSheet, nExtName;
2358 [ # # ][ # # ]: 0 : if( mxData->mpLinkMgr && mxData->mpLinkMgr->InsertEuroTool( nExtSheet, nExtName, rExtFuncData.maFuncName ) )
[ # # ][ # # ]
2359 [ # # ]: 0 : AppendNameXToken( nExtSheet, nExtName, nSpaces );
2360 : : else
2361 [ # # ]: 0 : AppendMacroCallToken( rExtFuncData, nSpaces );
2362 : 0 : }
2363 : :
2364 : 0 : void XclExpFmlaCompImpl::AppendOperatorTokenId( sal_uInt8 nTokenId, const XclExpOperandListRef& rxOperands, sal_uInt8 nSpaces )
2365 : : {
2366 : 0 : AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP, nSpaces );
2367 : 0 : PushOperatorPos( GetSize(), rxOperands );
2368 : 0 : Append( nTokenId );
2369 : 0 : }
2370 : :
2371 : 0 : void XclExpFmlaCompImpl::AppendUnaryOperatorToken( sal_uInt8 nTokenId, sal_uInt8 nSpaces )
2372 : : {
2373 [ # # ][ # # ]: 0 : XclExpOperandListRef xOperands( new XclExpOperandList );
[ # # ]
2374 [ # # ][ # # ]: 0 : xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, true );
2375 [ # # ][ # # ]: 0 : AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
2376 : 0 : }
2377 : :
2378 : 0 : void XclExpFmlaCompImpl::AppendBinaryOperatorToken( sal_uInt8 nTokenId, bool bValType, sal_uInt8 nSpaces )
2379 : : {
2380 [ # # ][ # # ]: 0 : XclExpOperandListRef xOperands( new XclExpOperandList );
[ # # ]
2381 [ # # ][ # # ]: 0 : xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
2382 [ # # ][ # # ]: 0 : xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPO, bValType );
2383 [ # # ][ # # ]: 0 : AppendOperatorTokenId( nTokenId, xOperands, nSpaces );
2384 : 0 : }
2385 : :
2386 : 0 : void XclExpFmlaCompImpl::AppendLogicalOperatorToken( sal_uInt16 nXclFuncIdx, sal_uInt8 nOpCount )
2387 : : {
2388 [ # # ][ # # ]: 0 : XclExpOperandListRef xOperands( new XclExpOperandList );
[ # # ]
2389 [ # # ]: 0 : for( sal_uInt8 nOpIdx = 0; nOpIdx < nOpCount; ++nOpIdx )
2390 [ # # ][ # # ]: 0 : xOperands->AppendOperand( PopOperandPos(), EXC_PARAMCONV_RPX, false );
2391 [ # # ]: 0 : AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, EXC_TOKCLASS_VAL ), xOperands );
2392 [ # # ]: 0 : Append( nOpCount );
2393 [ # # ][ # # ]: 0 : Append( nXclFuncIdx );
2394 : 0 : }
2395 : :
2396 : 0 : void XclExpFmlaCompImpl::AppendFuncToken( const XclExpFuncData& rFuncData )
2397 : : {
2398 : 0 : sal_uInt16 nXclFuncIdx = rFuncData.GetXclFuncIdx();
2399 : 0 : sal_uInt8 nParamCount = rFuncData.GetParamCount();
2400 : 0 : sal_uInt8 nRetClass = rFuncData.GetReturnClass();
2401 : :
2402 [ # # ][ # # ]: 0 : if( (nXclFuncIdx == EXC_FUNCID_SUM) && (nParamCount == 1) )
2403 : : {
2404 : : // SUM with only one parameter
2405 [ # # ]: 0 : AppendOperatorTokenId( EXC_TOKID_ATTR, rFuncData.GetOperandList() );
2406 : 0 : Append( EXC_TOK_ATTR_SUM );
2407 : 0 : Append( sal_uInt16( 0 ) );
2408 : : }
2409 [ # # ]: 0 : else if( rFuncData.IsFixedParamCount() )
2410 : : {
2411 : : // fixed number of parameters
2412 [ # # ]: 0 : AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNC, nRetClass ), rFuncData.GetOperandList() );
2413 : 0 : Append( nXclFuncIdx );
2414 : : }
2415 : : else
2416 : : {
2417 : : // variable number of parameters
2418 [ # # ]: 0 : AppendOperatorTokenId( GetTokenId( EXC_TOKID_FUNCVAR, nRetClass ), rFuncData.GetOperandList() );
2419 : 0 : Append( nParamCount );
2420 : 0 : Append( nXclFuncIdx );
2421 : : }
2422 : 0 : }
2423 : :
2424 : 0 : void XclExpFmlaCompImpl::AppendParenToken( sal_uInt8 nOpenSpaces, sal_uInt8 nCloseSpaces )
2425 : : {
2426 : 0 : AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_OPEN, nOpenSpaces );
2427 : 0 : AppendSpaceToken( EXC_TOK_ATTR_SPACE_SP_CLOSE, nCloseSpaces );
2428 : 0 : Append( EXC_TOKID_PAREN );
2429 : 0 : }
2430 : :
2431 : 0 : void XclExpFmlaCompImpl::AppendJumpToken( XclExpFuncData& rFuncData, sal_uInt8 nAttrType )
2432 : : {
2433 : : // store the start position of the token
2434 : 0 : rFuncData.AppendAttrPos( GetSize() );
2435 : : // create the tAttr token
2436 : 0 : Append( EXC_TOKID_ATTR );
2437 : 0 : Append( nAttrType );
2438 : 0 : Append( sal_uInt16( 0 ) ); // placeholder that will be updated later
2439 : 0 : }
2440 : :
2441 : 0 : void XclExpFmlaCompImpl::InsertZeros( sal_uInt16 nInsertPos, sal_uInt16 nInsertSize )
2442 : : {
2443 : : // insert zeros into the token array
2444 : : OSL_ENSURE( nInsertPos < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Insert - invalid position" );
2445 [ # # ][ # # ]: 0 : mxData->maTokVec.insert( mxData->maTokVec.begin() + nInsertPos, nInsertSize, 0 );
2446 : :
2447 : : // update positions of operands waiting for an operator
2448 [ # # ][ # # ]: 0 : for( ScfUInt16Vec::iterator aIt = mxData->maOpPosStack.begin(), aEnd = mxData->maOpPosStack.end(); aIt != aEnd; ++aIt )
[ # # ]
2449 [ # # ][ # # ]: 0 : if( nInsertPos <= *aIt )
2450 [ # # ][ # # ]: 0 : *aIt = *aIt + nInsertSize;
2451 : :
2452 : : // update operand lists of all operator tokens
2453 [ # # ]: 0 : if( nInsertPos < mxData->maOpListVec.size() )
2454 [ # # ][ # # ]: 0 : mxData->maOpListVec.insert( mxData->maOpListVec.begin() + nInsertPos, nInsertSize, XclExpOperandListRef() );
2455 [ # # ][ # # ]: 0 : for( XclExpOperandListVector::iterator aIt = mxData->maOpListVec.begin(), aEnd = mxData->maOpListVec.end(); aIt != aEnd; ++aIt )
2456 [ # # ]: 0 : if( aIt->get() )
2457 [ # # ][ # # ]: 0 : for( XclExpOperandList::iterator aIt2 = (*aIt)->begin(), aEnd2 = (*aIt)->end(); aIt2 != aEnd2; ++aIt2 )
2458 [ # # ]: 0 : if( nInsertPos <= aIt2->mnTokPos )
2459 : 0 : aIt2->mnTokPos = aIt2->mnTokPos + nInsertSize;
2460 : 0 : }
2461 : :
2462 : 0 : void XclExpFmlaCompImpl::Overwrite( sal_uInt16 nWriteToPos, sal_uInt16 nOffset )
2463 : : {
2464 : : OSL_ENSURE( static_cast< size_t >( nWriteToPos + 1 ) < mxData->maTokVec.size(), "XclExpFmlaCompImpl::Overwrite - invalid position" );
2465 : 0 : ShortToSVBT16( nOffset, &mxData->maTokVec[ nWriteToPos ] );
2466 : 0 : }
2467 : :
2468 : 0 : void XclExpFmlaCompImpl::UpdateAttrGoto( sal_uInt16 nAttrPos )
2469 : : {
2470 : : /* tAttrGoto contains distance from end of tAttr token to position behind
2471 : : the function token (for IF or CHOOSE function), which is currently at
2472 : : the end of the token array. Additionally this distance is decreased by
2473 : : one, for whatever reason. So we have to subtract 4 and 1 from the
2474 : : distance between the tAttr token start and the end of the token array. */
2475 : 0 : Overwrite( nAttrPos + 2, static_cast< sal_uInt16 >( GetSize() - nAttrPos - 5 ) );
2476 : 0 : }
2477 : :
2478 : 0 : bool XclExpFmlaCompImpl::IsSpaceToken( sal_uInt16 nPos ) const
2479 : : {
2480 : : return
2481 : 0 : (static_cast< size_t >( nPos + 4 ) <= mxData->maTokVec.size()) &&
2482 : 0 : (mxData->maTokVec[ nPos ] == EXC_TOKID_ATTR) &&
2483 [ # # ]: 0 : (mxData->maTokVec[ nPos + 1 ] == EXC_TOK_ATTR_SPACE);
[ # # # # ]
2484 : : }
2485 : :
2486 : 0 : void XclExpFmlaCompImpl::RemoveTrailingParen()
2487 : : {
2488 : : // remove trailing tParen token
2489 [ # # ][ # # ]: 0 : if( !mxData->maTokVec.empty() && (mxData->maTokVec.back() == EXC_TOKID_PAREN) )
[ # # ]
2490 : 0 : mxData->maTokVec.pop_back();
2491 : : // remove remaining tAttrSpace tokens
2492 [ # # ][ # # ]: 0 : while( (mxData->maTokVec.size() >= 4) && IsSpaceToken( GetSize() - 4 ) )
[ # # ]
2493 [ # # ][ # # ]: 0 : mxData->maTokVec.erase( mxData->maTokVec.end() - 4, mxData->maTokVec.end() );
2494 : 0 : }
2495 : :
2496 : 0 : void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData )
2497 : : {
2498 : 0 : mxData->maExtDataVec.push_back( nData );
2499 : 0 : }
2500 : :
2501 : 0 : void XclExpFmlaCompImpl::AppendExt( sal_uInt8 nData, size_t nCount )
2502 : : {
2503 : 0 : mxData->maExtDataVec.resize( mxData->maExtDataVec.size() + nCount, nData );
2504 : 0 : }
2505 : :
2506 : 0 : void XclExpFmlaCompImpl::AppendExt( sal_uInt16 nData )
2507 : : {
2508 : 0 : lclAppend( mxData->maExtDataVec, nData );
2509 : 0 : }
2510 : :
2511 : 0 : void XclExpFmlaCompImpl::AppendExt( double fData )
2512 : : {
2513 : 0 : lclAppend( mxData->maExtDataVec, fData );
2514 : 0 : }
2515 : :
2516 : 0 : void XclExpFmlaCompImpl::AppendExt( const String& rString )
2517 : : {
2518 [ # # ]: 0 : lclAppend( mxData->maExtDataVec, GetRoot(), rString, (meBiff == EXC_BIFF8) ? EXC_STR_DEFAULT : EXC_STR_8BITLENGTH );
2519 : 0 : }
2520 : :
2521 : : // ============================================================================
2522 : :
2523 : : namespace {
2524 : :
2525 : 0 : void lclInitOwnTab( ScSingleRefData& rRef, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
2526 : : {
2527 [ # # ]: 0 : if( b3DRefOnly )
2528 : : {
2529 : : // no reduction to 2D reference, if global link manager is used
2530 : 0 : rRef.SetFlag3D( sal_True );
2531 : : }
2532 [ # # ]: 0 : else if( rScPos.Tab() == nCurrScTab )
2533 : : {
2534 : 0 : rRef.SetTabRel( sal_True );
2535 : 0 : rRef.nRelTab = 0;
2536 : : }
2537 : 0 : }
2538 : :
2539 : 0 : void lclPutCellToTokenArray( ScTokenArray& rScTokArr, const ScAddress& rScPos, SCTAB nCurrScTab, bool b3DRefOnly )
2540 : : {
2541 : : ScSingleRefData aRef;
2542 : 0 : aRef.InitAddress( rScPos );
2543 : 0 : lclInitOwnTab( aRef, rScPos, nCurrScTab, b3DRefOnly );
2544 [ # # ]: 0 : rScTokArr.AddSingleReference( aRef );
2545 : 0 : }
2546 : :
2547 : 0 : void lclPutRangeToTokenArray( ScTokenArray& rScTokArr, const ScRange& rScRange, SCTAB nCurrScTab, bool b3DRefOnly )
2548 : : {
2549 [ # # ]: 0 : if( rScRange.aStart == rScRange.aEnd )
2550 : : {
2551 : 0 : lclPutCellToTokenArray( rScTokArr, rScRange.aStart, nCurrScTab, b3DRefOnly );
2552 : : }
2553 : : else
2554 : : {
2555 : : ScComplexRefData aRef;
2556 : 0 : aRef.InitRange( rScRange );
2557 : 0 : lclInitOwnTab( aRef.Ref1, rScRange.aStart, nCurrScTab, b3DRefOnly );
2558 : 0 : lclInitOwnTab( aRef.Ref2, rScRange.aEnd, nCurrScTab, b3DRefOnly );
2559 [ # # ]: 0 : rScTokArr.AddDoubleReference( aRef );
2560 : : }
2561 : 0 : }
2562 : :
2563 : : } // namespace
2564 : :
2565 : : // ----------------------------------------------------------------------------
2566 : :
2567 : 0 : XclExpFormulaCompiler::XclExpFormulaCompiler( const XclExpRoot& rRoot ) :
2568 : : XclExpRoot( rRoot ),
2569 [ # # ][ # # ]: 0 : mxImpl( new XclExpFmlaCompImpl( rRoot ) )
[ # # ]
2570 : : {
2571 : 0 : }
2572 : :
2573 [ # # ]: 0 : XclExpFormulaCompiler::~XclExpFormulaCompiler()
2574 : : {
2575 [ # # ]: 0 : }
2576 : :
2577 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula(
2578 : : XclFormulaType eType, const ScTokenArray& rScTokArr,
2579 : : const ScAddress* pScBasePos, XclExpRefLog* pRefLog )
2580 : : {
2581 : 0 : return mxImpl->CreateFormula( eType, rScTokArr, pScBasePos, pRefLog );
2582 : : }
2583 : :
2584 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScAddress& rScPos )
2585 : : {
2586 [ # # ]: 0 : ScTokenArray aScTokArr;
2587 [ # # ][ # # ]: 0 : lclPutCellToTokenArray( aScTokArr, rScPos, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
2588 [ # # ][ # # ]: 0 : return mxImpl->CreateFormula( eType, aScTokArr );
2589 : : }
2590 : :
2591 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScRange& rScRange )
2592 : : {
2593 [ # # ]: 0 : ScTokenArray aScTokArr;
2594 [ # # ][ # # ]: 0 : lclPutRangeToTokenArray( aScTokArr, rScRange, GetCurrScTab(), mxImpl->Is3DRefOnly( eType ) );
2595 [ # # ][ # # ]: 0 : return mxImpl->CreateFormula( eType, aScTokArr );
2596 : : }
2597 : :
2598 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateFormula( XclFormulaType eType, const ScRangeList& rScRanges )
2599 : : {
2600 [ # # ]: 0 : size_t nCount = rScRanges.size();
2601 [ # # ]: 0 : if( nCount == 0 )
2602 [ # # ]: 0 : return XclTokenArrayRef();
2603 : :
2604 [ # # ]: 0 : ScTokenArray aScTokArr;
2605 : 0 : SCTAB nCurrScTab = GetCurrScTab();
2606 [ # # ]: 0 : bool b3DRefOnly = mxImpl->Is3DRefOnly( eType );
2607 [ # # ]: 0 : for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
2608 : : {
2609 [ # # ]: 0 : if( nIdx > 0 )
2610 [ # # ]: 0 : aScTokArr.AddOpCode( ocUnion );
2611 [ # # ][ # # ]: 0 : lclPutRangeToTokenArray( aScTokArr, *rScRanges[ nIdx ], nCurrScTab, b3DRefOnly );
2612 : : }
2613 [ # # ][ # # ]: 0 : return mxImpl->CreateFormula( eType, aScTokArr );
2614 : : }
2615 : :
2616 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateErrorFormula( sal_uInt8 nErrCode )
2617 : : {
2618 : 0 : return mxImpl->CreateErrorFormula( nErrCode );
2619 : : }
2620 : :
2621 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateSpecialRefFormula(
2622 : : sal_uInt8 nTokenId, const XclAddress& rXclPos )
2623 : : {
2624 : 0 : return mxImpl->CreateSpecialRefFormula( nTokenId, rXclPos );
2625 : : }
2626 : :
2627 : 0 : XclTokenArrayRef XclExpFormulaCompiler::CreateNameXFormula(
2628 : : sal_uInt16 nExtSheet, sal_uInt16 nExtName )
2629 : : {
2630 : 0 : return mxImpl->CreateNameXFormula( nExtSheet, nExtName );
2631 [ + - ][ + - ]: 24 : }
2632 : :
2633 : : // ============================================================================
2634 : :
2635 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|