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 #include "oox/xls/formulaparser.hxx" 29 30 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 31 #include <com/sun/star/sheet/ComplexReference.hpp> 32 #include <com/sun/star/sheet/ExternalReference.hpp> 33 #include <com/sun/star/sheet/FormulaToken.hpp> 34 #include <com/sun/star/sheet/ReferenceFlags.hpp> 35 #include <com/sun/star/sheet/SingleReference.hpp> 36 #include "oox/core/filterbase.hxx" 37 #include "oox/xls/addressconverter.hxx" 38 #include "oox/xls/biffinputstream.hxx" 39 #include "oox/xls/defnamesbuffer.hxx" 40 #include "oox/xls/externallinkbuffer.hxx" 41 #include "oox/xls/tablebuffer.hxx" 42 #include "oox/xls/worksheethelper.hxx" 43 44 namespace oox { 45 namespace xls { 46 47 // ============================================================================ 48 49 using namespace ::com::sun::star::sheet; 50 using namespace ::com::sun::star::sheet::ReferenceFlags; 51 using namespace ::com::sun::star::table; 52 using namespace ::com::sun::star::uno; 53 54 using ::rtl::OUString; 55 56 // ============================================================================ 57 58 namespace { 59 60 sal_uInt16 lclReadFmlaSize( BiffInputStream& rStrm, BiffType eBiff, const sal_uInt16* pnFmlaSize ) 61 { 62 return pnFmlaSize ? *pnFmlaSize : ((eBiff == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16()); 63 } 64 65 } // namespace 66 67 // formula finalizer ========================================================== 68 69 FormulaFinalizer::FormulaFinalizer( const OpCodeProvider& rOpCodeProv ) : 70 OpCodeProvider( rOpCodeProv ), 71 ApiOpCodes( getOpCodes() ) 72 { 73 maTokens.reserve( 0x2000 ); 74 } 75 76 ApiTokenSequence FormulaFinalizer::finalizeTokenArray( const ApiTokenSequence& rTokens ) 77 { 78 maTokens.clear(); 79 if( rTokens.hasElements() ) 80 { 81 const ApiToken* pToken = rTokens.getConstArray(); 82 processTokens( pToken, pToken + rTokens.getLength() ); 83 } 84 return ContainerHelper::vectorToSequence( maTokens ); 85 } 86 87 const FunctionInfo* FormulaFinalizer::resolveBadFuncName( const OUString& ) const 88 { 89 return 0; 90 } 91 92 OUString FormulaFinalizer::resolveDefinedName( sal_Int32 ) const 93 { 94 return OUString(); 95 } 96 97 const FunctionInfo* FormulaFinalizer::getFunctionInfo( ApiToken& orFuncToken ) 98 { 99 // first, try to find a regular function info from token op-code 100 if( const FunctionInfo* pRegFuncInfo = getFuncInfoFromApiToken( orFuncToken ) ) 101 return pRegFuncInfo; 102 103 // try to recognize a function from an external library 104 if( (orFuncToken.OpCode == OPCODE_BAD) && orFuncToken.Data.has< OUString >() ) 105 { 106 // virtual call to resolveBadFuncName() 107 if( const FunctionInfo* pLibFuncInfo = resolveBadFuncName( orFuncToken.Data.get< OUString >() ) ) 108 { 109 // write function op-code to the OPCODE_BAD token 110 orFuncToken.OpCode = pLibFuncInfo->mnApiOpCode; 111 // if it is an external function, insert programmatic function name 112 if( (orFuncToken.OpCode == OPCODE_EXTERNAL) && (pLibFuncInfo->maExtProgName.getLength() > 0) ) 113 orFuncToken.Data <<= pLibFuncInfo->maExtProgName; 114 else 115 orFuncToken.Data.clear(); // clear string from OPCODE_BAD 116 return pLibFuncInfo; 117 } 118 } 119 120 // no success - return null 121 return 0; 122 } 123 124 const FunctionInfo* FormulaFinalizer::getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken ) 125 { 126 // try to resolve the passed token to a supported sheet function 127 if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( rECToken ) ) 128 { 129 orFuncToken.OpCode = pFuncInfo->mnApiOpCode; 130 // programmatic add-in function name 131 if( (pFuncInfo->mnApiOpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) ) 132 orFuncToken.Data <<= pFuncInfo->maExtProgName; 133 // name of unsupported function, convert to OPCODE_BAD to preserve the name 134 else if( (pFuncInfo->mnApiOpCode == OPCODE_BAD) && (pFuncInfo->maOoxFuncName.getLength() > 0) ) 135 orFuncToken.Data <<= pFuncInfo->maOoxFuncName; 136 return pFuncInfo; 137 } 138 139 // macro call or unknown function name, move data to function token 140 if( (rECToken.OpCode == OPCODE_MACRO) || (rECToken.OpCode == OPCODE_BAD) ) 141 orFuncToken = rECToken; 142 143 // defined name used as function call, convert to OPCODE_BAD to preserve the name 144 if( (rECToken.OpCode == OPCODE_NAME) && rECToken.Data.has< sal_Int32 >() ) 145 { 146 OUString aDefName = resolveDefinedName( rECToken.Data.get< sal_Int32 >() ); 147 if( aDefName.getLength() > 0 ) 148 { 149 orFuncToken.OpCode = OPCODE_BAD; 150 orFuncToken.Data <<= aDefName; 151 } 152 } 153 154 return 0; 155 } 156 157 void FormulaFinalizer::processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ) 158 { 159 while( pToken < pTokenEnd ) 160 { 161 // push the current token into the vector 162 bool bValid = appendFinalToken( *pToken ); 163 // try to process a function 164 if( const FunctionInfo* pFuncInfo = bValid ? getFunctionInfo( maTokens.back() ) : 0 ) 165 pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); 166 // otherwise, go to next token 167 else 168 ++pToken; 169 } 170 } 171 172 const ApiToken* FormulaFinalizer::processParameters( 173 const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ) 174 { 175 // remember position of the token containing the function op-code 176 size_t nFuncNameIdx = maTokens.size() - 1; 177 178 // process a function, if an OPCODE_OPEN token is following 179 OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::processParameters - OPCODE_OPEN expected" ); 180 if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN) ) 181 { 182 // append the OPCODE_OPEN token to the vector 183 maTokens.append( OPCODE_OPEN ); 184 185 // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE 186 ParameterPosVector aParams; 187 pToken = findParameters( aParams, pToken, pTokenEnd ); 188 OSL_ENSURE( aParams.size() >= 2, "FormulaFinalizer::processParameters - missing tokens" ); 189 size_t nParamCount = aParams.size() - 1; 190 191 if( (nParamCount == 1) && isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) ) 192 { 193 /* Empty pair of parentheses -> function call without parameters, 194 process parameter, there might be spaces between parentheses. */ 195 processTokens( aParams[ 0 ] + 1, aParams[ 1 ] ); 196 } 197 else 198 { 199 const FunctionInfo* pRealFuncInfo = &rFuncInfo; 200 ParameterPosVector::const_iterator aPosIt = aParams.begin(); 201 202 /* Preprocess EXTERN.CALL functions. The actual function name is 203 contained as reference to a defined name in the first (hidden) 204 parameter. */ 205 if( rFuncInfo.mnBiffFuncId == BIFF_FUNC_EXTERNCALL ) 206 { 207 ApiToken& rFuncToken = maTokens[ nFuncNameIdx ]; 208 rFuncToken.OpCode = OPCODE_NONAME; 209 210 // try to initialize function token from first parameter 211 if( const ApiToken* pECToken = getSingleToken( *aPosIt + 1, *(aPosIt + 1) ) ) 212 if( const FunctionInfo* pECFuncInfo = getExternCallInfo( rFuncToken, *pECToken ) ) 213 pRealFuncInfo = pECFuncInfo; 214 215 /* On success (something has been inserted into rFuncToken), 216 skip the first parameter. */ 217 if( rFuncToken.OpCode != OPCODE_NONAME ) 218 { 219 --nParamCount; 220 ++aPosIt; 221 } 222 } 223 224 // process all parameters 225 FunctionParamInfoIterator aParamInfoIt( *pRealFuncInfo ); 226 size_t nLastValidSize = maTokens.size(); 227 size_t nLastValidCount = 0; 228 for( size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aParamInfoIt ) 229 { 230 // add embedded Calc-only parameters 231 if( aParamInfoIt.isCalcOnlyParam() ) 232 { 233 appendCalcOnlyParameter( *pRealFuncInfo, nParam ); 234 while( aParamInfoIt.isCalcOnlyParam() ) ++aParamInfoIt; 235 } 236 237 const ApiToken* pParamBegin = *aPosIt + 1; 238 const ApiToken* pParamEnd = *(aPosIt + 1); 239 bool bIsEmpty = isEmptyParameter( pParamBegin, pParamEnd ); 240 241 if( !aParamInfoIt.isExcelOnlyParam() ) 242 { 243 // handle empty parameters 244 if( bIsEmpty ) 245 { 246 // append leading space tokens from original token array 247 while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) ) 248 maTokens.push_back( *pParamBegin++ ); 249 // add default values for some empty parameters, or the OPCODE_MISSING token 250 appendEmptyParameter( *pRealFuncInfo, nParam ); 251 // reset bIsEmpty flag, if something has been appended in appendEmptyParameter() 252 bIsEmpty = maTokens.back().OpCode == OPCODE_MISSING; 253 // skip OPCODE_MISSING token in the original token array 254 OSL_ENSURE( (pParamBegin == pParamEnd) || (pParamBegin->OpCode == OPCODE_MISSING), "FormulaFinalizer::processParameters - OPCODE_MISSING expected" ); 255 if( pParamBegin < pParamEnd ) ++pParamBegin; 256 // append trailing space tokens from original token array 257 while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) ) 258 maTokens.push_back( *pParamBegin++ ); 259 } 260 else 261 { 262 // if parameter is not empty, process all tokens of the parameter 263 processTokens( pParamBegin, pParamEnd ); 264 } 265 266 // append parameter separator token 267 maTokens.append( OPCODE_SEP ); 268 } 269 270 /* #84453# Update size of new token sequence with valid parameters 271 to be able to remove trailing optional empty parameters. */ 272 if( !bIsEmpty || (nParam < pRealFuncInfo->mnMinParamCount) ) 273 { 274 nLastValidSize = maTokens.size(); 275 nLastValidCount = nParam + 1; 276 } 277 } 278 279 // #84453# remove trailing optional empty parameters 280 maTokens.resize( nLastValidSize ); 281 282 // add trailing Calc-only parameters 283 if( aParamInfoIt.isCalcOnlyParam() ) 284 appendCalcOnlyParameter( *pRealFuncInfo, nLastValidCount ); 285 286 // add optional parameters that are required in Calc 287 appendRequiredParameters( *pRealFuncInfo, nLastValidCount ); 288 289 // remove last parameter separator token 290 if( maTokens.back().OpCode == OPCODE_SEP ) 291 maTokens.pop_back(); 292 } 293 294 /* Append the OPCODE_CLOSE token to the vector, but only if there is 295 no OPCODE_BAD token at the end, this token already contains the 296 trailing closing parentheses. */ 297 if( (pTokenEnd - 1)->OpCode != OPCODE_BAD ) 298 maTokens.append( OPCODE_CLOSE ); 299 } 300 301 /* Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell, 302 if no matching add-in function was found. */ 303 ApiToken& rFuncNameToken = maTokens[ nFuncNameIdx ]; 304 if( (rFuncNameToken.OpCode == OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() ) 305 rFuncNameToken.OpCode = OPCODE_NONAME; 306 307 return pToken; 308 } 309 310 bool FormulaFinalizer::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const 311 { 312 while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; 313 if( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_MISSING) ) ++pToken; 314 while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; 315 return pToken == pTokenEnd; 316 } 317 318 const ApiToken* FormulaFinalizer::getSingleToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const 319 { 320 const ApiToken* pSingleToken = 0; 321 // skip leading whitespace tokens 322 while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; 323 // remember first non-whitespace token 324 if( pToken < pTokenEnd ) pSingleToken = pToken++; 325 // skip trailing whitespace tokens 326 while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken; 327 // return null, if other non-whitespace tokens follow 328 return (pToken == pTokenEnd) ? pSingleToken : 0; 329 } 330 331 const ApiToken* FormulaFinalizer::skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const 332 { 333 // skip tokens between OPCODE_OPEN and OPCODE_CLOSE 334 OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "skipParentheses - OPCODE_OPEN expected" ); 335 ++pToken; 336 while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) ) 337 { 338 if( pToken->OpCode == OPCODE_OPEN ) 339 pToken = skipParentheses( pToken, pTokenEnd ); 340 else 341 ++pToken; 342 } 343 // skip the OPCODE_CLOSE token 344 OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "skipParentheses - OPCODE_CLOSE expected" ); 345 return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; 346 } 347 348 const ApiToken* FormulaFinalizer::findParameters( ParameterPosVector& rParams, 349 const ApiToken* pToken, const ApiToken* pTokenEnd ) const 350 { 351 // push position of OPCODE_OPEN 352 OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_OPEN), "FormulaFinalizer::findParameters - OPCODE_OPEN expected" ); 353 rParams.push_back( pToken++ ); 354 355 // find positions of parameter separators 356 while( (pToken < pTokenEnd) && (pToken->OpCode != OPCODE_CLOSE) ) 357 { 358 if( pToken->OpCode == OPCODE_OPEN ) 359 pToken = skipParentheses( pToken, pTokenEnd ); 360 else if( pToken->OpCode == OPCODE_SEP ) 361 rParams.push_back( pToken++ ); 362 else 363 ++pToken; 364 } 365 366 // push position of OPCODE_CLOSE 367 OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == OPCODE_BAD), "FormulaFinalizer::findParameters - OPCODE_CLOSE expected" ); 368 rParams.push_back( pToken ); 369 return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; 370 } 371 372 void FormulaFinalizer::appendEmptyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) 373 { 374 // remeber old size of the token array 375 size_t nTokenArraySize = maTokens.size(); 376 377 switch( rFuncInfo.mnBiff12FuncId ) 378 { 379 case BIFF_FUNC_IF: 380 if( (nParam == 1) || (nParam == 2) ) 381 maTokens.append< double >( OPCODE_PUSH, 0.0 ); 382 break; 383 default:; 384 } 385 386 // if no token has been added, append a OPCODE_MISSING token 387 if( nTokenArraySize == maTokens.size() ) 388 maTokens.append( OPCODE_MISSING ); 389 } 390 391 void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) 392 { 393 (void)nParam; // prevent 'unused' warning 394 switch( rFuncInfo.mnBiff12FuncId ) 395 { 396 case BIFF_FUNC_FLOOR: 397 case BIFF_FUNC_CEILING: 398 OSL_ENSURE( nParam == 2, "FormulaFinalizer::appendCalcOnlyParameter - unexpected parameter index" ); 399 maTokens.append< double >( OPCODE_PUSH, 1.0 ); 400 maTokens.append( OPCODE_SEP ); 401 break; 402 } 403 } 404 405 void FormulaFinalizer::appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ) 406 { 407 switch( rFuncInfo.mnBiff12FuncId ) 408 { 409 case BIFF_FUNC_WEEKNUM: 410 if( nParamCount == 1 ) 411 { 412 maTokens.append< double >( OPCODE_PUSH, 1.0 ); 413 maTokens.append( OPCODE_SEP ); 414 } 415 break; 416 } 417 } 418 419 bool FormulaFinalizer::appendFinalToken( const ApiToken& rToken ) 420 { 421 // replace OPCODE_MACRO without macro name with #NAME? error code 422 bool bValid = (rToken.OpCode != OPCODE_MACRO) || rToken.Data.hasValue(); 423 if( bValid ) 424 { 425 maTokens.push_back( rToken ); 426 } 427 else 428 { 429 maTokens.append( OPCODE_ARRAY_OPEN ); 430 maTokens.append( OPCODE_PUSH, BiffHelper::calcDoubleFromError( BIFF_ERR_NAME ) ); 431 maTokens.append( OPCODE_ARRAY_CLOSE ); 432 } 433 return bValid; 434 } 435 436 // parser implementation base ================================================= 437 438 class FormulaParserImpl : public FormulaFinalizer, public WorkbookHelper 439 { 440 public: 441 explicit FormulaParserImpl( const FormulaParser& rParent ); 442 443 /** Converts an OOXML formula string. */ 444 virtual ApiTokenSequence importOoxFormula( 445 const CellAddress& rBaseAddress, 446 const OUString& rFormulaString ); 447 448 /** Imports and converts a BIFF12 token array from the passed stream. */ 449 virtual ApiTokenSequence importBiff12Formula( 450 const CellAddress& rBaseAddress, 451 FormulaType eType, 452 SequenceInputStream& rStrm ); 453 454 /** Imports and converts a BIFF2-BIFF8 token array from the passed stream. */ 455 virtual ApiTokenSequence importBiffFormula( 456 const CellAddress& rBaseAddress, 457 FormulaType eType, 458 BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ); 459 460 /** Tries to resolve the passed ref-id to an OLE target URL. */ 461 OUString resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const; 462 463 protected: 464 typedef ::std::pair< sal_Int32, bool > WhiteSpace; 465 typedef ::std::vector< WhiteSpace > WhiteSpaceVec; 466 467 /** Initializes the formula parser before importing a formula. */ 468 void initializeImport( const CellAddress& rBaseAddress, FormulaType eType ); 469 /** Finalizes the internal token storage after import. */ 470 ApiTokenSequence finalizeImport(); 471 472 // token array ------------------------------------------------------------ 473 474 bool resetSpaces(); 475 static void appendSpaces( WhiteSpaceVec& orSpaces, sal_Int32 nCount, bool bLineFeed ); 476 void appendLeadingSpaces( sal_Int32 nCount, bool bLineFeed ); 477 void appendOpeningSpaces( sal_Int32 nCount, bool bLineFeed ); 478 void appendClosingSpaces( sal_Int32 nCount, bool bLineFeed ); 479 480 size_t getFormulaSize() const; 481 Any& appendRawToken( sal_Int32 nOpCode ); 482 Any& insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd ); 483 size_t appendWhiteSpaceTokens( const WhiteSpaceVec* pSpaces ); 484 size_t insertWhiteSpaceTokens( const WhiteSpaceVec* pSpaces, size_t nIndexFromEnd ); 485 486 size_t getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const; 487 void pushOperandSize( size_t nSize ); 488 size_t popOperandSize(); 489 490 ApiToken& getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex ); 491 void removeOperand( size_t nOpCountFromEnd, size_t nOpIndex ); 492 void removeLastOperands( size_t nOpCountFromEnd ); 493 494 bool pushOperandToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 ); 495 bool pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 ); 496 template< typename Type > 497 bool pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 ); 498 template< typename Type > 499 inline bool pushValueOperandToken( const Type& rValue, const WhiteSpaceVec* pSpaces = 0 ) 500 { return pushValueOperandToken( rValue, OPCODE_PUSH, pSpaces ); } 501 bool pushParenthesesOperandToken( const WhiteSpaceVec* pOpeningSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 ); 502 bool pushUnaryPreOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 ); 503 bool pushUnaryPostOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 ); 504 bool pushBinaryOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces = 0 ); 505 bool pushParenthesesOperatorToken( const WhiteSpaceVec* pOpeningSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 ); 506 bool pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 ); 507 bool pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces = 0, const WhiteSpaceVec* pClosingSpaces = 0 ); 508 509 bool pushOperand( sal_Int32 nOpCode ); 510 bool pushAnyOperand( const Any& rAny, sal_Int32 nOpCode ); 511 template< typename Type > 512 bool pushValueOperand( const Type& rValue, sal_Int32 nOpCode ); 513 template< typename Type > 514 inline bool pushValueOperand( const Type& rValue ) 515 { return pushValueOperand( rValue, OPCODE_PUSH ); } 516 bool pushBoolOperand( bool bValue ); 517 bool pushErrorOperand( double fEncodedError ); 518 bool pushBiffBoolOperand( sal_uInt8 nValue ); 519 bool pushBiffErrorOperand( sal_uInt8 nErrorCode ); 520 bool pushParenthesesOperand(); 521 bool pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); 522 bool pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); 523 template< typename Type > 524 bool pushReferenceOperand( const LinkSheetRange& rSheetRange, const Type& rApiRef ); 525 bool pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); 526 bool pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); 527 bool pushNlrOperand( const BinSingleRef2d& rRef ); 528 bool pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken ); 529 bool pushDefinedNameOperand( const DefinedNameRef& rxDefName ); 530 bool pushExternalFuncOperand( const FunctionInfo& rFuncInfo ); 531 bool pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ); 532 bool pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink ); 533 bool pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable ); 534 535 bool pushUnaryPreOperator( sal_Int32 nOpCode ); 536 bool pushUnaryPostOperator( sal_Int32 nOpCode ); 537 bool pushBinaryOperator( sal_Int32 nOpCode ); 538 bool pushParenthesesOperator(); 539 bool pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount ); 540 bool pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount ); 541 542 private: 543 // reference conversion --------------------------------------------------- 544 545 void initReference2d( SingleReference& orApiRef ) const; 546 void initReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet ) const; 547 void convertColRow( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bRelativeAsOffset ) const; 548 void convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; 549 void convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; 550 void convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; 551 void convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; 552 void convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; 553 void convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; 554 555 private: 556 // finalize token sequence ------------------------------------------------ 557 558 virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const; 559 virtual ::rtl::OUString resolveDefinedName( sal_Int32 nTokenIndex ) const; 560 561 protected: 562 const sal_Int32 mnMaxApiCol; /// Maximum column index in own document. 563 const sal_Int32 mnMaxApiRow; /// Maximum row index in own document. 564 const sal_Int32 mnMaxXlsCol; /// Maximum column index in imported document. 565 const sal_Int32 mnMaxXlsRow; /// Maximum row index in imported document. 566 567 CellAddress maBaseAddr; /// Base address for relative references. 568 bool mbRelativeAsOffset; /// True = relative row/column index is (signed) offset, false = explicit index. 569 bool mb2dRefsAs3dRefs; /// True = convert all 2D references to 3D references in sheet specified by base address. 570 bool mbSpecialTokens; /// True = special handling for tExp and tTbl tokens, false = exit with error. 571 bool mbAllowNulChars; /// True = keep NUL characters in string tokens. 572 573 private: 574 typedef ::std::vector< size_t > SizeTypeVector; 575 576 ApiTokenVector maTokenStorage; /// Raw unordered token storage. 577 SizeTypeVector maTokenIndexes; /// Indexes into maTokenStorage. 578 SizeTypeVector maOperandSizeStack; /// Stack with token sizes per operand. 579 WhiteSpaceVec maLeadingSpaces; /// List of whitespaces before next token. 580 WhiteSpaceVec maOpeningSpaces; /// List of whitespaces before opening parenthesis. 581 WhiteSpaceVec maClosingSpaces; /// List of whitespaces before closing parenthesis. 582 }; 583 584 // ---------------------------------------------------------------------------- 585 586 FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) : 587 FormulaFinalizer( rParent ), 588 WorkbookHelper( rParent ), 589 mnMaxApiCol( rParent.getAddressConverter().getMaxApiAddress().Column ), 590 mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().Row ), 591 mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().Column ), 592 mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().Row ), 593 mbRelativeAsOffset( false ), 594 mb2dRefsAs3dRefs( false ), 595 mbAllowNulChars( false ) 596 { 597 // reserve enough space to make resize(), push_back() etc. cheap 598 maTokenStorage.reserve( 0x2000 ); 599 maTokenIndexes.reserve( 0x2000 ); 600 maOperandSizeStack.reserve( 256 ); 601 maLeadingSpaces.reserve( 256 ); 602 maOpeningSpaces.reserve( 256 ); 603 maClosingSpaces.reserve( 256 ); 604 } 605 606 ApiTokenSequence FormulaParserImpl::importOoxFormula( const CellAddress&, const OUString& ) 607 { 608 OSL_ENSURE( false, "FormulaParserImpl::importOoxFormula - not implemented" ); 609 return ApiTokenSequence(); 610 } 611 612 ApiTokenSequence FormulaParserImpl::importBiff12Formula( const CellAddress&, FormulaType, SequenceInputStream& ) 613 { 614 OSL_ENSURE( false, "FormulaParserImpl::importBiff12Formula - not implemented" ); 615 return ApiTokenSequence(); 616 } 617 618 ApiTokenSequence FormulaParserImpl::importBiffFormula( const CellAddress&, FormulaType, BiffInputStream&, const sal_uInt16* ) 619 { 620 OSL_ENSURE( false, "FormulaParserImpl::importBiffFormula - not implemented" ); 621 return ApiTokenSequence(); 622 } 623 624 OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const 625 { 626 const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId, bUseRefSheets ).get(); 627 OSL_ENSURE( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE), "FormulaParserImpl::resolveOleTarget - missing or wrong link" ); 628 if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_OLE) ) 629 return getBaseFilter().getAbsoluteUrl( pExtLink->getTargetUrl() ); 630 return OUString(); 631 } 632 633 void FormulaParserImpl::initializeImport( const CellAddress& rBaseAddr, FormulaType eType ) 634 { 635 maBaseAddr = rBaseAddr; 636 mbRelativeAsOffset = mb2dRefsAs3dRefs = mbSpecialTokens = mbAllowNulChars = false; 637 switch( eType ) 638 { 639 case FORMULATYPE_CELL: 640 mbSpecialTokens = true; 641 break; 642 case FORMULATYPE_ARRAY: 643 break; 644 case FORMULATYPE_SHAREDFORMULA: 645 mbRelativeAsOffset = true; 646 break; 647 case FORMULATYPE_CONDFORMAT: 648 mbRelativeAsOffset = true; 649 break; 650 case FORMULATYPE_VALIDATION: 651 mbRelativeAsOffset = true; 652 // enable NUL characters in BIFF import, string list is single tStr token with NUL separators 653 mbAllowNulChars = getFilterType() == FILTER_BIFF; 654 break; 655 case FORMULATYPE_DEFINEDNAME: 656 mbRelativeAsOffset = true; 657 // BIFF2-BIFF4: convert 2D referebces to absolute 3D references 658 mb2dRefsAs3dRefs = (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4); 659 break; 660 } 661 662 maTokenStorage.clear(); 663 maTokenIndexes.clear(); 664 maOperandSizeStack.clear(); 665 } 666 667 ApiTokenSequence FormulaParserImpl::finalizeImport() 668 { 669 ApiTokenSequence aTokens( static_cast< sal_Int32 >( maTokenIndexes.size() ) ); 670 if( aTokens.hasElements() ) 671 { 672 ApiToken* pToken = aTokens.getArray(); 673 for( SizeTypeVector::const_iterator aIt = maTokenIndexes.begin(), aEnd = maTokenIndexes.end(); aIt != aEnd; ++aIt, ++pToken ) 674 *pToken = maTokenStorage[ *aIt ]; 675 } 676 return finalizeTokenArray( aTokens ); 677 } 678 679 // token array ---------------------------------------------------------------- 680 681 bool FormulaParserImpl::resetSpaces() 682 { 683 maLeadingSpaces.clear(); 684 maOpeningSpaces.clear(); 685 maClosingSpaces.clear(); 686 return true; 687 } 688 689 void FormulaParserImpl::appendSpaces( WhiteSpaceVec& orSpaces, sal_Int32 nCount, bool bLineFeed ) 690 { 691 OSL_ENSURE( nCount >= 0, "FormulaParserImpl::appendSpaces - negative count" ); 692 if( nCount > 0 ) 693 orSpaces.push_back( WhiteSpace( nCount, bLineFeed ) ); 694 } 695 696 void FormulaParserImpl::appendLeadingSpaces( sal_Int32 nCount, bool bLineFeed ) 697 { 698 appendSpaces( maLeadingSpaces, nCount, bLineFeed ); 699 } 700 701 void FormulaParserImpl::appendOpeningSpaces( sal_Int32 nCount, bool bLineFeed ) 702 { 703 appendSpaces( maOpeningSpaces, nCount, bLineFeed ); 704 } 705 706 void FormulaParserImpl::appendClosingSpaces( sal_Int32 nCount, bool bLineFeed ) 707 { 708 appendSpaces( maClosingSpaces, nCount, bLineFeed ); 709 } 710 711 size_t FormulaParserImpl::getFormulaSize() const 712 { 713 return maTokenIndexes.size(); 714 } 715 716 Any& FormulaParserImpl::appendRawToken( sal_Int32 nOpCode ) 717 { 718 maTokenIndexes.push_back( maTokenStorage.size() ); 719 return maTokenStorage.append( nOpCode ); 720 } 721 722 Any& FormulaParserImpl::insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd ) 723 { 724 maTokenIndexes.insert( maTokenIndexes.end() - nIndexFromEnd, maTokenStorage.size() ); 725 return maTokenStorage.append( nOpCode ); 726 } 727 728 size_t FormulaParserImpl::appendWhiteSpaceTokens( const WhiteSpaceVec* pSpaces ) 729 { 730 if( pSpaces && !pSpaces->empty() ) 731 for( WhiteSpaceVec::const_iterator aIt = pSpaces->begin(), aEnd = pSpaces->end(); aIt != aEnd; ++aIt ) 732 appendRawToken( OPCODE_SPACES ) <<= aIt->first; 733 return pSpaces ? pSpaces->size() : 0; 734 } 735 736 size_t FormulaParserImpl::insertWhiteSpaceTokens( const WhiteSpaceVec* pSpaces, size_t nIndexFromEnd ) 737 { 738 if( pSpaces && !pSpaces->empty() ) 739 for( WhiteSpaceVec::const_iterator aIt = pSpaces->begin(), aEnd = pSpaces->end(); aIt != aEnd; ++aIt ) 740 insertRawToken( OPCODE_SPACES, nIndexFromEnd ) <<= aIt->first; 741 return pSpaces ? pSpaces->size() : 0; 742 } 743 744 size_t FormulaParserImpl::getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const 745 { 746 OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()), 747 "FormulaParserImpl::getOperandSize - invalid parameters" ); 748 return maOperandSizeStack[ maOperandSizeStack.size() - nOpCountFromEnd + nOpIndex ]; 749 } 750 751 void FormulaParserImpl::pushOperandSize( size_t nSize ) 752 { 753 maOperandSizeStack.push_back( nSize ); 754 } 755 756 size_t FormulaParserImpl::popOperandSize() 757 { 758 OSL_ENSURE( !maOperandSizeStack.empty(), "FormulaParserImpl::popOperandSize - invalid call" ); 759 size_t nOpSize = maOperandSizeStack.back(); 760 maOperandSizeStack.pop_back(); 761 return nOpSize; 762 } 763 764 ApiToken& FormulaParserImpl::getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex ) 765 { 766 OSL_ENSURE( getOperandSize( nOpCountFromEnd, nOpIndex ) > nTokenIndex, 767 "FormulaParserImpl::getOperandToken - invalid parameters" ); 768 SizeTypeVector::const_iterator aIndexIt = maTokenIndexes.end(); 769 for( SizeTypeVector::const_iterator aEnd = maOperandSizeStack.end(), aIt = aEnd - nOpCountFromEnd + nOpIndex; aIt != aEnd; ++aIt ) 770 aIndexIt -= *aIt; 771 return maTokenStorage[ *(aIndexIt + nTokenIndex) ]; 772 } 773 774 void FormulaParserImpl::removeOperand( size_t nOpCountFromEnd, size_t nOpIndex ) 775 { 776 OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()), 777 "FormulaParserImpl::removeOperand - invalid parameters" ); 778 // remove indexes into token storage, but do not touch storage itself 779 SizeTypeVector::iterator aSizeEnd = maOperandSizeStack.end(); 780 SizeTypeVector::iterator aSizeIt = aSizeEnd - nOpCountFromEnd + nOpIndex; 781 size_t nRemainingSize = 0; 782 for( SizeTypeVector::iterator aIt = aSizeIt + 1; aIt != aSizeEnd; ++aIt ) 783 nRemainingSize += *aIt; 784 maTokenIndexes.erase( maTokenIndexes.end() - nRemainingSize - *aSizeIt, maTokenIndexes.end() - nRemainingSize ); 785 maOperandSizeStack.erase( aSizeIt ); 786 } 787 788 void FormulaParserImpl::removeLastOperands( size_t nOpCountFromEnd ) 789 { 790 for( size_t nOpIndex = 0; nOpIndex < nOpCountFromEnd; ++nOpIndex ) 791 removeOperand( 1, 0 ); 792 } 793 794 bool FormulaParserImpl::pushOperandToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces ) 795 { 796 size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces ); 797 appendRawToken( nOpCode ); 798 pushOperandSize( nSpacesSize + 1 ); 799 return true; 800 } 801 802 bool FormulaParserImpl::pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces ) 803 { 804 size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces ); 805 appendRawToken( nOpCode ) = rAny; 806 pushOperandSize( nSpacesSize + 1 ); 807 return true; 808 } 809 810 template< typename Type > 811 bool FormulaParserImpl::pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces ) 812 { 813 size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces ); 814 appendRawToken( nOpCode ) <<= rValue; 815 pushOperandSize( nSpacesSize + 1 ); 816 return true; 817 } 818 819 bool FormulaParserImpl::pushParenthesesOperandToken( const WhiteSpaceVec* pOpeningSpaces, const WhiteSpaceVec* pClosingSpaces ) 820 { 821 size_t nSpacesSize = appendWhiteSpaceTokens( pOpeningSpaces ); 822 appendRawToken( OPCODE_OPEN ); 823 nSpacesSize += appendWhiteSpaceTokens( pClosingSpaces ); 824 appendRawToken( OPCODE_CLOSE ); 825 pushOperandSize( nSpacesSize + 2 ); 826 return true; 827 } 828 829 bool FormulaParserImpl::pushUnaryPreOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces ) 830 { 831 bool bOk = maOperandSizeStack.size() >= 1; 832 if( bOk ) 833 { 834 size_t nOpSize = popOperandSize(); 835 size_t nSpacesSize = insertWhiteSpaceTokens( pSpaces, nOpSize ); 836 insertRawToken( nOpCode, nOpSize ); 837 pushOperandSize( nOpSize + nSpacesSize + 1 ); 838 } 839 return bOk; 840 } 841 842 bool FormulaParserImpl::pushUnaryPostOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces ) 843 { 844 bool bOk = maOperandSizeStack.size() >= 1; 845 if( bOk ) 846 { 847 size_t nOpSize = popOperandSize(); 848 size_t nSpacesSize = appendWhiteSpaceTokens( pSpaces ); 849 appendRawToken( nOpCode ); 850 pushOperandSize( nOpSize + nSpacesSize + 1 ); 851 } 852 return bOk; 853 } 854 855 bool FormulaParserImpl::pushBinaryOperatorToken( sal_Int32 nOpCode, const WhiteSpaceVec* pSpaces ) 856 { 857 bool bOk = maOperandSizeStack.size() >= 2; 858 if( bOk ) 859 { 860 size_t nOp2Size = popOperandSize(); 861 size_t nOp1Size = popOperandSize(); 862 size_t nSpacesSize = insertWhiteSpaceTokens( pSpaces, nOp2Size ); 863 insertRawToken( nOpCode, nOp2Size ); 864 pushOperandSize( nOp1Size + nSpacesSize + 1 + nOp2Size ); 865 } 866 return bOk; 867 } 868 869 bool FormulaParserImpl::pushParenthesesOperatorToken( const WhiteSpaceVec* pOpeningSpaces, const WhiteSpaceVec* pClosingSpaces ) 870 { 871 bool bOk = maOperandSizeStack.size() >= 1; 872 if( bOk ) 873 { 874 size_t nOpSize = popOperandSize(); 875 size_t nSpacesSize = insertWhiteSpaceTokens( pOpeningSpaces, nOpSize ); 876 insertRawToken( OPCODE_OPEN, nOpSize ); 877 nSpacesSize += appendWhiteSpaceTokens( pClosingSpaces ); 878 appendRawToken( OPCODE_CLOSE ); 879 pushOperandSize( nOpSize + nSpacesSize + 2 ); 880 } 881 return bOk; 882 } 883 884 bool FormulaParserImpl::pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces, const WhiteSpaceVec* pClosingSpaces ) 885 { 886 /* #i70925# if there are not enough tokens available on token stack, do 887 not exit with error, but reduce parameter count. */ 888 nParamCount = ::std::min( maOperandSizeStack.size(), nParamCount ); 889 890 // convert all parameters on stack to a single operand separated with OPCODE_SEP 891 bool bOk = true; 892 for( size_t nParam = 1; bOk && (nParam < nParamCount); ++nParam ) 893 bOk = pushBinaryOperatorToken( OPCODE_SEP ); 894 895 // add function parentheses and function name 896 return bOk && 897 ((nParamCount > 0) ? pushParenthesesOperatorToken( 0, pClosingSpaces ) : pushParenthesesOperandToken( 0, pClosingSpaces )) && 898 pushUnaryPreOperatorToken( nOpCode, pLeadingSpaces ); 899 } 900 901 bool FormulaParserImpl::pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, const WhiteSpaceVec* pLeadingSpaces, const WhiteSpaceVec* pClosingSpaces ) 902 { 903 bool bOk = pushFunctionOperatorToken( rFuncInfo.mnApiOpCode, nParamCount, pLeadingSpaces, pClosingSpaces ); 904 if( bOk ) 905 { 906 // create an external add-in call for the passed built-in function 907 if( (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) && (rFuncInfo.maExtProgName.getLength() > 0) ) 908 getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maExtProgName; 909 // create a bad token with unsupported function name 910 else if( (rFuncInfo.mnApiOpCode == OPCODE_BAD) && (rFuncInfo.maOoxFuncName.getLength() > 0) ) 911 getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maOoxFuncName; 912 } 913 return bOk; 914 } 915 916 bool FormulaParserImpl::pushOperand( sal_Int32 nOpCode ) 917 { 918 return pushOperandToken( nOpCode, &maLeadingSpaces ) && resetSpaces(); 919 } 920 921 bool FormulaParserImpl::pushAnyOperand( const Any& rAny, sal_Int32 nOpCode ) 922 { 923 return pushAnyOperandToken( rAny, nOpCode, &maLeadingSpaces ) && resetSpaces(); 924 } 925 926 template< typename Type > 927 bool FormulaParserImpl::pushValueOperand( const Type& rValue, sal_Int32 nOpCode ) 928 { 929 return pushValueOperandToken( rValue, nOpCode, &maLeadingSpaces ) && resetSpaces(); 930 } 931 932 bool FormulaParserImpl::pushBoolOperand( bool bValue ) 933 { 934 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) ) 935 return pushFunctionOperator( pFuncInfo->mnApiOpCode, 0 ); 936 return pushValueOperand< double >( bValue ? 1.0 : 0.0 ); 937 } 938 939 bool FormulaParserImpl::pushErrorOperand( double fEncodedError ) 940 { 941 // HACK: enclose all error codes into an 1x1 matrix 942 // start token array with opening brace and leading spaces 943 pushOperand( OPCODE_ARRAY_OPEN ); 944 size_t nOpSize = popOperandSize(); 945 size_t nOldArraySize = maTokenIndexes.size(); 946 // push a double containing the Calc error code 947 appendRawToken( OPCODE_PUSH ) <<= fEncodedError; 948 // close token array and set resulting operand size 949 appendRawToken( OPCODE_ARRAY_CLOSE ); 950 pushOperandSize( nOpSize + maTokenIndexes.size() - nOldArraySize ); 951 return true; 952 } 953 954 bool FormulaParserImpl::pushBiffBoolOperand( sal_uInt8 nValue ) 955 { 956 return pushBoolOperand( nValue != BIFF_TOK_BOOL_FALSE ); 957 } 958 959 bool FormulaParserImpl::pushBiffErrorOperand( sal_uInt8 nErrorCode ) 960 { 961 return pushErrorOperand( BiffHelper::calcDoubleFromError( nErrorCode ) ); 962 } 963 964 bool FormulaParserImpl::pushParenthesesOperand() 965 { 966 return pushParenthesesOperandToken( &maOpeningSpaces, &maClosingSpaces ) && resetSpaces(); 967 } 968 969 bool FormulaParserImpl::pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) 970 { 971 SingleReference aApiRef; 972 convertReference2d( aApiRef, rRef, bDeleted, bRelativeAsOffset ); 973 return pushValueOperand( aApiRef ); 974 } 975 976 bool FormulaParserImpl::pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) 977 { 978 ComplexReference aApiRef; 979 convertReference2d( aApiRef, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset ); 980 return pushValueOperand( aApiRef ); 981 } 982 983 template< typename Type > 984 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const Type& rApiRef ) 985 { 986 if( rSheetRange.isExternal() ) 987 { 988 ExternalReference aApiExtRef; 989 aApiExtRef.Index = rSheetRange.getDocLinkIndex(); 990 aApiExtRef.Reference <<= rApiRef; 991 return pushValueOperand( aApiExtRef ); 992 } 993 return pushValueOperand( rApiRef ); 994 } 995 996 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) 997 { 998 if( rSheetRange.is3dRange() ) 999 { 1000 // single-cell-range over several sheets, needs to create a ComplexReference 1001 ComplexReference aApiRef; 1002 convertReference3d( aApiRef, rSheetRange, rRef, rRef, bDeleted, bRelativeAsOffset ); 1003 return pushReferenceOperand( rSheetRange, aApiRef ); 1004 } 1005 SingleReference aApiRef; 1006 convertReference3d( aApiRef, rSheetRange.getFirstSheet(), rSheetRange.isSameSheet(), rRef, bDeleted, bRelativeAsOffset ); 1007 return pushReferenceOperand( rSheetRange, aApiRef ); 1008 } 1009 1010 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) 1011 { 1012 ComplexReference aApiRef; 1013 convertReference3d( aApiRef, rSheetRange, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset ); 1014 return pushReferenceOperand( rSheetRange, aApiRef ); 1015 } 1016 1017 bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d& rRef ) 1018 { 1019 SingleReference aApiRef; 1020 convertReference2d( aApiRef, rRef, false, false ); 1021 return pushValueOperand( aApiRef, OPCODE_NLR ); 1022 } 1023 1024 bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken ) 1025 { 1026 Any aRefAny = rName.getReference( maBaseAddr ); 1027 if( aRefAny.hasValue() ) 1028 return pushAnyOperand( aRefAny, OPCODE_PUSH ); 1029 if( bPushBadToken && (rName.getModelName().getLength() > 0) && (rName.getModelName()[ 0 ] >= ' ') ) 1030 return pushValueOperand( rName.getModelName(), OPCODE_BAD ); 1031 return pushBiffErrorOperand( BIFF_ERR_NAME ); 1032 } 1033 1034 bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef& rxDefName ) 1035 { 1036 if( !rxDefName || (rxDefName->getModelName().getLength() == 0) ) 1037 return pushBiffErrorOperand( BIFF_ERR_NAME ); 1038 if( rxDefName->isMacroFunction() ) 1039 return pushValueOperand( rxDefName->getModelName(), OPCODE_MACRO ); 1040 if( rxDefName->getTokenIndex() >= 0 ) 1041 return pushValueOperand( rxDefName->getTokenIndex(), OPCODE_NAME ); 1042 return pushEmbeddedRefOperand( *rxDefName, true ); 1043 } 1044 1045 bool FormulaParserImpl::pushExternalFuncOperand( const FunctionInfo& rFuncInfo ) 1046 { 1047 return (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) ? 1048 pushValueOperand( rFuncInfo.maExtProgName, OPCODE_EXTERNAL ) : 1049 pushOperand( rFuncInfo.mnApiOpCode ); 1050 } 1051 1052 bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ) 1053 { 1054 // create the function call DDE("server";"topic";"item") 1055 return 1056 pushValueOperandToken( rDdeServer ) && 1057 pushValueOperandToken( rDdeTopic ) && 1058 pushValueOperandToken( rDdeItem ) && 1059 pushFunctionOperator( OPCODE_DDE, 3 ); 1060 } 1061 1062 bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink ) 1063 { 1064 if( rxExtName.get() ) switch( rExtLink.getLinkType() ) 1065 { 1066 case LINKTYPE_INTERNAL: 1067 case LINKTYPE_EXTERNAL: 1068 return pushEmbeddedRefOperand( *rxExtName, false ); 1069 1070 case LINKTYPE_ANALYSIS: 1071 // TODO: need support for localized addin function names 1072 if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseModelName() ) ) 1073 return pushExternalFuncOperand( *pFuncInfo ); 1074 break; 1075 1076 case LINKTYPE_LIBRARY: 1077 if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseModelName() ) ) 1078 if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == rExtLink.getFuncLibraryType()) ) 1079 return pushExternalFuncOperand( *pFuncInfo ); 1080 break; 1081 1082 case LINKTYPE_DDE: 1083 { 1084 OUString aDdeServer, aDdeTopic, aDdeItem; 1085 if( rxExtName->getDdeLinkData( aDdeServer, aDdeTopic, aDdeItem ) ) 1086 return pushDdeLinkOperand( aDdeServer, aDdeTopic, aDdeItem ); 1087 } 1088 break; 1089 1090 default: 1091 OSL_ENSURE( rExtLink.getLinkType() != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" ); 1092 } 1093 return pushBiffErrorOperand( BIFF_ERR_NAME ); 1094 } 1095 1096 bool FormulaParserImpl::pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable ) 1097 { 1098 CellAddress aBaseAddr( maBaseAddr.Sheet, rBaseAddr.mnCol, rBaseAddr.mnRow ); 1099 ApiSpecialTokenInfo aTokenInfo( aBaseAddr, bTable ); 1100 return mbSpecialTokens && (getFormulaSize() == 0) && pushValueOperand( aTokenInfo, OPCODE_BAD ); 1101 } 1102 1103 bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode ) 1104 { 1105 return pushUnaryPreOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces(); 1106 } 1107 1108 bool FormulaParserImpl::pushUnaryPostOperator( sal_Int32 nOpCode ) 1109 { 1110 return pushUnaryPostOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces(); 1111 } 1112 1113 bool FormulaParserImpl::pushBinaryOperator( sal_Int32 nOpCode ) 1114 { 1115 return pushBinaryOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces(); 1116 } 1117 1118 bool FormulaParserImpl::pushParenthesesOperator() 1119 { 1120 return pushParenthesesOperatorToken( &maOpeningSpaces, &maClosingSpaces ) && resetSpaces(); 1121 } 1122 1123 bool FormulaParserImpl::pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount ) 1124 { 1125 return pushFunctionOperatorToken( nOpCode, nParamCount, &maLeadingSpaces, &maClosingSpaces ) && resetSpaces(); 1126 } 1127 1128 bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount ) 1129 { 1130 return pushFunctionOperatorToken( rFuncInfo, nParamCount, &maLeadingSpaces, &maClosingSpaces ) && resetSpaces(); 1131 } 1132 1133 // reference conversion ------------------------------------------------------- 1134 1135 void FormulaParserImpl::initReference2d( SingleReference& orApiRef ) const 1136 { 1137 if( mb2dRefsAs3dRefs ) 1138 { 1139 initReference3d( orApiRef, maBaseAddr.Sheet, false ); 1140 } 1141 else 1142 { 1143 orApiRef.Flags = SHEET_RELATIVE; 1144 // #i10184# absolute sheet index needed for relative references in shared formulas 1145 orApiRef.Sheet = maBaseAddr.Sheet; 1146 orApiRef.RelativeSheet = 0; 1147 } 1148 } 1149 1150 void FormulaParserImpl::initReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet ) const 1151 { 1152 orApiRef.Flags = SHEET_3D; 1153 if( nSheet < 0 ) 1154 { 1155 orApiRef.Sheet = 0; 1156 orApiRef.Flags |= SHEET_DELETED; 1157 } 1158 else if( bSameSheet ) 1159 { 1160 OSL_ENSURE( nSheet == 0, "FormulaParserImpl::initReference3d - invalid sheet index" ); 1161 orApiRef.Flags |= SHEET_RELATIVE; 1162 orApiRef.RelativeSheet = 0; 1163 } 1164 else 1165 { 1166 orApiRef.Sheet = nSheet; 1167 } 1168 } 1169 1170 void FormulaParserImpl::convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const 1171 { 1172 if( bDeleted ) 1173 { 1174 orApiRef.Column = 0; 1175 orApiRef.Row = 0; 1176 // no explicit information about whether row or column is deleted 1177 orApiRef.Flags |= COLUMN_DELETED | ROW_DELETED; 1178 } 1179 else 1180 { 1181 // column/row indexes and flags 1182 setFlag( orApiRef.Flags, COLUMN_RELATIVE, rRef.mbColRel ); 1183 setFlag( orApiRef.Flags, ROW_RELATIVE, rRef.mbRowRel ); 1184 (rRef.mbColRel ? orApiRef.RelativeColumn : orApiRef.Column) = rRef.mnCol; 1185 (rRef.mbRowRel ? orApiRef.RelativeRow : orApiRef.Row) = rRef.mnRow; 1186 // convert absolute indexes to relative offsets used in API 1187 if( !bRelativeAsOffset ) 1188 { 1189 if( rRef.mbColRel ) 1190 orApiRef.RelativeColumn -= maBaseAddr.Column; 1191 if( rRef.mbRowRel ) 1192 orApiRef.RelativeRow -= maBaseAddr.Row; 1193 } 1194 } 1195 } 1196 1197 void FormulaParserImpl::convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const 1198 { 1199 convertReference( orApiRef.Reference1, rRef1, bDeleted, bRelativeAsOffset ); 1200 convertReference( orApiRef.Reference2, rRef2, bDeleted, bRelativeAsOffset ); 1201 /* Handle references to complete rows or columns (e.g. $1:$2 or C:D), 1202 need to expand or shrink to limits of own document. */ 1203 if( !bDeleted && !rRef1.mbColRel && !rRef2.mbColRel && (orApiRef.Reference1.Column == 0) && (orApiRef.Reference2.Column == mnMaxXlsCol) ) 1204 orApiRef.Reference2.Column = mnMaxApiCol; 1205 if( !bDeleted && !rRef1.mbRowRel && !rRef2.mbRowRel && (orApiRef.Reference1.Row == 0) && (orApiRef.Reference2.Row == mnMaxXlsRow) ) 1206 orApiRef.Reference2.Row = mnMaxApiRow; 1207 } 1208 1209 void FormulaParserImpl::convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const 1210 { 1211 initReference2d( orApiRef ); 1212 convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset ); 1213 } 1214 1215 void FormulaParserImpl::convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const 1216 { 1217 initReference2d( orApiRef.Reference1 ); 1218 initReference2d( orApiRef.Reference2 ); 1219 convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset ); 1220 // remove sheet name from second part of reference 1221 setFlag( orApiRef.Reference2.Flags, SHEET_3D, false ); 1222 } 1223 1224 void FormulaParserImpl::convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, bool bSameSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const 1225 { 1226 initReference3d( orApiRef, nSheet, bSameSheet ); 1227 convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset ); 1228 } 1229 1230 void FormulaParserImpl::convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const 1231 { 1232 bool bSameSheet = rSheetRange.isSameSheet(); 1233 initReference3d( orApiRef.Reference1, rSheetRange.getFirstSheet(), bSameSheet ); 1234 initReference3d( orApiRef.Reference2, rSheetRange.getLastSheet(), bSameSheet ); 1235 convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset ); 1236 // remove sheet name from second part of reference 1237 setFlag( orApiRef.Reference2.Flags, SHEET_3D, rSheetRange.is3dRange() ); 1238 } 1239 1240 // finalize token sequence ---------------------------------------------------- 1241 1242 const FunctionInfo* FormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const 1243 { 1244 /* Try to parse calls to library functions. The format of such a function 1245 call is "[n]!funcname", n>0 being the link identifier of the function 1246 library spreadsheet file. */ 1247 sal_Int32 nBracketOpen = rTokenData.indexOf( '[' ); 1248 sal_Int32 nBracketClose = rTokenData.indexOf( ']' ); 1249 sal_Int32 nExclamation = rTokenData.indexOf( '!' ); 1250 if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < rTokenData.getLength()) ) 1251 { 1252 sal_Int32 nRefId = rTokenData.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32(); 1253 const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get(); 1254 if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) ) 1255 { 1256 OUString aFuncName = rTokenData.copy( nExclamation + 1 ).toAsciiUpperCase(); 1257 if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ) ) 1258 if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) ) 1259 return pFuncInfo; 1260 } 1261 } 1262 return 0; 1263 } 1264 1265 OUString FormulaParserImpl::resolveDefinedName( sal_Int32 nTokenIndex ) const 1266 { 1267 if( const DefinedName* pDefName = getDefinedNames().getByTokenIndex( nTokenIndex ).get() ) 1268 return pDefName->getCalcName(); 1269 return OUString(); 1270 } 1271 1272 // OOXML/BIFF12 parser implementation ========================================= 1273 1274 class OoxFormulaParserImpl : public FormulaParserImpl 1275 { 1276 public: 1277 explicit OoxFormulaParserImpl( const FormulaParser& rParent ); 1278 1279 virtual ApiTokenSequence importOoxFormula( 1280 const CellAddress& rBaseAddr, 1281 const OUString& rFormulaString ); 1282 1283 virtual ApiTokenSequence importBiff12Formula( 1284 const CellAddress& rBaseAddr, 1285 FormulaType eType, 1286 SequenceInputStream& rStrm ); 1287 1288 private: 1289 // import token contents and create API formula token --------------------- 1290 1291 bool importAttrToken( SequenceInputStream& rStrm ); 1292 bool importSpaceToken( SequenceInputStream& rStrm ); 1293 bool importTableToken( SequenceInputStream& rStrm ); 1294 bool importArrayToken( SequenceInputStream& rStrm ); 1295 bool importRefToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1296 bool importAreaToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1297 bool importRef3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1298 bool importArea3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1299 bool importMemAreaToken( SequenceInputStream& rStrm, bool bAddData ); 1300 bool importMemFuncToken( SequenceInputStream& rStrm ); 1301 bool importNameToken( SequenceInputStream& rStrm ); 1302 bool importNameXToken( SequenceInputStream& rStrm ); 1303 bool importFuncToken( SequenceInputStream& rStrm ); 1304 bool importFuncVarToken( SequenceInputStream& rStrm ); 1305 bool importExpToken( SequenceInputStream& rStrm ); 1306 1307 LinkSheetRange readSheetRange( SequenceInputStream& rStrm ); 1308 1309 void swapStreamPosition( SequenceInputStream& rStrm ); 1310 void skipMemAreaAddData( SequenceInputStream& rStrm ); 1311 1312 // convert BIN token and push API operand or operator --------------------- 1313 1314 bool pushBiff12Name( sal_Int32 nNameId ); 1315 bool pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId ); 1316 bool pushBiff12Function( sal_uInt16 nFuncId ); 1317 bool pushBiff12Function( sal_uInt16 nFuncId, sal_uInt8 nParamCount ); 1318 1319 private: 1320 ApiParserWrapper maApiParser; /// Wrapper for the API formula parser object. 1321 sal_Int64 mnAddDataPos; /// Current stream position for additional data (tExp, tArray, tMemArea). 1322 bool mbNeedExtRefs; /// True = parser needs initialization of external reference info. 1323 }; 1324 1325 // ---------------------------------------------------------------------------- 1326 1327 OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser& rParent ) : 1328 FormulaParserImpl( rParent ), 1329 maApiParser( rParent.getBaseFilter().getModelFactory(), rParent ), 1330 mnAddDataPos( 0 ), 1331 mbNeedExtRefs( true ) 1332 { 1333 } 1334 1335 ApiTokenSequence OoxFormulaParserImpl::importOoxFormula( const CellAddress& rBaseAddr, const OUString& rFormulaString ) 1336 { 1337 if( mbNeedExtRefs ) 1338 { 1339 maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() ); 1340 mbNeedExtRefs = false; 1341 } 1342 return finalizeTokenArray( maApiParser.parseFormula( rFormulaString, rBaseAddr ) ); 1343 } 1344 1345 ApiTokenSequence OoxFormulaParserImpl::importBiff12Formula( const CellAddress& rBaseAddr, FormulaType eType, SequenceInputStream& rStrm ) 1346 { 1347 initializeImport( rBaseAddr, eType ); 1348 1349 sal_Int32 nFmlaSize = rStrm.readInt32(); 1350 sal_Int64 nFmlaPos = rStrm.tell(); 1351 sal_Int64 nFmlaEndPos = nFmlaPos + nFmlaSize; 1352 1353 rStrm.seek( nFmlaEndPos ); 1354 sal_Int32 nAddDataSize = rStrm.readInt32(); 1355 mnAddDataPos = rStrm.tell(); 1356 sal_Int64 nAddDataEndPos = mnAddDataPos + nAddDataSize; 1357 rStrm.seek( nFmlaPos ); 1358 1359 bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0); 1360 bool bRelativeAsOffset = mbRelativeAsOffset; 1361 1362 while( bOk && !rStrm.isEof() && (rStrm.tell() < nFmlaEndPos) ) 1363 { 1364 sal_uInt8 nTokenId; 1365 rStrm >> nTokenId; 1366 sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK; 1367 sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; 1368 1369 if( nTokenClass == BIFF_TOKCLASS_NONE ) 1370 { 1371 // base tokens 1372 switch( nBaseId ) 1373 { 1374 case BIFF_TOKID_EXP: bOk = importExpToken( rStrm ); break; 1375 case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD ); break; 1376 case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB ); break; 1377 case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT ); break; 1378 case BIFF_TOKID_DIV: bOk = pushBinaryOperator( OPCODE_DIV ); break; 1379 case BIFF_TOKID_POWER: bOk = pushBinaryOperator( OPCODE_POWER ); break; 1380 case BIFF_TOKID_CONCAT: bOk = pushBinaryOperator( OPCODE_CONCAT ); break; 1381 case BIFF_TOKID_LT: bOk = pushBinaryOperator( OPCODE_LESS ); break; 1382 case BIFF_TOKID_LE: bOk = pushBinaryOperator( OPCODE_LESS_EQUAL ); break; 1383 case BIFF_TOKID_EQ: bOk = pushBinaryOperator( OPCODE_EQUAL ); break; 1384 case BIFF_TOKID_GE: bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL ); break; 1385 case BIFF_TOKID_GT: bOk = pushBinaryOperator( OPCODE_GREATER ); break; 1386 case BIFF_TOKID_NE: bOk = pushBinaryOperator( OPCODE_NOT_EQUAL ); break; 1387 case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( OPCODE_INTERSECT ); break; 1388 case BIFF_TOKID_LIST: bOk = pushBinaryOperator( OPCODE_LIST ); break; 1389 case BIFF_TOKID_RANGE: bOk = pushBinaryOperator( OPCODE_RANGE ); break; 1390 case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN ); break; 1391 case BIFF_TOKID_UMINUS: bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN ); break; 1392 case BIFF_TOKID_PERCENT: bOk = pushUnaryPostOperator( OPCODE_PERCENT ); break; 1393 case BIFF_TOKID_PAREN: bOk = pushParenthesesOperator(); break; 1394 case BIFF_TOKID_MISSARG: bOk = pushOperand( OPCODE_MISSING ); break; 1395 case BIFF_TOKID_STR: bOk = pushValueOperand( BiffHelper::readString( rStrm, false ) ); break; 1396 case BIFF_TOKID_NLR: bOk = importTableToken( rStrm ); break; 1397 case BIFF_TOKID_ATTR: bOk = importAttrToken( rStrm ); break; 1398 case BIFF_TOKID_ERR: bOk = pushBiffErrorOperand( rStrm.readuInt8() ); break; 1399 case BIFF_TOKID_BOOL: bOk = pushBiffBoolOperand( rStrm.readuInt8() ); break; 1400 case BIFF_TOKID_INT: bOk = pushValueOperand< double >( rStrm.readuInt16() ); break; 1401 case BIFF_TOKID_NUM: bOk = pushValueOperand( rStrm.readDouble() ); break; 1402 default: bOk = false; 1403 } 1404 } 1405 else 1406 { 1407 // classified tokens 1408 switch( nBaseId ) 1409 { 1410 case BIFF_TOKID_ARRAY: bOk = importArrayToken( rStrm ); break; 1411 case BIFF_TOKID_FUNC: bOk = importFuncToken( rStrm ); break; 1412 case BIFF_TOKID_FUNCVAR: bOk = importFuncVarToken( rStrm ); break; 1413 case BIFF_TOKID_NAME: bOk = importNameToken( rStrm ); break; 1414 case BIFF_TOKID_REF: bOk = importRefToken( rStrm, false, false ); break; 1415 case BIFF_TOKID_AREA: bOk = importAreaToken( rStrm, false, false ); break; 1416 case BIFF_TOKID_MEMAREA: bOk = importMemAreaToken( rStrm, true ); break; 1417 case BIFF_TOKID_MEMERR: bOk = importMemAreaToken( rStrm, false ); break; 1418 case BIFF_TOKID_MEMNOMEM: bOk = importMemAreaToken( rStrm, false ); break; 1419 case BIFF_TOKID_MEMFUNC: bOk = importMemFuncToken( rStrm ); break; 1420 case BIFF_TOKID_REFERR: bOk = importRefToken( rStrm, true, false ); break; 1421 case BIFF_TOKID_AREAERR: bOk = importAreaToken( rStrm, true, false ); break; 1422 case BIFF_TOKID_REFN: bOk = importRefToken( rStrm, false, true ); break; 1423 case BIFF_TOKID_AREAN: bOk = importAreaToken( rStrm, false, true ); break; 1424 case BIFF_TOKID_MEMAREAN: bOk = importMemFuncToken( rStrm ); break; 1425 case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; 1426 case BIFF_TOKID_NAMEX: bOk = importNameXToken( rStrm ); break; 1427 case BIFF_TOKID_REF3D: bOk = importRef3dToken( rStrm, false, bRelativeAsOffset ); break; 1428 case BIFF_TOKID_AREA3D: bOk = importArea3dToken( rStrm, false, bRelativeAsOffset ); break; 1429 case BIFF_TOKID_REFERR3D: bOk = importRef3dToken( rStrm, true, bRelativeAsOffset ); break; 1430 case BIFF_TOKID_AREAERR3D: bOk = importArea3dToken( rStrm, true, bRelativeAsOffset ); break; 1431 default: bOk = false; 1432 } 1433 } 1434 } 1435 1436 // build and finalize the token sequence 1437 ApiTokenSequence aFinalTokens; 1438 if( bOk && (rStrm.tell() == nFmlaEndPos) && (mnAddDataPos == nAddDataEndPos) ) 1439 aFinalTokens = finalizeImport(); 1440 1441 // seek behind token array 1442 if( (nFmlaSize >= 0) && (nAddDataSize >= 0) ) 1443 rStrm.seek( nAddDataEndPos ); 1444 1445 // return the final token sequence 1446 return aFinalTokens; 1447 } 1448 1449 // import token contents and create API formula token ------------------------- 1450 1451 bool OoxFormulaParserImpl::importAttrToken( SequenceInputStream& rStrm ) 1452 { 1453 bool bOk = true; 1454 sal_uInt8 nType; 1455 rStrm >> nType; 1456 // equal flags in all BIFFs 1457 switch( nType ) 1458 { 1459 case 0: // sometimes, tAttrSkip tokens miss the type flag 1460 case BIFF_TOK_ATTR_VOLATILE: 1461 case BIFF_TOK_ATTR_IF: 1462 case BIFF_TOK_ATTR_SKIP: 1463 case BIFF_TOK_ATTR_ASSIGN: 1464 case BIFF_TOK_ATTR_IFERROR: 1465 rStrm.skip( 2 ); 1466 break; 1467 case BIFF_TOK_ATTR_CHOOSE: 1468 rStrm.skip( 2 * rStrm.readuInt16() + 2 ); 1469 break; 1470 case BIFF_TOK_ATTR_SUM: 1471 rStrm.skip( 2 ); 1472 bOk = pushBiff12Function( BIFF_FUNC_SUM, 1 ); 1473 break; 1474 case BIFF_TOK_ATTR_SPACE: 1475 case BIFF_TOK_ATTR_SPACE_VOLATILE: 1476 bOk = importSpaceToken( rStrm ); 1477 break; 1478 default: 1479 bOk = false; 1480 } 1481 return bOk; 1482 } 1483 1484 bool OoxFormulaParserImpl::importSpaceToken( SequenceInputStream& rStrm ) 1485 { 1486 // equal constants in BIFF and OOX 1487 sal_uInt8 nType, nCount; 1488 rStrm >> nType >> nCount; 1489 switch( nType ) 1490 { 1491 case BIFF_TOK_ATTR_SPACE_SP: 1492 appendLeadingSpaces( nCount, false ); 1493 break; 1494 case BIFF_TOK_ATTR_SPACE_BR: 1495 appendLeadingSpaces( nCount, true ); 1496 break; 1497 case BIFF_TOK_ATTR_SPACE_SP_OPEN: 1498 appendOpeningSpaces( nCount, false ); 1499 break; 1500 case BIFF_TOK_ATTR_SPACE_BR_OPEN: 1501 appendOpeningSpaces( nCount, true ); 1502 break; 1503 case BIFF_TOK_ATTR_SPACE_SP_CLOSE: 1504 appendClosingSpaces( nCount, false ); 1505 break; 1506 case BIFF_TOK_ATTR_SPACE_BR_CLOSE: 1507 appendClosingSpaces( nCount, true ); 1508 break; 1509 } 1510 return true; 1511 } 1512 1513 bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm ) 1514 { 1515 sal_uInt16 nFlags, nTableId, nCol1, nCol2; 1516 rStrm.skip( 3 ); 1517 rStrm >> nFlags >> nTableId; 1518 rStrm.skip( 2 ); 1519 rStrm >> nCol1 >> nCol2; 1520 TableRef xTable = getTables().getTable( nTableId ); 1521 sal_Int32 nTokenIndex = xTable.get() ? xTable->getTokenIndex() : -1; 1522 if( nTokenIndex >= 0 ) 1523 { 1524 sal_Int32 nWidth = xTable->getWidth(); 1525 sal_Int32 nHeight = xTable->getHeight(); 1526 sal_Int32 nStartCol = 0; 1527 sal_Int32 nEndCol = nWidth - 1; 1528 sal_Int32 nStartRow = 0; 1529 sal_Int32 nEndRow = nHeight - 1; 1530 bool bFixedStartRow = true; 1531 bool bFixedHeight = false; 1532 1533 bool bSingleCol = getFlag( nFlags, BIFF12_TOK_TABLE_COLUMN ); 1534 bool bColRange = getFlag( nFlags, BIFF12_TOK_TABLE_COLRANGE ); 1535 bool bValidRef = !bSingleCol || !bColRange; 1536 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - illegal combination of single column and column range" ); 1537 if( bValidRef ) 1538 { 1539 if( bSingleCol ) 1540 nStartCol = nEndCol = nCol1; 1541 else if( bColRange ) 1542 { nStartCol = nCol1; nEndCol = nCol2; } 1543 bValidRef = (nStartCol <= nEndCol) && (nEndCol < nWidth); 1544 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid column range" ); 1545 } 1546 1547 if( bValidRef ) 1548 { 1549 bool bAllRows = getFlag( nFlags, BIFF12_TOK_TABLE_ALL ); 1550 bool bHeaderRows = getFlag( nFlags, BIFF12_TOK_TABLE_HEADERS ); 1551 bool bDataRows = getFlag( nFlags, BIFF12_TOK_TABLE_DATA ); 1552 bool bTotalsRows = getFlag( nFlags, BIFF12_TOK_TABLE_TOTALS ); 1553 bool bThisRow = getFlag( nFlags, BIFF12_TOK_TABLE_THISROW ); 1554 1555 sal_Int32 nStartDataRow = xTable->getHeaderRows(); 1556 sal_Int32 nEndDataRow = nEndRow - xTable->getTotalsRows(); 1557 bValidRef = (nStartRow <= nStartDataRow) && (nStartDataRow <= nEndDataRow) && (nEndDataRow <= nEndRow); 1558 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid data row range" ); 1559 if( bValidRef ) 1560 { 1561 if( bAllRows ) 1562 { 1563 bValidRef = !bHeaderRows && !bDataRows && !bTotalsRows && !bThisRow; 1564 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#All] table token" ); 1565 } 1566 else if( bHeaderRows ) 1567 { 1568 bValidRef = !bTotalsRows && !bThisRow; 1569 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Headers] table token" ); 1570 nEndRow = bDataRows ? nEndDataRow : (nStartDataRow - 1); 1571 bFixedHeight = !bDataRows; 1572 } 1573 else if( bDataRows ) 1574 { 1575 bValidRef = !bThisRow; 1576 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Data] table token" ); 1577 nStartRow = nStartDataRow; 1578 if( !bTotalsRows ) nEndRow = nEndDataRow; 1579 } 1580 else if( bTotalsRows ) 1581 { 1582 bValidRef = !bThisRow; 1583 OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Totals] table token" ); 1584 nStartRow = nEndDataRow + 1; 1585 bFixedStartRow = false; 1586 bFixedHeight = !bDataRows; 1587 } 1588 else if( bThisRow ) 1589 { 1590 nStartRow = nEndRow = maBaseAddr.Row - xTable->getRange().StartRow; 1591 bFixedHeight = true; 1592 } 1593 else 1594 { 1595 // nothing is the same as [#Data] 1596 nStartRow = nStartDataRow; 1597 nEndRow = nEndDataRow; 1598 } 1599 } 1600 if( bValidRef ) 1601 bValidRef = (0 <= nStartRow) && (nStartRow <= nEndRow) && (nEndRow < nHeight); 1602 } 1603 if( bValidRef ) 1604 { 1605 // push single database area token, if table token refers to entire table 1606 if( (nStartCol == 0) && (nEndCol + 1 == nWidth) && (nStartRow == 0) && (nEndRow + 1 == nHeight) ) 1607 return pushValueOperand( nTokenIndex, OPCODE_DBAREA ); 1608 // create an OFFSET function call to refer to a subrange of the table 1609 const FunctionInfo* pRowsInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_ROWS ); 1610 const FunctionInfo* pColumnsInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_COLUMNS ); 1611 return 1612 pRowsInfo && pColumnsInfo && 1613 pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) && 1614 (bFixedStartRow ? 1615 pushValueOperandToken< double >( nStartRow ) : 1616 (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) && 1617 pushFunctionOperatorToken( *pRowsInfo, 1 ) && 1618 pushValueOperandToken< double >( nHeight - nStartRow ) && 1619 pushBinaryOperatorToken( OPCODE_SUB ))) && 1620 pushValueOperandToken< double >( nStartCol ) && 1621 (bFixedHeight ? 1622 pushValueOperandToken< double >( nEndRow - nStartRow + 1 ) : 1623 (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) && 1624 pushFunctionOperatorToken( *pRowsInfo, 1 ) && 1625 (((nStartRow == 0) && (nEndRow + 1 == nHeight)) || 1626 (pushValueOperandToken< double >( nHeight - (nEndRow - nStartRow + 1) ) && 1627 pushBinaryOperatorToken( OPCODE_SUB ))))) && 1628 (((nStartCol == 0) && (nEndCol + 1 == nWidth)) ? 1629 (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) && 1630 pushFunctionOperatorToken( *pColumnsInfo, 1 )) : 1631 pushValueOperandToken< double >( nEndCol - nStartCol + 1 )) && 1632 pushBiff12Function( BIFF_FUNC_OFFSET, 5 ); 1633 } 1634 } 1635 return pushBiffErrorOperand( BIFF_ERR_REF ); 1636 } 1637 1638 bool OoxFormulaParserImpl::importArrayToken( SequenceInputStream& rStrm ) 1639 { 1640 rStrm.skip( 14 ); 1641 1642 // start token array with opening brace and leading spaces 1643 pushOperand( OPCODE_ARRAY_OPEN ); 1644 size_t nOpSize = popOperandSize(); 1645 size_t nOldArraySize = getFormulaSize(); 1646 1647 // read array size 1648 swapStreamPosition( rStrm ); 1649 sal_Int32 nRows = rStrm.readInt32(); 1650 sal_Int32 nCols = rStrm.readInt32(); 1651 OSL_ENSURE( (nCols > 0) && (nRows > 0), "OoxFormulaParserImpl::importArrayToken - empty array" ); 1652 1653 // read array values and build token array 1654 for( sal_Int32 nRow = 0; !rStrm.isEof() && (nRow < nRows); ++nRow ) 1655 { 1656 if( nRow > 0 ) 1657 appendRawToken( OPCODE_ARRAY_ROWSEP ); 1658 for( sal_Int32 nCol = 0; !rStrm.isEof() && (nCol < nCols); ++nCol ) 1659 { 1660 if( nCol > 0 ) 1661 appendRawToken( OPCODE_ARRAY_COLSEP ); 1662 switch( rStrm.readuInt8() ) 1663 { 1664 case BIFF_TOK_ARRAY_DOUBLE: 1665 appendRawToken( OPCODE_PUSH ) <<= rStrm.readDouble(); 1666 break; 1667 case BIFF_TOK_ARRAY_STRING: 1668 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::readString( rStrm, false ); 1669 break; 1670 case BIFF_TOK_ARRAY_BOOL: 1671 appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 ); 1672 break; 1673 case BIFF_TOK_ARRAY_ERROR: 1674 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() ); 1675 rStrm.skip( 3 ); 1676 break; 1677 default: 1678 OSL_ENSURE( false, "OoxFormulaParserImpl::importArrayToken - unknown data type" ); 1679 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA ); 1680 } 1681 } 1682 } 1683 swapStreamPosition( rStrm ); 1684 1685 // close token array and set resulting operand size 1686 appendRawToken( OPCODE_ARRAY_CLOSE ); 1687 pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize ); 1688 return true; 1689 } 1690 1691 bool OoxFormulaParserImpl::importRefToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 1692 { 1693 BinSingleRef2d aRef; 1694 aRef.readBiff12Data( rStrm, bRelativeAsOffset ); 1695 return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset ); 1696 } 1697 1698 bool OoxFormulaParserImpl::importAreaToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 1699 { 1700 BinComplexRef2d aRef; 1701 aRef.readBiff12Data( rStrm, bRelativeAsOffset ); 1702 return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset ); 1703 } 1704 1705 bool OoxFormulaParserImpl::importRef3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 1706 { 1707 LinkSheetRange aSheetRange = readSheetRange( rStrm ); 1708 BinSingleRef2d aRef; 1709 aRef.readBiff12Data( rStrm, bRelativeAsOffset ); 1710 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); 1711 } 1712 1713 bool OoxFormulaParserImpl::importArea3dToken( SequenceInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 1714 { 1715 LinkSheetRange aSheetRange = readSheetRange( rStrm ); 1716 BinComplexRef2d aRef; 1717 aRef.readBiff12Data( rStrm, bRelativeAsOffset ); 1718 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); 1719 } 1720 1721 bool OoxFormulaParserImpl::importMemAreaToken( SequenceInputStream& rStrm, bool bAddData ) 1722 { 1723 rStrm.skip( 6 ); 1724 if( bAddData ) 1725 skipMemAreaAddData( rStrm ); 1726 return true; 1727 } 1728 1729 bool OoxFormulaParserImpl::importMemFuncToken( SequenceInputStream& rStrm ) 1730 { 1731 rStrm.skip( 2 ); 1732 return true; 1733 } 1734 1735 bool OoxFormulaParserImpl::importNameToken( SequenceInputStream& rStrm ) 1736 { 1737 return pushBiff12Name( rStrm.readInt32() ); 1738 } 1739 1740 bool OoxFormulaParserImpl::importNameXToken( SequenceInputStream& rStrm ) 1741 { 1742 sal_Int32 nRefId = rStrm.readInt16(); 1743 sal_Int32 nNameId = rStrm.readInt32(); 1744 return pushBiff12ExtName( nRefId, nNameId ); 1745 } 1746 1747 bool OoxFormulaParserImpl::importFuncToken( SequenceInputStream& rStrm ) 1748 { 1749 sal_uInt16 nFuncId; 1750 rStrm >> nFuncId; 1751 return pushBiff12Function( nFuncId ); 1752 } 1753 1754 bool OoxFormulaParserImpl::importFuncVarToken( SequenceInputStream& rStrm ) 1755 { 1756 sal_uInt8 nParamCount; 1757 sal_uInt16 nFuncId; 1758 rStrm >> nParamCount >> nFuncId; 1759 return pushBiff12Function( nFuncId, nParamCount ); 1760 } 1761 1762 bool OoxFormulaParserImpl::importExpToken( SequenceInputStream& rStrm ) 1763 { 1764 BinAddress aBaseAddr; 1765 rStrm >> aBaseAddr.mnRow; 1766 swapStreamPosition( rStrm ); 1767 rStrm >> aBaseAddr.mnCol; 1768 swapStreamPosition( rStrm ); 1769 return pushSpecialTokenOperand( aBaseAddr, false ); 1770 } 1771 1772 LinkSheetRange OoxFormulaParserImpl::readSheetRange( SequenceInputStream& rStrm ) 1773 { 1774 return getExternalLinks().getSheetRange( rStrm.readInt16() ); 1775 } 1776 1777 void OoxFormulaParserImpl::swapStreamPosition( SequenceInputStream& rStrm ) 1778 { 1779 sal_Int64 nRecPos = rStrm.tell(); 1780 rStrm.seek( mnAddDataPos ); 1781 mnAddDataPos = nRecPos; 1782 } 1783 1784 void OoxFormulaParserImpl::skipMemAreaAddData( SequenceInputStream& rStrm ) 1785 { 1786 swapStreamPosition( rStrm ); 1787 rStrm.skip( 16 * rStrm.readInt32() ); 1788 swapStreamPosition( rStrm ); 1789 } 1790 1791 // convert BIN token and push API operand or operator ------------------------- 1792 1793 bool OoxFormulaParserImpl::pushBiff12Name( sal_Int32 nNameId ) 1794 { 1795 // one-based in BIFF12 formulas 1796 return pushDefinedNameOperand( getDefinedNames().getByIndex( nNameId - 1 ) ); 1797 } 1798 1799 bool OoxFormulaParserImpl::pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId ) 1800 { 1801 if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() ) 1802 { 1803 if( pExtLink->getLinkType() == LINKTYPE_SELF ) 1804 return pushBiff12Name( nNameId ); 1805 // external name indexes are one-based in BIFF12 1806 ExternalNameRef xExtName = pExtLink->getNameByIndex( nNameId - 1 ); 1807 return pushExternalNameOperand( xExtName, *pExtLink ); 1808 } 1809 return pushBiffErrorOperand( BIFF_ERR_NAME ); 1810 } 1811 1812 bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId ) 1813 { 1814 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) ) 1815 if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount ) 1816 return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount ); 1817 return pushFunctionOperator( OPCODE_NONAME, 0 ); 1818 } 1819 1820 bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId, sal_uInt8 nParamCount ) 1821 { 1822 if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) ) 1823 nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; 1824 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) ) 1825 return pushFunctionOperator( *pFuncInfo, nParamCount ); 1826 return pushFunctionOperator( OPCODE_NONAME, nParamCount ); 1827 } 1828 1829 // BIFF parser implementation ================================================= 1830 1831 namespace { 1832 1833 /** A natural language reference struct with relative flag. */ 1834 struct BiffNlr 1835 { 1836 sal_Int32 mnCol; /// Column index. 1837 sal_Int32 mnRow; /// Row index. 1838 bool mbRel; /// True = relative column/row reference. 1839 1840 explicit BiffNlr(); 1841 1842 void readBiff8Data( BiffInputStream& rStrm ); 1843 }; 1844 1845 BiffNlr::BiffNlr() : 1846 mnCol( 0 ), 1847 mnRow( 0 ), 1848 mbRel( false ) 1849 { 1850 } 1851 1852 void BiffNlr::readBiff8Data( BiffInputStream& rStrm ) 1853 { 1854 sal_uInt16 nRow, nCol; 1855 rStrm >> nRow >> nCol; 1856 mnCol = nCol & BIFF_TOK_NLR_MASK; 1857 mnRow = nRow; 1858 mbRel = getFlag( nCol, BIFF_TOK_NLR_REL ); 1859 } 1860 1861 bool lclIsValidNlrStack( const BinAddress& rAddr1, const BinAddress& rAddr2, bool bRow ) 1862 { 1863 return bRow ? 1864 ((rAddr1.mnRow == rAddr2.mnRow) && (rAddr1.mnCol + 1 == rAddr2.mnCol)) : 1865 ((rAddr1.mnCol == rAddr2.mnCol) && (rAddr1.mnRow + 1 == rAddr2.mnRow)); 1866 } 1867 1868 bool lclIsValidNlrRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow ) 1869 { 1870 return bRow ? 1871 ((rNlr.mnRow == rRange.maFirst.mnRow) && (rNlr.mnCol + 1 == rRange.maFirst.mnCol) && (rRange.maFirst.mnRow == rRange.maLast.mnRow)) : 1872 ((rNlr.mnCol == rRange.maFirst.mnCol) && (rNlr.mnRow + 1 == rRange.maFirst.mnRow) && (rRange.maFirst.mnCol == rRange.maLast.mnCol)); 1873 } 1874 1875 } // namespace 1876 1877 // ---------------------------------------------------------------------------- 1878 1879 class BiffFormulaParserImpl : public FormulaParserImpl 1880 { 1881 public: 1882 explicit BiffFormulaParserImpl( const FormulaParser& rParent ); 1883 1884 virtual ApiTokenSequence importBiffFormula( 1885 const CellAddress& rBaseAddr, 1886 FormulaType eType, 1887 BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ); 1888 1889 private: 1890 // import token contents and create API formula token --------------------- 1891 1892 bool importTokenNotAvailable( BiffInputStream& rStrm ); 1893 bool importRefTokenNotAvailable( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1894 bool importStrToken2( BiffInputStream& rStrm ); 1895 bool importStrToken8( BiffInputStream& rStrm ); 1896 bool importAttrToken( BiffInputStream& rStrm ); 1897 bool importSpaceToken3( BiffInputStream& rStrm ); 1898 bool importSpaceToken4( BiffInputStream& rStrm ); 1899 bool importSheetToken2( BiffInputStream& rStrm ); 1900 bool importSheetToken3( BiffInputStream& rStrm ); 1901 bool importEndSheetToken2( BiffInputStream& rStrm ); 1902 bool importEndSheetToken3( BiffInputStream& rStrm ); 1903 bool importNlrToken( BiffInputStream& rStrm ); 1904 bool importArrayToken( BiffInputStream& rStrm ); 1905 bool importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1906 bool importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1907 bool importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1908 bool importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1909 bool importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1910 bool importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1911 bool importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1912 bool importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); 1913 bool importMemAreaToken( BiffInputStream& rStrm, bool bAddData ); 1914 bool importMemFuncToken( BiffInputStream& rStrm ); 1915 bool importNameToken( BiffInputStream& rStrm ); 1916 bool importNameXToken( BiffInputStream& rStrm ); 1917 bool importFuncToken2( BiffInputStream& rStrm ); 1918 bool importFuncToken4( BiffInputStream& rStrm ); 1919 bool importFuncVarToken2( BiffInputStream& rStrm ); 1920 bool importFuncVarToken4( BiffInputStream& rStrm ); 1921 bool importFuncCEToken( BiffInputStream& rStrm ); 1922 bool importExpToken( BiffInputStream& rStrm ); 1923 bool importTblToken( BiffInputStream& rStrm ); 1924 1925 bool importNlrAddrToken( BiffInputStream& rStrm, bool bRow ); 1926 bool importNlrRangeToken( BiffInputStream& rStrm ); 1927 bool importNlrSAddrToken( BiffInputStream& rStrm, bool bRow ); 1928 bool importNlrSRangeToken( BiffInputStream& rStrm ); 1929 bool importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nSkip ); 1930 1931 sal_Int32 readRefId( BiffInputStream& rStrm ); 1932 sal_uInt16 readNameId( BiffInputStream& rStrm ); 1933 LinkSheetRange readSheetRange5( BiffInputStream& rStrm ); 1934 LinkSheetRange readSheetRange8( BiffInputStream& rStrm ); 1935 1936 void swapStreamPosition( BiffInputStream& rStrm ); 1937 void skipMemAreaAddData( BiffInputStream& rStrm ); 1938 bool readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow ); 1939 bool readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm ); 1940 1941 // convert BIFF token and push API operand or operator -------------------- 1942 1943 bool pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); 1944 bool pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); 1945 bool pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow ); 1946 bool pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange ); 1947 bool pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow ); 1948 bool pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow ); 1949 bool pushBiffName( sal_uInt16 nNameId ); 1950 bool pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId ); 1951 bool pushBiffFunction( sal_uInt16 nFuncId ); 1952 bool pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ); 1953 1954 // ------------------------------------------------------------------------ 1955 private: 1956 typedef bool (BiffFormulaParserImpl::*ImportTokenFunc)( BiffInputStream& ); 1957 typedef bool (BiffFormulaParserImpl::*ImportRefTokenFunc)( BiffInputStream&, bool, bool ); 1958 1959 ImportTokenFunc mpImportStrToken; /// Pointer to tStr import function (string constant). 1960 ImportTokenFunc mpImportSpaceToken; /// Pointer to tAttrSpace import function (spaces/line breaks). 1961 ImportTokenFunc mpImportSheetToken; /// Pointer to tSheet import function (external reference). 1962 ImportTokenFunc mpImportEndSheetToken; /// Pointer to tEndSheet import function (end of external reference). 1963 ImportTokenFunc mpImportNlrToken; /// Pointer to tNlr import function (natural language reference). 1964 ImportRefTokenFunc mpImportRefToken; /// Pointer to tRef import function (2d cell reference). 1965 ImportRefTokenFunc mpImportAreaToken; /// Pointer to tArea import function (2d area reference). 1966 ImportRefTokenFunc mpImportRef3dToken; /// Pointer to tRef3d import function (3d cell reference). 1967 ImportRefTokenFunc mpImportArea3dToken; /// Pointer to tArea3d import function (3d area reference). 1968 ImportTokenFunc mpImportNameXToken; /// Pointer to tNameX import function (external name). 1969 ImportTokenFunc mpImportFuncToken; /// Pointer to tFunc import function (function with fixed parameter count). 1970 ImportTokenFunc mpImportFuncVarToken; /// Pointer to tFuncVar import function (function with variable parameter count). 1971 ImportTokenFunc mpImportFuncCEToken; /// Pointer to tFuncCE import function (command macro call). 1972 sal_Int64 mnAddDataPos; /// Current stream position for additional data (tArray, tMemArea, tNlr). 1973 sal_Int32 mnCurrRefId; /// Current ref-id from tSheet token (BIFF2-BIFF4 only). 1974 sal_uInt16 mnAttrDataSize; /// Size of one tAttr data element. 1975 sal_uInt16 mnArraySize; /// Size of tArray data. 1976 sal_uInt16 mnNameSize; /// Size of tName data. 1977 sal_uInt16 mnMemAreaSize; /// Size of tMemArea data. 1978 sal_uInt16 mnMemFuncSize; /// Size of tMemFunc data. 1979 sal_uInt16 mnRefIdSize; /// Size of unused data following a reference identifier. 1980 }; 1981 1982 // ---------------------------------------------------------------------------- 1983 1984 BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : 1985 FormulaParserImpl( rParent ), 1986 mnAddDataPos( 0 ), 1987 mnCurrRefId( 0 ) 1988 { 1989 switch( getBiff() ) 1990 { 1991 case BIFF2: 1992 mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; 1993 mpImportSpaceToken = &BiffFormulaParserImpl::importTokenNotAvailable; 1994 mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken2; 1995 mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken2; 1996 mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; 1997 mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; 1998 mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; 1999 mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; 2000 mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; 2001 mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2002 mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2; 2003 mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2; 2004 mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken; 2005 mnAttrDataSize = 1; 2006 mnArraySize = 6; 2007 mnNameSize = 5; 2008 mnMemAreaSize = 4; 2009 mnMemFuncSize = 1; 2010 mnRefIdSize = 1; 2011 break; 2012 case BIFF3: 2013 mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; 2014 mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken3; 2015 mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3; 2016 mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3; 2017 mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2018 mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; 2019 mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; 2020 mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; 2021 mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; 2022 mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2023 mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2; 2024 mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2; 2025 mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken; 2026 mnAttrDataSize = 2; 2027 mnArraySize = 7; 2028 mnNameSize = 8; 2029 mnMemAreaSize = 6; 2030 mnMemFuncSize = 2; 2031 mnRefIdSize = 2; 2032 break; 2033 case BIFF4: 2034 mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; 2035 mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4; 2036 mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3; 2037 mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3; 2038 mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2039 mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; 2040 mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; 2041 mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; 2042 mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; 2043 mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2044 mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; 2045 mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; 2046 mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2047 mnAttrDataSize = 2; 2048 mnArraySize = 7; 2049 mnNameSize = 8; 2050 mnMemAreaSize = 6; 2051 mnMemFuncSize = 2; 2052 mnRefIdSize = 2; 2053 break; 2054 case BIFF5: 2055 mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; 2056 mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4; 2057 mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2058 mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2059 mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2060 mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; 2061 mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; 2062 mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken5; 2063 mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken5; 2064 mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken; 2065 mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; 2066 mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; 2067 mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2068 mnAttrDataSize = 2; 2069 mnArraySize = 7; 2070 mnNameSize = 12; 2071 mnMemAreaSize = 6; 2072 mnMemFuncSize = 2; 2073 mnRefIdSize = 8; 2074 break; 2075 case BIFF8: 2076 mpImportStrToken = &BiffFormulaParserImpl::importStrToken8; 2077 mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4; 2078 mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2079 mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2080 mpImportNlrToken = &BiffFormulaParserImpl::importNlrToken; 2081 mpImportRefToken = &BiffFormulaParserImpl::importRefToken8; 2082 mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken8; 2083 mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken8; 2084 mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken8; 2085 mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken; 2086 mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; 2087 mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; 2088 mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; 2089 mnAttrDataSize = 2; 2090 mnArraySize = 7; 2091 mnNameSize = 2; 2092 mnMemAreaSize = 6; 2093 mnMemFuncSize = 2; 2094 mnRefIdSize = 0; 2095 break; 2096 case BIFF_UNKNOWN: break; 2097 } 2098 } 2099 2100 ApiTokenSequence BiffFormulaParserImpl::importBiffFormula( const CellAddress& rBaseAddr, 2101 FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) 2102 { 2103 initializeImport( rBaseAddr, eType ); 2104 mnCurrRefId = 0; 2105 2106 sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize ); 2107 sal_Int64 nEndPos = mnAddDataPos = rStrm.tell() + nFmlaSize; 2108 2109 bool bOk = true; 2110 while( bOk && !rStrm.isEof() && (rStrm.tell() < nEndPos) ) 2111 { 2112 sal_uInt8 nTokenId; 2113 rStrm >> nTokenId; 2114 sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK; 2115 sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; 2116 2117 bOk = !getFlag( nTokenId, BIFF_TOKFLAG_INVALID ); 2118 if( bOk ) 2119 { 2120 if( nTokenClass == BIFF_TOKCLASS_NONE ) 2121 { 2122 // base tokens 2123 switch( nBaseId ) 2124 { 2125 case BIFF_TOKID_EXP: bOk = importExpToken( rStrm ); break; 2126 case BIFF_TOKID_TBL: bOk = importTblToken( rStrm ); break; 2127 case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD ); break; 2128 case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB ); break; 2129 case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT ); break; 2130 case BIFF_TOKID_DIV: bOk = pushBinaryOperator( OPCODE_DIV ); break; 2131 case BIFF_TOKID_POWER: bOk = pushBinaryOperator( OPCODE_POWER ); break; 2132 case BIFF_TOKID_CONCAT: bOk = pushBinaryOperator( OPCODE_CONCAT ); break; 2133 case BIFF_TOKID_LT: bOk = pushBinaryOperator( OPCODE_LESS ); break; 2134 case BIFF_TOKID_LE: bOk = pushBinaryOperator( OPCODE_LESS_EQUAL ); break; 2135 case BIFF_TOKID_EQ: bOk = pushBinaryOperator( OPCODE_EQUAL ); break; 2136 case BIFF_TOKID_GE: bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL ); break; 2137 case BIFF_TOKID_GT: bOk = pushBinaryOperator( OPCODE_GREATER ); break; 2138 case BIFF_TOKID_NE: bOk = pushBinaryOperator( OPCODE_NOT_EQUAL ); break; 2139 case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( OPCODE_INTERSECT ); break; 2140 case BIFF_TOKID_LIST: bOk = pushBinaryOperator( OPCODE_LIST ); break; 2141 case BIFF_TOKID_RANGE: bOk = pushBinaryOperator( OPCODE_RANGE ); break; 2142 case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN ); break; 2143 case BIFF_TOKID_UMINUS: bOk = pushUnaryPreOperator( OPCODE_MINUS_SIGN ); break; 2144 case BIFF_TOKID_PERCENT: bOk = pushUnaryPostOperator( OPCODE_PERCENT ); break; 2145 case BIFF_TOKID_PAREN: bOk = pushParenthesesOperator(); break; 2146 case BIFF_TOKID_MISSARG: bOk = pushOperand( OPCODE_MISSING ); break; 2147 case BIFF_TOKID_STR: bOk = (this->*mpImportStrToken)( rStrm ); break; 2148 case BIFF_TOKID_NLR: bOk = (this->*mpImportNlrToken)( rStrm ); break; 2149 case BIFF_TOKID_ATTR: bOk = importAttrToken( rStrm ); break; 2150 case BIFF_TOKID_SHEET: bOk = (this->*mpImportSheetToken)( rStrm ); break; 2151 case BIFF_TOKID_ENDSHEET: bOk = (this->*mpImportEndSheetToken)( rStrm ); break; 2152 case BIFF_TOKID_ERR: bOk = pushBiffErrorOperand( rStrm.readuInt8() ); break; 2153 case BIFF_TOKID_BOOL: bOk = pushBiffBoolOperand( rStrm.readuInt8() ); break; 2154 case BIFF_TOKID_INT: bOk = pushValueOperand< double >( rStrm.readuInt16() ); break; 2155 case BIFF_TOKID_NUM: bOk = pushValueOperand( rStrm.readDouble() ); break; 2156 default: bOk = false; 2157 } 2158 } 2159 else 2160 { 2161 // classified tokens 2162 switch( nBaseId ) 2163 { 2164 case BIFF_TOKID_ARRAY: bOk = importArrayToken( rStrm ); break; 2165 case BIFF_TOKID_FUNC: bOk = (this->*mpImportFuncToken)( rStrm ); break; 2166 case BIFF_TOKID_FUNCVAR: bOk = (this->*mpImportFuncVarToken)( rStrm ); break; 2167 case BIFF_TOKID_NAME: bOk = importNameToken( rStrm ); break; 2168 case BIFF_TOKID_REF: bOk = (this->*mpImportRefToken)( rStrm, false, false ); break; 2169 case BIFF_TOKID_AREA: bOk = (this->*mpImportAreaToken)( rStrm, false, false ); break; 2170 case BIFF_TOKID_MEMAREA: bOk = importMemAreaToken( rStrm, true ); break; 2171 case BIFF_TOKID_MEMERR: bOk = importMemAreaToken( rStrm, false ); break; 2172 case BIFF_TOKID_MEMNOMEM: bOk = importMemAreaToken( rStrm, false ); break; 2173 case BIFF_TOKID_MEMFUNC: bOk = importMemFuncToken( rStrm ); break; 2174 case BIFF_TOKID_REFERR: bOk = (this->*mpImportRefToken)( rStrm, true, false ); break; 2175 case BIFF_TOKID_AREAERR: bOk = (this->*mpImportAreaToken)( rStrm, true, false ); break; 2176 case BIFF_TOKID_REFN: bOk = (this->*mpImportRefToken)( rStrm, false, true ); break; 2177 case BIFF_TOKID_AREAN: bOk = (this->*mpImportAreaToken)( rStrm, false, true ); break; 2178 case BIFF_TOKID_MEMAREAN: bOk = importMemFuncToken( rStrm ); break; 2179 case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; 2180 case BIFF_TOKID_FUNCCE: bOk = (this->*mpImportFuncCEToken)( rStrm ); break; 2181 case BIFF_TOKID_NAMEX: bOk = (this->*mpImportNameXToken)( rStrm ); break; 2182 case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, mbRelativeAsOffset ); break; 2183 case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, mbRelativeAsOffset ); break; 2184 case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, mbRelativeAsOffset ); break; 2185 case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, mbRelativeAsOffset ); break; 2186 default: bOk = false; 2187 } 2188 } 2189 } 2190 } 2191 2192 // build and finalize the token sequence 2193 ApiTokenSequence aFinalTokens; 2194 if( bOk && (rStrm.tell() == nEndPos) ) 2195 aFinalTokens = finalizeImport(); 2196 2197 // seek behind additional token data of tArray, tMemArea, tNlr tokens 2198 rStrm.seek( mnAddDataPos ); 2199 2200 // return the final token sequence 2201 return aFinalTokens; 2202 } 2203 2204 // import token contents and create API formula token ------------------------- 2205 2206 bool BiffFormulaParserImpl::importTokenNotAvailable( BiffInputStream& ) 2207 { 2208 // dummy function for pointer-to-member-function 2209 return false; 2210 } 2211 2212 bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool, bool ) 2213 { 2214 // dummy function for pointer-to-member-function 2215 return false; 2216 } 2217 2218 bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm ) 2219 { 2220 return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ) ); 2221 } 2222 2223 bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm ) 2224 { 2225 // read flags field for empty strings also 2226 return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), mbAllowNulChars ) ); 2227 } 2228 2229 bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm ) 2230 { 2231 bool bOk = true; 2232 sal_uInt8 nType; 2233 rStrm >> nType; 2234 switch( nType ) 2235 { 2236 case 0: // sometimes, tAttrSkip tokens miss the type flag 2237 case BIFF_TOK_ATTR_VOLATILE: 2238 case BIFF_TOK_ATTR_IF: 2239 case BIFF_TOK_ATTR_SKIP: 2240 case BIFF_TOK_ATTR_ASSIGN: 2241 rStrm.skip( mnAttrDataSize ); 2242 break; 2243 case BIFF_TOK_ATTR_CHOOSE: 2244 rStrm.skip( mnAttrDataSize * (1 + ((getBiff() == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16())) ); 2245 break; 2246 case BIFF_TOK_ATTR_SUM: 2247 rStrm.skip( mnAttrDataSize ); 2248 bOk = pushBiffFunction( BIFF_FUNC_SUM, 1 ); 2249 break; 2250 case BIFF_TOK_ATTR_SPACE: 2251 case BIFF_TOK_ATTR_SPACE_VOLATILE: 2252 bOk = (this->*mpImportSpaceToken)( rStrm ); 2253 break; 2254 default: 2255 bOk = false; 2256 } 2257 return bOk; 2258 } 2259 2260 bool BiffFormulaParserImpl::importSpaceToken3( BiffInputStream& rStrm ) 2261 { 2262 rStrm.skip( 2 ); 2263 return true; 2264 } 2265 2266 bool BiffFormulaParserImpl::importSpaceToken4( BiffInputStream& rStrm ) 2267 { 2268 sal_uInt8 nType, nCount; 2269 rStrm >> nType >> nCount; 2270 switch( nType ) 2271 { 2272 case BIFF_TOK_ATTR_SPACE_SP: 2273 appendLeadingSpaces( nCount, false ); 2274 break; 2275 case BIFF_TOK_ATTR_SPACE_BR: 2276 appendLeadingSpaces( nCount, true ); 2277 break; 2278 case BIFF_TOK_ATTR_SPACE_SP_OPEN: 2279 appendOpeningSpaces( nCount, false ); 2280 break; 2281 case BIFF_TOK_ATTR_SPACE_BR_OPEN: 2282 appendOpeningSpaces( nCount, true ); 2283 break; 2284 case BIFF_TOK_ATTR_SPACE_SP_CLOSE: 2285 appendClosingSpaces( nCount, false ); 2286 break; 2287 case BIFF_TOK_ATTR_SPACE_BR_CLOSE: 2288 appendClosingSpaces( nCount, true ); 2289 break; 2290 } 2291 return true; 2292 } 2293 2294 bool BiffFormulaParserImpl::importSheetToken2( BiffInputStream& rStrm ) 2295 { 2296 rStrm.skip( 4 ); 2297 mnCurrRefId = readRefId( rStrm ); 2298 return true; 2299 } 2300 2301 bool BiffFormulaParserImpl::importSheetToken3( BiffInputStream& rStrm ) 2302 { 2303 rStrm.skip( 6 ); 2304 mnCurrRefId = readRefId( rStrm ); 2305 return true; 2306 } 2307 2308 bool BiffFormulaParserImpl::importEndSheetToken2( BiffInputStream& rStrm ) 2309 { 2310 rStrm.skip( 3 ); 2311 mnCurrRefId = 0; 2312 return true; 2313 } 2314 2315 bool BiffFormulaParserImpl::importEndSheetToken3( BiffInputStream& rStrm ) 2316 { 2317 rStrm.skip( 4 ); 2318 mnCurrRefId = 0; 2319 return true; 2320 } 2321 2322 bool BiffFormulaParserImpl::importNlrToken( BiffInputStream& rStrm ) 2323 { 2324 bool bOk = true; 2325 sal_uInt8 nNlrType; 2326 rStrm >> nNlrType; 2327 switch( nNlrType ) 2328 { 2329 case BIFF_TOK_NLR_ERR: bOk = importNlrErrToken( rStrm, 4 ); break; 2330 case BIFF_TOK_NLR_ROWR: bOk = importNlrAddrToken( rStrm, true ); break; 2331 case BIFF_TOK_NLR_COLR: bOk = importNlrAddrToken( rStrm, false ); break; 2332 case BIFF_TOK_NLR_ROWV: bOk = importNlrAddrToken( rStrm, true ); break; 2333 case BIFF_TOK_NLR_COLV: bOk = importNlrAddrToken( rStrm, false ); break; 2334 case BIFF_TOK_NLR_RANGE: bOk = importNlrRangeToken( rStrm ); break; 2335 case BIFF_TOK_NLR_SRANGE: bOk = importNlrSRangeToken( rStrm ); break; 2336 case BIFF_TOK_NLR_SROWR: bOk = importNlrSAddrToken( rStrm, true ); break; 2337 case BIFF_TOK_NLR_SCOLR: bOk = importNlrSAddrToken( rStrm, false ); break; 2338 case BIFF_TOK_NLR_SROWV: bOk = importNlrSAddrToken( rStrm, true ); break; 2339 case BIFF_TOK_NLR_SCOLV: bOk = importNlrSAddrToken( rStrm, false ); break; 2340 case BIFF_TOK_NLR_RANGEERR: bOk = importNlrErrToken( rStrm, 13 ); break; 2341 case BIFF_TOK_NLR_SXNAME: bOk = importNlrErrToken( rStrm, 4 ); break; 2342 default: bOk = false; 2343 } 2344 return bOk; 2345 } 2346 2347 bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm ) 2348 { 2349 rStrm.skip( mnArraySize ); 2350 2351 // start token array with opening brace and leading spaces 2352 pushOperand( OPCODE_ARRAY_OPEN ); 2353 size_t nOpSize = popOperandSize(); 2354 size_t nOldArraySize = getFormulaSize(); 2355 bool bBiff8 = getBiff() == BIFF8; 2356 2357 // read array size 2358 swapStreamPosition( rStrm ); 2359 sal_uInt16 nCols = rStrm.readuInt8(); 2360 sal_uInt16 nRows = rStrm.readuInt16(); 2361 if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256; 2362 OSL_ENSURE( (nCols > 0) && (nRows > 0), "BiffFormulaParserImpl::importArrayToken - empty array" ); 2363 2364 // read array values and build token array 2365 for( sal_uInt16 nRow = 0; !rStrm.isEof() && (nRow < nRows); ++nRow ) 2366 { 2367 if( nRow > 0 ) 2368 appendRawToken( OPCODE_ARRAY_ROWSEP ); 2369 for( sal_uInt16 nCol = 0; !rStrm.isEof() && (nCol < nCols); ++nCol ) 2370 { 2371 if( nCol > 0 ) 2372 appendRawToken( OPCODE_ARRAY_COLSEP ); 2373 switch( rStrm.readuInt8() ) 2374 { 2375 case BIFF_DATATYPE_EMPTY: 2376 appendRawToken( OPCODE_PUSH ) <<= OUString(); 2377 rStrm.skip( 8 ); 2378 break; 2379 case BIFF_DATATYPE_DOUBLE: 2380 appendRawToken( OPCODE_PUSH ) <<= rStrm.readDouble(); 2381 break; 2382 case BIFF_DATATYPE_STRING: 2383 appendRawToken( OPCODE_PUSH ) <<= bBiff8 ? 2384 rStrm.readUniString( mbAllowNulChars ) : 2385 rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ); 2386 break; 2387 case BIFF_DATATYPE_BOOL: 2388 appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 ); 2389 rStrm.skip( 7 ); 2390 break; 2391 case BIFF_DATATYPE_ERROR: 2392 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() ); 2393 rStrm.skip( 7 ); 2394 break; 2395 default: 2396 OSL_ENSURE( false, "BiffFormulaParserImpl::importArrayToken - unknown data type" ); 2397 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA ); 2398 } 2399 } 2400 } 2401 swapStreamPosition( rStrm ); 2402 2403 // close token array and set resulting operand size 2404 appendRawToken( OPCODE_ARRAY_CLOSE ); 2405 pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize ); 2406 return true; 2407 } 2408 2409 bool BiffFormulaParserImpl::importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2410 { 2411 BinSingleRef2d aRef; 2412 aRef.readBiff2Data( rStrm, bRelativeAsOffset ); 2413 return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); 2414 } 2415 2416 bool BiffFormulaParserImpl::importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2417 { 2418 BinSingleRef2d aRef; 2419 aRef.readBiff8Data( rStrm, bRelativeAsOffset ); 2420 return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); 2421 } 2422 2423 bool BiffFormulaParserImpl::importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2424 { 2425 BinComplexRef2d aRef; 2426 aRef.readBiff2Data( rStrm, bRelativeAsOffset ); 2427 return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); 2428 } 2429 2430 bool BiffFormulaParserImpl::importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2431 { 2432 BinComplexRef2d aRef; 2433 aRef.readBiff8Data( rStrm, bRelativeAsOffset ); 2434 return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); 2435 } 2436 2437 bool BiffFormulaParserImpl::importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2438 { 2439 LinkSheetRange aSheetRange = readSheetRange5( rStrm ); 2440 BinSingleRef2d aRef; 2441 aRef.readBiff2Data( rStrm, bRelativeAsOffset ); 2442 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); 2443 } 2444 2445 bool BiffFormulaParserImpl::importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2446 { 2447 LinkSheetRange aSheetRange = readSheetRange8( rStrm ); 2448 BinSingleRef2d aRef; 2449 aRef.readBiff8Data( rStrm, bRelativeAsOffset ); 2450 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); 2451 } 2452 2453 bool BiffFormulaParserImpl::importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2454 { 2455 LinkSheetRange aSheetRange = readSheetRange5( rStrm ); 2456 BinComplexRef2d aRef; 2457 aRef.readBiff2Data( rStrm, bRelativeAsOffset ); 2458 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); 2459 } 2460 2461 bool BiffFormulaParserImpl::importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) 2462 { 2463 LinkSheetRange aSheetRange = readSheetRange8( rStrm ); 2464 BinComplexRef2d aRef; 2465 aRef.readBiff8Data( rStrm, bRelativeAsOffset ); 2466 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); 2467 } 2468 2469 bool BiffFormulaParserImpl::importMemAreaToken( BiffInputStream& rStrm, bool bAddData ) 2470 { 2471 rStrm.skip( mnMemAreaSize ); 2472 if( bAddData ) 2473 skipMemAreaAddData( rStrm ); 2474 return true; 2475 } 2476 2477 bool BiffFormulaParserImpl::importMemFuncToken( BiffInputStream& rStrm ) 2478 { 2479 rStrm.skip( mnMemFuncSize ); 2480 return true; 2481 } 2482 2483 bool BiffFormulaParserImpl::importNameToken( BiffInputStream& rStrm ) 2484 { 2485 sal_uInt16 nNameId = readNameId( rStrm ); 2486 return (mnCurrRefId > 0) ? pushBiffExtName( mnCurrRefId, nNameId ) : pushBiffName( nNameId ); 2487 } 2488 2489 bool BiffFormulaParserImpl::importNameXToken( BiffInputStream& rStrm ) 2490 { 2491 sal_Int32 nRefId = readRefId( rStrm ); 2492 sal_uInt16 nNameId = readNameId( rStrm ); 2493 return pushBiffExtName( nRefId, nNameId ); 2494 } 2495 2496 bool BiffFormulaParserImpl::importFuncToken2( BiffInputStream& rStrm ) 2497 { 2498 sal_uInt8 nFuncId; 2499 rStrm >> nFuncId; 2500 return pushBiffFunction( nFuncId ); 2501 } 2502 2503 bool BiffFormulaParserImpl::importFuncToken4( BiffInputStream& rStrm ) 2504 { 2505 sal_uInt16 nFuncId; 2506 rStrm >> nFuncId; 2507 return pushBiffFunction( nFuncId ); 2508 } 2509 2510 bool BiffFormulaParserImpl::importFuncVarToken2( BiffInputStream& rStrm ) 2511 { 2512 sal_uInt8 nParamCount, nFuncId; 2513 rStrm >> nParamCount >> nFuncId; 2514 return pushBiffFunction( nFuncId, nParamCount ); 2515 } 2516 2517 bool BiffFormulaParserImpl::importFuncVarToken4( BiffInputStream& rStrm ) 2518 { 2519 sal_uInt8 nParamCount; 2520 sal_uInt16 nFuncId; 2521 rStrm >> nParamCount >> nFuncId; 2522 return pushBiffFunction( nFuncId, nParamCount & BIFF_TOK_FUNCVAR_COUNTMASK ); 2523 } 2524 2525 bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream& rStrm ) 2526 { 2527 sal_uInt8 nParamCount, nFuncId; 2528 rStrm >> nParamCount >> nFuncId; 2529 sal_uInt16 nCmdId = nFuncId; 2530 setFlag( nCmdId, BIFF_TOK_FUNCVAR_CMD ); 2531 return pushBiffFunction( nCmdId, nParamCount ); 2532 } 2533 2534 bool BiffFormulaParserImpl::importExpToken( BiffInputStream& rStrm ) 2535 { 2536 BinAddress aBaseAddr; 2537 aBaseAddr.read( rStrm ); 2538 return pushSpecialTokenOperand( aBaseAddr, false ); 2539 } 2540 2541 bool BiffFormulaParserImpl::importTblToken( BiffInputStream& rStrm ) 2542 { 2543 BinAddress aBaseAddr; 2544 aBaseAddr.read( rStrm ); 2545 return pushSpecialTokenOperand( aBaseAddr, true ); 2546 } 2547 2548 bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream& rStrm, bool bRow ) 2549 { 2550 BiffNlr aNlr; 2551 aNlr.readBiff8Data( rStrm ); 2552 return pushBiffNlrAddr( aNlr, bRow ); 2553 } 2554 2555 bool BiffFormulaParserImpl::importNlrRangeToken( BiffInputStream& rStrm ) 2556 { 2557 BiffNlr aNlr; 2558 aNlr.readBiff8Data( rStrm ); 2559 rStrm.skip( 1 ); 2560 BinRange aRange; 2561 rStrm >> aRange; 2562 return pushBiffNlrRange( aNlr, aRange ); 2563 } 2564 2565 bool BiffFormulaParserImpl::importNlrSAddrToken( BiffInputStream& rStrm, bool bRow ) 2566 { 2567 rStrm.skip( 4 ); 2568 BiffNlr aNlr; 2569 return readNlrSAddrAddData( aNlr, rStrm, bRow ) ? pushBiffNlrSAddr( aNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF ); 2570 } 2571 2572 bool BiffFormulaParserImpl::importNlrSRangeToken( BiffInputStream& rStrm ) 2573 { 2574 rStrm.skip( 5 ); 2575 BinRange aRange; 2576 rStrm >> aRange; 2577 BiffNlr aNlr; 2578 bool bRow; 2579 return readNlrSRangeAddData( aNlr, bRow, rStrm ) ? pushBiffNlrSRange( aNlr, aRange, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF ); 2580 } 2581 2582 bool BiffFormulaParserImpl::importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nIgnore ) 2583 { 2584 rStrm.skip( nIgnore ); 2585 return pushBiffErrorOperand( BIFF_ERR_NAME ); 2586 } 2587 2588 sal_Int32 BiffFormulaParserImpl::readRefId( BiffInputStream& rStrm ) 2589 { 2590 sal_Int16 nRefId; 2591 rStrm >> nRefId; 2592 rStrm.skip( mnRefIdSize ); 2593 return nRefId; 2594 } 2595 2596 sal_uInt16 BiffFormulaParserImpl::readNameId( BiffInputStream& rStrm ) 2597 { 2598 sal_uInt16 nNameId; 2599 rStrm >> nNameId; 2600 rStrm.skip( mnNameSize ); 2601 return nNameId; 2602 } 2603 2604 LinkSheetRange BiffFormulaParserImpl::readSheetRange5( BiffInputStream& rStrm ) 2605 { 2606 sal_Int32 nRefId = readRefId( rStrm ); 2607 sal_Int16 nTab1, nTab2; 2608 rStrm >> nTab1 >> nTab2; 2609 return getExternalLinks().getSheetRange( nRefId, nTab1, nTab2 ); 2610 } 2611 2612 LinkSheetRange BiffFormulaParserImpl::readSheetRange8( BiffInputStream& rStrm ) 2613 { 2614 return getExternalLinks().getSheetRange( readRefId( rStrm ) ); 2615 } 2616 2617 void BiffFormulaParserImpl::swapStreamPosition( BiffInputStream& rStrm ) 2618 { 2619 sal_Int64 nRecPos = rStrm.tell(); 2620 rStrm.seek( mnAddDataPos ); 2621 mnAddDataPos = nRecPos; 2622 } 2623 2624 void BiffFormulaParserImpl::skipMemAreaAddData( BiffInputStream& rStrm ) 2625 { 2626 swapStreamPosition( rStrm ); 2627 sal_Int32 nCount = rStrm.readuInt16(); 2628 rStrm.skip( ((getBiff() == BIFF8) ? 8 : 6) * nCount ); 2629 swapStreamPosition( rStrm ); 2630 } 2631 2632 bool BiffFormulaParserImpl::readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow ) 2633 { 2634 bool bIsRow; 2635 return readNlrSRangeAddData( orNlr, bIsRow, rStrm ) && (bIsRow == bRow); 2636 } 2637 2638 bool BiffFormulaParserImpl::readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm ) 2639 { 2640 swapStreamPosition( rStrm ); 2641 // read number of cell addresses and relative flag 2642 sal_uInt32 nCount; 2643 rStrm >> nCount; 2644 bool bRel = getFlag( nCount, BIFF_TOK_NLR_ADDREL ); 2645 nCount &= BIFF_TOK_NLR_ADDMASK; 2646 sal_Int64 nEndPos = rStrm.tell() + 4 * nCount; 2647 // read list of cell addresses 2648 bool bValid = false; 2649 if( nCount >= 2 ) 2650 { 2651 // detect column/row orientation 2652 BinAddress aAddr1, aAddr2; 2653 rStrm >> aAddr1 >> aAddr2; 2654 orbIsRow = aAddr1.mnRow == aAddr2.mnRow; 2655 bValid = lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow ); 2656 // read and verify additional cell positions 2657 for( sal_uInt32 nIndex = 2; bValid && (nIndex < nCount); ++nIndex ) 2658 { 2659 aAddr1 = aAddr2; 2660 rStrm >> aAddr2; 2661 bValid = !rStrm.isEof() && lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow ); 2662 } 2663 // check that last imported position (aAddr2) is not at the end of the sheet 2664 bValid = bValid && (orbIsRow ? (aAddr2.mnCol < mnMaxApiCol) : (aAddr2.mnRow < mnMaxApiRow)); 2665 // fill the NLR struct with the last imported position 2666 if( bValid ) 2667 { 2668 orNlr.mnCol = aAddr2.mnCol; 2669 orNlr.mnRow = aAddr2.mnRow; 2670 orNlr.mbRel = bRel; 2671 } 2672 } 2673 // seek to end of additional data for this token 2674 rStrm.seek( nEndPos ); 2675 swapStreamPosition( rStrm ); 2676 2677 return bValid; 2678 } 2679 2680 // convert BIFF token and push API operand or operator ------------------------ 2681 2682 bool BiffFormulaParserImpl::pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) 2683 { 2684 return (mnCurrRefId > 0) ? 2685 pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) : 2686 pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset ); 2687 } 2688 2689 bool BiffFormulaParserImpl::pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) 2690 { 2691 return (mnCurrRefId > 0) ? 2692 pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) : 2693 pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset ); 2694 } 2695 2696 bool BiffFormulaParserImpl::pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow ) 2697 { 2698 BinSingleRef2d aRef; 2699 aRef.mnCol = rNlr.mnCol; 2700 aRef.mnRow = rNlr.mnRow; 2701 aRef.mbColRel = !bRow; 2702 aRef.mbRowRel = bRow; 2703 return pushNlrOperand( aRef ); 2704 } 2705 2706 bool BiffFormulaParserImpl::pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange ) 2707 { 2708 bool bRow = rNlr.mnRow == rRange.maFirst.mnRow; 2709 return lclIsValidNlrRange( rNlr, rRange, bRow ) ? 2710 pushBiffNlrAddr( rNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF ); 2711 } 2712 2713 bool BiffFormulaParserImpl::pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow ) 2714 { 2715 BinRange aRange; 2716 aRange.maFirst.mnCol = rNlr.mnCol + (bRow ? 1 : 0); 2717 aRange.maFirst.mnRow = rNlr.mnRow + (bRow ? 0 : 1); 2718 aRange.maLast.mnCol = bRow ? mnMaxApiCol : rNlr.mnCol; 2719 aRange.maLast.mnRow = bRow ? rNlr.mnRow : mnMaxApiRow; 2720 return pushBiffNlrSRange( rNlr, aRange, bRow ); 2721 } 2722 2723 bool BiffFormulaParserImpl::pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow ) 2724 { 2725 if( lclIsValidNlrRange( rNlr, rRange, bRow ) ) 2726 { 2727 BinComplexRef2d aRef; 2728 aRef.maRef1.mnCol = rRange.maFirst.mnCol; 2729 aRef.maRef1.mnRow = rRange.maFirst.mnRow; 2730 aRef.maRef2.mnCol = rRange.maLast.mnCol; 2731 aRef.maRef2.mnRow = rRange.maLast.mnRow; 2732 aRef.maRef1.mbColRel = aRef.maRef2.mbColRel = !bRow && rNlr.mbRel; 2733 aRef.maRef1.mbRowRel = aRef.maRef2.mbRowRel = bRow && rNlr.mbRel; 2734 return pushReferenceOperand( aRef, false, false ); 2735 } 2736 return pushBiffErrorOperand( BIFF_ERR_REF ); 2737 } 2738 2739 bool BiffFormulaParserImpl::pushBiffName( sal_uInt16 nNameId ) 2740 { 2741 // one-based in BIFF formulas 2742 return pushDefinedNameOperand( getDefinedNames().getByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ) ); 2743 } 2744 2745 bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId ) 2746 { 2747 if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() ) 2748 { 2749 if( pExtLink->getLinkType() == LINKTYPE_SELF ) 2750 return pushBiffName( nNameId ); 2751 // external name indexes are one-based in BIFF 2752 ExternalNameRef xExtName = pExtLink->getNameByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ); 2753 return pushExternalNameOperand( xExtName, *pExtLink ); 2754 } 2755 return pushBiffErrorOperand( BIFF_ERR_NAME ); 2756 } 2757 2758 bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId ) 2759 { 2760 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( nFuncId ) ) 2761 if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount ) 2762 return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount ); 2763 return pushFunctionOperator( OPCODE_NONAME, 0 ); 2764 } 2765 2766 bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ) 2767 { 2768 if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) ) 2769 nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; 2770 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( nFuncId ) ) 2771 return pushFunctionOperator( *pFuncInfo, nParamCount ); 2772 return pushFunctionOperator( OPCODE_NONAME, nParamCount ); 2773 } 2774 2775 // ============================================================================ 2776 2777 namespace { 2778 2779 /** Extracts the reference identifier and the remaining data from a formula in 2780 the format '[RefID]Remaining'. */ 2781 bool lclExtractRefId( sal_Int32& rnRefId, OUString& rRemainder, const OUString& rFormulaString ) 2782 { 2783 if( (rFormulaString.getLength() >= 4) && (rFormulaString[ 0 ] == '[') ) 2784 { 2785 sal_Int32 nBracketClose = rFormulaString.indexOf( ']', 1 ); 2786 if( nBracketClose >= 2 ) 2787 { 2788 rnRefId = rFormulaString.copy( 1, nBracketClose - 1 ).toInt32(); 2789 rRemainder = rFormulaString.copy( nBracketClose + 1 ); 2790 return rRemainder.getLength() > 0; 2791 } 2792 } 2793 return false; 2794 } 2795 2796 } 2797 2798 // ---------------------------------------------------------------------------- 2799 2800 FormulaParser::FormulaParser( const WorkbookHelper& rHelper ) : 2801 FormulaProcessorBase( rHelper ) 2802 { 2803 switch( getFilterType() ) 2804 { 2805 case FILTER_OOXML: mxImpl.reset( new OoxFormulaParserImpl( *this ) ); break; 2806 case FILTER_BIFF: mxImpl.reset( new BiffFormulaParserImpl( *this ) ); break; 2807 case FILTER_UNKNOWN: break; 2808 } 2809 } 2810 2811 FormulaParser::~FormulaParser() 2812 { 2813 } 2814 2815 ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, const OUString& rFormulaString ) const 2816 { 2817 return mxImpl->importOoxFormula( rBaseAddress, rFormulaString ); 2818 } 2819 2820 ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, SequenceInputStream& rStrm ) const 2821 { 2822 return mxImpl->importBiff12Formula( rBaseAddress, eType, rStrm ); 2823 } 2824 2825 ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const 2826 { 2827 return mxImpl->importBiffFormula( rBaseAddress, eType, rStrm, pnFmlaSize ); 2828 } 2829 2830 ApiTokenSequence FormulaParser::convertBoolToFormula( bool bValue ) const 2831 { 2832 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) ) 2833 { 2834 ApiTokenSequence aTokens( 3 ); 2835 aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode; 2836 aTokens[ 1 ].OpCode = OPCODE_OPEN; 2837 aTokens[ 2 ].OpCode = OPCODE_CLOSE; 2838 return aTokens; 2839 } 2840 return ApiTokenSequence(); 2841 } 2842 2843 ApiTokenSequence FormulaParser::convertErrorToFormula( sal_uInt8 nErrorCode ) const 2844 { 2845 ApiTokenSequence aTokens( 3 ); 2846 // HACK: enclose all error codes into an 1x1 matrix 2847 aTokens[ 0 ].OpCode = OPCODE_ARRAY_OPEN; 2848 aTokens[ 1 ].OpCode = OPCODE_PUSH; 2849 aTokens[ 1 ].Data <<= BiffHelper::calcDoubleFromError( nErrorCode ); 2850 aTokens[ 2 ].OpCode = OPCODE_ARRAY_CLOSE; 2851 return aTokens; 2852 } 2853 2854 ApiTokenSequence FormulaParser::convertNameToFormula( sal_Int32 nTokenIndex ) const 2855 { 2856 if( nTokenIndex < 0 ) 2857 return convertErrorToFormula( BIFF_ERR_REF ); 2858 2859 ApiTokenSequence aTokens( 1 ); 2860 aTokens[ 0 ].OpCode = OPCODE_NAME; 2861 aTokens[ 0 ].Data <<= nTokenIndex; 2862 return aTokens; 2863 } 2864 2865 ApiTokenSequence FormulaParser::convertNumberToHyperlink( const OUString& rUrl, double fValue ) const 2866 { 2867 OSL_ENSURE( rUrl.getLength() > 0, "FormulaParser::convertNumberToHyperlink - missing URL" ); 2868 if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( BIFF_FUNC_HYPERLINK ) ) 2869 { 2870 ApiTokenSequence aTokens( 6 ); 2871 aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode; 2872 aTokens[ 1 ].OpCode = OPCODE_OPEN; 2873 aTokens[ 2 ].OpCode = OPCODE_PUSH; 2874 aTokens[ 2 ].Data <<= rUrl; 2875 aTokens[ 3 ].OpCode = OPCODE_SEP; 2876 aTokens[ 4 ].OpCode = OPCODE_PUSH; 2877 aTokens[ 4 ].Data <<= fValue; 2878 aTokens[ 5 ].OpCode = OPCODE_CLOSE; 2879 return aTokens; 2880 } 2881 return ApiTokenSequence(); 2882 } 2883 2884 OUString FormulaParser::importOleTargetLink( const OUString& rFormulaString ) 2885 { 2886 sal_Int32 nRefId = -1; 2887 OUString aRemainder; 2888 if( lclExtractRefId( nRefId, aRemainder, rFormulaString ) && (aRemainder.getLength() >= 3) && 2889 (aRemainder[ 0 ] == '!') && (aRemainder[ 1 ] == '\'') && (aRemainder[ aRemainder.getLength() - 1 ] == '\'') ) 2890 return mxImpl->resolveOleTarget( nRefId, false ); 2891 return OUString(); 2892 } 2893 2894 OUString FormulaParser::importOleTargetLink( SequenceInputStream& rStrm ) 2895 { 2896 OUString aTargetLink; 2897 sal_Int32 nFmlaSize = rStrm.readInt32(); 2898 sal_Int64 nFmlaEndPos = rStrm.tell() + ::std::max< sal_Int32 >( nFmlaSize, 0 ); 2899 if( (nFmlaSize == 7) && (rStrm.getRemaining() >= 7) ) 2900 { 2901 sal_uInt8 nToken; 2902 sal_Int16 nRefId; 2903 sal_Int32 nNameId; 2904 rStrm >> nToken >> nRefId >> nNameId; 2905 if( nToken == (BIFF_TOKCLASS_VAL|BIFF_TOKID_NAMEX) ) 2906 aTargetLink = mxImpl->resolveOleTarget( nRefId, true ); 2907 } 2908 rStrm.seek( nFmlaEndPos ); 2909 return aTargetLink; 2910 } 2911 2912 OUString FormulaParser::importOleTargetLink( BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const 2913 { 2914 OUString aTargetLink; 2915 sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize ); 2916 rStrm.skip( nFmlaSize ); 2917 return aTargetLink; 2918 } 2919 2920 OUString FormulaParser::importMacroName( const OUString& rFormulaString ) 2921 { 2922 /* Valid macros are either sheet macros or VBA macros. OOXML and all BIFF 2923 documents store defined names for sheet macros, but OOXML documents do 2924 not store any defined name for VBA macros (while BIFF documents do). 2925 Sheet macros may be defined locally to a sheet, or globally to the 2926 document. As a result, all of the following macro specifiers are valid: 2927 2928 1) Macros located in the own document: 2929 [0]!MySheetMacro (global sheet macro 'MySheetMacro') 2930 Macro1!MyMacro (sheet-local sheet macro 'MyMacro') 2931 [0]!MyVBAProc (VBA macro 'MyVBAProc') 2932 [0]!Mod1.MyVBAProc (VBA macro 'MyVBAProc' from code module 'Mod1') 2933 2934 2) Macros from an external document: 2935 [2]!MySheetMacro (global external sheet macro 'MySheetMacro') 2936 [2]Macro1!MyMacro (sheet-local external sheet macro 'MyMacro') 2937 [2]!MyVBAProc (external VBA macro 'MyVBAProc') 2938 [2]!Mod1.MyVBAProc (external VBA macro from code module 'Mod1') 2939 2940 This implementation is only interested in VBA macros from the own 2941 document, ignoring the valid syntax 'Macro1!MyMacro' for sheet-local 2942 sheet macros. 2943 */ 2944 sal_Int32 nRefId = -1; 2945 OUString aRemainder; 2946 if( lclExtractRefId( nRefId, aRemainder, rFormulaString ) && (aRemainder.getLength() > 1) && (aRemainder[ 0 ] == '!') ) 2947 { 2948 /* In BIFF12 documents, the reference identifier is always the 2949 one-based index of the external link as it is in OOXML documents 2950 (it is not an index into the list of reference sheets as used in 2951 cell formulas). Index 0 is an implicit placeholder for the own 2952 document. In BIFF12 documents, the reference to the own document is 2953 stored explicitly, mostly at the top of the list, so index 1 may 2954 resolve to the own document too. 2955 Passing 'false' to getExternalLink() specifies to ignore the 2956 reference sheets list (if existing) and to access the list of 2957 external links directly. */ 2958 const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId, false ).get(); 2959 OSL_ENSURE( pExtLink, "FormulaParser::importMacroName - missing link" ); 2960 // do not accept macros in external documents (not supported) 2961 if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_SELF) ) 2962 { 2963 // ignore sheet macros (defined name for VBA macros may not exist, see above) 2964 OUString aMacroName = aRemainder.copy( 1 ); 2965 const DefinedName* pDefName = getDefinedNames().getByModelName( aMacroName ).get(); 2966 if( !pDefName || pDefName->isVBName() ) 2967 return aMacroName; 2968 } 2969 } 2970 return OUString(); 2971 } 2972 2973 // ============================================================================ 2974 2975 } // namespace xls 2976 } // namespace oox 2977