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