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