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