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