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