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