Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : : #include <sal/macros.h>
20 : : #include "formula/FormulaCompiler.hxx"
21 : : #include "formula/errorcodes.hxx"
22 : : #include "formula/token.hxx"
23 : : #include "formula/tokenarray.hxx"
24 : : #include "core_resource.hxx"
25 : : #include "core_resource.hrc"
26 : :
27 : : #include <svl/zforlist.hxx>
28 : : #include <tools/rc.hxx>
29 : : #include <tools/rcid.h>
30 : : #include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp>
31 : : #include <com/sun/star/sheet/FormulaMapGroup.hpp>
32 : : #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
33 : : #include <rtl/strbuf.hxx>
34 : : #include <stdio.h>
35 : :
36 : : // =============================================================================
37 : : namespace formula
38 : : {
39 : : // =============================================================================
40 : : using namespace ::com::sun::star;
41 : :
42 : : static const sal_Char* pInternal[ 1 ] = { "TTT" };
43 : :
44 : : // =============================================================================
45 : : namespace
46 : : {
47 : : // =============================================================================
48 : : class FormulaCompilerRecursionGuard
49 : : {
50 : : private:
51 : : short& rRecursion;
52 : : public:
53 : 95245 : FormulaCompilerRecursionGuard( short& rRec )
54 : 95245 : : rRecursion( rRec ) { ++rRecursion; }
55 : 95245 : ~FormulaCompilerRecursionGuard() { --rRecursion; }
56 : : };
57 : :
58 : 4170 : short lcl_GetRetFormat( OpCode eOpCode )
59 : : {
60 [ + - + - : 4170 : switch (eOpCode)
- - + ]
61 : : {
62 : : case ocEqual:
63 : : case ocNotEqual:
64 : : case ocLess:
65 : : case ocGreater:
66 : : case ocLessEqual:
67 : : case ocGreaterEqual:
68 : : case ocAnd:
69 : : case ocOr:
70 : : case ocXor:
71 : : case ocNot:
72 : : case ocTrue:
73 : : case ocFalse:
74 : : case ocIsEmpty:
75 : : case ocIsString:
76 : : case ocIsNonString:
77 : : case ocIsLogical:
78 : : case ocIsRef:
79 : : case ocIsValue:
80 : : case ocIsFormula:
81 : : case ocIsNA:
82 : : case ocIsErr:
83 : : case ocIsError:
84 : : case ocIsEven:
85 : : case ocIsOdd:
86 : : case ocExact:
87 : 366 : return NUMBERFORMAT_LOGICAL;
88 : : case ocGetActDate:
89 : : case ocGetDate:
90 : : case ocEasterSunday :
91 : 0 : return NUMBERFORMAT_DATE;
92 : : case ocGetActTime:
93 : 3 : return NUMBERFORMAT_DATETIME;
94 : : case ocGetTime:
95 : 0 : return NUMBERFORMAT_TIME;
96 : : case ocNPV:
97 : : case ocBW:
98 : : case ocDIA:
99 : : case ocGDA:
100 : : case ocGDA2:
101 : : case ocVBD:
102 : : case ocLIA:
103 : : case ocRMZ:
104 : : case ocZW:
105 : : case ocZinsZ:
106 : : case ocKapz:
107 : : case ocKumZinsZ:
108 : : case ocKumKapZ:
109 : 0 : return NUMBERFORMAT_CURRENCY;
110 : : case ocZins:
111 : : case ocIRR:
112 : : case ocMIRR:
113 : : case ocZGZ:
114 : : case ocEffektiv:
115 : : case ocNominal:
116 : : case ocPercentSign:
117 : 0 : return NUMBERFORMAT_PERCENT;
118 : : default:
119 : 4170 : return NUMBERFORMAT_NUMBER;
120 : : }
121 : : }
122 : :
123 : 7704 : inline void lclPushOpCodeMapEntry( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec, const String* pTable, sal_uInt16 nOpCode )
124 : : {
125 : 7704 : sheet::FormulaOpCodeMapEntry aEntry;
126 : 7704 : aEntry.Token.OpCode = nOpCode;
127 [ + - ]: 7704 : aEntry.Name = pTable[nOpCode];
128 [ + - ]: 7704 : rVec.push_back( aEntry);
129 : 7704 : }
130 : :
131 : 48 : void lclPushOpCodeMapEntries( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec, const String* pTable, sal_uInt16 nOpCodeBeg, sal_uInt16 nOpCodeEnd )
132 : : {
133 [ + + ]: 2208 : for (sal_uInt16 nOpCode = nOpCodeBeg; nOpCode < nOpCodeEnd; ++nOpCode)
134 : 2160 : lclPushOpCodeMapEntry( rVec, pTable, nOpCode );
135 : 48 : }
136 : :
137 : 72 : void lclPushOpCodeMapEntries( ::std::vector< sheet::FormulaOpCodeMapEntry >& rVec, const String* pTable, const sal_uInt16* pnOpCodes, size_t nCount )
138 : : {
139 [ + + ]: 384 : for (const sal_uInt16* pnEnd = pnOpCodes + nCount; pnOpCodes < pnEnd; ++pnOpCodes)
140 : 312 : lclPushOpCodeMapEntry( rVec, pTable, *pnOpCodes );
141 : 72 : }
142 : :
143 : 444 : class OpCodeList : public Resource // temp object for resource
144 : : {
145 : : public:
146 : :
147 : : OpCodeList( sal_uInt16, FormulaCompiler::NonConstOpCodeMapPtr );
148 : :
149 : : private:
150 : : bool getOpCodeString( String& rStr, sal_uInt16 nOp );
151 : : void putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp );
152 : :
153 : : private:
154 : : enum SeparatorType
155 : : {
156 : : SEMICOLON_BASE,
157 : : COMMA_BASE
158 : : };
159 : : SeparatorType meSepType;
160 : : };
161 : :
162 : 444 : OpCodeList::OpCodeList( sal_uInt16 nRID, FormulaCompiler::NonConstOpCodeMapPtr xMap ) :
163 : 444 : Resource( ResId(nRID,*ResourceManager::getResManager()) )
164 [ + - ]: 444 : ,meSepType(SEMICOLON_BASE)
165 : : {
166 [ + + ]: 179376 : for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
167 : : {
168 [ + - ]: 178932 : String aOpStr;
169 [ + - ][ + + ]: 178932 : if ( getOpCodeString(aOpStr, i) )
170 [ + - ]: 1332 : xMap->putOpCode(aOpStr, OpCode(i));
171 : : else
172 [ + - ][ + - ]: 177600 : putDefaultOpCode(xMap, i);
[ + - ]
173 [ + - ]: 178932 : }
174 : :
175 [ + - ]: 444 : FreeResource();
176 : 444 : }
177 : :
178 : 178932 : bool OpCodeList::getOpCodeString( String& rStr, sal_uInt16 nOp )
179 : : {
180 [ + + + + ]: 178932 : switch (nOp)
181 : : {
182 : : case SC_OPCODE_SEP:
183 : : {
184 [ - + ]: 444 : if (meSepType == COMMA_BASE)
185 : : {
186 [ # # ]: 0 : rStr = rtl::OUString(",");
187 : 0 : return true;
188 : : }
189 [ + - ]: 444 : else if (meSepType == SEMICOLON_BASE)
190 : : {
191 [ + - ]: 444 : rStr = rtl::OUString(";");
192 : 444 : return true;
193 : : }
194 : : }
195 : 0 : break;
196 : : case SC_OPCODE_ARRAY_COL_SEP:
197 : : {
198 [ - + ]: 444 : if (meSepType == COMMA_BASE)
199 : : {
200 [ # # ]: 0 : rStr = rtl::OUString(",");
201 : 0 : return true;
202 : : }
203 [ + - ]: 444 : else if (meSepType == SEMICOLON_BASE)
204 : : {
205 [ + - ]: 444 : rStr = rtl::OUString(";");
206 : 444 : return true;
207 : : }
208 : : }
209 : 0 : break;
210 : : case SC_OPCODE_ARRAY_ROW_SEP:
211 : : {
212 [ - + ]: 444 : if (meSepType == COMMA_BASE)
213 : : {
214 [ # # ]: 0 : rStr = rtl::OUString(";");
215 : 0 : return true;
216 : : }
217 [ + - ]: 444 : else if (meSepType == SEMICOLON_BASE)
218 : : {
219 [ + - ]: 444 : rStr = rtl::OUString("|");
220 : 444 : return true;
221 : : }
222 : : }
223 : 0 : break;
224 : : }
225 : :
226 : 178932 : return false;
227 : : }
228 : :
229 : 177600 : void OpCodeList::putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp )
230 : : {
231 [ + - ]: 177600 : ResId aRes(nOp,*ResourceManager::getResManager());
232 : 177600 : aRes.SetRT(RSC_STRING);
233 [ + + ][ + - ]: 177600 : if (IsAvailableRes(aRes))
234 [ + - ][ + - ]: 143397 : xMap->putOpCode(aRes, OpCode(nOp));
[ + - ]
235 : 177600 : }
236 : : // -----------------------------------------------------------------------------
237 : : // static
238 : 9 : const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr,sal_Unicode c )
239 : : {
240 [ - + ]: 9 : if ( !pStr )
241 : 0 : return NULL;
242 [ + + ]: 36 : while ( *pStr )
243 : : {
244 [ - + ]: 27 : if ( *pStr == c )
245 : 0 : return pStr;
246 : 27 : pStr++;
247 : : }
248 : 9 : return NULL;
249 : : }
250 : : // =============================================================================
251 : : } // empty
252 : : // =============================================================================
253 : :
254 : 5393 : void FormulaCompiler::OpCodeMap::putExternal( const String & rSymbol, const String & rAddIn )
255 : : {
256 [ + - ]: 5393 : bool bOk = mpExternalHashMap->insert( ExternalHashMap::value_type( rSymbol, rAddIn)).second;
257 [ + - ]: 5393 : if (bOk)
258 [ + - ]: 5393 : bOk = mpReverseExternalHashMap->insert( ExternalHashMap::value_type( rAddIn, rSymbol)).second;
259 : : DBG_ASSERT( bOk, "OpCodeMap::putExternal: symbol not inserted");
260 : 5393 : }
261 : :
262 : 1308 : void FormulaCompiler::OpCodeMap::putExternalSoftly( const String & rSymbol, const String & rAddIn )
263 : : {
264 [ + - ]: 1308 : bool bOk = mpReverseExternalHashMap->insert( ExternalHashMap::value_type( rAddIn, rSymbol)).second;
265 [ - + ]: 1308 : if (bOk)
266 [ # # ]: 0 : mpExternalHashMap->insert( ExternalHashMap::value_type( rSymbol, rAddIn));
267 : 1308 : }
268 : 0 : uno::Sequence< sheet::FormulaToken > FormulaCompiler::OpCodeMap::createSequenceOfFormulaTokens(const FormulaCompiler& _rCompiler,const uno::Sequence< ::rtl::OUString >& rNames ) const
269 : : {
270 : 0 : const sal_Int32 nLen = rNames.getLength();
271 : 0 : uno::Sequence< sheet::FormulaToken > aTokens( nLen);
272 [ # # ]: 0 : sheet::FormulaToken* pToken = aTokens.getArray();
273 : 0 : ::rtl::OUString const * pName = rNames.getConstArray();
274 : 0 : ::rtl::OUString const * const pStop = pName + nLen;
275 [ # # ]: 0 : for ( ; pName < pStop; ++pName, ++pToken)
276 : : {
277 [ # # ][ # # ]: 0 : OpCodeHashMap::const_iterator iLook( mpHashMap->find( *pName));
[ # # ]
278 [ # # ][ # # ]: 0 : if (iLook != mpHashMap->end())
279 [ # # ]: 0 : pToken->OpCode = (*iLook).second;
280 : : else
281 : : {
282 : 0 : ::rtl::OUString aIntName;
283 [ # # ][ # # ]: 0 : if (hasExternals())
284 : : {
285 [ # # ][ # # ]: 0 : ExternalHashMap::const_iterator iExt( mpExternalHashMap->find( *pName));
[ # # ]
286 [ # # ][ # # ]: 0 : if (iExt != mpExternalHashMap->end())
287 [ # # ][ # # ]: 0 : aIntName = (*iExt).second;
288 : : // Check for existence not needed here, only name-mapping is of
289 : : // interest.
290 : : }
291 [ # # ]: 0 : if (aIntName.isEmpty())
292 [ # # ][ # # ]: 0 : aIntName = _rCompiler.FindAddInFunction(*pName, !isEnglish()); // bLocalFirst=false for english
[ # # ][ # # ]
[ # # ]
293 [ # # ]: 0 : if (aIntName.isEmpty())
294 [ # # ]: 0 : pToken->OpCode = getOpCodeUnknown();
295 : : else
296 : : {
297 : 0 : pToken->OpCode = ocExternal;
298 [ # # ]: 0 : pToken->Data <<= aIntName;
299 : 0 : }
300 : : }
301 : : }
302 : 0 : return aTokens;
303 : : }
304 : 144 : uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::createSequenceOfAvailableMappings(const FormulaCompiler& _rCompiler,const sal_Int32 nGroups ) const
305 : : {
306 : : using namespace sheet;
307 : :
308 : : // Unfortunately uno::Sequence can't grow without cumbersome reallocs. As
309 : : // we don't know in advance how many elements it will have we use a
310 : : // temporary vector to add elements and then copy to Sequence :-(
311 [ + - ]: 144 : ::std::vector< FormulaOpCodeMapEntry > aVec;
312 : :
313 [ + + ]: 144 : if (nGroups == FormulaMapGroup::SPECIAL)
314 : : {
315 : : // Use specific order, keep in sync with
316 : : // offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
317 : : static const struct
318 : : {
319 : : sal_Int32 nOff;
320 : : OpCode eOp;
321 : : } aMap[] = {
322 : : { FormulaMapGroupSpecialOffset::PUSH , ocPush } ,
323 : : { FormulaMapGroupSpecialOffset::CALL , ocCall } ,
324 : : { FormulaMapGroupSpecialOffset::STOP , ocStop } ,
325 : : { FormulaMapGroupSpecialOffset::EXTERNAL , ocExternal } ,
326 : : { FormulaMapGroupSpecialOffset::NAME , ocName } ,
327 : : { FormulaMapGroupSpecialOffset::NO_NAME , ocNoName } ,
328 : : { FormulaMapGroupSpecialOffset::MISSING , ocMissing } ,
329 : : { FormulaMapGroupSpecialOffset::BAD , ocBad } ,
330 : : { FormulaMapGroupSpecialOffset::SPACES , ocSpaces } ,
331 : : { FormulaMapGroupSpecialOffset::MAT_REF , ocMatRef } ,
332 : : { FormulaMapGroupSpecialOffset::DB_AREA , ocDBArea } ,
333 : : { FormulaMapGroupSpecialOffset::MACRO , ocMacro } ,
334 : : { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName }
335 : : };
336 : 24 : const size_t nCount = sizeof(aMap)/sizeof(aMap[0]);
337 : : // Preallocate vector elements.
338 [ + - ]: 24 : if (aVec.size() < nCount)
339 : : {
340 : 24 : FormulaOpCodeMapEntry aEntry;
341 [ + - ]: 24 : aEntry.Token.OpCode = getOpCodeUnknown();
342 [ + - ]: 24 : aVec.resize( nCount, aEntry);
343 : : } // if (aVec.size() < nCount)
344 : :
345 : 24 : FormulaOpCodeMapEntry aEntry;
346 [ + + ]: 336 : for (size_t i=0; i < nCount; ++i)
347 : : {
348 : 312 : size_t nIndex = static_cast< size_t >( aMap[i].nOff );
349 [ - + ]: 312 : if (aVec.size() <= nIndex)
350 : : {
351 : : // The offsets really should be aligned with the size, so if
352 : : // the vector was preallocated above this code to resize it is
353 : : // just a measure in case the table isn't in sync with the API,
354 : : // usually it isn't executed.
355 [ # # ]: 0 : aEntry.Token.OpCode = getOpCodeUnknown();
356 [ # # ]: 0 : aVec.resize( nIndex + 1, aEntry );
357 : : }
358 : 312 : aEntry.Token.OpCode = aMap[i].eOp;
359 : 312 : aVec[nIndex] = aEntry;
360 : 24 : }
361 : : }
362 : : else
363 : : {
364 : : /* FIXME: Once we support error constants in formulas we'll need a map
365 : : * group for that, e.g. FormulaMapGroup::ERROR_CONSTANTS, and fill
366 : : * SC_OPCODE_START_ERRORS to SC_OPCODE_STOP_ERRORS. */
367 : :
368 : : // Anything else but SPECIAL.
369 [ + + ]: 120 : if ((nGroups & FormulaMapGroup::SEPARATORS) != 0)
370 : : {
371 : : static const sal_uInt16 aOpCodes[] = {
372 : : SC_OPCODE_OPEN,
373 : : SC_OPCODE_CLOSE,
374 : : SC_OPCODE_SEP,
375 : : };
376 [ + - ]: 24 : lclPushOpCodeMapEntries( aVec, mpTable, aOpCodes, sizeof(aOpCodes)/sizeof(aOpCodes[0]) );
377 : : }
378 [ + + ]: 120 : if ((nGroups & FormulaMapGroup::ARRAY_SEPARATORS) != 0)
379 : : {
380 : : static const sal_uInt16 aOpCodes[] = {
381 : : SC_OPCODE_ARRAY_OPEN,
382 : : SC_OPCODE_ARRAY_CLOSE,
383 : : SC_OPCODE_ARRAY_ROW_SEP,
384 : : SC_OPCODE_ARRAY_COL_SEP
385 : : };
386 [ + - ]: 24 : lclPushOpCodeMapEntries( aVec, mpTable, aOpCodes, sizeof(aOpCodes)/sizeof(aOpCodes[0]) );
387 : : }
388 [ + + ]: 120 : if ((nGroups & FormulaMapGroup::UNARY_OPERATORS) != 0)
389 : : {
390 : : // Due to the nature of the percent operator following its operand
391 : : // it isn't sorted into unary operators for compiler interna.
392 [ + - ]: 24 : lclPushOpCodeMapEntry( aVec, mpTable, ocPercentSign );
393 : : // "+" can be used as unary operator too, push only if binary group is not set
394 [ + - ]: 24 : if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) == 0)
395 [ + - ]: 24 : lclPushOpCodeMapEntry( aVec, mpTable, ocAdd );
396 : : // regular unary operators
397 [ + + ][ + - ]: 96 : for (sal_uInt16 nOp = SC_OPCODE_START_UN_OP; nOp < SC_OPCODE_STOP_UN_OP && nOp < mnSymbols; ++nOp)
[ + + ]
398 : : {
399 [ + + ]: 72 : switch (nOp)
400 : : {
401 : : // NOT and NEG in fact are functions but for legacy reasons
402 : : // are sorted into unary operators for compiler interna.
403 : : case SC_OPCODE_NOT :
404 : : case SC_OPCODE_NEG :
405 : 48 : break; // nothing,
406 : : default:
407 [ + - ]: 24 : lclPushOpCodeMapEntry( aVec, mpTable, nOp );
408 : : }
409 : : }
410 : : }
411 [ + + ]: 120 : if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) != 0)
412 : : {
413 [ + + ][ + - ]: 432 : for (sal_uInt16 nOp = SC_OPCODE_START_BIN_OP; nOp < SC_OPCODE_STOP_BIN_OP && nOp < mnSymbols; ++nOp)
[ + + ]
414 : : {
415 [ + + ]: 408 : switch (nOp)
416 : : {
417 : : // AND and OR in fact are functions but for legacy reasons
418 : : // are sorted into binary operators for compiler interna.
419 : : case SC_OPCODE_AND :
420 : : case SC_OPCODE_OR :
421 : 48 : break; // nothing,
422 : : default:
423 [ + - ]: 360 : lclPushOpCodeMapEntry( aVec, mpTable, nOp );
424 : : }
425 : : }
426 : : }
427 [ + + ]: 120 : if ((nGroups & FormulaMapGroup::FUNCTIONS) != 0)
428 : : {
429 : : // Function names are not consecutive, skip the gaps between
430 : : // functions with no parameter, functions with 1 parameter
431 [ + - ][ + - ]: 24 : lclPushOpCodeMapEntries( aVec, mpTable, SC_OPCODE_START_NO_PAR, ::std::min< sal_uInt16 >( SC_OPCODE_STOP_NO_PAR, mnSymbols ) );
432 [ + - ][ + - ]: 24 : lclPushOpCodeMapEntries( aVec, mpTable, SC_OPCODE_START_1_PAR, ::std::min< sal_uInt16 >( SC_OPCODE_STOP_1_PAR, mnSymbols ) );
433 : : // Additional functions not within range of functions.
434 : : static const sal_uInt16 aOpCodes[] = {
435 : : SC_OPCODE_IF,
436 : : SC_OPCODE_CHOSE,
437 : : SC_OPCODE_AND,
438 : : SC_OPCODE_OR,
439 : : SC_OPCODE_NOT,
440 : : SC_OPCODE_NEG
441 : : };
442 [ + - ]: 24 : lclPushOpCodeMapEntries( aVec, mpTable, aOpCodes, sizeof(aOpCodes)/sizeof(aOpCodes[0]) );
443 : : // functions with 2 or more parameters.
444 [ + + ][ + - ]: 4848 : for (sal_uInt16 nOp = SC_OPCODE_START_2_PAR; nOp < SC_OPCODE_STOP_2_PAR && nOp < mnSymbols; ++nOp)
[ + + ]
445 : : {
446 [ + + ]: 4824 : switch (nOp)
447 : : {
448 : : // NO_NAME is in SPECIAL.
449 : : case SC_OPCODE_NO_NAME :
450 : 24 : break; // nothing,
451 : : default:
452 [ + - ]: 4800 : lclPushOpCodeMapEntry( aVec, mpTable, nOp );
453 : : }
454 : : }
455 : : // If AddIn functions are present in this mapping, use them, and only those.
456 [ + - ][ + - ]: 24 : if (hasExternals())
457 : : {
458 [ + - ][ + - ]: 2640 : for (ExternalHashMap::const_iterator it( mpExternalHashMap->begin());it != mpExternalHashMap->end(); ++it)
[ + + ]
459 : : {
460 : 2616 : FormulaOpCodeMapEntry aEntry;
461 [ + - ][ + - ]: 2616 : aEntry.Name = (*it).first;
462 [ + - ][ + - ]: 2616 : aEntry.Token.Data <<= ::rtl::OUString( (*it).second);
[ + - ]
463 : 2616 : aEntry.Token.OpCode = ocExternal;
464 [ + - ]: 2616 : aVec.push_back( aEntry);
465 : 2616 : }
466 : : }
467 : : else
468 : : {
469 [ # # ]: 0 : _rCompiler.fillAddInToken(aVec,isEnglish());
470 : : }
471 : : }
472 : : }
473 [ - + ]: 144 : const FormulaOpCodeMapEntry* pRet = aVec.empty() ? 0 : &aVec[0];
474 [ + - ]: 144 : return uno::Sequence< FormulaOpCodeMapEntry >(pRet, aVec.size());
475 : : }
476 : : //-----------------------------------------------------------------------------
477 : :
478 : 152493 : void FormulaCompiler::OpCodeMap::putOpCode( const String & rStr, const OpCode eOp )
479 : : {
480 : : DBG_ASSERT( 0 < eOp && sal_uInt16(eOp) < mnSymbols, "OpCodeMap::putOpCode: OpCode out of range");
481 [ + - ][ + - ]: 152493 : if (0 < eOp && sal_uInt16(eOp) < mnSymbols)
482 : : {
483 : : DBG_ASSERT( (mpTable[eOp].Len() == 0) || (mpTable[eOp] == rStr) ||
484 : : (eOp == ocCurrency) || (eOp == ocSep) || (eOp == ocArrayColSep) ||
485 : : (eOp == ocArrayRowSep),
486 : : rtl::OStringBuffer(
487 : : RTL_CONSTASCII_STRINGPARAM("OpCodeMap::putOpCode: reusing OpCode ")).
488 : : append(sal_Int32(eOp)).append(RTL_CONSTASCII_STRINGPARAM(" (")).
489 : : append(rtl::OUStringToOString(rStr, RTL_TEXTENCODING_ASCII_US)).
490 : : append(')').getStr());
491 : 152493 : mpTable[eOp] = rStr;
492 [ + - ]: 152493 : mpHashMap->insert( OpCodeHashMap::value_type( rStr, eOp));
493 : : }
494 : 152493 : }
495 : : // -----------------------------------------------------------------------------
496 : : // class FormulaCompiler
497 : : // -----------------------------------------------------------------------------
498 : : DBG_NAME(FormulaCompiler)
499 : 5336 : FormulaCompiler::FormulaCompiler(FormulaTokenArray& _rArr)
500 : : :
501 : : pArr( &_rArr ),
502 : : pExternalRef(NULL),
503 : : pStack( NULL ),
504 : : nRecursion(0),
505 : : nNumFmt( NUMBERFORMAT_UNDEFINED ),
506 : : meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ),
507 : : bAutoCorrect( false ),
508 : : bCorrected( false ),
509 : : bCompileForFAP( false ),
510 [ + - ][ + - ]: 5336 : bIgnoreErrors( false )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
511 : :
512 : : {
513 : : DBG_CTOR(FormulaCompiler,NULL);
514 : 5336 : }
515 : 28025 : FormulaCompiler::FormulaCompiler()
516 : : :
517 : : pArr( NULL ),
518 : : pExternalRef(NULL),
519 : : pStack( NULL ),
520 : : nRecursion(0),
521 : : nNumFmt( NUMBERFORMAT_UNDEFINED ),
522 : : meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ),
523 : : bAutoCorrect( false ),
524 : : bCorrected( false ),
525 : : bCompileForFAP( false ),
526 [ + - ][ + - ]: 28025 : bIgnoreErrors( false )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
527 : :
528 : : {
529 : : DBG_CTOR(FormulaCompiler,NULL);
530 : 28025 : }
531 [ + - ][ + - ]: 33361 : FormulaCompiler::~FormulaCompiler()
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
532 : : {
533 : : DBG_DTOR(FormulaCompiler,NULL);
534 [ - + ]: 33361 : }
535 : :
536 : 33505 : FormulaCompiler::OpCodeMapPtr FormulaCompiler::GetOpCodeMap( const sal_Int32 nLanguage ) const
537 : : {
538 : 33505 : FormulaCompiler::OpCodeMapPtr xMap;
539 : : using namespace sheet;
540 [ + + + + : 33505 : switch (nLanguage)
- - ]
541 : : {
542 : : case FormulaLanguage::ODFF :
543 [ + + ]: 2775 : if (!mxSymbolsODFF)
544 [ + - ]: 2655 : InitSymbolsODFF();
545 [ + - ]: 2775 : xMap = mxSymbolsODFF;
546 : 2775 : break;
547 : : case FormulaLanguage::ODF_11 :
548 [ + - ]: 266 : if (!mxSymbolsPODF)
549 [ + - ]: 266 : InitSymbolsPODF();
550 [ + - ]: 266 : xMap = mxSymbolsPODF;
551 : 266 : break;
552 : : case FormulaLanguage::ENGLISH :
553 [ + - ]: 69 : if (!mxSymbolsEnglish)
554 [ + - ]: 69 : InitSymbolsEnglish();
555 [ + - ]: 69 : xMap = mxSymbolsEnglish;
556 : 69 : break;
557 : : case FormulaLanguage::NATIVE :
558 [ + - ]: 30395 : if (!mxSymbolsNative)
559 [ + - ]: 30395 : InitSymbolsNative();
560 [ + - ]: 30395 : xMap = mxSymbolsNative;
561 : 30395 : break;
562 : : case FormulaLanguage::XL_ENGLISH:
563 [ # # ]: 0 : if (!mxSymbolsEnglishXL)
564 [ # # ]: 0 : InitSymbolsEnglishXL();
565 [ # # ]: 0 : xMap = mxSymbolsEnglishXL;
566 : 0 : break;
567 : : default:
568 : : ; // nothing, NULL map returned
569 : : }
570 : 33505 : return xMap;
571 : : }
572 : : // -----------------------------------------------------------------------------
573 : :
574 : 0 : String FormulaCompiler::FindAddInFunction( const String& /*rUpperName*/, bool /*bLocalFirst*/ ) const
575 : : {
576 : 0 : return String();
577 : : }
578 : : // -----------------------------------------------------------------------------
579 : 24 : FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap(
580 : : const uno::Sequence<
581 : : const sheet::FormulaOpCodeMapEntry > & rMapping,
582 : : bool bEnglish )
583 : : {
584 : : using sheet::FormulaOpCodeMapEntry;
585 : : // Filter / API maps are never Core
586 [ + - ][ + - ]: 24 : NonConstOpCodeMapPtr xMap( new OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1,false, FormulaGrammar::mergeToGrammar( FormulaGrammar::setEnglishBit(FormulaGrammar::GRAM_EXTERNAL, bEnglish),FormulaGrammar::CONV_UNSPECIFIED)));
[ + - ]
587 : 24 : FormulaOpCodeMapEntry const * pArr2 = rMapping.getConstArray();
588 : 24 : FormulaOpCodeMapEntry const * const pStop = pArr2 + rMapping.getLength();
589 [ + + ]: 8784 : for ( ; pArr2 < pStop; ++pArr2)
590 : : {
591 : 8760 : OpCode eOp = OpCode(pArr2->Token.OpCode);
592 [ + + ]: 8760 : if (eOp != ocExternal)
593 [ + - ][ + - ]: 6528 : xMap->putOpCode( pArr2->Name, eOp);
[ + - ]
594 : : else
595 : : {
596 : 2232 : ::rtl::OUString aExternalName;
597 [ + - ]: 2232 : if (pArr2->Token.Data >>= aExternalName)
598 [ + - ][ + - ]: 2232 : xMap->putExternal( pArr2->Name, aExternalName);
[ + - ][ + - ]
[ + - ]
599 : : else
600 : : {
601 : : SAL_WARN( "formula.core", "FormulaCompiler::CreateOpCodeMap: no Token.Data external name");
602 : 2232 : }
603 : : }
604 : : }
605 [ + - ][ + - ]: 24 : return xMap;
606 : : }
607 : :
608 : : // -----------------------------------------------------------------------------
609 : 63121 : void lcl_fillNativeSymbols(FormulaCompiler::NonConstOpCodeMapPtr& _xMap,bool _destroy = false)
610 : : {
611 [ + + ][ + - ]: 63121 : static FormulaCompiler::NonConstOpCodeMapPtr s_SymbolMap;
[ + - ][ # # ]
612 [ + + ]: 63121 : if ( _destroy )
613 : : {
614 : 412 : s_SymbolMap.reset();
615 : : } // if ( _destroy )
616 [ + + ]: 62709 : else if ( !s_SymbolMap.get() )
617 : : {
618 : : // Core
619 [ + - ][ + - ]: 415 : s_SymbolMap.reset( new FormulaCompiler::OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, true, FormulaGrammar::GRAM_NATIVE_UI));
[ + - ]
620 [ + - ]: 415 : OModuleClient aModuleClient;
621 [ + - ][ + - ]: 415 : OpCodeList aOpCodeListNative( RID_STRLIST_FUNCTION_NAMES, s_SymbolMap );
[ + - ][ + - ]
622 : : // No AddInMap for native core mapping.
623 : : } // if ( !s_SymbolMap.get() )
624 : 63121 : _xMap = s_SymbolMap;
625 : 63121 : }
626 : : // -----------------------------------------------------------------------------
627 : 31490 : const String& FormulaCompiler::GetNativeSymbol( OpCode eOp )
628 : : {
629 [ + - ]: 31490 : NonConstOpCodeMapPtr xSymbolsNative;
630 [ + - ]: 31490 : lcl_fillNativeSymbols(xSymbolsNative);
631 [ + - ][ + - ]: 31490 : return xSymbolsNative->getSymbol( eOp );
632 : : }
633 : : // -----------------------------------------------------------------------------
634 : 30395 : void FormulaCompiler::InitSymbolsNative() const
635 : : {
636 : 30395 : lcl_fillNativeSymbols(mxSymbolsNative);
637 : 30395 : }
638 : : // -----------------------------------------------------------------------------
639 : 69 : void FormulaCompiler::InitSymbolsEnglish() const
640 : : {
641 [ + + ][ + - ]: 69 : static NonConstOpCodeMapPtr s_sSymbol;
[ + - ][ # # ]
642 [ + + ]: 69 : if ( !s_sSymbol.get() )
643 : 4 : loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH,FormulaGrammar::GRAM_ENGLISH,s_sSymbol);
644 : 69 : mxSymbolsEnglish = s_sSymbol;
645 : 69 : }
646 : : // -----------------------------------------------------------------------------
647 : 266 : void FormulaCompiler::InitSymbolsPODF() const
648 : : {
649 [ + + ][ + - ]: 266 : static NonConstOpCodeMapPtr s_sSymbol;
[ + - ][ # # ]
650 [ + + ]: 266 : if ( !s_sSymbol.get() )
651 : 11 : loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH,FormulaGrammar::GRAM_PODF,s_sSymbol);
652 : 266 : mxSymbolsPODF = s_sSymbol;
653 : 266 : }
654 : : // -----------------------------------------------------------------------------
655 : 2655 : void FormulaCompiler::InitSymbolsODFF() const
656 : : {
657 [ + + ][ + - ]: 2655 : static NonConstOpCodeMapPtr s_sSymbol;
[ + - ][ # # ]
658 [ + + ]: 2655 : if ( !s_sSymbol.get() )
659 : 14 : loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF,FormulaGrammar::GRAM_ODFF,s_sSymbol);
660 : 2655 : mxSymbolsODFF = s_sSymbol;
661 : 2655 : }
662 : : // -----------------------------------------------------------------------------
663 : 0 : void FormulaCompiler::InitSymbolsEnglishXL() const
664 : : {
665 [ # # ][ # # ]: 0 : static NonConstOpCodeMapPtr s_sSymbol;
[ # # ][ # # ]
666 [ # # ]: 0 : if ( !s_sSymbol.get() )
667 : 0 : loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH,FormulaGrammar::GRAM_ENGLISH,s_sSymbol);
668 : 0 : mxSymbolsEnglishXL = s_sSymbol;
669 : :
670 : : // TODO: For now, just replace the separators to the Excel English
671 : : // variants. Later, if we want to properly map Excel functions with Calc
672 : : // functions, we'll need to do a little more work here.
673 [ # # ][ # # ]: 0 : mxSymbolsEnglishXL->putOpCode(rtl::OUString(','), ocSep);
[ # # ]
674 [ # # ][ # # ]: 0 : mxSymbolsEnglishXL->putOpCode(rtl::OUString(','), ocArrayColSep);
[ # # ]
675 [ # # ][ # # ]: 0 : mxSymbolsEnglishXL->putOpCode(rtl::OUString(';'), ocArrayRowSep);
[ # # ]
676 : 0 : }
677 : :
678 : : // -----------------------------------------------------------------------------
679 : 29 : void FormulaCompiler::loadSymbols(sal_uInt16 _nSymbols,FormulaGrammar::Grammar _eGrammar,NonConstOpCodeMapPtr& _xMap) const
680 : : {
681 [ + - ]: 29 : if ( !_xMap.get() )
682 : : {
683 : : // not Core
684 [ + - ][ + - ]: 29 : _xMap.reset( new OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, _eGrammar != FormulaGrammar::GRAM_ODFF, _eGrammar ));
[ + - ]
685 [ + - ]: 29 : OModuleClient aModuleClient;
686 [ + - ][ + - ]: 29 : OpCodeList aOpCodeList( _nSymbols, _xMap );
[ + - ]
687 : :
688 [ + - ][ + - ]: 29 : fillFromAddInMap( _xMap, _eGrammar);
[ + - ]
689 : : // Fill from collection for AddIns not already present.
690 [ + + ]: 29 : if ( FormulaGrammar::GRAM_ENGLISH != _eGrammar )
691 [ + - ][ + - ]: 25 : fillFromAddInCollectionUpperName( _xMap);
[ + - ]
692 : : else
693 [ + - ][ + - ]: 29 : fillFromAddInCollectionEnglishName( _xMap);
[ + - ][ + - ]
694 : : }
695 : 29 : }
696 : : // -----------------------------------------------------------------------------
697 : 0 : void FormulaCompiler::fillFromAddInCollectionUpperName( NonConstOpCodeMapPtr /*xMap */) const
698 : : {
699 : 0 : }
700 : : // -----------------------------------------------------------------------------
701 : 0 : void FormulaCompiler::fillFromAddInCollectionEnglishName( NonConstOpCodeMapPtr /*xMap */) const
702 : : {
703 : 0 : }
704 : : // -----------------------------------------------------------------------------
705 : 0 : void FormulaCompiler::fillFromAddInMap( NonConstOpCodeMapPtr /*xMap*/, FormulaGrammar::Grammar /*_eGrammar */) const
706 : : {
707 : 0 : }
708 : : // -----------------------------------------------------------------------------
709 : 0 : OpCode FormulaCompiler::GetEnglishOpCode( const String& rName ) const
710 : : {
711 [ # # ]: 0 : FormulaCompiler::OpCodeMapPtr xMap = GetOpCodeMap(sheet::FormulaLanguage::ENGLISH);
712 : :
713 [ # # ]: 0 : formula::OpCodeHashMap::const_iterator iLook( xMap->getHashMap()->find( rName ) );
714 [ # # ]: 0 : bool bFound = (iLook != xMap->getHashMap()->end());
715 [ # # ][ # # ]: 0 : return bFound ? (*iLook).second : OpCode(ocNone);
[ # # ]
716 : : }
717 : :
718 : 13730 : bool FormulaCompiler::IsOpCodeVolatile( OpCode eOp )
719 : : {
720 : 13730 : bool bRet = false;
721 [ + + ]: 13730 : switch (eOp)
722 : : {
723 : : // no parameters:
724 : : case ocRandom:
725 : : case ocGetActDate:
726 : : case ocGetActTime:
727 : : // one parameter:
728 : : case ocFormula:
729 : : case ocInfo:
730 : : // more than one parameters:
731 : : // ocIndirect/ocIndirectXL otherwise would have to do
732 : : // StopListening and StartListening on a reference for every
733 : : // interpreted value.
734 : : case ocIndirect:
735 : : case ocIndirectXL:
736 : : // ocOffset results in indirect references.
737 : : case ocOffset:
738 : 195 : bRet = true;
739 : 195 : break;
740 : : default:
741 : 13535 : bRet = false;
742 : 13535 : break;
743 : : }
744 : 13730 : return bRet;
745 : : }
746 : :
747 : : // Remove quotes, escaped quotes are unescaped.
748 : 27 : bool FormulaCompiler::DeQuote( String& rStr )
749 : : {
750 : 27 : xub_StrLen nLen = rStr.Len();
751 [ - + ][ # # ]: 27 : if ( nLen > 1 && rStr.GetChar(0) == '\'' && rStr.GetChar( nLen-1 ) == '\'' )
[ - + ][ + + ]
752 : : {
753 : 0 : rStr.Erase( nLen-1, 1 );
754 : 0 : rStr.Erase( 0, 1 );
755 : 0 : xub_StrLen nPos = 0;
756 [ # # ]: 0 : while ( (nPos = rStr.SearchAscii( "\\\'", nPos)) != STRING_NOTFOUND )
757 : : {
758 : 0 : rStr.Erase( nPos, 1 );
759 : 0 : ++nPos;
760 : : }
761 : 0 : return true;
762 : : }
763 : 27 : return false;
764 : : }
765 : : // -----------------------------------------------------------------------------
766 : 0 : void FormulaCompiler::fillAddInToken(::std::vector< sheet::FormulaOpCodeMapEntry >& /*_rVec*/,bool /*_bIsEnglish*/) const
767 : : {
768 : 0 : }
769 : : // -----------------------------------------------------------------------------
770 : 0 : bool FormulaCompiler::IsMatrixFunction(OpCode _eOpCode)
771 : : {
772 [ # # ]: 0 : switch ( _eOpCode )
773 : : {
774 : : case ocDde :
775 : : case ocGrowth :
776 : : case ocTrend :
777 : : case ocRKP :
778 : : case ocRGP :
779 : : case ocFrequency :
780 : : case ocMatTrans :
781 : : case ocMatMult :
782 : : case ocMatInv :
783 : : case ocMatrixUnit :
784 : 0 : return true;
785 : : default:
786 : : {
787 : : // added to avoid warnings
788 : : }
789 : : }
790 : 0 : return false;
791 : : }
792 : :
793 : : // -----------------------------------------------------------------------------
794 : 936 : FormulaCompiler::OpCodeMap::~OpCodeMap()
795 : : {
796 [ + - ]: 468 : delete mpReverseExternalHashMap;
797 [ + - ]: 468 : delete mpExternalHashMap;
798 [ + - ][ + + ]: 189072 : delete [] mpTable;
799 [ + - ]: 468 : delete mpHashMap;
800 [ - + ]: 936 : }
801 : : // -----------------------------------------------------------------------------
802 : 0 : void FormulaCompiler::OpCodeMap::copyFrom( const OpCodeMap& r )
803 : : {
804 [ # # ]: 0 : delete mpHashMap;
805 [ # # ][ # # ]: 0 : mpHashMap = new OpCodeHashMap(mnSymbols);
806 : :
807 : 0 : sal_uInt16 n = r.getSymbolCount();
808 [ # # ]: 0 : for (sal_uInt16 i = 0; i < n; ++i)
809 : : {
810 : 0 : OpCode eOp = OpCode(i);
811 : 0 : const String& rSymbol = r.getSymbol(eOp);
812 : 0 : putOpCode(rSymbol, eOp);
813 : : }
814 : :
815 : : // TODO: maybe copy the external maps too?
816 : 0 : }
817 : : // -----------------------------------------------------------------------------
818 : :
819 : 0 : sal_uInt16 FormulaCompiler::GetErrorConstant( const String& rName )
820 : : {
821 : 0 : sal_uInt16 nError = 0;
822 [ # # ]: 0 : OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName));
823 [ # # ][ # # ]: 0 : if (iLook != mxSymbols->getHashMap()->end())
824 : : {
825 [ # # ][ # # : 0 : switch ((*iLook).second)
# # # # #
# ]
826 : : {
827 : : // Not all may make sense in a formula, but these we know as
828 : : // opcodes.
829 : : case ocErrNull:
830 : 0 : nError = errNoCode;
831 : 0 : break;
832 : : case ocErrDivZero:
833 : 0 : nError = errDivisionByZero;
834 : 0 : break;
835 : : case ocErrValue:
836 : 0 : nError = errNoValue;
837 : 0 : break;
838 : : case ocErrRef:
839 : 0 : nError = errNoRef;
840 : 0 : break;
841 : : case ocErrName:
842 : 0 : nError = errNoName;
843 : 0 : break;
844 : : case ocErrNum:
845 : 0 : nError = errIllegalFPOperation;
846 : 0 : break;
847 : : case ocErrNA:
848 : 0 : nError = NOTAVAILABLE;
849 : 0 : break;
850 : : default:
851 : : ; // nothing
852 : : }
853 : : }
854 : 0 : return nError;
855 : : }
856 : :
857 : :
858 : 0 : void FormulaCompiler::AppendErrorConstant( rtl::OUStringBuffer& rBuffer, sal_uInt16 nError )
859 : : {
860 : : OpCode eOp;
861 [ # # # # : 0 : switch (nError)
# # # ]
862 : : {
863 : : default:
864 : : case errNoCode:
865 : 0 : eOp = ocErrNull;
866 : 0 : break;
867 : : case errDivisionByZero:
868 : 0 : eOp = ocErrDivZero;
869 : 0 : break;
870 : : case errNoValue:
871 : 0 : eOp = ocErrValue;
872 : 0 : break;
873 : : case errNoRef:
874 : 0 : eOp = ocErrRef;
875 : 0 : break;
876 : : case errNoName:
877 : 0 : eOp = ocErrName;
878 : 0 : break;
879 : : case errIllegalFPOperation:
880 : 0 : eOp = ocErrNum;
881 : 0 : break;
882 : : case NOTAVAILABLE:
883 : 0 : eOp = ocErrNA;
884 : 0 : break;
885 : : }
886 [ # # ]: 0 : rBuffer.append( mxSymbols->getSymbol( eOp));
887 : 0 : }
888 : :
889 : : // -----------------------------------------------------------------------------
890 : 48 : sal_Int32 FormulaCompiler::OpCodeMap::getOpCodeUnknown()
891 : : {
892 : : static const sal_Int32 kOpCodeUnknown = -1;
893 : 48 : return kOpCodeUnknown;
894 : : }
895 : : // -----------------------------------------------------------------------------
896 : 71295 : bool FormulaCompiler::GetToken()
897 : : {
898 : : static const short nRecursionMax = 42;
899 : 71295 : FormulaCompilerRecursionGuard aRecursionGuard( nRecursion );
900 [ - + ]: 71295 : if ( nRecursion > nRecursionMax )
901 : : {
902 [ # # ]: 0 : SetError( errStackOverflow );
903 [ # # ][ # # ]: 0 : mpToken = new FormulaByteToken( ocStop );
[ # # ]
904 : 0 : return false;
905 : : }
906 [ - + ][ # # ]: 71295 : if ( bAutoCorrect && !pStack )
907 : : { // don't merge stacked subroutine code into entered formula
908 [ # # ]: 0 : aCorrectedFormula += aCorrectedSymbol;
909 [ # # ]: 0 : aCorrectedSymbol.Erase();
910 : : }
911 : 71295 : bool bStop = false;
912 [ - + ][ # # ]: 71295 : if( pArr->GetCodeError() && !bIgnoreErrors )
[ - + ]
913 : 0 : bStop = true;
914 : : else
915 : : {
916 : : short nWasColRowName;
917 [ + + - + ]: 137392 : if ( pArr->nIndex
[ - + ]
918 : 66097 : && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
919 : 0 : nWasColRowName = 1;
920 : : else
921 : 71295 : nWasColRowName = 0;
922 [ + - ][ + - ]: 71295 : mpToken = pArr->Next();
923 [ + + ][ + + ]: 71375 : while( mpToken && mpToken->GetOpCode() == ocSpaces )
[ + + ]
924 : : {
925 [ - + ]: 80 : if ( nWasColRowName )
926 : 0 : nWasColRowName++;
927 [ - + ][ # # ]: 80 : if ( bAutoCorrect && !pStack )
928 [ # # ]: 0 : CreateStringFromToken( aCorrectedFormula, mpToken.get(), false );
929 [ + - ][ + - ]: 80 : mpToken = pArr->Next();
930 : : }
931 [ - + ][ # # ]: 71295 : if ( bAutoCorrect && !pStack && mpToken )
[ # # ][ - + ]
932 [ # # ]: 0 : CreateStringFromToken( aCorrectedSymbol, mpToken.get(), false );
933 [ + + ]: 71295 : if( !mpToken )
934 : : {
935 [ + + ]: 4123 : if( pStack )
936 : : {
937 [ + - ]: 284 : PopTokenArray();
938 [ + - ]: 284 : return GetToken();
939 : : }
940 : : else
941 : 3839 : bStop = true;
942 : : }
943 : : else
944 : : {
945 [ - + ][ # # ]: 67172 : if ( nWasColRowName >= 2 && mpToken->GetOpCode() == ocColRowName )
[ - + ]
946 : : { // convert an ocSpaces to ocIntersect in RPN
947 [ # # ][ # # ]: 0 : mpToken = new FormulaByteToken( ocIntersect );
[ # # ]
948 : 0 : pArr->nIndex--; // we advanced to the second ocColRowName, step back
949 : : }
950 : : }
951 : : }
952 [ + + ]: 71011 : if( bStop )
953 : : {
954 [ + - ][ + - ]: 3839 : mpToken = new FormulaByteToken( ocStop );
[ + - ]
955 : 3839 : return false;
956 : : }
957 [ + + ]: 67172 : if( mpToken->GetOpCode() == ocSubTotal )
958 : 5 : glSubTotal = true;
959 [ + - ][ + + ]: 67167 : else if ( mpToken->IsExternalRef() )
960 : : {
961 [ + - ]: 100 : return HandleExternalReference(*mpToken);
962 : : }
963 [ + + ]: 67067 : else if( mpToken->GetOpCode() == ocName )
964 : : {
965 [ + - ]: 218 : return HandleRange();
966 : : }
967 [ - + ]: 66849 : else if( mpToken->GetOpCode() == ocColRowName )
968 : : {
969 [ # # ]: 0 : return HandleSingleRef();
970 : : }
971 [ + + ]: 66849 : else if( mpToken->GetOpCode() == ocDBArea )
972 : : {
973 [ + - ]: 6 : return HandleDbData();
974 : : }
975 [ + + ]: 66843 : else if( mpToken->GetType() == svSingleRef )
976 : : {
977 : 4726 : pArr->nRefs++;
978 : : }
979 [ + + ]: 62117 : else if( mpToken->GetType() == svDoubleRef )
980 : : {
981 : 5566 : pArr->nRefs++;
982 : : }
983 : 71295 : return true;
984 : : }
985 : : //---------------------------------------------------------------------------
986 : : // RPN creation by recursion
987 : : //---------------------------------------------------------------------------
988 : :
989 : 30874 : void FormulaCompiler::Factor()
990 : : {
991 [ - + ][ # # ]: 30874 : if ( pArr->GetCodeError() && !bIgnoreErrors )
[ + - ]
992 : 30874 : return;
993 : :
994 [ + - ]: 30874 : CurrentFactor pFacToken( this );
995 : :
996 : 30874 : OpCode eOp = mpToken->GetOpCode();
997 [ + - ][ + + ]: 30874 : if( eOp == ocPush || eOp == ocColRowNameAuto || eOp == ocMatRef ||
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + + ]
998 : : eOp == ocDBArea
999 : : || (bCompileForFAP && ((eOp == ocName) || (eOp == ocDBArea)
1000 : : || (eOp == ocColRowName) || (eOp == ocBad)))
1001 : : )
1002 : : {
1003 [ + - ]: 19910 : PutCode( mpToken );
1004 [ + - ]: 19910 : eOp = NextToken();
1005 [ - + ]: 19910 : if( eOp == ocOpen )
1006 : : {
1007 : : // PUSH( is an error that may be caused by an unknown function.
1008 : : SetError(
1009 : 0 : ( mpToken->GetType() == svString
1010 : 0 : || mpToken->GetType() == svSingleRef )
1011 [ # # ]: 0 : ? errNoName : errOperatorExpected );
[ # # # # ]
1012 [ # # ][ # # ]: 0 : if ( bAutoCorrect && !pStack )
1013 : : { // assume multiplication
1014 [ # # ][ # # ]: 0 : aCorrectedFormula += mxSymbols->getSymbol(ocMul);
1015 : 0 : bCorrected = true;
1016 [ # # ]: 0 : NextToken();
1017 [ # # ]: 0 : eOp = Expression();
1018 [ # # ]: 0 : if( eOp != ocClose )
1019 [ # # ]: 0 : SetError(errPairExpected);
1020 : : else
1021 [ # # ]: 0 : eOp = NextToken();
1022 : : }
1023 : : }
1024 : : }
1025 [ + + ]: 10964 : else if( eOp == ocOpen )
1026 : : {
1027 [ + - ]: 110 : NextToken();
1028 [ + - ]: 110 : eOp = Expression();
1029 [ - + ][ # # ]: 110 : while ((eOp == ocSep) && (!pArr->GetCodeError() || bIgnoreErrors))
[ # # ][ - + ]
1030 : : { // range list (A1;A2) converted to (A1~A2)
1031 [ # # ]: 0 : pFacToken = mpToken;
1032 [ # # ]: 0 : NextToken();
1033 [ # # ]: 0 : eOp = Expression();
1034 : : // Do not ignore error here, regardless of bIgnoreErrors, otherwise
1035 : : // errors like =(1;) would also result in display of =(1~)
1036 [ # # ]: 0 : if (!pArr->GetCodeError())
1037 : : {
1038 [ # # ]: 0 : pFacToken->NewOpCode( ocUnion,FormulaToken::PrivateAccess());
1039 [ # # ]: 0 : PutCode( pFacToken);
1040 : : }
1041 : : }
1042 [ - + ]: 110 : if (eOp != ocClose)
1043 [ # # ]: 0 : SetError(errPairExpected);
1044 : : else
1045 [ + - ]: 110 : eOp = NextToken();
1046 : : }
1047 : : else
1048 : : {
1049 [ + + ]: 10854 : if( nNumFmt == NUMBERFORMAT_UNDEFINED )
1050 : 4170 : nNumFmt = lcl_GetRetFormat( eOp );
1051 : :
1052 [ + - ][ + + ]: 10854 : if ( IsOpCodeVolatile(eOp) )
1053 : 66 : pArr->SetRecalcModeAlways();
1054 : : else
1055 : : {
1056 [ - + - + ]: 10788 : switch( eOp )
1057 : : {
1058 : : // Functions recalculated on every document load.
1059 : : // Don't use SetRecalcModeOnLoad() which would override
1060 : : // ModeAlways.
1061 : : case ocConvert :
1062 [ # # ]: 0 : pArr->AddRecalcMode( RECALCMODE_ONLOAD );
1063 : 0 : break;
1064 : : // If the referred cell is moved the value changes.
1065 : : case ocColumn :
1066 : : case ocRow :
1067 : : // ocCell needs recalc on move for some possible type values.
1068 : : case ocCell :
1069 : 162 : pArr->SetRecalcModeOnRefMove();
1070 : 162 : break;
1071 : : case ocHyperLink :
1072 : 0 : pArr->SetHyperLink(true);
1073 : 0 : break;
1074 : : default:
1075 : : ; // nothing
1076 : : }
1077 : : }
1078 [ + + ][ + + ]: 10854 : if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
1079 : : {
1080 [ + - ]: 156 : pFacToken = mpToken;
1081 [ + - ]: 156 : eOp = NextToken();
1082 [ - + ]: 312 : if (eOp != ocOpen)
1083 : : {
1084 [ # # ]: 0 : SetError(errPairExpected);
1085 [ # # ]: 0 : PutCode( pFacToken );
1086 : : }
1087 : : else
1088 : : {
1089 [ + - ]: 156 : eOp = NextToken();
1090 [ - + ]: 156 : if (eOp != ocClose)
1091 [ # # ]: 0 : SetError(errPairExpected);
1092 [ + - ]: 156 : PutCode(pFacToken);
1093 [ + - ]: 156 : eOp = NextToken();
1094 : : }
1095 : : }
1096 : : // special cases NOT() and NEG()
1097 [ + - ][ + - ]: 10698 : else if( eOp == ocNot || eOp == ocNeg
[ + + ][ + + ]
1098 : : || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) )
1099 : : {
1100 [ + - ]: 607 : pFacToken = mpToken;
1101 [ + - ]: 607 : eOp = NextToken();
1102 [ - + ][ # # ]: 607 : if( nNumFmt == NUMBERFORMAT_UNDEFINED && eOp == ocNot )
1103 : 0 : nNumFmt = NUMBERFORMAT_LOGICAL;
1104 [ + - ]: 607 : if (eOp == ocOpen)
1105 : : {
1106 [ + - ]: 607 : NextToken();
1107 [ + - ]: 607 : eOp = Expression();
1108 : : }
1109 : : else
1110 [ # # ]: 0 : SetError(errPairExpected);
1111 [ - + ]: 607 : if (eOp != ocClose)
1112 [ # # ]: 0 : SetError(errPairExpected);
1113 [ + - ]: 607 : else if ( !pArr->GetCodeError() )
1114 [ + - ][ + - ]: 607 : pFacToken->SetByte( 1 );
1115 [ + - ]: 607 : PutCode( pFacToken );
1116 [ + - ]: 607 : eOp = NextToken();
1117 : : }
1118 [ + + ][ - + ]: 10091 : else if ((SC_OPCODE_START_2_PAR <= eOp && eOp < SC_OPCODE_STOP_2_PAR)
[ + - ][ + + ]
[ + + ][ + + ]
[ + + ][ - + ]
[ # # ][ - + ]
[ # # ][ # # ]
1119 : : || eOp == ocExternal
1120 : : || eOp == ocMacro
1121 : : || eOp == ocAnd
1122 : : || eOp == ocOr
1123 : : || eOp == ocBad
1124 : : || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
1125 : : || (bCompileForFAP && ((eOp == ocIf) || (eOp == ocChose)))
1126 : : )
1127 : : {
1128 [ + - ]: 8964 : pFacToken = mpToken;
1129 : 8964 : OpCode eMyLastOp = eOp;
1130 [ + - ]: 8964 : eOp = NextToken();
1131 : 8964 : bool bNoParam = false;
1132 : 8964 : bool bBadName = false;
1133 [ + + ]: 8964 : if (eOp == ocOpen)
1134 : : {
1135 [ + - ]: 8940 : eOp = NextToken();
1136 [ + + ]: 8940 : if (eOp == ocClose)
1137 : 15 : bNoParam = true;
1138 : : else
1139 [ + - ]: 8925 : eOp = Expression();
1140 : : }
1141 [ + - ]: 24 : else if (eMyLastOp == ocBad)
1142 : : {
1143 : : // Just a bad name, not an unknown function, no parameters, no
1144 : : // closing expected.
1145 : 24 : bBadName = true;
1146 : 24 : bNoParam = true;
1147 : : }
1148 : : else
1149 [ # # ]: 0 : SetError(errPairExpected);
1150 : 8964 : sal_uInt8 nSepCount = 0;
1151 [ + + ]: 8964 : if( !bNoParam )
1152 : : {
1153 : 8925 : nSepCount++;
1154 [ + + ][ - + ]: 18229 : while ( (eOp == ocSep) && (!pArr->GetCodeError() || bIgnoreErrors) )
[ # # ][ + + ]
1155 : : {
1156 : 9304 : nSepCount++;
1157 [ + - ]: 9304 : NextToken();
1158 [ + - ]: 9304 : eOp = Expression();
1159 : : }
1160 : : }
1161 [ + + ]: 8964 : if (bBadName)
1162 : : ; // nothing, keep current token for return
1163 [ - + ]: 8940 : else if (eOp != ocClose)
1164 [ # # ]: 0 : SetError(errPairExpected);
1165 : : else
1166 [ + - ]: 8940 : eOp = NextToken();
1167 : : // Jumps are just normal functions for the FunctionAutoPilot tree view
1168 [ - + ][ # # ]: 8964 : if ( bCompileForFAP && pFacToken->GetType() == svJump )
[ # # ][ - + ]
1169 [ # # ][ # # ]: 0 : pFacToken = new FormulaFAPToken( pFacToken->GetOpCode(), nSepCount, pFacToken );
[ # # ][ # # ]
[ # # ]
1170 : : else
1171 [ + - ][ + - ]: 8964 : pFacToken->SetByte( nSepCount );
1172 [ + - ]: 8964 : PutCode( pFacToken );
1173 : : }
1174 [ + + ][ - + ]: 1127 : else if (eOp == ocIf || eOp == ocChose)
1175 : : {
1176 : : // the PC counters are -1
1177 [ + - ]: 42 : pFacToken = mpToken;
1178 [ + - ]: 42 : if ( eOp == ocIf )
1179 [ + - ][ + - ]: 42 : pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
1180 : : else
1181 [ # # ][ # # ]: 0 : pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
1182 [ + - ]: 42 : eOp = NextToken();
1183 [ + - ]: 42 : if (eOp == ocOpen)
1184 : : {
1185 [ + - ]: 42 : NextToken();
1186 [ + - ]: 42 : eOp = Expression();
1187 : : }
1188 : : else
1189 [ # # ]: 0 : SetError(errPairExpected);
1190 : 42 : short nJumpCount = 0;
1191 [ + - ]: 42 : PutCode( pFacToken );
1192 : : // during AutoCorrect (since pArr->GetCodeError() is
1193 : : // ignored) an unlimited ocIf would crash because
1194 : : // ScRawToken::Clone() allocates the JumpBuffer according to
1195 : : // nJump[0]*2+2, which is 3*2+2 on ocIf.
1196 : : const short nJumpMax =
1197 [ + - ][ + - ]: 42 : (pFacToken->GetOpCode() == ocIf ? 3 : MAXJUMPCOUNT);
1198 [ + - ]: 138 : while ( (nJumpCount < (MAXJUMPCOUNT - 1)) && (eOp == ocSep)
[ + + - + ]
[ # # ][ + + ]
1199 : 48 : && (!pArr->GetCodeError() || bIgnoreErrors) )
1200 : : {
1201 [ + - ]: 48 : if ( ++nJumpCount <= nJumpMax )
1202 [ + - ][ + - ]: 48 : pFacToken->GetJump()[nJumpCount] = pc-1;
1203 [ + - ]: 48 : NextToken();
1204 [ + - ]: 48 : eOp = Expression();
1205 : : // ocSep or ocClose terminate the subexpression
1206 [ + - ]: 48 : PutCode( mpToken );
1207 : : }
1208 [ - + ]: 42 : if (eOp != ocClose)
1209 [ # # ]: 0 : SetError(errPairExpected);
1210 : : else
1211 : : {
1212 [ + - ]: 42 : eOp = NextToken();
1213 : : // always limit to nJumpMax, no arbitrary overwrites
1214 [ + - ]: 42 : if ( ++nJumpCount <= nJumpMax )
1215 [ + - ][ + - ]: 42 : pFacToken->GetJump()[ nJumpCount ] = pc-1;
1216 [ + - ][ + - ]: 42 : if ((pFacToken->GetOpCode() == ocIf && (nJumpCount > 3)) ||
[ + - ][ - + ]
[ - + ]
1217 : : (nJumpCount >= MAXJUMPCOUNT))
1218 [ # # ]: 0 : SetError(errIllegalParameter);
1219 : : else
1220 [ + - ][ + - ]: 42 : pFacToken->GetJump()[ 0 ] = nJumpCount;
1221 : 42 : }
1222 : : }
1223 [ + + ]: 1085 : else if ( eOp == ocMissing )
1224 : : {
1225 [ + - ]: 18 : PutCode( mpToken );
1226 [ + - ]: 18 : eOp = NextToken();
1227 : : }
1228 [ - + ]: 1067 : else if ( eOp == ocClose )
1229 : : {
1230 [ # # ]: 0 : SetError( errParameterExpected );
1231 : : }
1232 [ - + ]: 1067 : else if ( eOp == ocSep )
1233 : : { // Subsequent ocSep
1234 [ # # ]: 0 : SetError( errParameterExpected );
1235 [ # # ][ # # ]: 0 : if ( bAutoCorrect && !pStack )
1236 : : {
1237 [ # # ]: 0 : aCorrectedSymbol.Erase();
1238 : 0 : bCorrected = true;
1239 : : }
1240 : : }
1241 [ + - ][ - + ]: 1067 : else if ( mpToken->IsExternalRef() )
1242 : : {
1243 [ # # ]: 0 : PutCode(mpToken);
1244 [ # # ]: 0 : eOp = NextToken();
1245 : : }
1246 : : else
1247 : : {
1248 [ + - ]: 1067 : SetError( errUnknownToken );
1249 [ - + ][ # # ]: 1067 : if ( bAutoCorrect && !pStack )
1250 : : {
1251 [ # # ]: 0 : if ( eOp == ocStop )
1252 : : { // trailing operator w/o operand
1253 : 0 : xub_StrLen nLen = aCorrectedFormula.Len();
1254 [ # # ]: 0 : if ( nLen )
1255 [ # # ]: 0 : aCorrectedFormula.Erase( nLen - 1 );
1256 [ # # ]: 0 : aCorrectedSymbol.Erase();
1257 : 0 : bCorrected = true;
1258 : : }
1259 : : }
1260 : : }
1261 [ + - ]: 30874 : }
1262 : : }
1263 : :
1264 : : //---------------------------------------------------------------------------
1265 : :
1266 : 30874 : void FormulaCompiler::RangeLine()
1267 : : {
1268 : 30874 : Factor();
1269 [ - + ]: 30874 : while (mpToken->GetOpCode() == ocRange)
1270 : : {
1271 : 0 : FormulaToken** pCode1 = pCode - 1;
1272 : 0 : FormulaTokenRef p = mpToken;
1273 [ # # ]: 0 : NextToken();
1274 [ # # ]: 0 : Factor();
1275 : 0 : FormulaToken** pCode2 = pCode - 1;
1276 [ # # ][ # # ]: 0 : if (!MergeRangeReference( pCode1, pCode2))
1277 [ # # ]: 0 : PutCode(p);
1278 [ # # ]: 0 : }
1279 : 30874 : }
1280 : :
1281 : : //---------------------------------------------------------------------------
1282 : :
1283 : 30874 : void FormulaCompiler::IntersectionLine()
1284 : : {
1285 : 30874 : RangeLine();
1286 [ - + ]: 30874 : while (mpToken->GetOpCode() == ocIntersect)
1287 : : {
1288 : 0 : FormulaTokenRef p = mpToken;
1289 [ # # ]: 0 : NextToken();
1290 [ # # ]: 0 : RangeLine();
1291 [ # # ]: 0 : PutCode(p);
1292 [ # # ]: 0 : }
1293 : 30874 : }
1294 : :
1295 : : //---------------------------------------------------------------------------
1296 : :
1297 : 30874 : void FormulaCompiler::UnionLine()
1298 : : {
1299 : 30874 : IntersectionLine();
1300 [ - + ]: 30874 : while (mpToken->GetOpCode() == ocUnion)
1301 : : {
1302 : 0 : FormulaTokenRef p = mpToken;
1303 [ # # ]: 0 : NextToken();
1304 [ # # ]: 0 : IntersectionLine();
1305 [ # # ]: 0 : PutCode(p);
1306 [ # # ]: 0 : }
1307 : 30874 : }
1308 : :
1309 : : //---------------------------------------------------------------------------
1310 : :
1311 : 31064 : void FormulaCompiler::UnaryLine()
1312 : : {
1313 [ - + ]: 31064 : if( mpToken->GetOpCode() == ocAdd )
1314 : 0 : GetToken();
1315 [ + + + + ]: 40873 : else if (SC_OPCODE_START_UN_OP <= mpToken->GetOpCode() &&
[ + + ]
1316 : 9809 : mpToken->GetOpCode() < SC_OPCODE_STOP_UN_OP)
1317 : : {
1318 : 190 : FormulaTokenRef p = mpToken;
1319 [ + - ]: 190 : NextToken();
1320 [ + - ]: 190 : UnaryLine();
1321 [ + - ][ + - ]: 190 : PutCode( p );
1322 : : }
1323 : : else
1324 : 30874 : UnionLine();
1325 : 31064 : }
1326 : :
1327 : : //---------------------------------------------------------------------------
1328 : :
1329 : 30874 : void FormulaCompiler::PostOpLine()
1330 : : {
1331 : 30874 : UnaryLine();
1332 [ - + ]: 30874 : while ( mpToken->GetOpCode() == ocPercentSign )
1333 : : { // this operator _follows_ its operand
1334 : 0 : PutCode( mpToken );
1335 : 0 : NextToken();
1336 : : }
1337 : 30874 : }
1338 : :
1339 : : //---------------------------------------------------------------------------
1340 : :
1341 : 30873 : void FormulaCompiler::PowLine()
1342 : : {
1343 : 30873 : PostOpLine();
1344 [ + + ]: 30874 : while (mpToken->GetOpCode() == ocPow)
1345 : : {
1346 : 1 : FormulaTokenRef p = mpToken;
1347 [ + - ]: 1 : NextToken();
1348 [ + - ]: 1 : PostOpLine();
1349 [ + - ]: 1 : PutCode(p);
1350 [ + - ]: 1 : }
1351 : 30873 : }
1352 : :
1353 : : //---------------------------------------------------------------------------
1354 : :
1355 : 30722 : void FormulaCompiler::MulDivLine()
1356 : : {
1357 : 30722 : PowLine();
1358 [ + + ][ + + ]: 30873 : while (mpToken->GetOpCode() == ocMul || mpToken->GetOpCode() == ocDiv)
[ + + ]
1359 : : {
1360 : 151 : FormulaTokenRef p = mpToken;
1361 [ + - ]: 151 : NextToken();
1362 [ + - ]: 151 : PowLine();
1363 [ + - ]: 151 : PutCode(p);
1364 [ + - ]: 151 : }
1365 : 30722 : }
1366 : :
1367 : : //---------------------------------------------------------------------------
1368 : :
1369 : 23992 : void FormulaCompiler::AddSubLine()
1370 : : {
1371 : 23992 : MulDivLine();
1372 [ + + ][ + + ]: 30722 : while (mpToken->GetOpCode() == ocAdd || mpToken->GetOpCode() == ocSub)
[ + + ]
1373 : : {
1374 : 6730 : FormulaTokenRef p = mpToken;
1375 [ + - ]: 6730 : NextToken();
1376 [ + - ]: 6730 : MulDivLine();
1377 [ + - ]: 6730 : PutCode(p);
1378 [ + - ]: 6730 : }
1379 : 23992 : }
1380 : :
1381 : : //---------------------------------------------------------------------------
1382 : :
1383 : 23992 : void FormulaCompiler::ConcatLine()
1384 : : {
1385 : 23992 : AddSubLine();
1386 [ - + ]: 23992 : while (mpToken->GetOpCode() == ocAmpersand)
1387 : : {
1388 : 0 : FormulaTokenRef p = mpToken;
1389 [ # # ]: 0 : NextToken();
1390 [ # # ]: 0 : AddSubLine();
1391 [ # # ]: 0 : PutCode(p);
1392 [ # # ]: 0 : }
1393 : 23992 : }
1394 : :
1395 : : //---------------------------------------------------------------------------
1396 : :
1397 : 23950 : void FormulaCompiler::CompareLine()
1398 : : {
1399 : 23950 : ConcatLine();
1400 [ + + ][ + - ]: 23992 : while (mpToken->GetOpCode() >= ocEqual && mpToken->GetOpCode() <= ocGreaterEqual)
[ + + ]
1401 : : {
1402 : 42 : FormulaTokenRef p = mpToken;
1403 [ + - ]: 42 : NextToken();
1404 [ + - ]: 42 : ConcatLine();
1405 [ + - ]: 42 : PutCode(p);
1406 [ + - ]: 42 : }
1407 : 23950 : }
1408 : :
1409 : : //---------------------------------------------------------------------------
1410 : :
1411 : 23950 : void FormulaCompiler::NotLine()
1412 : : {
1413 : 23950 : CompareLine();
1414 [ - + ]: 23950 : while (mpToken->GetOpCode() == ocNot)
1415 : : {
1416 : 0 : FormulaTokenRef p = mpToken;
1417 [ # # ]: 0 : NextToken();
1418 [ # # ]: 0 : CompareLine();
1419 [ # # ]: 0 : PutCode(p);
1420 [ # # ]: 0 : }
1421 : 23950 : }
1422 : :
1423 : : //---------------------------------------------------------------------------
1424 : :
1425 : 23950 : OpCode FormulaCompiler::Expression()
1426 : : {
1427 : : static const short nRecursionMax = 42;
1428 : 23950 : FormulaCompilerRecursionGuard aRecursionGuard( nRecursion );
1429 [ - + ]: 23950 : if ( nRecursion > nRecursionMax )
1430 : : {
1431 [ # # ]: 0 : SetError( errStackOverflow );
1432 : 0 : return ocStop; //! generate token instead?
1433 : : }
1434 [ + - ]: 23950 : NotLine();
1435 [ + - ][ - + ]: 23950 : while (mpToken->GetOpCode() == ocAnd || mpToken->GetOpCode() == ocOr)
[ - + ]
1436 : : {
1437 : 0 : FormulaTokenRef p = mpToken;
1438 [ # # ]: 0 : mpToken->SetByte( 2 ); // 2 parameters!
1439 [ # # ]: 0 : NextToken();
1440 [ # # ]: 0 : NotLine();
1441 [ # # ]: 0 : PutCode(p);
1442 [ # # ]: 0 : }
1443 : 23950 : return mpToken->GetOpCode();
1444 : : }
1445 : : // -----------------------------------------------------------------------------
1446 : 0 : void FormulaCompiler::SetError(sal_uInt16 /*nError*/)
1447 : : {
1448 : 0 : }
1449 : : // -----------------------------------------------------------------------------
1450 : 0 : FormulaTokenRef FormulaCompiler::ExtendRangeReference( FormulaToken & /*rTok1*/, FormulaToken & /*rTok2*/, bool /*bReuseDoubleRef*/ )
1451 : : {
1452 : 0 : return FormulaTokenRef();
1453 : : }
1454 : : // -----------------------------------------------------------------------------
1455 : 0 : bool FormulaCompiler::MergeRangeReference(FormulaToken * * const pCode1, FormulaToken * const * const pCode2 )
1456 : : {
1457 : : FormulaToken *p1, *p2;
1458 [ # # ][ # # ]: 0 : if (pc < 2 || !pCode1 || !pCode2 ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1459 : : (pCode2 - pCode1 != 1) || (pCode - pCode2 != 1) ||
1460 : : ((p1 = *pCode1) == 0) || ((p2 = *pCode2) == 0) )
1461 : 0 : return false;
1462 : :
1463 [ # # ]: 0 : FormulaTokenRef p = ExtendRangeReference( *p1, *p2, true);
1464 [ # # ]: 0 : if (!p)
1465 : 0 : return false;
1466 : :
1467 : 0 : p->IncRef();
1468 [ # # ]: 0 : p1->DecRef();
1469 [ # # ]: 0 : p2->DecRef();
1470 : 0 : *pCode1 = p.get();
1471 : 0 : --pCode, --pc;
1472 : 0 : pArr->nRefs--;
1473 : :
1474 [ # # ]: 0 : return true;
1475 : : }
1476 : : // -----------------------------------------------------------------------------
1477 : 4914 : bool FormulaCompiler::CompileTokenArray()
1478 : : {
1479 : 4914 : glSubTotal = false;
1480 : 4914 : bCorrected = false;
1481 [ - + ][ # # ]: 4914 : if( !pArr->GetCodeError() || bIgnoreErrors )
[ + - ]
1482 : : {
1483 [ - + ]: 4914 : if ( bAutoCorrect )
1484 : : {
1485 [ # # ]: 0 : aCorrectedFormula.Erase();
1486 [ # # ]: 0 : aCorrectedSymbol.Erase();
1487 : : }
1488 : 4914 : pArr->nRefs = 0; // count from start
1489 [ + - ]: 4914 : pArr->DelRPN();
1490 : 4914 : pStack = NULL;
1491 : : FormulaToken* pData[ MAXCODE ];
1492 : 4914 : pCode = pData;
1493 : 4914 : bool bWasForced = pArr->IsRecalcModeForced();
1494 [ - + ]: 4914 : if ( bWasForced )
1495 : : {
1496 [ # # ]: 0 : if ( bAutoCorrect )
1497 [ # # ]: 0 : aCorrectedFormula = '=';
1498 : : }
1499 : 4914 : pArr->ClearRecalcMode();
1500 : 4914 : pArr->Reset();
1501 : 4914 : eLastOp = ocOpen;
1502 : 4914 : pc = 0;
1503 [ + - ]: 4914 : NextToken();
1504 [ + - ]: 4914 : OpCode eOp = Expression();
1505 : : // Some trailing garbage that doesn't form an expression?
1506 [ + + ]: 4914 : if (eOp != ocStop)
1507 [ + - ]: 1067 : SetError( errOperatorExpected);
1508 : :
1509 : 4914 : sal_uInt16 nErrorBeforePop = pArr->GetCodeError();
1510 : :
1511 [ - + ]: 4914 : while( pStack )
1512 [ # # ]: 0 : PopTokenArray();
1513 [ + + ]: 4914 : if( pc )
1514 : : {
1515 [ + - ]: 3847 : pArr->pRPN = new FormulaToken*[ pc ];
1516 : 3847 : pArr->nRPN = pc;
1517 : 3847 : memcpy( pArr->pRPN, pData, pc * sizeof( FormulaToken* ) );
1518 : : }
1519 : :
1520 : : // once an error, always an error
1521 [ + + ][ - + ]: 4914 : if( !pArr->GetCodeError() && nErrorBeforePop )
[ - + ]
1522 : 0 : pArr->SetCodeError( nErrorBeforePop);
1523 : :
1524 [ + + ][ + - ]: 4914 : if( pArr->GetCodeError() && !bIgnoreErrors )
[ + + ]
1525 : : {
1526 [ + - ]: 1067 : pArr->DelRPN();
1527 : 1067 : pArr->SetHyperLink(false);
1528 : : }
1529 : :
1530 [ - + ]: 4914 : if ( bWasForced )
1531 : 4914 : pArr->SetRecalcModeForced();
1532 : : }
1533 [ + + ]: 4914 : if( nNumFmt == NUMBERFORMAT_UNDEFINED )
1534 : 744 : nNumFmt = NUMBERFORMAT_NUMBER;
1535 : 4914 : return glSubTotal;
1536 : : }
1537 : : // -----------------------------------------------------------------------------
1538 : 284 : void FormulaCompiler::PopTokenArray()
1539 : : {
1540 [ + - ]: 284 : if( pStack )
1541 : : {
1542 : 284 : FormulaArrayStack* p = pStack;
1543 : 284 : pStack = p->pNext;
1544 : 284 : p->pArr->nRefs = sal::static_int_cast<short>( p->pArr->nRefs + pArr->nRefs );
1545 : : // obtain special RecalcMode from SharedFormula
1546 [ - + ]: 284 : if ( pArr->IsRecalcModeAlways() )
1547 : 0 : p->pArr->SetRecalcModeAlways();
1548 [ - + ][ # # ]: 284 : else if ( !pArr->IsRecalcModeNormal() && p->pArr->IsRecalcModeNormal() )
[ - + ]
1549 : 0 : p->pArr->SetMaskedRecalcMode( pArr->GetRecalcMode() );
1550 : 284 : p->pArr->SetCombinedBitsRecalcMode( pArr->GetRecalcMode() );
1551 [ + - ]: 284 : if( p->bTemp )
1552 [ + - ]: 284 : delete pArr;
1553 : 284 : pArr = p->pArr;
1554 : 284 : delete p;
1555 : : }
1556 : 284 : }
1557 : : // -----------------------------------------------------------------------------
1558 : 134 : void FormulaCompiler::CreateStringFromTokenArray( String& rFormula )
1559 : : {
1560 : 134 : rtl::OUStringBuffer aBuffer( pArr->GetLen() * 5 );
1561 [ + - ]: 134 : CreateStringFromTokenArray( aBuffer );
1562 [ + - ][ + - ]: 134 : rFormula = aBuffer.makeStringAndClear();
1563 : 134 : }
1564 : :
1565 : 283 : void FormulaCompiler::CreateStringFromTokenArray( rtl::OUStringBuffer& rBuffer )
1566 : : {
1567 : 283 : rBuffer.setLength(0);
1568 [ - + ]: 283 : if( !pArr->GetLen() )
1569 : 283 : return;
1570 : :
1571 : 283 : FormulaTokenArray* pSaveArr = pArr;
1572 : 283 : bool bODFF = FormulaGrammar::isODFF( meGrammar);
1573 [ + + ][ + + ]: 283 : if (bODFF || FormulaGrammar::isPODF( meGrammar) )
[ + + ]
1574 : : {
1575 : : // Scan token array for missing args and re-write if present.
1576 : 146 : MissingConvention aConv( bODFF);
1577 [ - + ][ + - ]: 146 : if (pArr->NeedsPofRewrite( aConv))
1578 [ # # ]: 146 : pArr = pArr->RewriteMissingToPof( aConv);
1579 : : }
1580 : :
1581 : : // At least one character per token, plus some are references, some are
1582 : : // function names, some are numbers, ...
1583 : 283 : rBuffer.ensureCapacity( pArr->GetLen() * 5 );
1584 : :
1585 [ - + ]: 283 : if ( pArr->IsRecalcModeForced() )
1586 : 0 : rBuffer.append(sal_Unicode('='));
1587 : 283 : FormulaToken* t = pArr->First();
1588 [ + + ]: 822 : while( t )
1589 : 539 : t = CreateStringFromToken( rBuffer, t, true );
1590 : :
1591 [ - + ]: 283 : if (pSaveArr != pArr)
1592 : : {
1593 [ # # ]: 0 : delete pArr;
1594 : 0 : pArr = pSaveArr;
1595 : : }
1596 : : }
1597 : : // -----------------------------------------------------------------------------
1598 : 24861 : FormulaToken* FormulaCompiler::CreateStringFromToken( String& rFormula, FormulaToken* pTokenP,bool bAllowArrAdvance )
1599 : : {
1600 : 24861 : rtl::OUStringBuffer aBuffer;
1601 [ + - ]: 24861 : FormulaToken* p = CreateStringFromToken( aBuffer, pTokenP, bAllowArrAdvance );
1602 [ + - ][ + - ]: 24861 : rFormula += aBuffer.makeStringAndClear();
1603 : 24861 : return p;
1604 : : }
1605 : :
1606 : 25400 : FormulaToken* FormulaCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, FormulaToken* pTokenP,bool bAllowArrAdvance )
1607 : : {
1608 : 25400 : bool bNext = true;
1609 : 25400 : bool bSpaces = false;
1610 : 25400 : FormulaToken* t = pTokenP;
1611 : 25400 : OpCode eOp = t->GetOpCode();
1612 [ - + ][ + + ]: 25400 : if( eOp >= ocAnd && eOp <= ocOr )
1613 : : {
1614 : : // AND, OR infix?
1615 [ # # ]: 0 : if ( bAllowArrAdvance )
1616 : 0 : t = pArr->Next();
1617 : : else
1618 : 0 : t = pArr->PeekNext();
1619 : 0 : bNext = false;
1620 [ # # ][ # # ]: 0 : bSpaces = ( !t || t->GetOpCode() != ocOpen );
1621 : : }
1622 [ - + ]: 25400 : if( bSpaces )
1623 : 0 : rBuffer.append(sal_Unicode(' '));
1624 : :
1625 [ + + ]: 25400 : if( eOp == ocSpaces )
1626 : : {
1627 : 8 : bool bIntersectionOp = mxSymbols->isODFF();
1628 [ - + ]: 8 : if (bIntersectionOp)
1629 : : {
1630 : 0 : const FormulaToken* p = pArr->PeekPrevNoSpaces();
1631 [ # # ][ # # ]: 0 : bIntersectionOp = (p && p->GetOpCode() == ocColRowName);
1632 [ # # ]: 0 : if (bIntersectionOp)
1633 : : {
1634 : 0 : p = pArr->PeekNextNoSpaces();
1635 [ # # ][ # # ]: 0 : bIntersectionOp = (p && p->GetOpCode() == ocColRowName);
1636 : : }
1637 : : }
1638 [ - + ]: 8 : if (bIntersectionOp)
1639 : 0 : rBuffer.appendAscii( "!!");
1640 : : else
1641 : : {
1642 : : // most times it's just one blank
1643 : 8 : sal_uInt8 n = t->GetByte();
1644 [ + + ]: 16 : for ( sal_uInt8 j=0; j<n; ++j )
1645 : : {
1646 : 8 : rBuffer.append(sal_Unicode(' '));
1647 : : }
1648 : : }
1649 : : }
1650 [ - + ][ # # ]: 25392 : else if( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
1651 : 0 : rBuffer.appendAscii( pInternal[ eOp - ocInternalBegin ] );
1652 [ + - ]: 25392 : else if( (sal_uInt16) eOp < mxSymbols->getSymbolCount()) // Keyword:
1653 [ + - ]: 25392 : rBuffer.append(mxSymbols->getSymbol(eOp));
1654 : : else
1655 : : {
1656 : : SAL_WARN( "formula.core","unknown OpCode");
1657 [ # # ]: 0 : rBuffer.append(GetNativeSymbol( ocErrName ));
1658 : : }
1659 [ + - ]: 25400 : if( bNext )
1660 : : {
1661 [ + + ]: 25400 : if (t->IsExternalRef())
1662 : : {
1663 : 11 : CreateStringFromExternal(rBuffer, pTokenP);
1664 : : }
1665 : : else
1666 : : {
1667 [ + + + + : 25389 : switch( t->GetType() )
- + - - +
- ]
1668 : : {
1669 : : case svDouble:
1670 : 30 : AppendDouble( rBuffer, t->GetDouble() );
1671 : 30 : break;
1672 : :
1673 : : case svString:
1674 [ + + ][ + + ]: 105 : if( eOp == ocBad || eOp == ocStringXML )
1675 [ + - ]: 96 : rBuffer.append(t->GetString());
1676 : : else
1677 : 9 : AppendString( rBuffer, t->GetString() );
1678 : 105 : break;
1679 : : case svSingleRef:
1680 : 12382 : CreateStringFromSingleRef(rBuffer,t);
1681 : 12382 : break;
1682 : : case svDoubleRef:
1683 : 12675 : CreateStringFromDoubleRef(rBuffer,t);
1684 : 12675 : break;
1685 : : case svMatrix:
1686 : 0 : CreateStringFromMatrix( rBuffer, t );
1687 : 0 : break;
1688 : :
1689 : : case svIndex:
1690 : 16 : CreateStringFromIndex( rBuffer, t );
1691 : 16 : break;
1692 : : case svExternal:
1693 : : {
1694 : : // mapped or translated name of AddIns
1695 [ # # ][ # # ]: 0 : String aAddIn( t->GetExternal() );
1696 : 0 : bool bMapped = mxSymbols->isPODF(); // ODF 1.1 directly uses programmatical name
1697 [ # # ][ # # ]: 0 : if (!bMapped && mxSymbols->hasExternals())
[ # # ][ # # ]
1698 : : {
1699 [ # # ]: 0 : ExternalHashMap::const_iterator iLook = mxSymbols->getReverseExternalHashMap()->find( aAddIn);
1700 [ # # ][ # # ]: 0 : if (iLook != mxSymbols->getReverseExternalHashMap()->end())
1701 : : {
1702 [ # # ][ # # ]: 0 : aAddIn = (*iLook).second;
1703 : 0 : bMapped = true;
1704 : : }
1705 : : }
1706 [ # # ][ # # ]: 0 : if (!bMapped && !mxSymbols->isEnglish())
[ # # ]
1707 [ # # ]: 0 : LocalizeString( aAddIn );
1708 [ # # ][ # # ]: 0 : rBuffer.append(aAddIn);
[ # # ]
1709 : : }
1710 : 0 : break;
1711 : : case svError:
1712 : 0 : AppendErrorConstant( rBuffer, t->GetError());
1713 : 0 : break;
1714 : : case svByte:
1715 : : case svJump:
1716 : : case svFAP:
1717 : : case svMissing:
1718 : : case svSep:
1719 : 25400 : break; // Opcodes
1720 : : default:
1721 : : OSL_FAIL("FormulaCompiler:: GetStringFromToken errUnknownVariable");
1722 : : } // of switch
1723 : : }
1724 : : }
1725 [ - + ]: 25400 : if( bSpaces )
1726 : 0 : rBuffer.append(sal_Unicode(' '));
1727 [ + + ]: 25400 : if ( bAllowArrAdvance )
1728 : : {
1729 [ + - ]: 539 : if( bNext )
1730 : 539 : t = pArr->Next();
1731 : 539 : return t;
1732 : : }
1733 : 25400 : return pTokenP;
1734 : : }
1735 : : // -----------------------------------------------------------------------------
1736 : :
1737 : 30 : void FormulaCompiler::AppendDouble( rtl::OUStringBuffer& rBuffer, double fVal )
1738 : : {
1739 [ + + ]: 30 : if ( mxSymbols->isEnglish() )
1740 : : {
1741 : : ::rtl::math::doubleToUStringBuffer( rBuffer, fVal,
1742 : : rtl_math_StringFormat_Automatic,
1743 : 6 : rtl_math_DecimalPlaces_Max, '.', true );
1744 : : }
1745 : : else
1746 : : {
1747 [ + - ]: 24 : SvtSysLocale aSysLocale;
1748 : : ::rtl::math::doubleToUStringBuffer( rBuffer, fVal,
1749 : : rtl_math_StringFormat_Automatic,
1750 : : rtl_math_DecimalPlaces_Max,
1751 [ + - ][ + - ]: 24 : aSysLocale.GetLocaleDataPtr()->getNumDecimalSep()[0],
1752 [ + - ]: 24 : true );
1753 : : }
1754 : 30 : }
1755 : : // -----------------------------------------------------------------------------
1756 : 0 : void FormulaCompiler::AppendBoolean( rtl::OUStringBuffer& rBuffer, bool bVal )
1757 : : {
1758 [ # # ][ # # ]: 0 : rBuffer.append( mxSymbols->getSymbol(static_cast<OpCode>(bVal ? ocTrue : ocFalse)) );
1759 : 0 : }
1760 : : // -----------------------------------------------------------------------------
1761 : 9 : void FormulaCompiler::AppendString( rtl::OUStringBuffer& rBuffer, const String & rStr )
1762 : : {
1763 : 9 : rBuffer.append(sal_Unicode('"'));
1764 [ + - ]: 9 : if ( lcl_UnicodeStrChr( rStr.GetBuffer(), '"' ) == NULL )
1765 [ + - ]: 9 : rBuffer.append( rStr );
1766 : : else
1767 : : {
1768 [ # # ]: 0 : String aStr( rStr );
1769 [ # # ][ # # ]: 0 : aStr.SearchAndReplaceAll( rtl::OUString('"'), rtl::OUString("\"\"") );
[ # # ][ # # ]
[ # # ]
1770 [ # # ][ # # ]: 0 : rBuffer.append(aStr);
[ # # ]
1771 : : }
1772 : 9 : rBuffer.append(sal_Unicode('"'));
1773 : 9 : }
1774 : :
1775 : 412 : void FormulaCompiler::UpdateSeparatorsNative(
1776 : : const rtl::OUString& rSep, const rtl::OUString& rArrayColSep, const rtl::OUString& rArrayRowSep )
1777 : : {
1778 [ + - ]: 412 : NonConstOpCodeMapPtr xSymbolsNative;
1779 [ + - ]: 412 : lcl_fillNativeSymbols(xSymbolsNative);
1780 [ + - ][ + - ]: 412 : xSymbolsNative->putOpCode(rSep, ocSep);
[ + - ]
1781 [ + - ][ + - ]: 412 : xSymbolsNative->putOpCode(rArrayColSep, ocArrayColSep);
[ + - ]
1782 [ + - ][ + - ]: 412 : xSymbolsNative->putOpCode(rArrayRowSep, ocArrayRowSep);
[ + - ][ + - ]
1783 : 412 : }
1784 : :
1785 : 412 : void FormulaCompiler::ResetNativeSymbols()
1786 : : {
1787 [ + - ]: 412 : NonConstOpCodeMapPtr xSymbolsNative;
1788 [ + - ]: 412 : lcl_fillNativeSymbols(xSymbolsNative, true);
1789 [ + - ][ + - ]: 412 : lcl_fillNativeSymbols(xSymbolsNative);
1790 : 412 : }
1791 : :
1792 : 0 : void FormulaCompiler::SetNativeSymbols( const OpCodeMapPtr& xMap )
1793 : : {
1794 [ # # ]: 0 : NonConstOpCodeMapPtr xSymbolsNative;
1795 [ # # ]: 0 : lcl_fillNativeSymbols(xSymbolsNative);
1796 [ # # ][ # # ]: 0 : xSymbolsNative->copyFrom(*xMap);
1797 : 0 : }
1798 : :
1799 : : // -----------------------------------------------------------------------------
1800 : 70787 : OpCode FormulaCompiler::NextToken()
1801 : : {
1802 [ + + ]: 70787 : if( !GetToken() )
1803 : 3839 : return ocStop;
1804 : 66948 : OpCode eOp = mpToken->GetOpCode();
1805 : : // There must be an operator before a push
1806 [ - + ][ + + ]: 66948 : if ( (eOp == ocPush || eOp == ocColRowNameAuto) &&
[ + + ]
1807 : : !( (eLastOp == ocOpen) || (eLastOp == ocSep) ||
1808 [ + + ][ + - ]: 9766 : (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)) )
[ - + ]
1809 : 0 : SetError(errOperatorExpected);
1810 : : // Operator and Plus => operator
1811 [ + + ][ + - ]: 66948 : if (eOp == ocAdd && (eLastOp == ocOpen || eLastOp == ocSep ||
[ + - ][ - + ]
[ # # ]
1812 : : (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)))
1813 : 0 : eOp = NextToken();
1814 : : else
1815 : : {
1816 : : // Before an operator there must not be another operator, with the
1817 : : // exception of AND and OR.
1818 [ + + ][ + + ]: 66948 : if ( eOp != ocAnd && eOp != ocOr &&
[ + + ][ + + ]
[ + - ][ + - ]
[ - + ][ # # ]
1819 : : (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP )
1820 : : && (eLastOp == ocOpen || eLastOp == ocSep ||
1821 : : (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_UN_OP)))
1822 : : {
1823 : 0 : SetError(errVariableExpected);
1824 [ # # ][ # # ]: 0 : if ( bAutoCorrect && !pStack )
1825 : : {
1826 [ # # ][ # # ]: 0 : if ( eOp == eLastOp || eLastOp == ocOpen )
1827 : : { // throw away duplicated operator
1828 : 0 : aCorrectedSymbol.Erase();
1829 : 0 : bCorrected = true;
1830 : : }
1831 : : else
1832 : : {
1833 : 0 : xub_StrLen nPos = aCorrectedFormula.Len();
1834 [ # # ]: 0 : if ( nPos )
1835 : : {
1836 : 0 : nPos--;
1837 : 0 : sal_Unicode c = aCorrectedFormula.GetChar( nPos );
1838 [ # # # # : 0 : switch ( eOp )
# ]
1839 : : { // swap operators
1840 : : case ocGreater:
1841 [ # # ]: 0 : if ( c == mxSymbols->getSymbol(ocEqual).GetChar(0) )
1842 : : { // >= instead of =>
1843 : : aCorrectedFormula.SetChar( nPos,
1844 : 0 : mxSymbols->getSymbol(ocGreater).GetChar(0) );
1845 : 0 : aCorrectedSymbol = c;
1846 : 0 : bCorrected = true;
1847 : : }
1848 : 0 : break;
1849 : : case ocLess:
1850 [ # # ]: 0 : if ( c == mxSymbols->getSymbol(ocEqual).GetChar(0) )
1851 : : { // <= instead of =<
1852 : : aCorrectedFormula.SetChar( nPos,
1853 : 0 : mxSymbols->getSymbol(ocLess).GetChar(0) );
1854 : 0 : aCorrectedSymbol = c;
1855 : 0 : bCorrected = true;
1856 : : }
1857 [ # # ]: 0 : else if ( c == mxSymbols->getSymbol(ocGreater).GetChar(0) )
1858 : : { // <> instead of ><
1859 : : aCorrectedFormula.SetChar( nPos,
1860 : 0 : mxSymbols->getSymbol(ocLess).GetChar(0) );
1861 : 0 : aCorrectedSymbol = c;
1862 : 0 : bCorrected = true;
1863 : : }
1864 : 0 : break;
1865 : : case ocMul:
1866 [ # # ]: 0 : if ( c == mxSymbols->getSymbol(ocSub).GetChar(0) )
1867 : : { // *- instead of -*
1868 : : aCorrectedFormula.SetChar( nPos,
1869 : 0 : mxSymbols->getSymbol(ocMul).GetChar(0) );
1870 : 0 : aCorrectedSymbol = c;
1871 : 0 : bCorrected = true;
1872 : : }
1873 : 0 : break;
1874 : : case ocDiv:
1875 [ # # ]: 0 : if ( c == mxSymbols->getSymbol(ocSub).GetChar(0) )
1876 : : { // /- instead of -/
1877 : : aCorrectedFormula.SetChar( nPos,
1878 : 0 : mxSymbols->getSymbol(ocDiv).GetChar(0) );
1879 : 0 : aCorrectedSymbol = c;
1880 : 0 : bCorrected = true;
1881 : : }
1882 : 0 : break;
1883 : : default:
1884 : : ; // nothing
1885 : : }
1886 : : }
1887 : : }
1888 : : }
1889 : : }
1890 : 66948 : eLastOp = eOp;
1891 : : }
1892 : 70787 : return eOp;
1893 : : }
1894 : 36859 : void FormulaCompiler::PutCode( FormulaTokenRef& p )
1895 : : {
1896 [ - + ]: 36859 : if( pc >= MAXCODE-1 )
1897 : : {
1898 [ # # ]: 0 : if ( pc == MAXCODE-1 )
1899 : : {
1900 [ # # ]: 0 : p = new FormulaByteToken( ocStop );
1901 : 0 : p->IncRef();
1902 : 0 : *pCode++ = p.get();
1903 : 0 : ++pc;
1904 : : }
1905 : 0 : SetError(errCodeOverflow);
1906 : 0 : return;
1907 : : }
1908 [ - + ][ # # ]: 36859 : if( pArr->GetCodeError() && !bCompileForFAP )
[ - + ]
1909 : 0 : return;
1910 : 36859 : ForceArrayOperator( p, pCurrentFactorToken);
1911 : 36859 : p->IncRef();
1912 : 36859 : *pCode++ = p.get();
1913 : 36859 : pc++;
1914 : : }
1915 : :
1916 : : // -----------------------------------------------------------------------------
1917 : 0 : bool FormulaCompiler::HandleExternalReference(const FormulaToken& /*_aToken*/)
1918 : : {
1919 : 0 : return true;
1920 : : }
1921 : : // -----------------------------------------------------------------------------
1922 : 0 : bool FormulaCompiler::HandleRange()
1923 : : {
1924 : 0 : return true;
1925 : : }
1926 : : // -----------------------------------------------------------------------------
1927 : 0 : bool FormulaCompiler::HandleSingleRef()
1928 : : {
1929 : 0 : return true;
1930 : : }
1931 : : // -----------------------------------------------------------------------------
1932 : 0 : bool FormulaCompiler::HandleDbData()
1933 : : {
1934 : 0 : return true;
1935 : : }
1936 : : // -----------------------------------------------------------------------------
1937 : 0 : void FormulaCompiler::CreateStringFromSingleRef(rtl::OUStringBuffer& /*rBuffer*/,FormulaToken* /*pTokenP*/)
1938 : : {
1939 : 0 : }
1940 : : // -----------------------------------------------------------------------------
1941 : 0 : void FormulaCompiler::CreateStringFromDoubleRef(rtl::OUStringBuffer& /*rBuffer*/,FormulaToken* /*pTokenP*/)
1942 : : {
1943 : 0 : }
1944 : : // -----------------------------------------------------------------------------
1945 : 0 : void FormulaCompiler::CreateStringFromIndex(rtl::OUStringBuffer& /*rBuffer*/,FormulaToken* /*pTokenP*/)
1946 : : {
1947 : 0 : }
1948 : : // -----------------------------------------------------------------------------
1949 : 0 : void FormulaCompiler::CreateStringFromMatrix(rtl::OUStringBuffer& /*rBuffer*/,FormulaToken* /*pTokenP*/)
1950 : : {
1951 : 0 : }
1952 : : // -----------------------------------------------------------------------------
1953 : 0 : void FormulaCompiler::CreateStringFromExternal(rtl::OUStringBuffer& /*rBuffer*/,FormulaToken* /*pTokenP*/)
1954 : : {
1955 : 0 : }
1956 : : // -----------------------------------------------------------------------------
1957 : 0 : void FormulaCompiler::LocalizeString( String& /*rName*/ )
1958 : : {
1959 : 0 : }
1960 : 284 : void FormulaCompiler::PushTokenArray( FormulaTokenArray* pa, bool bTemp )
1961 : : {
1962 [ - + ][ # # ]: 284 : if ( bAutoCorrect && !pStack )
1963 : : { // don't merge stacked subroutine code into entered formula
1964 : 0 : aCorrectedFormula += aCorrectedSymbol;
1965 : 0 : aCorrectedSymbol.Erase();
1966 : : }
1967 : 284 : FormulaArrayStack* p = new FormulaArrayStack;
1968 : 284 : p->pNext = pStack;
1969 : 284 : p->pArr = pArr;
1970 : 284 : p->bTemp = bTemp;
1971 : 284 : pStack = p;
1972 : 284 : pArr = pa;
1973 : 284 : }
1974 : :
1975 : : // =============================================================================
1976 : : } // formula
1977 : : // =============================================================================
1978 : :
1979 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|