Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/unoobj/tokenuno.cxx
Line
Count
Source
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
20
#include <memory>
21
#include <tokenuno.hxx>
22
23
#include <sal/macros.h>
24
#include <sal/log.hxx>
25
26
#include <com/sun/star/sheet/ComplexReference.hpp>
27
#include <com/sun/star/sheet/ExternalReference.hpp>
28
#include <com/sun/star/sheet/ReferenceFlags.hpp>
29
#include <com/sun/star/sheet/AddressConvention.hpp>
30
#include <com/sun/star/sheet/NameToken.hpp>
31
#include <com/sun/star/sheet/TableRefToken.hpp>
32
#include <com/sun/star/table/CellAddress.hpp>
33
34
#include <svl/itemprop.hxx>
35
#include <vcl/svapp.hxx>
36
#include <comphelper/string.hxx>
37
38
#include <miscuno.hxx>
39
#include <convuno.hxx>
40
#include <unonames.hxx>
41
#include <compiler.hxx>
42
#include <tokenarray.hxx>
43
#include <docsh.hxx>
44
#include <rangeseq.hxx>
45
#include <externalrefmgr.hxx>
46
47
using namespace ::formula;
48
using namespace ::com::sun::star;
49
50
static std::span<const SfxItemPropertyMapEntry> lcl_GetFormulaParserMap()
51
1
{
52
1
    static const SfxItemPropertyMapEntry aFormulaParserMap_Impl[] =
53
1
    {
54
1
        { SC_UNO_COMPILEFAP,           0,  cppu::UnoType<bool>::get(),                   0, 0 },
55
1
        { SC_UNO_COMPILEENGLISH,       0,  cppu::UnoType<bool>::get(),                   0, 0 },
56
1
        { SC_UNO_IGNORELEADING,        0,  cppu::UnoType<bool>::get(),                   0, 0 },
57
1
        { SC_UNO_FORMULACONVENTION,    0,  cppu::UnoType<decltype(sheet::AddressConvention::UNSPECIFIED)>::get(), 0, 0 },
58
1
        { SC_UNO_OPCODEMAP,            0,  cppu::UnoType<uno::Sequence< sheet::FormulaOpCodeMapEntry >>::get(), 0, 0 },
59
1
    };
60
1
    return aFormulaParserMap_Impl;
61
1
}
62
63
const formula::FormulaGrammar::AddressConvention aConvMap[] = {
64
    formula::FormulaGrammar::CONV_OOO,        // <- AddressConvention::OOO
65
    formula::FormulaGrammar::CONV_XL_A1,      // <- AddressConvention::XL_A1
66
    formula::FormulaGrammar::CONV_XL_R1C1,    // <- AddressConvention::XL_R1C1
67
    formula::FormulaGrammar::CONV_XL_OOX,     // <- AddressConvention::XL_OOX
68
    formula::FormulaGrammar::CONV_LOTUS_A1    // <- AddressConvention::LOTUS_A1
69
};
70
// sal_Int16 because of comparison of integer expressions below.
71
constexpr sal_Int16 nConvMapCount = SAL_N_ELEMENTS(aConvMap);
72
73
74
SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, u"ScFormulaParserObj"_ustr, SC_SERVICENAME_FORMULAPARS )
75
76
ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) :
77
10.4k
    mpDocShell( pDocSh ),
78
10.4k
    mnConv( sheet::AddressConvention::UNSPECIFIED ),
79
10.4k
    mbEnglish( false ),
80
10.4k
    mbIgnoreSpaces( true ),
81
10.4k
    mbCompileFAP( false ),
82
10.4k
    mbRefConventionChartOOXML( false )
83
10.4k
{
84
10.4k
    mpDocShell->GetDocument().AddUnoObject(*this);
85
10.4k
}
86
87
ScFormulaParserObj::~ScFormulaParserObj()
88
10.4k
{
89
10.4k
    SolarMutexGuard g;
90
91
10.4k
    if (mpDocShell)
92
10.4k
        mpDocShell->GetDocument().RemoveUnoObject(*this);
93
10.4k
}
94
95
void ScFormulaParserObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
96
278k
{
97
278k
    if ( rHint.GetId() == SfxHintId::Dying )
98
0
        mpDocShell = nullptr;
99
278k
}
100
101
// XFormulaParser
102
103
void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
104
5.00k
{
105
5.00k
    formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
106
5.00k
    if (mnConv >= 0 && mnConv < nConvMapCount)
107
5.00k
        eConv = aConvMap[mnConv];
108
109
    // If mxOpCodeMap is not empty it overrides mbEnglish, and vice versa. We
110
    // don't need to initialize things twice.
111
5.00k
    if (mxOpCodeMap)
112
5.00k
        rCompiler.SetFormulaLanguage( mxOpCodeMap );
113
0
    else
114
0
    {
115
0
        const sal_Int32 nFormulaLanguage = (eConv == formula::FormulaGrammar::CONV_XL_OOX ?
116
0
                sheet::FormulaLanguage::OOXML :
117
0
                (mbEnglish ? sheet::FormulaLanguage::ENGLISH : sheet::FormulaLanguage::NATIVE));
118
0
        ScCompiler::OpCodeMapPtr xMap = rCompiler.GetOpCodeMap( nFormulaLanguage);
119
0
        rCompiler.SetFormulaLanguage( xMap);
120
0
    }
121
122
5.00k
    rCompiler.SetRefConvention( eConv );
123
5.00k
    rCompiler.EnableJumpCommandReorder(!mbCompileFAP);
124
5.00k
    rCompiler.EnableStopOnError(!mbCompileFAP);
125
126
5.00k
    rCompiler.SetExternalLinks(maExternalLinks);
127
5.00k
    rCompiler.SetRefConventionChartOOXML(mbRefConventionChartOOXML);
128
5.00k
}
129
130
uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula(
131
    const OUString& aFormula, const table::CellAddress& rReferencePos )
132
5.00k
{
133
5.00k
    SolarMutexGuard aGuard;
134
5.00k
    uno::Sequence<sheet::FormulaToken> aRet;
135
136
5.00k
    if (mpDocShell)
137
5.00k
    {
138
5.00k
        ScDocument& rDoc = mpDocShell->GetDocument();
139
5.00k
        ScExternalRefManager::ApiGuard aExtRefGuard(rDoc);
140
141
5.00k
        ScAddress aRefPos( ScAddress::UNINITIALIZED );
142
5.00k
        ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
143
5.00k
        ScCompiler aCompiler( rDoc, aRefPos, rDoc.GetGrammar());
144
5.00k
        SetCompilerFlags( aCompiler );
145
146
5.00k
        std::unique_ptr<ScTokenArray> pCode = aCompiler.CompileString( aFormula );
147
5.00k
        if (pCode->HasOpCode(ocTableRef))
148
0
        {
149
0
            FormulaError nErr = pCode->GetCodeError();
150
0
            aCompiler.EnableJumpCommandReorder(true);
151
0
            aCompiler.CompileTokenArray();  // needed for corresponding inner reference
152
0
            pCode->DelRPN();                // can be discarded
153
0
            pCode->SetCodeError(nErr);      // reset to parsing error, if any
154
0
        }
155
5.00k
        ScTokenConversion::ConvertToTokenSequence( rDoc, aRet, *pCode );
156
5.00k
    }
157
158
5.00k
    return aRet;
159
5.00k
}
160
161
OUString SAL_CALL ScFormulaParserObj::printFormula(
162
        const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos )
163
0
{
164
0
    SolarMutexGuard aGuard;
165
0
    OUString aRet;
166
167
0
    if (mpDocShell)
168
0
    {
169
0
        ScDocument& rDoc = mpDocShell->GetDocument();
170
0
        ScTokenArray aCode(rDoc);
171
0
        (void)ScTokenConversion::ConvertToTokenArray( rDoc, aCode, aTokens );
172
0
        ScAddress aRefPos( ScAddress::UNINITIALIZED );
173
0
        ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
174
0
        ScCompiler aCompiler(rDoc, aRefPos, aCode, rDoc.GetGrammar());
175
0
        SetCompilerFlags( aCompiler );
176
177
0
        OUStringBuffer aBuffer;
178
0
        aCompiler.CreateStringFromTokenArray( aBuffer );
179
0
        aRet = aBuffer.makeStringAndClear();
180
0
    }
181
182
0
    return aRet;
183
0
}
184
185
// XPropertySet
186
187
uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFormulaParserObj::getPropertySetInfo()
188
10.4k
{
189
10.4k
    static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetFormulaParserMap() ));
190
10.4k
    return aRef;
191
10.4k
}
192
193
void SAL_CALL ScFormulaParserObj::setPropertyValue(
194
                        const OUString& aPropertyName, const uno::Any& aValue )
195
42.0k
{
196
42.0k
    SolarMutexGuard aGuard;
197
42.0k
    if ( aPropertyName == SC_UNO_COMPILEFAP )
198
0
    {
199
0
        aValue >>= mbCompileFAP;
200
0
    }
201
42.0k
    else if ( aPropertyName == SC_UNO_COMPILEENGLISH )
202
10.4k
    {
203
10.4k
        bool bOldEnglish = mbEnglish;
204
10.4k
        if (!(aValue >>= mbEnglish))
205
0
            throw lang::IllegalArgumentException();
206
207
        // Need to recreate the symbol map to change English property
208
        // because the map is const. So for performance reasons set
209
        // CompileEnglish _before_ OpCodeMap!
210
10.4k
        if (mxOpCodeMap && mbEnglish != bOldEnglish)
211
0
        {
212
0
            mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish);
213
0
        }
214
215
10.4k
    }
216
31.6k
    else if ( aPropertyName == SC_UNO_FORMULACONVENTION )
217
10.4k
    {
218
10.4k
        aValue >>= mnConv;
219
220
10.4k
        bool bOldEnglish = mbEnglish;
221
10.4k
        if (mnConv >= 0 && mnConv < nConvMapCount
222
10.4k
                && aConvMap[mnConv] == formula::FormulaGrammar::CONV_XL_OOX)
223
10.4k
            mbEnglish = true;
224
225
        // Same as for SC_UNO_COMPILEENGLISH, though an OpCodeMap should not
226
        // had been set for CONV_XL_OOX.
227
10.4k
        if (mxOpCodeMap && mbEnglish != bOldEnglish)
228
0
        {
229
0
            mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish);
230
0
        }
231
10.4k
    }
232
21.1k
    else if ( aPropertyName == SC_UNO_IGNORELEADING )
233
10.4k
    {
234
10.4k
        aValue >>= mbIgnoreSpaces;
235
10.4k
    }
236
10.7k
    else if ( aPropertyName == SC_UNO_OPCODEMAP )
237
10.4k
    {
238
10.4k
        if (!(aValue >>= maOpCodeMapping))
239
0
            throw lang::IllegalArgumentException();
240
241
10.4k
        mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish);
242
243
10.4k
    }
244
315
    else if ( aPropertyName == SC_UNO_EXTERNALLINKS )
245
320
    {
246
320
        if (!(aValue >>= maExternalLinks))
247
0
            throw lang::IllegalArgumentException();
248
320
    }
249
18.4E
    else if ( aPropertyName == SC_UNO_REF_CONV_CHARTOOXML )
250
0
    {
251
0
        if (!(aValue >>= mbRefConventionChartOOXML))
252
0
            throw lang::IllegalArgumentException();
253
0
    }
254
18.4E
    else
255
18.4E
        throw beans::UnknownPropertyException(aPropertyName);
256
42.0k
}
257
258
uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const OUString& aPropertyName )
259
0
{
260
0
    SolarMutexGuard aGuard;
261
0
    uno::Any aRet;
262
0
    if ( aPropertyName == SC_UNO_COMPILEFAP )
263
0
    {
264
0
        aRet <<= mbCompileFAP;
265
0
    }
266
0
    else if ( aPropertyName == SC_UNO_COMPILEENGLISH )
267
0
    {
268
0
        aRet <<= mbEnglish;
269
0
    }
270
0
    else if ( aPropertyName == SC_UNO_FORMULACONVENTION )
271
0
    {
272
0
        aRet <<= mnConv;
273
0
    }
274
0
    else if ( aPropertyName == SC_UNO_IGNORELEADING )
275
0
    {
276
0
        aRet <<= mbIgnoreSpaces;
277
0
    }
278
0
    else if ( aPropertyName == SC_UNO_OPCODEMAP )
279
0
    {
280
0
        aRet <<= maOpCodeMapping;
281
0
    }
282
0
    else if ( aPropertyName == SC_UNO_EXTERNALLINKS )
283
0
    {
284
0
        aRet <<= maExternalLinks;
285
0
    }
286
0
    else if ( aPropertyName == SC_UNO_REF_CONV_CHARTOOXML )
287
0
    {
288
0
        aRet <<= mbRefConventionChartOOXML;
289
0
    }
290
0
    else
291
0
        throw beans::UnknownPropertyException(aPropertyName);
292
0
    return aRet;
293
0
}
294
295
SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
296
297
static void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
298
115
{
299
115
    rAPI.Column         = 0;
300
115
    rAPI.Row            = 0;
301
115
    rAPI.Sheet          = 0;
302
115
    rAPI.RelativeColumn = 0;
303
115
    rAPI.RelativeRow    = 0;
304
115
    rAPI.RelativeSheet  = 0;
305
306
115
    sal_Int32 nFlags = 0;
307
115
    if ( rRef.IsColRel() )
308
0
    {
309
0
        nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
310
0
        rAPI.RelativeColumn = rRef.Col();
311
0
    }
312
115
    else
313
115
        rAPI.Column = rRef.Col();
314
315
115
    if ( rRef.IsRowRel() )
316
0
    {
317
0
        nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
318
0
        rAPI.RelativeRow = rRef.Row();
319
0
    }
320
115
    else
321
115
        rAPI.Row = rRef.Row();
322
323
115
    if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
324
115
    if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
325
115
    if ( rRef.IsFlag3D() )     nFlags |= sheet::ReferenceFlags::SHEET_3D;
326
115
    if ( rRef.IsRelName() )    nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
327
115
    rAPI.Flags = nFlags;
328
115
}
329
330
static void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
331
13.4k
{
332
13.4k
    sal_Int32 nFlags = 0;
333
13.4k
    if ( rRef.IsColRel() )
334
1.18k
    {
335
1.18k
        nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
336
1.18k
        rAPI.RelativeColumn = rRef.Col();
337
1.18k
        rAPI.Column = 0;
338
1.18k
    }
339
12.2k
    else
340
12.2k
    {
341
12.2k
        rAPI.RelativeColumn = 0;
342
12.2k
        rAPI.Column = rRef.Col();
343
12.2k
    }
344
345
13.4k
    if ( rRef.IsRowRel() )
346
1.34k
    {
347
1.34k
        nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
348
1.34k
        rAPI.RelativeRow = rRef.Row();
349
1.34k
        rAPI.Row = 0;
350
1.34k
    }
351
12.0k
    else
352
12.0k
    {
353
12.0k
        rAPI.RelativeRow = 0;
354
12.0k
        rAPI.Row = rRef.Row();
355
12.0k
    }
356
357
13.4k
    if ( rRef.IsTabRel() )
358
2.73k
    {
359
2.73k
        nFlags |= sheet::ReferenceFlags::SHEET_RELATIVE;
360
2.73k
        rAPI.RelativeSheet = rRef.Tab();
361
2.73k
        rAPI.Sheet = 0;
362
2.73k
    }
363
10.6k
    else
364
10.6k
    {
365
10.6k
        rAPI.RelativeSheet = 0;
366
10.6k
        rAPI.Sheet = rRef.Tab();
367
10.6k
    }
368
369
13.4k
    if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
370
13.4k
    if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
371
13.4k
    if ( rRef.IsTabDeleted() ) nFlags |= sheet::ReferenceFlags::SHEET_DELETED;
372
13.4k
    if ( rRef.IsFlag3D() )     nFlags |= sheet::ReferenceFlags::SHEET_3D;
373
13.4k
    if ( rRef.IsRelName() )    nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
374
13.4k
    rAPI.Flags = nFlags;
375
13.4k
}
376
377
bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
378
        ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
379
3.12k
{
380
3.12k
    return !rTokenArray.Fill(rSequence, rDoc.GetSharedStringPool(), rDoc.GetExternalRefManager());
381
3.12k
}
382
383
void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc,
384
        uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray,
385
        bool bIgnoreTableRefNoInnerReference )
386
12.4k
{
387
12.4k
    sal_Int32 nLen = static_cast<sal_Int32>(rTokenArray.GetLen());
388
12.4k
    formula::FormulaToken** pTokens = rTokenArray.GetArray();
389
12.4k
    if ( pTokens )
390
12.1k
    {
391
12.1k
        rSequence.realloc(nLen);
392
12.1k
        auto pSequence = rSequence.getArray();
393
45.4k
        for (sal_Int32 nPos=0; nPos<nLen; nPos++)
394
33.2k
        {
395
33.2k
            const formula::FormulaToken& rToken = *pTokens[nPos];
396
33.2k
            sheet::FormulaToken& rAPI = pSequence[nPos];
397
398
33.2k
            OpCode eOpCode = rToken.GetOpCode();
399
            // eOpCode may be changed in the following switch/case
400
33.2k
            switch ( rToken.GetType() )
401
33.2k
            {
402
4.87k
                case svByte:
403
                    // Only the count of spaces is stored as "long". Parameter count is ignored.
404
4.87k
                    if ( eOpCode == ocSpaces )
405
54
                        rAPI.Data <<= static_cast<sal_Int32>(static_cast<const FormulaByteToken&>(rToken).GetByte());
406
4.81k
                    else if (eOpCode == ocWhitespace)
407
0
                    {
408
0
                        auto const & rSToken = static_cast<const FormulaSpaceToken&>(rToken);
409
                        // Convention is one character repeated.
410
0
                        if (rSToken.GetByte() == 1)
411
0
                            rAPI.Data <<= OUString( rSToken.GetChar());
412
0
                        else
413
0
                        {
414
0
                            OUStringBuffer aBuf(rSToken.GetByte());
415
0
                            comphelper::string::padToLength( aBuf, rSToken.GetByte(), rSToken.GetChar());
416
0
                            rAPI.Data <<= aBuf.makeStringAndClear();
417
0
                        }
418
0
                    }
419
4.81k
                    else
420
4.81k
                        rAPI.Data.clear();      // no data
421
4.87k
                    break;
422
2.48k
                case formula::svDouble:
423
2.48k
                    rAPI.Data <<= static_cast<const FormulaDoubleToken&>(rToken).GetDouble();
424
2.48k
                    break;
425
2.38k
                case formula::svString:
426
2.38k
                    rAPI.Data <<= static_cast<const FormulaStringToken&>(rToken).GetString().getString();
427
2.38k
                    break;
428
0
                case svExternal:
429
                    // Function name is stored as string.
430
                    // Byte (parameter count) is ignored.
431
0
                    rAPI.Data <<= static_cast<const FormulaExternalToken&>(rToken).GetExternal();
432
0
                    break;
433
3.82k
                case svSingleRef:
434
3.82k
                    {
435
3.82k
                        sheet::SingleReference aSingleRef;
436
3.82k
                        lcl_SingleRefToApi( aSingleRef, static_cast<const ScSingleRefToken&>(rToken).GetSingleRef() );
437
3.82k
                        rAPI.Data <<= aSingleRef;
438
3.82k
                    }
439
3.82k
                    break;
440
4.78k
                case formula::svDoubleRef:
441
4.78k
                    {
442
4.78k
                        sheet::ComplexReference aCompRef;
443
4.78k
                        lcl_SingleRefToApi( aCompRef.Reference1, static_cast<const ScDoubleRefToken&>(rToken).GetSingleRef() );
444
4.78k
                        lcl_SingleRefToApi( aCompRef.Reference2, static_cast<const ScDoubleRefToken&>(rToken).GetSingleRef2() );
445
4.78k
                        rAPI.Data <<= aCompRef;
446
4.78k
                    }
447
4.78k
                    break;
448
331
                case svIndex:
449
331
                    {
450
331
                        if (rToken.GetOpCode() == ocTableRef)
451
15
                        {
452
15
                            const ScTableRefToken* pTR = static_cast<const ScTableRefToken*>(&rToken);
453
15
                            sheet::TableRefToken aTableRefToken;
454
15
                            aTableRefToken.Index = static_cast<sal_Int32>( pTR->GetIndex());
455
15
                            aTableRefToken.Item = static_cast<sal_Int16>( pTR->GetItem());
456
15
                            const FormulaToken* pRef = pTR->GetAreaRefRPN();
457
15
                            assert((pRef || bIgnoreTableRefNoInnerReference)
458
15
                                    && "something forgot to create RPN for ocTableRef inner reference");
459
15
                            (void)bIgnoreTableRefNoInnerReference;
460
15
                            if (pRef)
461
15
                            {
462
15
                                switch (pRef->GetType())
463
15
                                {
464
0
                                    case svSingleRef:
465
0
                                        lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, static_cast<const ScSingleRefToken*>(pRef)->GetSingleRef());
466
0
                                        aTableRefToken.Reference.Reference2 = aTableRefToken.Reference.Reference1;
467
0
                                    break;
468
15
                                    case svDoubleRef:
469
15
                                        lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, static_cast<const ScDoubleRefToken*>(pRef)->GetSingleRef());
470
15
                                        lcl_SingleRefToApi( aTableRefToken.Reference.Reference2, static_cast<const ScDoubleRefToken*>(pRef)->GetSingleRef2());
471
15
                                    break;
472
0
                                    default:
473
0
                                        ;   // nothing
474
15
                                }
475
15
                            }
476
15
                            rAPI.Data <<= aTableRefToken;
477
15
                        }
478
316
                        else
479
316
                        {
480
316
                            auto const & rIndexToken = static_cast<const FormulaIndexToken&>(rToken);
481
316
                            sheet::NameToken aNameToken;
482
316
                            aNameToken.Index = static_cast<sal_Int32>( rIndexToken.GetIndex() );
483
316
                            aNameToken.Sheet = rIndexToken.GetSheet();
484
316
                            rAPI.Data <<= aNameToken;
485
316
                        }
486
331
                    }
487
331
                    break;
488
331
                case svMatrix:
489
6
                    if (!ScRangeToSequence::FillMixedArray( rAPI.Data, static_cast<const ScMatrixToken&>(rToken).GetMatrix(), true))
490
0
                        rAPI.Data.clear();
491
6
                    break;
492
27
                case svExternalSingleRef:
493
27
                    {
494
27
                        const auto & rESRToken = static_cast<const ScExternalSingleRefToken&>(rToken);
495
27
                        sheet::SingleReference aSingleRef;
496
27
                        lcl_ExternalRefToApi( aSingleRef, rESRToken.GetSingleRef() );
497
27
                        size_t nCacheId;
498
27
                        rDoc.GetExternalRefManager()->getCacheTable(
499
27
                            rESRToken.GetFileId(), rESRToken.GetTableName().getString(), false, &nCacheId);
500
27
                        aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
501
27
                        sheet::ExternalReference aExtRef;
502
27
                        aExtRef.Index = rESRToken.GetFileId();
503
27
                        aExtRef.Reference <<= aSingleRef;
504
27
                        rAPI.Data <<= aExtRef;
505
27
                        eOpCode = ocPush;
506
27
                    }
507
27
                    break;
508
44
                case svExternalDoubleRef:
509
44
                    {
510
44
                        const auto & rEDRToken = static_cast<const ScExternalDoubleRefToken&>(rToken);
511
44
                        sheet::ComplexReference aComplRef;
512
44
                        lcl_ExternalRefToApi( aComplRef.Reference1, rEDRToken.GetSingleRef() );
513
44
                        lcl_ExternalRefToApi( aComplRef.Reference2, rEDRToken.GetSingleRef2() );
514
44
                        size_t nCacheId;
515
44
                        rDoc.GetExternalRefManager()->getCacheTable(
516
44
                            rEDRToken.GetFileId(), rEDRToken.GetTableName().getString(), false, &nCacheId);
517
44
                        aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId );
518
                        // NOTE: This assumes that cached sheets are in consecutive order!
519
44
                        aComplRef.Reference2.Sheet =
520
44
                            aComplRef.Reference1.Sheet +
521
44
                            (rEDRToken.GetSingleRef2().Tab() - rEDRToken.GetSingleRef().Tab());
522
44
                        sheet::ExternalReference aExtRef;
523
44
                        aExtRef.Index = rEDRToken.GetFileId();
524
44
                        aExtRef.Reference <<= aComplRef;
525
44
                        rAPI.Data <<= aExtRef;
526
44
                        eOpCode = ocPush;
527
44
                    }
528
44
                    break;
529
0
                case svExternalName:
530
0
                    {
531
0
                        auto const & rExtNameToken = static_cast<const ScExternalNameToken&>(rToken);
532
0
                        sheet::ExternalReference aExtRef;
533
0
                        aExtRef.Index = rExtNameToken.GetFileId();
534
0
                        aExtRef.Reference <<= rExtNameToken.GetName().getString();
535
0
                        rAPI.Data <<= aExtRef;
536
0
                        eOpCode = ocPush;
537
0
                    }
538
0
                    break;
539
0
                default:
540
0
                    SAL_WARN("sc",  "ScTokenConversion::ConvertToTokenSequence: unhandled token type " << StackVarEnumToString(rToken.GetType()));
541
0
                    [[fallthrough]];
542
1.12k
                case svError:
543
1.12k
                    switch (static_cast<const FormulaErrorToken&>(rToken).GetError())
544
1.12k
                    {
545
0
                        case FormulaError::NoCode:
546
0
                            eOpCode = ocErrNull;
547
0
                            break;
548
0
                        case FormulaError::DivisionByZero:
549
0
                            eOpCode = ocErrDivZero;
550
0
                            break;
551
0
                        case FormulaError::NoValue:
552
0
                            eOpCode = ocErrValue;
553
0
                            break;
554
1.11k
                        case FormulaError::NoRef:
555
1.11k
                            eOpCode = ocErrRef;
556
1.11k
                            break;
557
0
                        case FormulaError::NoName:
558
0
                            eOpCode = ocErrName;
559
0
                            break;
560
0
                        case FormulaError::IllegalFPOperation:
561
0
                            eOpCode = ocErrNum;
562
0
                            break;
563
8
                        case FormulaError::NotAvailable:
564
8
                            eOpCode = ocErrNA;
565
8
                            break;
566
0
                        default:
567
0
                            break;
568
1.12k
                    }
569
1.12k
                    [[fallthrough]];
570
1.12k
                case svJump:    // occurs with ocIf, ocChoose
571
1.12k
                case svMissing: // occurs with ocMissing
572
14.5k
                case svSep:     // occurs with ocSep, ocOpen, ocClose, ocArray*
573
14.5k
                    rAPI.Data.clear();      // no data
574
33.2k
            }
575
33.2k
            rAPI.OpCode = static_cast<sal_Int32>(eOpCode);      //! assuming equal values for the moment
576
33.2k
        }
577
12.1k
    }
578
343
    else
579
343
        rSequence.realloc(0);
580
12.4k
}
581
582
ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::unique_ptr<formula::FormulaCompiler> && _pCompiler)
583
0
: formula::FormulaOpCodeMapperObj(std::move(_pCompiler))
584
0
{
585
0
}
586
587
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */