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