LibreOffice Module basic (master) 1
runtime.cxx
Go to the documentation of this file.
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 <stdlib.h>
21
22#include <algorithm>
23#include <string_view>
24#include <unordered_map>
25
26#include <com/sun/star/beans/XPropertySet.hpp>
27#include <com/sun/star/container/XEnumerationAccess.hpp>
28#include <com/sun/star/container/XIndexAccess.hpp>
29#include <com/sun/star/script/XDefaultMethod.hpp>
30#include <com/sun/star/uno/Any.hxx>
31#include <com/sun/star/util/SearchAlgorithms2.hpp>
32
34#include <comphelper/string.hxx>
35#include <o3tl/safeint.hxx>
36#include <sal/log.hxx>
37
38#include <tools/wldcrd.hxx>
40
41#include <utility>
42#include <vcl/svapp.hxx>
43#include <vcl/settings.hxx>
44
45#include <rtl/math.hxx>
46#include <rtl/ustrbuf.hxx>
47#include <rtl/character.hxx>
48
49#include <svl/numformat.hxx>
50#include <svl/zforlist.hxx>
51
55
56#include <basic/sbuno.hxx>
57
58#include <codegen.hxx>
59#include "comenumwrapper.hxx"
60#include "ddectrl.hxx"
61#include "dllmgr.hxx"
62#include <errobject.hxx>
63#include <image.hxx>
64#include <iosys.hxx>
65#include <opcodes.hxx>
66#include <runtime.hxx>
67#include <sb.hxx>
68#include <sbintern.hxx>
69#include <sbprop.hxx>
70#include <sbunoobj.hxx>
72#include <memory>
73
75
76using namespace com::sun::star::uno;
77using namespace com::sun::star::container;
78using namespace com::sun::star::lang;
79using namespace com::sun::star::beans;
80using namespace com::sun::star::script;
81
82using namespace ::com::sun::star;
83
84static void lcl_clearImpl( SbxVariableRef const & refVar, SbxDataType const & eType );
85static void lcl_eraseImpl( SbxVariableRef const & refVar, bool bVBAEnabled );
86
87namespace
88{
89class ScopedWritableGuard
90{
91public:
92 ScopedWritableGuard(const SbxVariableRef& rVar, bool bMakeWritable)
93 : m_rVar(rVar)
94 , m_bReset(bMakeWritable && !rVar->CanWrite())
95 {
96 if (m_bReset)
97 {
98 m_rVar->SetFlag(SbxFlagBits::Write);
99 }
100 }
101 ~ScopedWritableGuard()
102 {
103 if (m_bReset)
104 {
105 m_rVar->ResetFlag(SbxFlagBits::Write);
106 }
107 }
108
109private:
110 SbxVariableRef m_rVar;
111 bool m_bReset;
112};
113}
114
116{
118 return pInst && pInst->pRun && pInst->pRun->bVBAEnabled;
119}
120
121void StarBASIC::SetVBAEnabled( bool bEnabled )
122{
123 if ( bDocBasic )
124 {
125 bVBAEnabled = bEnabled;
126 }
127}
128
130{
132}
133
134struct SbiArgv { // Argv stack:
136 short nArgc; // Argc
137
138 SbiArgv(SbxArrayRef refArgv_, short nArgc_) :
139 refArgv(std::move(refArgv_)),
140 nArgc(nArgc_) {}
141};
142
143struct SbiGosub { // GOSUB-Stack:
144 const sal_uInt8* pCode; // Return-Pointer
145 sal_uInt16 nStartForLvl; // #118235: For Level in moment of gosub
146
147 SbiGosub(const sal_uInt8* pCode_, sal_uInt16 nStartForLvl_) :
148 pCode(pCode_),
149 nStartForLvl(nStartForLvl_) {}
150};
151
152const SbiRuntime::pStep0 SbiRuntime::aStep0[] = { // all opcodes without operands
175
178 // load/save
179 &SbiRuntime::StepARGC, // establish new Argv
180 &SbiRuntime::StepARGV, // TOS ==> current Argv
181 &SbiRuntime::StepINPUT, // Input ==> TOS
182 &SbiRuntime::StepLINPUT, // Line Input ==> TOS
183 &SbiRuntime::StepGET, // touch TOS
184 &SbiRuntime::StepSET, // save object TOS ==> TOS-1
185 &SbiRuntime::StepPUT, // TOS ==> TOS-1
186 &SbiRuntime::StepPUTC, // TOS ==> TOS-1, then ReadOnly
187 &SbiRuntime::StepDIM, // DIM
188 &SbiRuntime::StepREDIM, // REDIM
189 &SbiRuntime::StepREDIMP, // REDIM PRESERVE
190 &SbiRuntime::StepERASE, // delete TOS
191 // branch
192 &SbiRuntime::StepSTOP, // program end
193 &SbiRuntime::StepINITFOR, // initialize FOR-Variable
194 &SbiRuntime::StepNEXT, // increment FOR-Variable
195 &SbiRuntime::StepCASE, // beginning CASE
196 &SbiRuntime::StepENDCASE, // end CASE
197 &SbiRuntime::StepSTDERROR, // standard error handling
198 &SbiRuntime::StepNOERROR, // no error handling
199 &SbiRuntime::StepLEAVE, // leave UP
200 // E/A
201 &SbiRuntime::StepCHANNEL, // TOS = channel number
202 &SbiRuntime::StepPRINT, // print TOS
203 &SbiRuntime::StepPRINTF, // print TOS in field
204 &SbiRuntime::StepWRITE, // write TOS
205 &SbiRuntime::StepRENAME, // Rename Tos+1 to Tos
206 &SbiRuntime::StepPROMPT, // define Input Prompt from TOS
207 &SbiRuntime::StepRESTART, // Set restart point
208 &SbiRuntime::StepCHANNEL0, // set E/A-channel 0
209 &SbiRuntime::StepEMPTY, // empty expression on stack
210 &SbiRuntime::StepERROR, // TOS = error code
211 &SbiRuntime::StepLSET, // save object TOS ==> TOS-1
212 &SbiRuntime::StepRSET, // save object TOS ==> TOS-1
213 &SbiRuntime::StepREDIMP_ERASE,// Copy array object for REDIMP
214 &SbiRuntime::StepINITFOREACH,// Init for each loop
215 &SbiRuntime::StepVBASET,// vba-like set statement
216 &SbiRuntime::StepERASE_CLEAR,// vba-like set statement
217 &SbiRuntime::StepARRAYACCESS,// access TOS as array
218 &SbiRuntime::StepBYVAL, // access TOS as array
219};
220
221const SbiRuntime::pStep1 SbiRuntime::aStep1[] = { // all opcodes with one operand
222 &SbiRuntime::StepLOADNC, // loading a numeric constant (+ID)
223 &SbiRuntime::StepLOADSC, // loading a string constant (+ID)
224 &SbiRuntime::StepLOADI, // Immediate Load (+value)
225 &SbiRuntime::StepARGN, // save a named Args in Argv (+StringID)
226 &SbiRuntime::StepPAD, // bring string to a definite length (+length)
227 // branches
228 &SbiRuntime::StepJUMP, // jump (+Target)
229 &SbiRuntime::StepJUMPT, // evaluate TOS, conditional jump (+Target)
230 &SbiRuntime::StepJUMPF, // evaluate TOS, conditional jump (+Target)
231 &SbiRuntime::StepONJUMP, // evaluate TOS, jump into JUMP-table (+MaxVal)
232 &SbiRuntime::StepGOSUB, // UP-call (+Target)
233 &SbiRuntime::StepRETURN, // UP-return (+0 or Target)
234 &SbiRuntime::StepTESTFOR, // check FOR-variable, increment (+Endlabel)
235 &SbiRuntime::StepCASETO, // Tos+1 <= Case <= Tos), 2xremove (+Target)
236 &SbiRuntime::StepERRHDL, // error handler (+Offset)
237 &SbiRuntime::StepRESUME, // resume after errors (+0 or 1 or Label)
238 // E/A
239 &SbiRuntime::StepCLOSE, // (+channel/0)
240 &SbiRuntime::StepPRCHAR, // (+char)
241 // management
242 &SbiRuntime::StepSETCLASS, // check set + class names (+StringId)
243 &SbiRuntime::StepTESTCLASS, // Check TOS class (+StringId)
244 &SbiRuntime::StepLIB, // lib for declare-call (+StringId)
245 &SbiRuntime::StepBASED, // TOS is incremented by BASE, BASE is pushed before
246 &SbiRuntime::StepARGTYP, // convert last parameter in Argv (+Type)
247 &SbiRuntime::StepVBASETCLASS,// vba-like set statement
248};
249
250const SbiRuntime::pStep2 SbiRuntime::aStep2[] = {// all opcodes with two operands
251 &SbiRuntime::StepRTL, // load from RTL (+StringID+Typ)
252 &SbiRuntime::StepFIND, // load (+StringID+Typ)
253 &SbiRuntime::StepELEM, // load element (+StringID+Typ)
254 &SbiRuntime::StepPARAM, // Parameter (+Offset+Typ)
255 // branches
256 &SbiRuntime::StepCALL, // Declare-Call (+StringID+Typ)
257 &SbiRuntime::StepCALLC, // CDecl-Declare-Call (+StringID+Typ)
258 &SbiRuntime::StepCASEIS, // Case-Test (+Test-Opcode+False-Target)
259 // management
260 &SbiRuntime::StepSTMNT, // beginning of a statement (+Line+Col)
261 // E/A
262 &SbiRuntime::StepOPEN, // (+StreamMode+Flags)
263 // Objects
264 &SbiRuntime::StepLOCAL, // define local variable (+StringId+Typ)
265 &SbiRuntime::StepPUBLIC, // module global variable (+StringID+Typ)
266 &SbiRuntime::StepGLOBAL, // define global variable (+StringID+Typ)
267 &SbiRuntime::StepCREATE, // create object (+StringId+StringId)
268 &SbiRuntime::StepSTATIC, // static variable (+StringId+StringId)
269 &SbiRuntime::StepTCREATE, // user-defined objects (+StringId+StringId)
270 &SbiRuntime::StepDCREATE, // create object-array (+StringID+StringID)
271 &SbiRuntime::StepGLOBAL_P, // define global variable which is not overwritten
272 // by the Basic on a restart (+StringID+Typ)
273 &SbiRuntime::StepFIND_G, // finds global variable with special treatment because of _GLOBAL_P
274 &SbiRuntime::StepDCREATE_REDIMP, // redimension object array (+StringID+StringID)
275 &SbiRuntime::StepFIND_CM, // Search inside a class module (CM) to enable global search in time
276 &SbiRuntime::StepPUBLIC_P, // Search inside a class module (CM) to enable global search in time
277 &SbiRuntime::StepFIND_STATIC, // Search inside a class module (CM) to enable global search in time
278};
279
280
281// SbiRTLData
282
284 : nDirFlags(SbAttributes::NONE)
285 , nCurDirPos(0)
286{
287}
288
290{
291}
292
293// SbiInstance
294
295// 16.10.96: #31460 new concept for StepInto/Over/Out
296// The decision whether StepPoint shall be called is done with the help of
297// the CallLevel. It's stopped when the current CallLevel is <= nBreakCallLvl.
298// The current CallLevel can never be smaller than 1, as it's also incremented
299// during the call of a method (also main). Therefore a BreakCallLvl from 0
300// means that the program isn't stopped at all.
301// (also have a look at: step2.cxx, SbiRuntime::StepSTMNT() )
302
303
305{
306
307 nFlags &= ~BasicDebugFlags::Break;
308
309 sal_uInt16 nRet;
310 if (nFlags == BasicDebugFlags::StepInto) {
311 nRet = nCallLvl + 1; // CallLevel+1 is also stopped
312 } else if (nFlags == (BasicDebugFlags::StepOver | BasicDebugFlags::StepInto)) {
313 nRet = nCallLvl; // current CallLevel is stopped
314 } else if (nFlags == BasicDebugFlags::StepOut) {
315 nRet = nCallLvl - 1; // smaller CallLevel is stopped
316 } else {
317 // Basic-IDE returns 0 instead of BasicDebugFlags::Continue, so also default=continue
318 nRet = 0; // CallLevel is always > 0 -> no StepPoint
319 }
320 nBreakCallLvl = nRet; // take result
321}
322
324 : pIosys(new SbiIoSystem)
325 , pDdeCtrl(new SbiDdeControl)
326 , pBasic(p)
327 , meFormatterLangType(LANGUAGE_DONTKNOW)
328 , meFormatterDateOrder(DateOrder::YMD)
329 , nStdDateIdx(0)
330 , nStdTimeIdx(0)
331 , nStdDateTimeIdx(0)
332 , nErr(0)
333 , nErl(0)
334 , bReschedule(true)
335 , bCompatibility(false)
336 , pRun(nullptr)
337 , nCallLvl(0)
338 , nBreakCallLvl(0)
339{
340}
341
343{
344 while( pRun )
345 {
347 delete pRun;
348 pRun = p;
349 }
350
351 try
352 {
353 int nSize = ComponentVector.size();
354 if( nSize )
355 {
356 for( int i = nSize - 1 ; i >= 0 ; --i )
357 {
359 if( xDlgComponent.is() )
360 xDlgComponent->dispose();
361 }
362 }
363 }
364 catch( const Exception& )
365 {
366 TOOLS_WARN_EXCEPTION("basic", "SbiInstance::~SbiInstance: caught an exception while disposing the components" );
367 }
368}
369
371{
372 if( !pDllMgr )
373 {
374 pDllMgr.reset(new SbiDllMgr);
375 }
376 return pDllMgr.get();
377}
378
379// #39629 create NumberFormatter with the help of a static method now
380std::shared_ptr<SvNumberFormatter> const & SbiInstance::GetNumberFormatter()
381{
383 SvtSysLocale aSysLocale;
384 DateOrder eDate = aSysLocale.GetLocaleData().getDateOrder();
385 if( pNumberFormatter )
386 {
387 if( eLangType != meFormatterLangType ||
388 eDate != meFormatterDateOrder )
389 {
390 pNumberFormatter.reset();
391 }
392 }
393 meFormatterLangType = eLangType;
394 meFormatterDateOrder = eDate;
395 if( !pNumberFormatter )
396 {
399 }
400 return pNumberFormatter;
401}
402
403// #39629 offer NumberFormatter static too
404std::shared_ptr<SvNumberFormatter> SbiInstance::PrepareNumberFormatter( sal_uInt32 &rnStdDateIdx,
405 sal_uInt32 &rnStdTimeIdx, sal_uInt32 &rnStdDateTimeIdx,
406 LanguageType const * peFormatterLangType, DateOrder const * peFormatterDateOrder )
407{
408 LanguageType eLangType;
409 if( peFormatterLangType )
410 {
411 eLangType = *peFormatterLangType;
412 }
413 else
414 {
416 }
417 DateOrder eDate;
418 if( peFormatterDateOrder )
419 {
420 eDate = *peFormatterDateOrder;
421 }
422 else
423 {
424 SvtSysLocale aSysLocale;
425 eDate = aSysLocale.GetLocaleData().getDateOrder();
426 }
427
428 std::shared_ptr<SvNumberFormatter> pNumberFormatter =
429 std::make_shared<SvNumberFormatter>( comphelper::getProcessComponentContext(), eLangType );
430
431 // Several parser methods pass SvNumberFormatter::IsNumberFormat() a number
432 // format index to parse against. Tell the formatter the proper date
433 // evaluation order, which also determines the date acceptance patterns to
434 // use if a format was passed. NF_EVALDATEFORMAT_FORMAT restricts to the
435 // format's locale's date patterns/order (no init/system locale match
436 // tried) and falls back to NF_EVALDATEFORMAT_INTL if no specific (i.e. 0)
437 // (or an unknown) format index was passed.
438 pNumberFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT);
439
440 sal_Int32 nCheckPos = 0;
442 rnStdTimeIdx = pNumberFormatter->GetStandardFormat( SvNumFormatType::TIME, eLangType );
443
444 // the formatter's standard templates have only got a two-digit date
445 // -> registering an own format
446
447 // HACK, because the numberformatter doesn't swap the place holders
448 // for month, day and year according to the system setting.
449 // Problem: Print Year(Date) under engl. BS
450 // also have a look at: basic/source/sbx/sbxdate.cxx
451
452 OUString aDateStr;
453 switch( eDate )
454 {
455 default:
456 case DateOrder::MDY: aDateStr = "MM/DD/YYYY"; break;
457 case DateOrder::DMY: aDateStr = "DD/MM/YYYY"; break;
458 case DateOrder::YMD: aDateStr = "YYYY/MM/DD"; break;
459 }
460 OUString aStr( aDateStr ); // PutandConvertEntry() modifies string!
461 pNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
462 rnStdDateIdx, LANGUAGE_ENGLISH_US, eLangType, true);
463 nCheckPos = 0;
464 aDateStr += " HH:MM:SS";
465 aStr = aDateStr;
466 pNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
467 rnStdDateTimeIdx, LANGUAGE_ENGLISH_US, eLangType, true);
468 return pNumberFormatter;
469}
470
471
472// Let engine run. If Flags == BasicDebugFlags::Continue, take Flags over
473
475{
476 for( SbiRuntime* p = pRun; p; p = p->pNext )
477 {
478 p->Stop();
479 }
480}
481
482// Allows Basic IDE to set watch mode to suppress errors
483static bool bWatchMode = false;
484
485void setBasicWatchMode( bool bOn )
486{
487 bWatchMode = bOn;
488}
489
491{
492 Error( n, OUString() );
493}
494
495void SbiInstance::Error( ErrCode n, const OUString& rMsg )
496{
497 if( !bWatchMode )
498 {
499 aErrorMsg = rMsg;
500 pRun->Error( n );
501 }
502}
503
504void SbiInstance::ErrorVB( sal_Int32 nVBNumber, const OUString& rMsg )
505{
506 if( !bWatchMode )
507 {
508 ErrCode n = StarBASIC::GetSfxFromVBError( static_cast< sal_uInt16 >( nVBNumber ) );
509 if ( !n )
510 {
511 n = ErrCode(nVBNumber); // force orig number, probably should have a specific table of vb ( localized ) errors
512 }
513 aErrorMsg = rMsg;
515
516 pRun->Error( ERRCODE_BASIC_COMPAT, true/*bVBATranslationAlreadyDone*/ );
517 }
518}
519
520void SbiInstance::setErrorVB( sal_Int32 nVBNumber )
521{
522 ErrCode n = StarBASIC::GetSfxFromVBError( static_cast< sal_uInt16 >( nVBNumber ) );
523 if( !n )
524 {
525 n = ErrCode(nVBNumber); // force orig number, probably should have a specific table of vb ( localized ) errors
526 }
527 aErrorMsg = OUString();
529
530 nErr = n;
531}
532
533
535{
536 pRun->FatalError( n );
537}
538
539void SbiInstance::FatalError( ErrCode _errCode, const OUString& _details )
540{
541 pRun->FatalError( _errCode, _details );
542}
543
545{
546 StarBASIC* pErrBasic = GetCurrentBasic( pBasic );
547 pErrBasic->RTError( nErr, aErrorMsg, pRun->nLine, pRun->nCol1, pRun->nCol2 );
549}
550
551// can be unequal to pRTBasic
553{
554 StarBASIC* pCurBasic = pRTBasic;
555 SbModule* pActiveModule = StarBASIC::GetActiveModule();
556 if( pActiveModule )
557 {
558 SbxObject* pParent = pActiveModule->GetParent();
559 if (StarBASIC *pBasic = dynamic_cast<StarBASIC*>(pParent))
560 pCurBasic = pBasic;
561 }
562 return pCurBasic;
563}
564
566{
567 if( pRun )
568 {
569 return pRun->GetModule();
570 }
571 else
572 {
573 return nullptr;
574 }
575}
576
577SbMethod* SbiInstance::GetCaller( sal_uInt16 nLevel )
578{
579 SbiRuntime* p = pRun;
580 while( nLevel-- && p )
581 {
582 p = p->pNext;
583 }
584 return p ? p->GetCaller() : nullptr;
585}
586
587// SbiInstance
588
589// Attention: pMeth can also be NULL (on a call of the init-code)
590
591SbiRuntime::SbiRuntime( SbModule* pm, SbMethod* pe, sal_uInt32 nStart )
592 : rBasic( *static_cast<StarBASIC*>(pm->pParent) ), pInst( GetSbData()->pInst ),
593 pMod( pm ), pMeth( pe ), pImg( pMod->pImage.get() )
594{
597 pCode =
598 pStmnt = pImg->GetCode() + nStart;
599 refExprStk = new SbxArray;
601 SetParameters( pe ? pe->GetParameters() : nullptr );
602}
603
605{
608}
609
610void SbiRuntime::SetVBAEnabled(bool bEnabled )
611{
612 bVBAEnabled = bEnabled;
613 if ( bVBAEnabled )
614 {
615 if ( pMeth )
616 {
618 }
619 }
620 else
621 {
622 mpExtCaller = nullptr;
623 }
624}
625
626// tdf#79426, tdf#125180 - adds the information about a missing parameter
628{
629 SbxInfo* pInfo = pVar->GetInfo() ? pVar->GetInfo() : new SbxInfo();
630 pInfo->AddParam( pVar->GetName(), SbxMISSING, pVar->GetFlags() );
631 pVar->SetInfo( pInfo );
632}
633
634// tdf#79426, tdf#125180 - checks if a variable contains the information about a missing parameter
635bool SbiRuntime::IsMissing( SbxVariable* pVar, sal_uInt16 nIdx )
636{
637 return pVar->GetInfo() && pVar->GetInfo()->GetParam( nIdx ) && pVar->GetInfo()->GetParam( nIdx )->eType & SbxMISSING;
638}
639
640// Construction of the parameter list. All ByRef-parameters are directly
641// taken over; copies of ByVal-parameters are created. If a particular
642// data type is requested, it is converted.
643
645{
646 refParams = new SbxArray;
647 // for the return value
648 refParams->Put(pMeth, 0);
649
650 SbxInfo* pInfo = pMeth ? pMeth->GetInfo() : nullptr;
651 sal_uInt32 nParamCount = pParams ? pParams->Count() : 1;
652 assert(nParamCount <= std::numeric_limits<sal_uInt16>::max());
653 if( nParamCount > 1 )
654 {
655 for( sal_uInt32 i = 1 ; i < nParamCount ; i++ )
656 {
657 const SbxParamInfo* p = pInfo ? pInfo->GetParam( sal::static_int_cast<sal_uInt16>(i) ) : nullptr;
658
659 // #111897 ParamArray
660 if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 )
661 {
662 SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
663 sal_uInt32 nParamArrayParamCount = nParamCount - i;
664 pArray->unoAddDim(0, nParamArrayParamCount - 1);
665 for (sal_uInt32 j = i; j < nParamCount ; ++j)
666 {
667 SbxVariable* v = pParams->Get(j);
668 sal_Int32 aDimIndex[1];
669 aDimIndex[0] = j - i;
670 pArray->Put(v, aDimIndex);
671 }
672 SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT );
673 pArrayVar->SetFlag( SbxFlagBits::ReadWrite );
674 pArrayVar->PutObject( pArray );
675 refParams->Put(pArrayVar, i);
676
677 // Block ParamArray for missing parameter
678 pInfo = nullptr;
679 break;
680 }
681
682 SbxVariable* v = pParams->Get(i);
683 // methods are always byval!
684 bool bByVal = dynamic_cast<const SbxMethod *>(v) != nullptr;
685 SbxDataType t = v->GetType();
686 bool bTargetTypeIsArray = false;
687 if( p )
688 {
689 bByVal |= ( p->eType & SbxBYREF ) == 0;
690 // tdf#79426, tdf#125180 - don't convert missing arguments to the requested parameter type
691 if ( !IsMissing( v, 1 ) )
692 {
693 t = static_cast<SbxDataType>( p->eType & 0x0FFF );
694 }
695
696 if( !bByVal && t != SbxVARIANT &&
697 (!v->IsFixed() || static_cast<SbxDataType>(v->GetType() & 0x0FFF ) != t) )
698 {
699 bByVal = true;
700 }
701
702 bTargetTypeIsArray = (p->nUserData & PARAM_INFO_WITHBRACKETS) != 0;
703 }
704 if( bByVal )
705 {
706 // tdf#79426, tdf#125180 - don't convert missing arguments to the requested parameter type
707 if( bTargetTypeIsArray && !IsMissing( v, 1 ) )
708 {
709 t = SbxOBJECT;
710 }
711 SbxVariable* v2 = new SbxVariable( t );
713 // tdf#79426, tdf#125180 - if parameter was missing, readd additional information about a missing parameter
714 if ( IsMissing( v, 1 ) )
715 {
716 SetIsMissing( v2 );
717 }
718 *v2 = *v;
719 refParams->Put(v2, i);
720 }
721 else
722 {
723 // tdf#79426, tdf#125180 - don't convert missing arguments to the requested parameter type
724 if( t != SbxVARIANT && !IsMissing( v, 1 ) && t != ( v->GetType() & 0x0FFF ) )
725 {
726 if( p && (p->eType & SbxARRAY) )
727 {
729 }
730 else
731 {
732 v->Convert( t );
733 }
734 }
735 refParams->Put(v, i);
736 }
737 if( p )
738 {
739 refParams->PutAlias(p->aName, i);
740 }
741 }
742 }
743
744 // ParamArray for missing parameter
745 if( !pInfo )
746 return;
747
748 // #111897 Check first missing parameter for ParamArray
749 const SbxParamInfo* p = pInfo->GetParam(sal::static_int_cast<sal_uInt16>(nParamCount));
750 if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 )
751 {
752 SbxDimArray* pArray = new SbxDimArray( SbxVARIANT );
753 pArray->unoAddDim(0, -1);
754 SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT );
755 pArrayVar->SetFlag( SbxFlagBits::ReadWrite );
756 pArrayVar->PutObject( pArray );
757 refParams->Put(pArrayVar, nParamCount);
758 }
759}
760
761
762// execute a P-Code
763
765{
766 if( bRun )
767 {
768 static sal_uInt32 nLastTime = osl_getGlobalTimer();
769
770 // in any case check casually!
771 if( !( ++nOps & 0xF ) && pInst->IsReschedule() )
772 {
773 sal_uInt32 nTime = osl_getGlobalTimer();
774 if (nTime - nLastTime > 5) // 20 ms
775 {
776 nLastTime = nTime;
778 }
779 }
780
781 // #i48868 blocked by next call level?
782 while( bBlocked )
783 {
784 if( pInst->IsReschedule() ) // And what if not? Busy loop?
785 {
787 nLastTime = osl_getGlobalTimer();
788 }
789 }
790
791 SbiOpcode eOp = static_cast<SbiOpcode>( *pCode++ );
792 sal_uInt32 nOp1;
793 if (eOp <= SbiOpcode::SbOP0_END)
794 {
795 (this->*( aStep0[ int(eOp) ] ) )();
796 }
797 else if (eOp >= SbiOpcode::SbOP1_START && eOp <= SbiOpcode::SbOP1_END)
798 {
799 nOp1 = *pCode++; nOp1 |= *pCode++ << 8; nOp1 |= *pCode++ << 16; nOp1 |= *pCode++ << 24;
800
801 (this->*( aStep1[ int(eOp) - int(SbiOpcode::SbOP1_START) ] ) )( nOp1 );
802 }
803 else if (eOp >= SbiOpcode::SbOP2_START && eOp <= SbiOpcode::SbOP2_END)
804 {
805 nOp1 = *pCode++; nOp1 |= *pCode++ << 8; nOp1 |= *pCode++ << 16; nOp1 |= *pCode++ << 24;
806 sal_uInt32 nOp2 = *pCode++; nOp2 |= *pCode++ << 8; nOp2 |= *pCode++ << 16; nOp2 |= *pCode++ << 24;
807 (this->*( aStep2[ int(eOp) - int(SbiOpcode::SbOP2_START) ] ) )( nOp1, nOp2 );
808 }
809 else
810 {
812 }
813
814 ErrCode nErrCode = SbxBase::GetError();
815 Error( nErrCode.IgnoreWarning() );
816
817 // from 13.2.1997, new error handling:
818 // ATTENTION: nError can be set already even if !nErrCode
819 // since nError can now also be set from other RT-instances
820
821 if( nError )
822 {
824 }
825
826 // from 15.3.96: display errors only if BASIC is still active
827 // (especially not after compiler errors at the runtime)
828 if( nError && bRun )
829 {
833 pInst->nErr = err;
834 pInst->nErl = nLine;
835 pErrCode = pCode;
837 // An error occurred in an error handler
838 // force parent handler ( if there is one )
839 // to handle the error
840 bool bLetParentHandleThis = false;
841
842 // in the error handler? so std-error
843 if ( !bInError )
844 {
845 bInError = true;
846
847 if( !bError ) // On Error Resume Next
848 {
849 StepRESUME( 1 );
850 }
851 else if( pError ) // On Error Goto ...
852 {
853 pCode = pError;
854 }
855 else
856 {
857 bLetParentHandleThis = true;
858 }
859 }
860 else
861 {
862 bLetParentHandleThis = true;
863 pError = nullptr; //terminate the handler
864 }
865 if ( bLetParentHandleThis )
866 {
867 // from 13.2.1997, new error handling:
868 // consider superior error handlers
869
870 // there's no error handler -> find one farther above
871 SbiRuntime* pRtErrHdl = nullptr;
872 SbiRuntime* pRt = this;
873 while( (pRt = pRt->pNext) != nullptr )
874 {
875 if( !pRt->bError || pRt->pError != nullptr )
876 {
877 pRtErrHdl = pRt;
878 break;
879 }
880 }
881
882
883 if( pRtErrHdl )
884 {
885 // manipulate all the RTs that are below in the call-stack
886 pRt = this;
887 do
888 {
889 pRt->nError = err;
890 if( pRt != pRtErrHdl )
891 {
892 pRt->bRun = false;
893 }
894 else
895 {
896 break;
897 }
898 pRt = pRt->pNext;
899 }
900 while( pRt );
901 }
902 // no error-hdl found -> old behaviour
903 else
904 {
905 pInst->Abort();
906 }
907 }
908 }
909 }
910 return bRun;
911}
912
913void SbiRuntime::Error( ErrCode n, bool bVBATranslationAlreadyDone )
914{
915 if( !n )
916 return;
917
918 nError = n;
919 if( !isVBAEnabled() || bVBATranslationAlreadyDone )
920 return;
921
922 OUString aMsg = pInst->GetErrorMsg();
923 sal_Int32 nVBAErrorNumber = translateErrorToVba( nError, aMsg );
924 SbxVariable* pSbxErrObjVar = SbxErrObject::getErrObject().get();
925 SbxErrObject* pGlobErr = static_cast< SbxErrObject* >( pSbxErrObjVar );
926 if( pGlobErr != nullptr )
927 {
928 pGlobErr->setNumberAndDescription( nVBAErrorNumber, aMsg );
929 }
930 pInst->aErrorMsg = aMsg;
932}
933
934void SbiRuntime::Error( ErrCode _errCode, const OUString& _details )
935{
936 if ( !_errCode )
937 return;
938
939 // Not correct for class module usage, remove for now
940 //OSL_WARN_IF( pInst->pRun != this, "basic", "SbiRuntime::Error: can't propagate the error message details!" );
941 if ( pInst->pRun == this )
942 {
943 pInst->Error( _errCode, _details );
944 //OSL_WARN_IF( nError != _errCode, "basic", "SbiRuntime::Error: the instance is expected to propagate the error code back to me!" );
945 }
946 else
947 {
948 nError = _errCode;
949 }
950}
951
953{
954 StepSTDERROR();
955 Error( n );
956}
957
958void SbiRuntime::FatalError( ErrCode _errCode, const OUString& _details )
959{
960 StepSTDERROR();
961 Error( _errCode, _details );
962}
963
964sal_Int32 SbiRuntime::translateErrorToVba( ErrCode nError, OUString& rMsg )
965{
966 // If a message is defined use that ( in preference to
967 // the defined one for the error ) NB #TODO
968 // if there is an error defined it more than likely
969 // is not the one you want ( some are the same though )
970 // we really need a new vba compatible error list
971 // tdf#123144 - always translate an error number to a vba error message
974 // no num? most likely then it *is* really a vba err
975 sal_uInt16 nVBErrorCode = StarBASIC::GetVBErrorCode( nError );
976 sal_Int32 nVBAErrorNumber = ( nVBErrorCode == 0 ) ? sal_uInt32(nError) : nVBErrorCode;
977 return nVBAErrorNumber;
978}
979
980// Stacks
981
982// The expression-stack is available for the continuous evaluation
983// of expressions.
984
986{
987 if( pVar )
988 {
989 refExprStk->Put(pVar, nExprLvl++);
990 }
991}
992
994{
995#ifdef DBG_UTIL
996 if( !nExprLvl )
997 {
999 return new SbxVariable;
1000 }
1001#endif
1002 SbxVariableRef xVar = refExprStk->Get(--nExprLvl);
1003 SAL_INFO_IF( xVar->GetName() == "Cells", "basic", "PopVar: Name equals 'Cells'" );
1004 // methods hold themselves in parameter 0
1005 if( dynamic_cast<const SbxMethod *>(xVar.get()) != nullptr )
1006 {
1007 xVar->SetParameters(nullptr);
1008 }
1009 return xVar;
1010}
1011
1013{
1014 // Attention: Clear() doesn't suffice as methods must be deleted
1015 while ( nExprLvl )
1016 {
1017 PopVar();
1018 }
1019 refExprStk->Clear();
1020}
1021
1022// Take variable from the expression-stack without removing it
1023// n counts from 0
1024
1026{
1027 short n = nExprLvl - 1;
1028#ifdef DBG_UTIL
1029 if( n < 0 )
1030 {
1032 return new SbxVariable;
1033 }
1034#endif
1035 return refExprStk->Get(static_cast<sal_uInt32>(n));
1036}
1037
1038
1040{
1041 SbxVariable* p = refExprStk->Get(nExprLvl - 1);
1042 if ( p->GetType() == SbxEMPTY )
1043 {
1044 p->Broadcast( SfxHintId::BasicDataWanted );
1045 }
1046
1047 SbxVariable* pDflt = nullptr;
1048 if ( bVBAEnabled && ( p->GetType() == SbxOBJECT || p->GetType() == SbxVARIANT ) && ((pDflt = getDefaultProp(p)) != nullptr) )
1049 {
1050 pDflt->Broadcast( SfxHintId::BasicDataWanted );
1051 // replacing new p on stack causes object pointed by
1052 // pDft->pParent to be deleted, when p2->Compute() is
1053 // called below pParent is accessed (but it's deleted)
1054 // so set it to NULL now
1055 pDflt->SetParent( nullptr );
1056 p = new SbxVariable( *pDflt );
1057 p->SetFlag( SbxFlagBits::ReadWrite );
1058 refExprStk->Put(p, nExprLvl - 1);
1059 }
1060 else if( p->GetRefCount() != 1 )
1061 {
1062 SbxVariable* pNew = new SbxVariable( *p );
1064 refExprStk->Put(pNew, nExprLvl - 1);
1065 }
1066}
1067
1068// the GOSUB-stack collects return-addresses for GOSUBs
1070{
1071 if( pGosubStk.size() >= MAXRECURSION )
1072 {
1074 }
1075 pGosubStk.emplace_back(pc, nForLvl);
1076}
1077
1079{
1080 if( pGosubStk.empty() )
1081 {
1083 }
1084 else
1085 {
1086 pCode = pGosubStk.back().pCode;
1087 pGosubStk.pop_back();
1088 }
1089}
1090
1091// the Argv-stack collects current argument-vectors
1092
1094{
1095 pArgvStk.emplace_back(refArgv, nArgc);
1096 nArgc = 1;
1097 refArgv.clear();
1098}
1099
1101{
1102 if( !pArgvStk.empty() )
1103 {
1104 refArgv = pArgvStk.back().refArgv;
1105 nArgc = pArgvStk.back().nArgc;
1106 pArgvStk.pop_back();
1107 }
1108}
1109
1110
1112{
1113 while( !pArgvStk.empty() )
1114 {
1115 PopArgv();
1116 }
1117}
1118
1119// Push of the for-stack. The stack has increment, end, begin and variable.
1120// After the creation of the stack-element the stack's empty.
1121
1123{
1124 SbiForStack* p = new SbiForStack;
1125 p->eForType = ForType::To;
1126 p->pNext = pForStk;
1127 pForStk = p;
1128
1129 p->refInc = PopVar();
1130 p->refEnd = PopVar();
1131 SbxVariableRef xBgn = PopVar();
1132 p->refVar = PopVar();
1133 // tdf#85371 - grant explicitly write access to the index variable
1134 // since it could be the name of a method itself used in the next statement.
1135 ScopedWritableGuard aGuard(p->refVar, p->refVar.get() == pMeth);
1136 *(p->refVar) = *xBgn;
1137 nForLvl++;
1138}
1139
1141{
1142 SbiForStack* p = new SbiForStack;
1143 // Set default value in case of error which is ignored in Resume Next
1144 p->eForType = ForType::EachArray;
1145 p->pNext = pForStk;
1146 pForStk = p;
1147
1148 SbxVariableRef xObjVar = PopVar();
1149 SbxBase* pObj(nullptr);
1150 if (xObjVar)
1151 {
1153 // Here it may retrieve the value, and change the type from SbxEMPTY to SbxOBJECT
1154 xObjVar->Get(v);
1155 if (v.eType == SbxOBJECT)
1156 pObj = v.pObj;
1157 }
1158
1159 if (SbxDimArray* pArray = dynamic_cast<SbxDimArray*>(pObj))
1160 {
1161 p->refEnd = reinterpret_cast<SbxVariable*>(pArray);
1162
1163 sal_Int32 nDims = pArray->GetDims();
1164 p->pArrayLowerBounds.reset( new sal_Int32[nDims] );
1165 p->pArrayUpperBounds.reset( new sal_Int32[nDims] );
1166 p->pArrayCurIndices.reset( new sal_Int32[nDims] );
1167 sal_Int32 lBound, uBound;
1168 for( sal_Int32 i = 0 ; i < nDims ; i++ )
1169 {
1170 pArray->GetDim(i + 1, lBound, uBound);
1171 p->pArrayCurIndices[i] = p->pArrayLowerBounds[i] = lBound;
1172 p->pArrayUpperBounds[i] = uBound;
1173 }
1174 }
1175 else if (BasicCollection* pCollection = dynamic_cast<BasicCollection*>(pObj))
1176 {
1177 p->eForType = ForType::EachCollection;
1178 p->refEnd = pCollection;
1179 p->nCurCollectionIndex = 0;
1180 }
1181 else if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj))
1182 {
1183 // XEnumerationAccess or XIndexAccess?
1184 Any aAny = pUnoObj->getUnoAny();
1185 Reference<XIndexAccess> xIndexAccess;
1186 Reference< XEnumerationAccess > xEnumerationAccess;
1187 if( aAny >>= xEnumerationAccess )
1188 {
1189 p->xEnumeration = xEnumerationAccess->createEnumeration();
1190 p->eForType = ForType::EachXEnumeration;
1191 }
1192 // tdf#130307 - support for each loop for objects exposing XIndexAccess
1193 else if (aAny >>= xIndexAccess)
1194 {
1195 p->eForType = ForType::EachXIndexAccess;
1196 p->xIndexAccess = xIndexAccess;
1197 p->nCurCollectionIndex = 0;
1198 }
1199 else if ( isVBAEnabled() && pUnoObj->isNativeCOMObject() )
1200 {
1201 uno::Reference< script::XInvocation > xInvocation;
1202 if ( ( aAny >>= xInvocation ) && xInvocation.is() )
1203 {
1204 try
1205 {
1206 p->xEnumeration = new ComEnumerationWrapper( xInvocation );
1207 p->eForType = ForType::EachXEnumeration;
1208 }
1209 catch(const uno::Exception& )
1210 {}
1211 }
1212 }
1213 }
1214
1215 // Container variable
1216 p->refVar = PopVar();
1217 nForLvl++;
1218}
1219
1220
1222{
1223 if( pForStk )
1224 {
1226 pForStk = p->pNext;
1227 delete p;
1228 nForLvl--;
1229 }
1230}
1231
1232
1234{
1235 while( pForStk )
1236 {
1237 PopFor();
1238 }
1239}
1240
1242{
1243 for (SbiForStack *p = pForStk; p; p = p->pNext)
1244 {
1245 SbxVariable* pVar = p->refEnd.is() ? p->refEnd.get() : nullptr;
1246 if( p->eForType == ForType::EachCollection
1247 && pVar != nullptr
1248 && dynamic_cast<BasicCollection*>( pVar) == pCollection )
1249 {
1250 return p;
1251 }
1252 }
1253
1254 return nullptr;
1255}
1256
1257
1258// DLL-calls
1259
1261 ( std::u16string_view aFuncName,
1262 std::u16string_view aDLLName,
1263 SbxArray* pArgs, // parameter (from index 1, can be NULL)
1264 SbxDataType eResType, // return value
1265 bool bCDecl ) // true: according to C-conventions
1266{
1267 SbxVariable* pRes = new SbxVariable( eResType );
1268 SbiDllMgr* pDllMgr = pInst->GetDllMgr();
1269 ErrCode nErr = pDllMgr->Call( aFuncName, aDLLName, pArgs, *pRes, bCDecl );
1270 if( nErr )
1271 {
1272 Error( nErr );
1273 }
1274 PushVar( pRes );
1275}
1276
1278{
1279 return pImg->IsFlag( n );
1280}
1281
1282sal_uInt16 SbiRuntime::GetBase() const
1283{
1284 return pImg->GetBase();
1285}
1286
1288{}
1289
1291{
1292 SbxVariableRef p1 = PopVar();
1293 TOSMakeTemp();
1294 SbxVariable* p2 = GetTOS();
1295
1296 // tdf#144353 - do not compute any operation with a missing optional variable
1297 if ((p1->GetType() == SbxERROR && IsMissing(p1.get(), 1))
1298 || (p2->GetType() == SbxERROR && IsMissing(p2, 1)))
1299 {
1301 return;
1302 }
1303
1305 p2->Compute( eOp, *p1 );
1306
1308}
1309
1311{
1312 TOSMakeTemp();
1313 SbxVariable* p = GetTOS();
1314 // tdf#144353 - do not compute any operation with a missing optional variable
1315 if (p->GetType() == SbxERROR && IsMissing(p, 1))
1316 {
1318 return;
1319 }
1320 p->Compute( eOp, *p );
1321}
1322
1324{
1325 SbxVariableRef p1 = PopVar();
1326 SbxVariableRef p2 = PopVar();
1327
1328 // tdf#144353 - do not compare a missing optional variable
1329 if ((p1->GetType() == SbxERROR && SbiRuntime::IsMissing(p1.get(), 1))
1330 || (p2->GetType() == SbxERROR && SbiRuntime::IsMissing(p2.get(), 1)))
1331 {
1333 return;
1334 }
1335
1336 // Make sure objects with default params have
1337 // values ( and type ) set as appropriate
1338 SbxDataType p1Type = p1->GetType();
1339 SbxDataType p2Type = p2->GetType();
1340 if ( p1Type == SbxEMPTY )
1341 {
1342 p1->Broadcast( SfxHintId::BasicDataWanted );
1343 p1Type = p1->GetType();
1344 }
1345 if ( p2Type == SbxEMPTY )
1346 {
1347 p2->Broadcast( SfxHintId::BasicDataWanted );
1348 p2Type = p2->GetType();
1349 }
1350 if ( p1Type == p2Type )
1351 {
1352 // if both sides are an object and have default props
1353 // then we need to use the default props
1354 // we don't need to worry if only one side ( lhs, rhs ) is an
1355 // object ( object side will get coerced to correct type in
1356 // Compare )
1357 if ( p1Type == SbxOBJECT )
1358 {
1359 SbxVariable* pDflt = getDefaultProp( p1.get() );
1360 if ( pDflt )
1361 {
1362 p1 = pDflt;
1363 p1->Broadcast( SfxHintId::BasicDataWanted );
1364 }
1365 pDflt = getDefaultProp( p2.get() );
1366 if ( pDflt )
1367 {
1368 p2 = pDflt;
1369 p2->Broadcast( SfxHintId::BasicDataWanted );
1370 }
1371 }
1372
1373 }
1374 static SbxVariable* pTRUE = nullptr;
1375 static SbxVariable* pFALSE = nullptr;
1376 // why do this on non-windows ?
1377 // why do this at all ?
1378 // I dumbly follow the pattern :-/
1379 if ( bVBAEnabled && ( p1->IsNull() || p2->IsNull() ) )
1380 {
1381 static SbxVariable* pNULL = []() {
1382 SbxVariable* p = new SbxVariable;
1383 p->PutNull();
1384 p->AddFirstRef();
1385 return p;
1386 }();
1387 PushVar( pNULL );
1388 }
1389 else if( p2->Compare( eOp, *p1 ) )
1390 {
1391 if( !pTRUE )
1392 {
1393 pTRUE = new SbxVariable;
1394 pTRUE->PutBool( true );
1395 pTRUE->AddFirstRef();
1396 }
1397 PushVar( pTRUE );
1398 }
1399 else
1400 {
1401 if( !pFALSE )
1402 {
1403 pFALSE = new SbxVariable;
1404 pFALSE->PutBool( false );
1405 pFALSE->AddFirstRef();
1406 }
1407 PushVar( pFALSE );
1408 }
1409}
1410
1424
1427
1434
1435namespace
1436{
1437 bool NeedEsc(sal_Unicode cCode)
1438 {
1439 if(!rtl::isAscii(cCode))
1440 {
1441 return false;
1442 }
1443 switch(cCode)
1444 {
1445 case '.':
1446 case '^':
1447 case '$':
1448 case '+':
1449 case '\\':
1450 case '|':
1451 case '{':
1452 case '}':
1453 case '(':
1454 case ')':
1455 return true;
1456 default:
1457 return false;
1458 }
1459 }
1460
1461 OUString VBALikeToRegexp(const OUString &rIn)
1462 {
1463 OUStringBuffer sResult;
1464 const sal_Unicode *start = rIn.getStr();
1465 const sal_Unicode *end = start + rIn.getLength();
1466
1467 int seenright = 0;
1468
1469 sResult.append('^');
1470
1471 while (start < end)
1472 {
1473 switch (*start)
1474 {
1475 case '?':
1476 sResult.append('.');
1477 start++;
1478 break;
1479 case '*':
1480 sResult.append(".*");
1481 start++;
1482 break;
1483 case '#':
1484 sResult.append("[0-9]");
1485 start++;
1486 break;
1487 case ']':
1488 sResult.append('\\');
1489 sResult.append(*start++);
1490 break;
1491 case '[':
1492 sResult.append(*start++);
1493 seenright = 0;
1494 if (start < end && *start == '!')
1495 {
1496 sResult.append('^');
1497 start++;
1498 }
1499 while (start < end && !seenright)
1500 {
1501 switch (*start)
1502 {
1503 case '[':
1504 case '?':
1505 case '*':
1506 sResult.append('\\');
1507 sResult.append(*start);
1508 break;
1509 case ']':
1510 sResult.append(*start);
1511 seenright = 1;
1512 break;
1513 default:
1514 if (NeedEsc(*start))
1515 {
1516 sResult.append('\\');
1517 }
1518 sResult.append(*start);
1519 break;
1520 }
1521 start++;
1522 }
1523 break;
1524 default:
1525 if (NeedEsc(*start))
1526 {
1527 sResult.append('\\');
1528 }
1529 sResult.append(*start++);
1530 }
1531 }
1532
1533 sResult.append('$');
1534
1535 return sResult.makeStringAndClear();
1536 }
1537}
1538
1540{
1541 SbxVariableRef refVar1 = PopVar();
1542 SbxVariableRef refVar2 = PopVar();
1543
1544 OUString pattern = VBALikeToRegexp(refVar1->GetOUString());
1545 OUString value = refVar2->GetOUString();
1546
1547 i18nutil::SearchOptions2 aSearchOpt;
1548
1549 aSearchOpt.AlgorithmType2 = css::util::SearchAlgorithms2::REGEXP;
1550
1552 aSearchOpt.searchString = pattern;
1553
1554 bool bTextMode(true);
1555 bool bCompatibility = ( GetSbData()->pInst && GetSbData()->pInst->IsCompatibility() );
1556 if( bCompatibility )
1557 {
1559 }
1560 if( bTextMode )
1561 {
1562 aSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
1563 }
1564 SbxVariable* pRes = new SbxVariable;
1565 utl::TextSearch aSearch( aSearchOpt);
1566 sal_Int32 nStart=0, nEnd=value.getLength();
1567 bool bRes = aSearch.SearchForward(value, &nStart, &nEnd);
1568 pRes->PutBool( bRes );
1569
1570 PushVar( pRes );
1571}
1572
1573// TOS and TOS-1 are both object variables and contain the same pointer
1574
1576{
1577 SbxVariableRef refVar1 = PopVar();
1578 SbxVariableRef refVar2 = PopVar();
1579
1580 SbxDataType eType1 = refVar1->GetType();
1581 SbxDataType eType2 = refVar2->GetType();
1582 if ( eType1 == SbxEMPTY )
1583 {
1584 refVar1->Broadcast( SfxHintId::BasicDataWanted );
1585 eType1 = refVar1->GetType();
1586 }
1587 if ( eType2 == SbxEMPTY )
1588 {
1589 refVar2->Broadcast( SfxHintId::BasicDataWanted );
1590 eType2 = refVar2->GetType();
1591 }
1592
1593 bool bRes = ( eType1 == SbxOBJECT && eType2 == SbxOBJECT );
1594 if ( bVBAEnabled && !bRes )
1595 {
1597 }
1598 bRes = ( bRes && refVar1->GetObject() == refVar2->GetObject() );
1599 SbxVariable* pRes = new SbxVariable;
1600 pRes->PutBool( bRes );
1601 PushVar( pRes );
1602}
1603
1604// update the value of TOS
1605
1607{
1608 SbxVariable* p = GetTOS();
1609 p->Broadcast( SfxHintId::BasicDataWanted );
1610}
1611
1612// #67607 copy Uno-Structs
1613static bool checkUnoStructCopy( bool bVBA, SbxVariableRef const & refVal, SbxVariableRef const & refVar )
1614{
1615 SbxDataType eVarType = refVar->GetType();
1616 SbxDataType eValType = refVal->GetType();
1617
1618 // tdf#144353 - do not assign a missing optional variable to a property
1619 if (refVal->GetType() == SbxERROR && SbiRuntime::IsMissing(refVal.get(), 1))
1620 {
1622 return true;
1623 }
1624
1625 if ( ( bVBA && ( eVarType == SbxEMPTY ) ) || !refVar->CanWrite() )
1626 return false;
1627
1628 if ( eValType != SbxOBJECT )
1629 return false;
1630 // we seem to be duplicating parts of SbxValue=operator, maybe we should just move this to
1631 // there :-/ not sure if for every '=' we would want struct handling
1632 if( eVarType != SbxOBJECT )
1633 {
1634 if ( refVar->IsFixed() )
1635 return false;
1636 }
1637 // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
1638 else if( dynamic_cast<const SbProcedureProperty*>( refVar.get() ) != nullptr )
1639 return false;
1640
1641 SbxObjectRef xValObj = static_cast<SbxObject*>(refVal->GetObject());
1642 if( !xValObj.is() || dynamic_cast<const SbUnoAnyObject*>( xValObj.get() ) != nullptr )
1643 return false;
1644
1645 SbUnoObject* pUnoVal = dynamic_cast<SbUnoObject*>( xValObj.get() );
1646 SbUnoStructRefObject* pUnoStructVal = dynamic_cast<SbUnoStructRefObject*>( xValObj.get() );
1647 Any aAny;
1648 // make doubly sure value is either a Uno object or
1649 // a uno struct
1650 if ( pUnoVal || pUnoStructVal )
1651 aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny();
1652 else
1653 return false;
1654 if ( aAny.getValueType().getTypeClass() != TypeClass_STRUCT )
1655 return false;
1656
1657 refVar->SetType( SbxOBJECT );
1658 ErrCode eOldErr = SbxBase::GetError();
1659 // There are some circumstances when calling GetObject
1660 // will trigger an error, we need to squash those here.
1661 // Alternatively it is possible that the same scenario
1662 // could overwrite and existing error. Lets prevent that
1663 SbxObjectRef xVarObj = static_cast<SbxObject*>(refVar->GetObject());
1664 if ( eOldErr != ERRCODE_NONE )
1665 SbxBase::SetError( eOldErr );
1666 else
1668
1669 SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>( xVarObj.get() );
1670
1671 OUString sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName();
1672 OUString sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName();
1673
1674 if ( pUnoStructObj )
1675 {
1676 StructRefInfo aInfo = pUnoStructObj->getStructInfo();
1677 aInfo.setValue( aAny );
1678 }
1679 else
1680 {
1681 SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny );
1682 // #70324: adopt ClassName
1683 pNewUnoObj->SetClassName( sClassName );
1684 refVar->PutObject( pNewUnoObj );
1685 }
1686 return true;
1687}
1688
1689
1690// laying down TOS in TOS-1
1691
1693{
1694 SbxVariableRef refVal = PopVar();
1695 SbxVariableRef refVar = PopVar();
1696 // store on its own method (inside a function)?
1697 bool bFlagsChanged = false;
1699 if( refVar.get() == pMeth )
1700 {
1701 bFlagsChanged = true;
1702 n = refVar->GetFlags();
1703 refVar->SetFlag( SbxFlagBits::Write );
1704 }
1705
1706 // if left side arg is an object or variant and right handside isn't
1707 // either an object or a variant then try and see if a default
1708 // property exists.
1709 // to use e.g. Range{"A1") = 34
1710 // could equate to Range("A1").Value = 34
1711 if ( bVBAEnabled )
1712 {
1713 // yet more hacking at this, I feel we don't quite have the correct
1714 // heuristics for dealing with obj1 = obj2 ( where obj2 ( and maybe
1715 // obj1 ) has default member/property ) ) It seems that default props
1716 // aren't dealt with if the object is a member of some parent object
1717 bool bObjAssign = false;
1718 if ( refVar->GetType() == SbxEMPTY )
1719 refVar->Broadcast( SfxHintId::BasicDataWanted );
1720 if ( refVar->GetType() == SbxOBJECT )
1721 {
1722 if ( dynamic_cast<const SbxMethod *>(refVar.get()) != nullptr || ! refVar->GetParent() )
1723 {
1724 SbxVariable* pDflt = getDefaultProp( refVar.get() );
1725
1726 if ( pDflt )
1727 refVar = pDflt;
1728 }
1729 else
1730 bObjAssign = true;
1731 }
1732 if ( refVal->GetType() == SbxOBJECT && !bObjAssign && ( dynamic_cast<const SbxMethod *>(refVal.get()) != nullptr || ! refVal->GetParent() ) )
1733 {
1734 SbxVariable* pDflt = getDefaultProp( refVal.get() );
1735 if ( pDflt )
1736 refVal = pDflt;
1737 }
1738 }
1739
1740 if ( !checkUnoStructCopy( bVBAEnabled, refVal, refVar ) )
1741 *refVar = *refVal;
1742
1743 if( bFlagsChanged )
1744 refVar->SetFlags( n );
1745}
1746
1747namespace {
1748
1749// VBA Dim As New behavior handling, save init object information
1750struct DimAsNewRecoverItem
1751{
1752 OUString m_aObjClass;
1753 OUString m_aObjName;
1754 SbxObject* m_pObjParent;
1755 SbModule* m_pClassModule;
1756
1757 DimAsNewRecoverItem()
1758 : m_pObjParent( nullptr )
1759 , m_pClassModule( nullptr )
1760 {}
1761
1762 DimAsNewRecoverItem( OUString aObjClass, OUString aObjName,
1763 SbxObject* pObjParent, SbModule* pClassModule )
1764 : m_aObjClass(std::move( aObjClass ))
1765 , m_aObjName(std::move( aObjName ))
1766 , m_pObjParent( pObjParent )
1767 , m_pClassModule( pClassModule )
1768 {}
1769
1770};
1771
1772
1773struct SbxVariablePtrHash
1774{
1775 size_t operator()( SbxVariable* pVar ) const
1776 { return reinterpret_cast<size_t>(pVar); }
1777};
1778
1779}
1780
1781typedef std::unordered_map< SbxVariable*, DimAsNewRecoverItem,
1782 SbxVariablePtrHash > DimAsNewRecoverHash;
1783
1784namespace {
1785
1786DimAsNewRecoverHash gaDimAsNewRecoverHash;
1787
1788}
1789
1791{
1792 DimAsNewRecoverHash::iterator it = gaDimAsNewRecoverHash.find( pVar );
1793 if( it != gaDimAsNewRecoverHash.end() )
1794 {
1795 gaDimAsNewRecoverHash.erase( it );
1796 }
1797}
1798
1799
1800// saving object variable
1801// not-object variables will cause errors
1802
1803constexpr OUStringLiteral pCollectionStr = u"Collection";
1804
1805void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
1806{
1807 // #67733 types with array-flag are OK too
1808
1809 // Check var, !object is no error for sure if, only if type is fixed
1810 SbxDataType eVarType = refVar->GetType();
1811 if( !bHandleDefaultProp && eVarType != SbxOBJECT && !(eVarType & SbxARRAY) && refVar->IsFixed() )
1812 {
1814 return;
1815 }
1816
1817 // Check value, !object is no error for sure if, only if type is fixed
1818 SbxDataType eValType = refVal->GetType();
1819 if( !bHandleDefaultProp && eValType != SbxOBJECT && !(eValType & SbxARRAY) && refVal->IsFixed() )
1820 {
1822 return;
1823 }
1824
1825 // Getting in here causes problems with objects with default properties
1826 // if they are SbxEMPTY I guess
1827 if ( !bHandleDefaultProp || eValType == SbxOBJECT )
1828 {
1829 // activate GetObject for collections on refVal
1830 SbxBase* pObjVarObj = refVal->GetObject();
1831 if( pObjVarObj )
1832 {
1833 SbxVariableRef refObjVal = dynamic_cast<SbxObject*>( pObjVarObj );
1834
1835 if( refObjVal.is() )
1836 {
1837 refVal = refObjVal;
1838 }
1839 else if( !(eValType & SbxARRAY) )
1840 {
1841 refVal = nullptr;
1842 }
1843 }
1844 }
1845
1846 // #52896 refVal can be invalid here, if uno-sequences - or more
1847 // general arrays - are assigned to variables that are declared
1848 // as an object!
1849 if( !refVal.is() )
1850 {
1852 }
1853 else
1854 {
1855 bool bFlagsChanged = false;
1857 if( refVar.get() == pMeth )
1858 {
1859 bFlagsChanged = true;
1860 n = refVar->GetFlags();
1861 refVar->SetFlag( SbxFlagBits::Write );
1862 }
1863 SbProcedureProperty* pProcProperty = dynamic_cast<SbProcedureProperty*>( refVar.get() );
1864 if( pProcProperty )
1865 {
1866 pProcProperty->setSet( true );
1867 }
1868 if ( bHandleDefaultProp )
1869 {
1870 // get default properties for lhs & rhs where necessary
1871 // SbxVariable* defaultProp = NULL; unused variable
1872 // LHS try determine if a default prop exists
1873 // again like in StepPUT (see there too ) we are tweaking the
1874 // heuristics again for when to assign an object reference or
1875 // use default members if they exist
1876 // #FIXME we really need to get to the bottom of this mess
1877 bool bObjAssign = false;
1878 if ( refVar->GetType() == SbxOBJECT )
1879 {
1880 if ( dynamic_cast<const SbxMethod *>(refVar.get()) != nullptr || ! refVar->GetParent() )
1881 {
1882 SbxVariable* pDflt = getDefaultProp( refVar.get() );
1883 if ( pDflt )
1884 {
1885 refVar = pDflt;
1886 }
1887 }
1888 else
1889 bObjAssign = true;
1890 }
1891 // RHS only get a default prop is the rhs has one
1892 if ( refVal->GetType() == SbxOBJECT )
1893 {
1894 // check if lhs is a null object
1895 // if it is then use the object not the default property
1896 SbxObject* pObj = dynamic_cast<SbxObject*>( refVar.get() );
1897
1898 // calling GetObject on a SbxEMPTY variable raises
1899 // object not set errors, make sure it's an Object
1900 if ( !pObj && refVar->GetType() == SbxOBJECT )
1901 {
1902 SbxBase* pObjVarObj = refVar->GetObject();
1903 pObj = dynamic_cast<SbxObject*>( pObjVarObj );
1904 }
1905 SbxVariable* pDflt = nullptr;
1906 if ( pObj && !bObjAssign )
1907 {
1908 // lhs is either a valid object || or has a defaultProp
1909 pDflt = getDefaultProp( refVal.get() );
1910 }
1911 if ( pDflt )
1912 {
1913 refVal = pDflt;
1914 }
1915 }
1916 }
1917
1918 // Handle Dim As New
1919 bool bDimAsNew = bVBAEnabled && refVar->IsSet( SbxFlagBits::DimAsNew );
1920 SbxBaseRef xPrevVarObj;
1921 if( bDimAsNew )
1922 {
1923 xPrevVarObj = refVar->GetObject();
1924 }
1925 // Handle withevents
1926 bool bWithEvents = refVar->IsSet( SbxFlagBits::WithEvents );
1927 if ( bWithEvents )
1928 {
1929 Reference< XInterface > xComListener;
1930
1931 SbxBase* pObj = refVal->GetObject();
1932 SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj );
1933 if( pUnoObj != nullptr )
1934 {
1935 Any aControlAny = pUnoObj->getUnoAny();
1936 OUString aDeclareClassName = refVar->GetDeclareClassName();
1937 OUString aPrefix = refVar->GetName();
1938 SbxObjectRef xScopeObj = refVar->GetParent();
1939 xComListener = createComListener( aControlAny, aDeclareClassName, aPrefix, xScopeObj );
1940
1941 refVal->SetDeclareClassName( aDeclareClassName );
1942 refVal->SetComListener( xComListener, &rBasic ); // Hold reference
1943 }
1944
1945 }
1946
1947 // lhs is a property who's value is currently (Empty e.g. no broadcast yet)
1948 // in this case if there is a default prop involved the value of the
1949 // default property may in fact be void so the type will also be SbxEMPTY
1950 // in this case we do not want to call checkUnoStructCopy 'cause that will
1951 // cause an error also
1952 if ( !checkUnoStructCopy( bHandleDefaultProp, refVal, refVar ) )
1953 {
1954 *refVar = *refVal;
1955 }
1956 if ( bDimAsNew )
1957 {
1958 if( dynamic_cast<const SbxObject*>( refVar.get() ) == nullptr )
1959 {
1960 SbxBase* pValObjBase = refVal->GetObject();
1961 if( pValObjBase == nullptr )
1962 {
1963 if( xPrevVarObj.is() )
1964 {
1965 // Object is overwritten with NULL, instantiate init object
1966 DimAsNewRecoverHash::iterator it = gaDimAsNewRecoverHash.find( refVar.get() );
1967 if( it != gaDimAsNewRecoverHash.end() )
1968 {
1969 const DimAsNewRecoverItem& rItem = it->second;
1970 if( rItem.m_pClassModule != nullptr )
1971 {
1972 SbClassModuleObject* pNewObj = new SbClassModuleObject( rItem.m_pClassModule );
1973 pNewObj->SetName( rItem.m_aObjName );
1974 pNewObj->SetParent( rItem.m_pObjParent );
1975 refVar->PutObject( pNewObj );
1976 }
1977 else if( rItem.m_aObjClass.equalsIgnoreAsciiCase( pCollectionStr ) )
1978 {
1979 BasicCollection* pNewCollection = new BasicCollection( pCollectionStr );
1980 pNewCollection->SetName( rItem.m_aObjName );
1981 pNewCollection->SetParent( rItem.m_pObjParent );
1982 refVar->PutObject( pNewCollection );
1983 }
1984 }
1985 }
1986 }
1987 else
1988 {
1989 // Does old value exist?
1990 bool bFirstInit = !xPrevVarObj.is();
1991 if( bFirstInit )
1992 {
1993 // Store information to instantiate object later
1994 SbxObject* pValObj = dynamic_cast<SbxObject*>( pValObjBase );
1995 if( pValObj != nullptr )
1996 {
1997 OUString aObjClass = pValObj->GetClassName();
1998
1999 SbClassModuleObject* pClassModuleObj = dynamic_cast<SbClassModuleObject*>( pValObjBase );
2000 if( pClassModuleObj != nullptr )
2001 {
2002 SbModule* pClassModule = pClassModuleObj->getClassModule();
2003 gaDimAsNewRecoverHash[refVar.get()] =
2004 DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule );
2005 }
2006 else if( aObjClass.equalsIgnoreAsciiCase( "Collection" ) )
2007 {
2008 gaDimAsNewRecoverHash[refVar.get()] =
2009 DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), nullptr );
2010 }
2011 }
2012 }
2013 }
2014 }
2015 }
2016
2017 if( bFlagsChanged )
2018 {
2019 refVar->SetFlags( n );
2020 }
2021 }
2022}
2023
2025{
2026 SbxVariableRef refVal = PopVar();
2027 SbxVariableRef refVar = PopVar();
2028 StepSET_Impl( refVal, refVar, bVBAEnabled ); // this is really assignment
2029}
2030
2032{
2033 SbxVariableRef refVal = PopVar();
2034 SbxVariableRef refVar = PopVar();
2035 // don't handle default property
2036 StepSET_Impl( refVal, refVar ); // set obj = something
2037}
2038
2039
2041{
2042 SbxVariableRef refVal = PopVar();
2043 SbxVariableRef refVar = PopVar();
2044 if( refVar->GetType() != SbxSTRING ||
2045 refVal->GetType() != SbxSTRING )
2046 {
2048 }
2049 else
2050 {
2051 SbxFlagBits n = refVar->GetFlags();
2052 if( refVar.get() == pMeth )
2053 {
2054 refVar->SetFlag( SbxFlagBits::Write );
2055 }
2056 OUString aRefVarString = refVar->GetOUString();
2057 OUString aRefValString = refVal->GetOUString();
2058
2059 sal_Int32 nVarStrLen = aRefVarString.getLength();
2060 sal_Int32 nValStrLen = aRefValString.getLength();
2061 OUString aNewStr;
2062 if( nVarStrLen > nValStrLen )
2063 {
2064 OUStringBuffer buf(aRefValString);
2065 comphelper::string::padToLength(buf, nVarStrLen, ' ');
2066 aNewStr = buf.makeStringAndClear();
2067 }
2068 else
2069 {
2070 aNewStr = aRefValString.copy( 0, nVarStrLen );
2071 }
2072
2073 refVar->PutString(aNewStr);
2074 refVar->SetFlags( n );
2075 }
2076}
2077
2079{
2080 SbxVariableRef refVal = PopVar();
2081 SbxVariableRef refVar = PopVar();
2082 if( refVar->GetType() != SbxSTRING || refVal->GetType() != SbxSTRING )
2083 {
2085 }
2086 else
2087 {
2088 SbxFlagBits n = refVar->GetFlags();
2089 if( refVar.get() == pMeth )
2090 {
2091 refVar->SetFlag( SbxFlagBits::Write );
2092 }
2093 OUString aRefVarString = refVar->GetOUString();
2094 OUString aRefValString = refVal->GetOUString();
2095 sal_Int32 nVarStrLen = aRefVarString.getLength();
2096 sal_Int32 nValStrLen = aRefValString.getLength();
2097
2098 OUStringBuffer aNewStr(nVarStrLen);
2099 if (nVarStrLen > nValStrLen)
2100 {
2101 comphelper::string::padToLength(aNewStr, nVarStrLen - nValStrLen, ' ');
2102 aNewStr.append(aRefValString);
2103 }
2104 else
2105 {
2106 aNewStr.append(aRefValString.subView(0, nVarStrLen));
2107 }
2108 refVar->PutString(aNewStr.makeStringAndClear());
2109
2110 refVar->SetFlags( n );
2111 }
2112}
2113
2114// laying down TOS in TOS-1, then set ReadOnly-Bit
2115
2117{
2118 SbxVariableRef refVal = PopVar();
2119 SbxVariableRef refVar = PopVar();
2120 refVar->SetFlag( SbxFlagBits::Write );
2121 *refVar = *refVal;
2122 refVar->ResetFlag( SbxFlagBits::Write );
2123 refVar->SetFlag( SbxFlagBits::Const );
2124}
2125
2126// DIM
2127// TOS = variable for the array with dimension information as parameter
2128
2130{
2131 SbxVariableRef refVar = PopVar();
2132 DimImpl( refVar );
2133}
2134
2135// #56204 swap out DIM-functionality into a help method (step0.cxx)
2137{
2138 // If refDim then this DIM statement is terminating a ReDIM and
2139 // previous StepERASE_CLEAR for an array, the following actions have
2140 // been delayed from ( StepERASE_CLEAR ) 'till here
2141 if ( refRedim.is() )
2142 {
2143 if ( !refRedimpArray.is() ) // only erase the array not ReDim Preserve
2144 {
2145 lcl_eraseImpl( refVar, bVBAEnabled );
2146 }
2147 SbxDataType eType = refVar->GetType();
2148 lcl_clearImpl( refVar, eType );
2149 refRedim = nullptr;
2150 }
2151 SbxArray* pDims = refVar->GetParameters();
2152 // must have an even number of arguments
2153 // have in mind that Arg[0] does not count!
2154 if (pDims && !(pDims->Count() & 1))
2155 {
2157 }
2158 else
2159 {
2160 SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
2161 SbxDimArray* pArray = new SbxDimArray( eType );
2162 // allow arrays without dimension information, too (VB-compatible)
2163 if( pDims )
2164 {
2165 refVar->ResetFlag( SbxFlagBits::VarToDim );
2166
2167 for (sal_uInt32 i = 1; i < pDims->Count();)
2168 {
2169 sal_Int32 lb = pDims->Get(i++)->GetLong();
2170 sal_Int32 ub = pDims->Get(i++)->GetLong();
2171 if( ub < lb )
2172 {
2174 ub = lb;
2175 }
2176 pArray->AddDim(lb, ub);
2177 if ( lb != ub )
2178 {
2179 pArray->setHasFixedSize( true );
2180 }
2181 }
2182 }
2183 else
2184 {
2185 // #62867 On creating an array of the length 0, create
2186 // a dimension (like for Uno-Sequences of the length 0)
2187 pArray->unoAddDim(0, -1);
2188 }
2189 SbxFlagBits nSavFlags = refVar->GetFlags();
2190 refVar->ResetFlag( SbxFlagBits::Fixed );
2191 refVar->PutObject( pArray );
2192 refVar->SetFlags( nSavFlags );
2193 refVar->SetParameters( nullptr );
2194 }
2195}
2196
2197// REDIM
2198// TOS = variable for the array
2199// argv = dimension information
2200
2202{
2203 // Nothing different than dim at the moment because
2204 // a double dim is already recognized by the compiler.
2205 StepDIM();
2206}
2207
2208
2209// Helper function for StepREDIMP and StepDCREATE_IMPL / bRedimp = true
2210static void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, sal_Int32 nMaxDimIndex,
2211 sal_Int32 nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
2212{
2213 sal_Int32& ri = pActualIndices[nActualDim];
2214 for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
2215 {
2216 if( nActualDim < nMaxDimIndex )
2217 {
2218 implCopyDimArray( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
2219 pActualIndices, pLowerBounds, pUpperBounds );
2220 }
2221 else
2222 {
2223 SbxVariable* pSource = pOldArray->Get(pActualIndices);
2224 if (pSource && pOldArray->GetRefCount() > 1)
2225 // tdf#134692: old array will stay alive after the redim - we need to copy deep
2226 pSource = new SbxVariable(*pSource);
2227 pNewArray->Put(pSource, pActualIndices);
2228 }
2229 }
2230}
2231
2232// Returns true when actually restored
2233static bool implRestorePreservedArray(SbxDimArray* pNewArray, SbxArrayRef& rrefRedimpArray, bool* pbWasError = nullptr)
2234{
2235 assert(pNewArray);
2236 bool bResult = false;
2237 if (pbWasError)
2238 *pbWasError = false;
2239 if (rrefRedimpArray)
2240 {
2241 SbxDimArray* pOldArray = static_cast<SbxDimArray*>(rrefRedimpArray.get());
2242 const sal_Int32 nDimsNew = pNewArray->GetDims();
2243 const sal_Int32 nDimsOld = pOldArray->GetDims();
2244
2245 if (nDimsOld != nDimsNew)
2246 {
2248 if (pbWasError)
2249 *pbWasError = true;
2250 }
2251 else if (nDimsNew > 0)
2252 {
2253 // Store dims to use them for copying later
2254 std::unique_ptr<sal_Int32[]> pLowerBounds(new sal_Int32[nDimsNew]);
2255 std::unique_ptr<sal_Int32[]> pUpperBounds(new sal_Int32[nDimsNew]);
2256 std::unique_ptr<sal_Int32[]> pActualIndices(new sal_Int32[nDimsNew]);
2257 bool bNeedsPreallocation = true;
2258
2259 // Compare bounds
2260 for (sal_Int32 i = 1; i <= nDimsNew; i++)
2261 {
2262 sal_Int32 lBoundNew, uBoundNew;
2263 sal_Int32 lBoundOld, uBoundOld;
2264 pNewArray->GetDim(i, lBoundNew, uBoundNew);
2265 pOldArray->GetDim(i, lBoundOld, uBoundOld);
2266 lBoundNew = std::max(lBoundNew, lBoundOld);
2267 uBoundNew = std::min(uBoundNew, uBoundOld);
2268 sal_Int32 j = i - 1;
2269 pActualIndices[j] = pLowerBounds[j] = lBoundNew;
2270 pUpperBounds[j] = uBoundNew;
2271 if (lBoundNew > uBoundNew) // No elements in the dimension -> no elements to restore
2272 bNeedsPreallocation = false;
2273 }
2274
2275 // Optimization: pre-allocate underlying container
2276 if (bNeedsPreallocation)
2277 pNewArray->Put(nullptr, pUpperBounds.get());
2278
2279 // Copy data from old array by going recursively through all dimensions
2280 // (It would be faster to work on the flat internal data array of an
2281 // SbyArray but this solution is clearer and easier)
2282 implCopyDimArray(pNewArray, pOldArray, nDimsNew - 1, 0, pActualIndices.get(),
2283 pLowerBounds.get(), pUpperBounds.get());
2284 bResult = true;
2285 }
2286
2287 rrefRedimpArray.clear();
2288 }
2289 return bResult;
2290}
2291
2292// REDIM PRESERVE
2293// TOS = variable for the array
2294// argv = dimension information
2295
2297{
2298 SbxVariableRef refVar = PopVar();
2299 DimImpl( refVar );
2300
2301 // Now check, if we can copy from the old array
2302 if( refRedimpArray.is() )
2303 {
2304 if (SbxDimArray* pNewArray = dynamic_cast<SbxDimArray*>(refVar->GetObject()))
2306 }
2307}
2308
2309// REDIM_COPY
2310// TOS = Array-Variable, Reference to array is copied
2311// Variable is cleared as in ERASE
2312
2314{
2315 SbxVariableRef refVar = PopVar();
2316 refRedim = refVar;
2317 SbxDataType eType = refVar->GetType();
2318 if( eType & SbxARRAY )
2319 {
2320 SbxBase* pElemObj = refVar->GetObject();
2321 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>( pElemObj );
2322 if( pDimArray )
2323 {
2324 refRedimpArray = pDimArray;
2325 }
2326
2327 }
2328 else if( refVar->IsFixed() )
2329 {
2330 refVar->Clear();
2331 }
2332 else
2333 {
2334 refVar->SetType( SbxEMPTY );
2335 }
2336}
2337
2338static void lcl_clearImpl( SbxVariableRef const & refVar, SbxDataType const & eType )
2339{
2340 SbxFlagBits nSavFlags = refVar->GetFlags();
2341 refVar->ResetFlag( SbxFlagBits::Fixed );
2342 refVar->SetType( SbxDataType(eType & 0x0FFF) );
2343 refVar->SetFlags( nSavFlags );
2344 refVar->Clear();
2345}
2346
2347static void lcl_eraseImpl( SbxVariableRef const & refVar, bool bVBAEnabled )
2348{
2349 SbxDataType eType = refVar->GetType();
2350 if( eType & SbxARRAY )
2351 {
2352 if ( bVBAEnabled )
2353 {
2354 SbxBase* pElemObj = refVar->GetObject();
2355 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>( pElemObj );
2356 if( pDimArray )
2357 {
2358 if ( pDimArray->hasFixedSize() )
2359 {
2360 // Clear all Value(s)
2361 pDimArray->SbxArray::Clear();
2362 }
2363 else
2364 {
2365 pDimArray->Clear(); // clear dims and values
2366 }
2367 }
2368 else
2369 {
2370 SbxArray* pArray = dynamic_cast<SbxArray*>( pElemObj );
2371 if ( pArray )
2372 {
2373 pArray->Clear();
2374 }
2375 }
2376 }
2377 else
2378 {
2379 // Arrays have on an erase to VB quite a complex behaviour. Here are
2380 // only the type problems at REDIM (#26295) removed at first:
2381 // Set type hard onto the array-type, because a variable with array is
2382 // SbxOBJECT. At REDIM there's an SbxOBJECT-array generated then and
2383 // the original type is lost -> runtime error
2384 lcl_clearImpl( refVar, eType );
2385 }
2386 }
2387 else if( refVar->IsFixed() )
2388 {
2389 refVar->Clear();
2390 }
2391 else
2392 {
2393 refVar->SetType( SbxEMPTY );
2394 }
2395}
2396
2397// delete variable
2398// TOS = variable
2399
2401{
2402 SbxVariableRef refVar = PopVar();
2403 lcl_eraseImpl( refVar, bVBAEnabled );
2404}
2405
2407{
2408 refRedim = PopVar();
2409}
2410
2412{
2413 if( !refArgv.is() )
2414 {
2416 }
2417 SbxVariableRef refVar = PopVar();
2418 refVar->SetParameters( refArgv.get() );
2419 PopArgv();
2420 PushVar( CheckArray( refVar.get() ) );
2421}
2422
2424{
2425 // Copy variable on stack to break call by reference
2426 SbxVariableRef pVar = PopVar();
2427 SbxDataType t = pVar->GetType();
2428
2429 SbxVariable* pCopyVar = new SbxVariable( t );
2430 pCopyVar->SetFlag( SbxFlagBits::ReadWrite );
2431 *pCopyVar = *pVar;
2432
2433 PushVar( pCopyVar );
2434}
2435
2436// establishing an argv
2437// nOp1 stays as it is -> 1st element is the return value
2438
2440{
2441 PushArgv();
2442 refArgv = new SbxArray;
2443 nArgc = 1;
2444}
2445
2446// storing an argument in Argv
2447
2449{
2450 if( !refArgv.is() )
2451 {
2453 }
2454 else
2455 {
2456 SbxVariableRef pVal = PopVar();
2457
2458 // Before fix of #94916:
2459 if( dynamic_cast<const SbxMethod*>( pVal.get() ) != nullptr
2460 || dynamic_cast<const SbUnoProperty*>( pVal.get() ) != nullptr
2461 || dynamic_cast<const SbProcedureProperty*>( pVal.get() ) != nullptr )
2462 {
2463 // evaluate methods and properties!
2464 SbxVariable* pRes = new SbxVariable( *pVal );
2465 pVal = pRes;
2466 }
2467 refArgv->Put(pVal.get(), nArgc++);
2468 }
2469}
2470
2471// Input to Variable. The variable is on TOS and is
2472// is removed afterwards.
2474{
2475 OUStringBuffer sin;
2476 char ch = 0;
2477 ErrCode err;
2478 // Skip whitespace
2479 while( ( err = pIosys->GetError() ) == ERRCODE_NONE )
2480 {
2481 ch = pIosys->Read();
2482 if( ch != ' ' && ch != '\t' && ch != '\n' )
2483 {
2484 break;
2485 }
2486 }
2487 if( !err )
2488 {
2489 // Scan until comma or whitespace
2490 char sep = ( ch == '"' ) ? ch : 0;
2491 if( sep )
2492 {
2493 ch = pIosys->Read();
2494 }
2495 while( ( err = pIosys->GetError() ) == ERRCODE_NONE )
2496 {
2497 if( ch == sep )
2498 {
2499 ch = pIosys->Read();
2500 if( ch != sep )
2501 {
2502 break;
2503 }
2504 }
2505 else if( !sep && (ch == ',' || ch == '\n') )
2506 {
2507 break;
2508 }
2509 sin.append( ch );
2510 ch = pIosys->Read();
2511 }
2512 // skip whitespace
2513 if( ch == ' ' || ch == '\t' )
2514 {
2515 while( ( err = pIosys->GetError() ) == ERRCODE_NONE )
2516 {
2517 if( ch != ' ' && ch != '\t' && ch != '\n' )
2518 {
2519 break;
2520 }
2521 ch = pIosys->Read();
2522 }
2523 }
2524 }
2525 if( !err )
2526 {
2527 OUString s = sin.makeStringAndClear();
2528 SbxVariableRef pVar = GetTOS();
2529 // try to fill the variable with a numeric value first,
2530 // then with a string value
2531 if( !pVar->IsFixed() || pVar->IsNumeric() )
2532 {
2533 sal_uInt16 nLen = 0;
2534 if( !pVar->Scan( s, &nLen ) )
2535 {
2538 }
2539 // the value has to be scanned in completely
2540 else if( nLen != s.getLength() && !pVar->PutString( s ) )
2541 {
2544 }
2545 else if( nLen != s.getLength() && pVar->IsNumeric() )
2546 {
2549 if( !err )
2550 {
2552 }
2553 }
2554 }
2555 else
2556 {
2557 pVar->PutString( s );
2560 }
2561 }
2563 {
2564 Error( err );
2565 }
2566 else if( err )
2567 {
2568 if( pRestart && !pIosys->GetChannel() )
2569 {
2570 pCode = pRestart;
2571 }
2572 else
2573 {
2574 Error( err );
2575 }
2576 }
2577 else
2578 {
2579 PopVar();
2580 }
2581}
2582
2583// Line Input to Variable. The variable is on TOS and is
2584// deleted afterwards.
2585
2587{
2588 OString aInput;
2589 pIosys->Read( aInput );
2590 Error( pIosys->GetError() );
2592 p->PutString(OStringToOUString(aInput, osl_getThreadTextEncoding()));
2593}
2594
2595// end of program
2596
2598{
2599 pInst->Stop();
2600}
2601
2602
2604{
2605 PushFor();
2606}
2607
2609{
2610 PushForEach();
2611}
2612
2613// increment FOR-variable
2614
2616{
2617 if( !pForStk )
2618 {
2620 return;
2621 }
2623 return;
2624 if (!pForStk->refVar)
2625 {
2627 return;
2628 }
2629 // tdf#85371 - grant explicitly write access to the index variable
2630 // since it could be the name of a method itself used in the next statement.
2631 ScopedWritableGuard aGuard(pForStk->refVar, pForStk->refVar.get() == pMeth);
2632 pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
2633}
2634
2635// beginning CASE: TOS in CASE-stack
2636
2638{
2639 if( !refCaseStk.is() )
2640 {
2641 refCaseStk = new SbxArray;
2642 }
2643 SbxVariableRef xVar = PopVar();
2644 refCaseStk->Put(xVar.get(), refCaseStk->Count());
2645}
2646
2647// end CASE: free variable
2648
2650{
2651 if (!refCaseStk.is() || !refCaseStk->Count())
2652 {
2654 }
2655 else
2656 {
2657 refCaseStk->Remove(refCaseStk->Count() - 1);
2658 }
2659}
2660
2661
2663{
2664 pError = nullptr; bError = true;
2665 pInst->aErrorMsg.clear();
2667 pInst->nErl = 0;
2670}
2671
2673{
2674 pInst->aErrorMsg.clear();
2676 pInst->nErl = 0;
2679 bError = false;
2680}
2681
2682// leave UP
2683
2685{
2686 bRun = false;
2687 // If VBA and we are leaving an ErrorHandler then clear the error ( it's been processed )
2688 if ( bInError && pError )
2689 {
2691 }
2692}
2693
2694void SbiRuntime::StepCHANNEL() // TOS = channel number
2695{
2696 SbxVariableRef pChan = PopVar();
2697 short nChan = pChan->GetInteger();
2698 pIosys->SetChannel( nChan );
2699 Error( pIosys->GetError() );
2700}
2701
2703{
2705}
2706
2707void SbiRuntime::StepPRINT() // print TOS
2708{
2710 OUString s1 = p->GetOUString();
2711 OUString s;
2712 if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
2713 {
2714 s = " "; // one blank before
2715 }
2716 s += s1;
2717 pIosys->Write( s );
2718 Error( pIosys->GetError() );
2719}
2720
2721void SbiRuntime::StepPRINTF() // print TOS in field
2722{
2724 OUString s1 = p->GetOUString();
2725 OUStringBuffer s;
2726 if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
2727 {
2728 s.append(' ');
2729 }
2730 s.append(s1);
2732 pIosys->Write( s );
2733 Error( pIosys->GetError() );
2734}
2735
2736void SbiRuntime::StepWRITE() // write TOS
2737{
2739 // Does the string have to be encapsulated?
2740 char ch = 0;
2741 switch (p->GetType() )
2742 {
2743 case SbxSTRING: ch = '"'; break;
2744 case SbxCURRENCY:
2745 case SbxBOOL:
2746 case SbxDATE: ch = '#'; break;
2747 default: break;
2748 }
2749 OUString s;
2750 if( ch )
2751 {
2752 s += OUStringChar(ch);
2753 }
2754 s += p->GetOUString();
2755 if( ch )
2756 {
2757 s += OUStringChar(ch);
2758 }
2759 pIosys->Write( s );
2760 Error( pIosys->GetError() );
2761}
2762
2763void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos
2764{
2765 SbxVariableRef pTos1 = PopVar();
2766 SbxVariableRef pTos = PopVar();
2767 OUString aDest = pTos1->GetOUString();
2768 OUString aSource = pTos->GetOUString();
2769
2770 if( hasUno() )
2771 {
2772 implStepRenameUCB( aSource, aDest );
2773 }
2774 else
2775 {
2776 implStepRenameOSL( aSource, aDest );
2777 }
2778}
2779
2780// TOS = Prompt
2781
2783{
2785 OString aStr(OUStringToOString(p->GetOUString(), osl_getThreadTextEncoding()));
2786 pIosys->SetPrompt( aStr );
2787}
2788
2789// Set Restart point
2790
2792{
2793 pRestart = pCode;
2794}
2795
2796// empty expression on stack for missing parameter
2797
2799{
2800 // #57915 The semantics of StepEMPTY() is the representation of a missing argument.
2801 // This is represented by the value 448 (ERRCODE_BASIC_NAMED_NOT_FOUND) of the type error
2802 // in VB. StepEmpty should now rather be named StepMISSING() but the name is kept
2803 // to simplify matters.
2805 xVar->PutErr( 448 );
2806 // tdf#79426, tdf#125180 - add additional information about a missing parameter
2807 SetIsMissing( xVar.get() );
2808 PushVar( xVar.get() );
2809}
2810
2811// TOS = error code
2812
2814{
2815 SbxVariableRef refCode = PopVar();
2816 sal_uInt16 n = refCode->GetUShort();
2818 if ( bVBAEnabled )
2819 {
2820 pInst->Error( error );
2821 }
2822 else
2823 {
2824 Error( error );
2825 }
2826}
2827
2828// loading a numeric constant (+ID)
2829
2830void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 )
2831{
2832 // tdf#143707 - check if the data type character was added after the string termination symbol
2833 SbxDataType eTypeStr;
2834 // #57844 use localized function
2835 OUString aStr = pImg->GetString(nOp1, &eTypeStr);
2836 // also allow , !!!
2837 sal_Int32 iComma = aStr.indexOf(',');
2838 if( iComma >= 0 )
2839 {
2840 aStr = aStr.replaceAt(iComma, 1, u".");
2841 }
2842 sal_Int32 nParseEnd = 0;
2843 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
2844 double n = ::rtl::math::stringToDouble( aStr, '.', ',', &eStatus, &nParseEnd );
2845
2846 // tdf#131296 - retrieve data type put in SbiExprNode::Gen
2848 if ( nParseEnd < aStr.getLength() )
2849 {
2850 // tdf#143707 - Check if there was a data type character after the numeric constant,
2851 // added by older versions of the fix of the default values for strings.
2852 switch ( aStr[nParseEnd] )
2853 {
2854 // See GetSuffixType in basic/source/comp/scanner.cxx for type characters
2855 case '%': eType = SbxINTEGER; break;
2856 case '&': eType = SbxLONG; break;
2857 case '!': eType = SbxSINGLE; break;
2858 case '@': eType = SbxCURRENCY; break;
2859 // tdf#142460 - properly handle boolean values in string pool
2860 case 'b': eType = SbxBOOL; break;
2861 }
2862 }
2863 // tdf#143707 - if the data type character is different from the default value, it was added
2864 // in basic/source/comp/symtbl.cxx. Hence, change the type of the numeric constant to be loaded.
2865 else if (eTypeStr != SbxSTRING)
2866 {
2867 eType = eTypeStr;
2868 }
2869 SbxVariable* p = new SbxVariable( eType );
2870 p->PutDouble( n );
2871 // tdf#133913 - create variable with Variant/Type in order to prevent type conversion errors
2872 p->ResetFlag( SbxFlagBits::Fixed );
2873 PushVar( p );
2874}
2875
2876// loading a string constant (+ID)
2877
2878void SbiRuntime::StepLOADSC( sal_uInt32 nOp1 )
2879{
2880 SbxVariable* p = new SbxVariable;
2881 p->PutString( pImg->GetString( nOp1 ) );
2882 PushVar( p );
2883}
2884
2885// Immediate Load (+value)
2886// The opcode is not generated in SbiExprNode::Gen anymore; used for legacy images
2887
2888void SbiRuntime::StepLOADI( sal_uInt32 nOp1 )
2889{
2890 SbxVariable* p = new SbxVariable;
2891 p->PutInteger( static_cast<sal_Int16>( nOp1 ) );
2892 PushVar( p );
2893}
2894
2895// store a named argument in Argv (+Arg-no. from 1!)
2896
2897void SbiRuntime::StepARGN( sal_uInt32 nOp1 )
2898{
2899 if( !refArgv.is() )
2901 else
2902 {
2903 OUString aAlias( pImg->GetString( nOp1 ) );
2904 SbxVariableRef pVal = PopVar();
2905 if( bVBAEnabled &&
2906 ( dynamic_cast<const SbxMethod*>( pVal.get()) != nullptr
2907 || dynamic_cast<const SbUnoProperty*>( pVal.get()) != nullptr
2908 || dynamic_cast<const SbProcedureProperty*>( pVal.get()) != nullptr ) )
2909 {
2910 // named variables ( that are Any especially properties ) can be empty at this point and need a broadcast
2911 if ( pVal->GetType() == SbxEMPTY )
2912 pVal->Broadcast( SfxHintId::BasicDataWanted );
2913 // evaluate methods and properties!
2914 SbxVariable* pRes = new SbxVariable( *pVal );
2915 pVal = pRes;
2916 }
2917 refArgv->Put(pVal.get(), nArgc);
2918 refArgv->PutAlias(aAlias, nArgc++);
2919 }
2920}
2921
2922// converting the type of an argument in Argv for DECLARE-Fkt. (+type)
2923
2924void SbiRuntime::StepARGTYP( sal_uInt32 nOp1 )
2925{
2926 if( !refArgv.is() )
2928 else
2929 {
2930 bool bByVal = (nOp1 & 0x8000) != 0; // Is BYVAL requested?
2931 SbxDataType t = static_cast<SbxDataType>(nOp1 & 0x7FFF);
2932 SbxVariable* pVar = refArgv->Get(refArgv->Count() - 1); // last Arg
2933
2934 // check BYVAL
2935 if( pVar->GetRefCount() > 2 ) // 2 is normal for BYVAL
2936 {
2937 // parameter is a reference
2938 if( bByVal )
2939 {
2940 // Call by Value is requested -> create a copy
2941 pVar = new SbxVariable( *pVar );
2943 refExprStk->Put(pVar, refArgv->Count() - 1);
2944 }
2945 else
2946 pVar->SetFlag( SbxFlagBits::Reference ); // Ref-Flag for DllMgr
2947 }
2948 else
2949 {
2950 // parameter is NO reference
2951 if( bByVal )
2952 pVar->ResetFlag( SbxFlagBits::Reference ); // no reference -> OK
2953 else
2954 Error( ERRCODE_BASIC_BAD_PARAMETERS ); // reference needed
2955 }
2956
2957 if( pVar->GetType() != t )
2958 {
2959 // variant for correct conversion
2960 // besides error, if SbxBYREF
2961 pVar->Convert( SbxVARIANT );
2962 pVar->Convert( t );
2963 }
2964 }
2965}
2966
2967// bring string to a definite length (+length)
2968
2969void SbiRuntime::StepPAD( sal_uInt32 nOp1 )
2970{
2971 SbxVariable* p = GetTOS();
2972 OUString s = p->GetOUString();
2973 sal_Int32 nLen(nOp1);
2974 if( s.getLength() == nLen )
2975 return;
2976
2977 OUStringBuffer aBuf(s);
2978 if (aBuf.getLength() > nLen)
2979 {
2981 }
2982 else
2983 {
2985 }
2986 s = aBuf.makeStringAndClear();
2987}
2988
2989// jump (+target)
2990
2991void SbiRuntime::StepJUMP( sal_uInt32 nOp1 )
2992{
2993#ifdef DBG_UTIL
2994 // #QUESTION shouldn't this be
2995 // if( (sal_uInt8*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() )
2996 if( nOp1 >= pImg->GetCodeSize() )
2998#endif
2999 pCode = pImg->GetCode() + nOp1;
3000}
3001
3003{
3004 SbxVariableRef tos = PopVar();
3005 // In a test e.g. If Null then
3006 // will evaluate Null will act as if False
3007 if ( bVBAEnabled && tos->IsNull() )
3008 {
3009 return false;
3010 }
3011
3012 // tdf#151503 - do not evaluate a missing optional variable to a boolean
3013 if (tos->GetType() == SbxERROR && IsMissing(tos.get(), 1))
3014 {
3016 return false;
3017 }
3018
3019 if ( tos->IsObject() )
3020 {
3021 //GetBool applied to an Object attempts to dereference and evaluate
3022 //the underlying value as Bool. Here, we're checking rather that
3023 //it is not null
3024 return tos->GetObject();
3025 }
3026 else
3027 {
3028 return tos->GetBool();
3029 }
3030}
3031
3032// evaluate TOS, conditional jump (+target)
3033
3034void SbiRuntime::StepJUMPT( sal_uInt32 nOp1 )
3035{
3037 {
3038 StepJUMP( nOp1 );
3039 }
3040}
3041
3042// evaluate TOS, conditional jump (+target)
3043
3044void SbiRuntime::StepJUMPF( sal_uInt32 nOp1 )
3045{
3046 if ( !EvaluateTopOfStackAsBool() )
3047 {
3048 StepJUMP( nOp1 );
3049 }
3050}
3051
3052// evaluate TOS, jump into JUMP-table (+MaxVal)
3053// looks like this:
3054// ONJUMP 2
3055// JUMP target1
3056// JUMP target2
3057
3058// if 0x8000 is set in the operand, push the return address (ON..GOSUB)
3059
3060void SbiRuntime::StepONJUMP( sal_uInt32 nOp1 )
3061{
3063 sal_Int16 n = p->GetInteger();
3064 if( nOp1 & 0x8000 )
3065 {
3066 nOp1 &= 0x7FFF;
3067 PushGosub( pCode + 5 * nOp1 );
3068 }
3069 if( n < 1 || o3tl::make_unsigned(n) > nOp1 )
3070 n = static_cast<sal_Int16>( nOp1 + 1 );
3071 nOp1 = static_cast<sal_uInt32>(pCode - pImg->GetCode()) + 5 * --n;
3072 StepJUMP( nOp1 );
3073}
3074
3075// UP-call (+target)
3076
3077void SbiRuntime::StepGOSUB( sal_uInt32 nOp1 )
3078{
3079 PushGosub( pCode );
3080 if( nOp1 >= pImg->GetCodeSize() )
3082 pCode = pImg->GetCode() + nOp1;
3083}
3084
3085// UP-return (+0 or target)
3086
3087void SbiRuntime::StepRETURN( sal_uInt32 nOp1 )
3088{
3089 PopGosub();
3090 if( nOp1 )
3091 StepJUMP( nOp1 );
3092}
3093
3094// check FOR-variable (+Endlabel)
3095
3096void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 )
3097{
3098 if( !pForStk )
3099 {
3101 return;
3102 }
3103
3104 bool bEndLoop = false;
3105 switch( pForStk->eForType )
3106 {
3107 case ForType::To:
3108 {
3109 SbxOperator eOp = ( pForStk->refInc->GetDouble() < 0 ) ? SbxLT : SbxGT;
3110 if( pForStk->refVar->Compare( eOp, *pForStk->refEnd ) )
3111 bEndLoop = true;
3112 if (SbxBase::IsError())
3113 pForStk->eForType = ForType::Error; // terminate loop at the next iteration
3114 break;
3115 }
3116 case ForType::EachArray:
3117 {
3119 if (!p->refEnd)
3120 {
3122 pForStk->eForType = ForType::Error; // terminate loop at the next iteration
3123 }
3124 else if (p->pArrayCurIndices == nullptr)
3125 {
3126 bEndLoop = true;
3127 }
3128 else
3129 {
3130 SbxDimArray* pArray = reinterpret_cast<SbxDimArray*>(p->refEnd.get());
3131 sal_Int32 nDims = pArray->GetDims();
3132
3133 // Empty array?
3134 if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] )
3135 {
3136 bEndLoop = true;
3137 break;
3138 }
3139 SbxVariable* pVal = pArray->Get(p->pArrayCurIndices.get());
3140 *(p->refVar) = *pVal;
3141
3142 bool bFoundNext = false;
3143 for(sal_Int32 i = 0 ; i < nDims ; i++ )
3144 {
3145 if( p->pArrayCurIndices[i] < p->pArrayUpperBounds[i] )
3146 {
3147 bFoundNext = true;
3148 p->pArrayCurIndices[i]++;
3149 for( sal_Int32 j = i - 1 ; j >= 0 ; j-- )
3150 p->pArrayCurIndices[j] = p->pArrayLowerBounds[j];
3151 break;
3152 }
3153 }
3154 if( !bFoundNext )
3155 {
3156 p->pArrayCurIndices.reset();
3157 }
3158 }
3159 break;
3160 }
3162 {
3163 if (!pForStk->refEnd)
3164 {
3166 pForStk->eForType = ForType::Error; // terminate loop at the next iteration
3167 break;
3168 }
3169
3170 BasicCollection* pCollection = static_cast<BasicCollection*>(pForStk->refEnd.get());
3171 SbxArrayRef xItemArray = pCollection->xItemArray;
3172 sal_Int32 nCount = xItemArray->Count();
3174 {
3175 SbxVariable* pRes = xItemArray->Get(pForStk->nCurCollectionIndex);
3177 (*pForStk->refVar) = *pRes;
3178 }
3179 else
3180 {
3181 bEndLoop = true;
3182 }
3183 break;
3184 }
3186 {
3188 if (!p->xEnumeration)
3189 {
3191 pForStk->eForType = ForType::Error; // terminate loop at the next iteration
3192 }
3193 else if (p->xEnumeration->hasMoreElements())
3194 {
3195 Any aElem = p->xEnumeration->nextElement();
3197 unoToSbxValue( xVar.get(), aElem );
3198 (*pForStk->refVar) = *xVar;
3199 }
3200 else
3201 {
3202 bEndLoop = true;
3203 }
3204 break;
3205 }
3206 // tdf#130307 - support for each loop for objects exposing XIndexAccess
3208 {
3210 if (!p->xIndexAccess)
3211 {
3213 pForStk->eForType = ForType::Error; // terminate loop at the next iteration
3214 }
3215 else if (pForStk->nCurCollectionIndex < p->xIndexAccess->getCount())
3216 {
3217 Any aElem = p->xIndexAccess->getByIndex(pForStk->nCurCollectionIndex);
3220 unoToSbxValue(xVar.get(), aElem);
3221 (*pForStk->refVar) = *xVar;
3222 }
3223 else
3224 {
3225 bEndLoop = true;
3226 }
3227 break;
3228 }
3229 case ForType::Error:
3230 {
3231 // We are in Resume Next mode after failed loop initialization
3232 bEndLoop = true;
3234 break;
3235 }
3236 }
3237 if( bEndLoop )
3238 {
3239 PopFor();
3240 StepJUMP( nOp1 );
3241 }
3242}
3243
3244// Tos+1 <= Tos+2 <= Tos, 2xremove (+Target)
3245
3246void SbiRuntime::StepCASETO( sal_uInt32 nOp1 )
3247{
3248 if (!refCaseStk.is() || !refCaseStk->Count())
3250 else
3251 {
3252 SbxVariableRef xTo = PopVar();
3253 SbxVariableRef xFrom = PopVar();
3254 SbxVariableRef xCase = refCaseStk->Get(refCaseStk->Count() - 1);
3255 if( *xCase >= *xFrom && *xCase <= *xTo )
3256 StepJUMP( nOp1 );
3257 }
3258}
3259
3260
3261void SbiRuntime::StepERRHDL( sal_uInt32 nOp1 )
3262{
3263 const sal_uInt8* p = pCode;
3264 StepJUMP( nOp1 );
3265 pError = pCode;
3266 pCode = p;
3267 pInst->aErrorMsg.clear();
3269 pInst->nErl = 0;
3272}
3273
3274// Resume after errors (+0=statement, 1=next or Label)
3275
3276void SbiRuntime::StepRESUME( sal_uInt32 nOp1 )
3277{
3278 // #32714 Resume without error? -> error
3279 if( !bInError )
3280 {
3282 return;
3283 }
3284 if( nOp1 )
3285 {
3286 // set Code-pointer to the next statement
3287 sal_uInt16 n1, n2;
3288 pCode = pMod->FindNextStmnt( pErrCode, n1, n2, true, pImg );
3289 }
3290 else
3291 pCode = pErrStmnt;
3292 if ( pError ) // current in error handler ( and got a Resume Next statement )
3294
3295 if( nOp1 > 1 )
3296 StepJUMP( nOp1 );
3297 pInst->aErrorMsg.clear();
3299 pInst->nErl = 0;
3301 bInError = false;
3302}
3303
3304// close channel (+channel, 0=all)
3305void SbiRuntime::StepCLOSE( sal_uInt32 nOp1 )
3306{
3307 ErrCode err;
3308 if( !nOp1 )
3309 pIosys->Shutdown();
3310 else
3311 {
3312 err = pIosys->GetError();
3313 if( !err )
3314 {
3315 pIosys->Close();
3316 }
3317 }
3318 err = pIosys->GetError();
3319 Error( err );
3320}
3321
3322// output character (+char)
3323
3324void SbiRuntime::StepPRCHAR( sal_uInt32 nOp1 )
3325{
3326 OUString s(static_cast<sal_Unicode>(nOp1));
3327 pIosys->Write( s );
3328 Error( pIosys->GetError() );
3329}
3330
3331// check whether TOS is a certain object class (+StringID)
3332
3333bool SbiRuntime::implIsClass( SbxObject const * pObj, const OUString& aClass )
3334{
3335 bool bRet = true;
3336
3337 if( !aClass.isEmpty() )
3338 {
3339 bRet = pObj->IsClass( aClass );
3340 if( !bRet )
3341 bRet = aClass.equalsIgnoreAsciiCase( "object" );
3342 if( !bRet )
3343 {
3344 const OUString& aObjClass = pObj->GetClassName();
3345 SbModule* pClassMod = GetSbData()->pClassFac->FindClass( aObjClass );
3346 if( pClassMod )
3347 {
3348 SbClassData* pClassData = pClassMod->pClassData.get();
3349 if (pClassData != nullptr )
3350 {
3351 SbxVariable* pClassVar = pClassData->mxIfaces->Find( aClass, SbxClassType::DontCare );
3352 bRet = (pClassVar != nullptr);
3353 }
3354 }
3355 }
3356 }
3357 return bRet;
3358}
3359
3361 const OUString& aClass, bool bRaiseErrors, bool bDefault )
3362{
3363 bool bOk = bDefault;
3364
3365 SbxDataType t = refVal->GetType();
3366 SbxVariable* pVal = refVal.get();
3367 // we don't know the type of uno properties that are (maybevoid)
3368 if ( t == SbxEMPTY )
3369 {
3370 if ( auto pProp = dynamic_cast<SbUnoProperty*>( refVal.get() ) )
3371 {
3372 t = pProp->getRealType();
3373 }
3374 }
3375 if( t == SbxOBJECT || bVBAEnabled )
3376 {
3377 SbxObject* pObj = dynamic_cast<SbxObject*>(pVal);
3378 if (!pObj)
3379 {
3380 pObj = dynamic_cast<SbxObject*>(refVal->GetObject());
3381 }
3382 if( pObj )
3383 {
3384 if( !implIsClass( pObj, aClass ) )
3385 {
3386 SbUnoObject* pUnoObj(nullptr);
3388 {
3389 pUnoObj = dynamic_cast<SbUnoObject*>(pObj);
3390 }
3391
3392 if (pUnoObj)
3393 bOk = checkUnoObjectType(*pUnoObj, aClass);
3394 else
3395 bOk = false;
3396 if ( !bOk && bRaiseErrors )
3398 }
3399 else
3400 {
3401 bOk = true;
3402
3403 SbClassModuleObject* pClassModuleObject = dynamic_cast<SbClassModuleObject*>( pObj );
3404 if( pClassModuleObject != nullptr )
3405 pClassModuleObject->triggerInitializeEvent();
3406 }
3407 }
3408 }
3409 else
3410 {
3411 if( bRaiseErrors )
3413 bOk = false;
3414 }
3415 return bOk;
3416}
3417
3418void SbiRuntime::StepSETCLASS_impl( sal_uInt32 nOp1, bool bHandleDflt )
3419{
3420 SbxVariableRef refVal = PopVar();
3421 SbxVariableRef refVar = PopVar();
3422 OUString aClass( pImg->GetString( nOp1 ) );
3423
3424 bool bOk = checkClass_Impl( refVal, aClass, true, true );
3425 if( bOk )
3426 {
3427 StepSET_Impl( refVal, refVar, bHandleDflt ); // don't do handle default prop for a "proper" set
3428 }
3429}
3430
3431void SbiRuntime::StepVBASETCLASS( sal_uInt32 nOp1 )
3432{
3433 StepSETCLASS_impl( nOp1, false );
3434}
3435
3436void SbiRuntime::StepSETCLASS( sal_uInt32 nOp1 )
3437{
3438 StepSETCLASS_impl( nOp1, true );
3439}
3440
3441void SbiRuntime::StepTESTCLASS( sal_uInt32 nOp1 )
3442{
3443 SbxVariableRef xObjVal = PopVar();
3444 OUString aClass( pImg->GetString( nOp1 ) );
3445 bool bDefault = !bVBAEnabled;
3446 bool bOk = checkClass_Impl( xObjVal, aClass, false, bDefault );
3447
3448 SbxVariable* pRet = new SbxVariable;
3449 pRet->PutBool( bOk );
3450 PushVar( pRet );
3451}
3452
3453// define library for following declare-call
3454
3455void SbiRuntime::StepLIB( sal_uInt32 nOp1 )
3456{
3457 aLibName = pImg->GetString( nOp1 );
3458}
3459
3460// TOS is incremented by BASE, BASE is pushed before (+BASE)
3461// This opcode is pushed before DIM/REDIM-commands,
3462// if there's been only one index named.
3463
3464void SbiRuntime::StepBASED( sal_uInt32 nOp1 )
3465{
3466 SbxVariable* p1 = new SbxVariable;
3467 SbxVariableRef x2 = PopVar();
3468
3469 // #109275 Check compatibility mode
3470 bool bCompatible = ((nOp1 & 0x8000) != 0);
3471 sal_uInt16 uBase = static_cast<sal_uInt16>(nOp1 & 1); // Can only be 0 or 1
3472 p1->PutInteger( uBase );
3473 if( !bCompatible )
3474 {
3475 // tdf#85371 - grant explicitly write access to the dimension variable
3476 // since in Star/OpenOffice Basic the upper index border is affected,
3477 // and the dimension variable could be the name of the method itself.
3478 ScopedWritableGuard aGuard(x2, x2.get() == pMeth);
3479 x2->Compute( SbxPLUS, *p1 );
3480 }
3481 PushVar( x2.get() ); // first the Expr
3482 PushVar( p1 ); // then the Base
3483}
3484
3485// the bits in the String-ID:
3486// 0x8000 - Argv is reserved
3487
3488SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
3489 ErrCode nNotFound, bool bLocal, bool bStatic )
3490{
3491 bool bIsVBAInterOp = SbiRuntime::isVBAEnabled();
3492 if( bIsVBAInterOp )
3493 {
3494 StarBASIC* pMSOMacroRuntimeLib = GetSbData()->pMSOMacroRuntimLib;
3495 if( pMSOMacroRuntimeLib != nullptr )
3496 {
3497 pMSOMacroRuntimeLib->ResetFlag( SbxFlagBits::ExtSearch );
3498 }
3499 }
3500
3501 SbxVariable* pElem = nullptr;
3502 if( !pObj )
3503 {
3505 pElem = new SbxVariable;
3506 }
3507 else
3508 {
3509 bool bFatalError = false;
3510 SbxDataType t = static_cast<SbxDataType>(nOp2);
3511 OUString aName( pImg->GetString( nOp1 & 0x7FFF ) );
3512 // Hacky capture of Evaluate [] syntax
3513 // this should be tackled I feel at the pcode level
3514 if ( bIsVBAInterOp && aName.startsWith("[") )
3515 {
3516 // emulate pcode here
3517 StepARGC();
3518 // pseudo StepLOADSC
3519 OUString sArg = aName.copy( 1, aName.getLength() - 2 );
3520 SbxVariable* p = new SbxVariable;
3521 p->PutString( sArg );
3522 PushVar( p );
3523 StepARGV();
3524 nOp1 = nOp1 | 0x8000; // indicate params are present
3525 aName = "Evaluate";
3526 }
3527 if( bLocal )
3528 {
3529 if ( bStatic && pMeth )
3530 {
3532 }
3533
3534 if ( !pElem )
3535 {
3536 pElem = refLocals->Find( aName, SbxClassType::DontCare );
3537 }
3538 }
3539 if( !pElem )
3540 {
3541 bool bSave = rBasic.bNoRtl;
3542 rBasic.bNoRtl = true;
3543 pElem = pObj->Find( aName, SbxClassType::DontCare );
3544
3545 // #110004, #112015: Make private really private
3546 if( bLocal && pElem ) // Local as flag for global search
3547 {
3548 if( pElem->IsSet( SbxFlagBits::Private ) )
3549 {
3550 SbiInstance* pInst_ = GetSbData()->pInst;
3551 if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() )
3552 {
3553 pElem = nullptr; // Found but in wrong module!
3554 }
3555 // Interfaces: Use SbxFlagBits::ExtFound
3556 }
3557 }
3558 rBasic.bNoRtl = bSave;
3559
3560 // is it a global uno-identifier?
3561 if( bLocal && !pElem )
3562 {
3563 bool bSetName = true; // preserve normal behaviour
3564
3565 // i#i68894# if VBAInterOp favour searching vba globals
3566 // over searching for uno classes
3567 if ( bVBAEnabled )
3568 {
3569 // Try Find in VBA symbols space
3571 if ( pElem )
3572 {
3573 bSetName = false; // don't overwrite uno name
3574 }
3575 else
3576 {
3578 }
3579 }
3580
3581 if( !pElem )
3582 {
3583 // #72382 ATTENTION! ALWAYS returns a result now
3584 // because of unknown modules!
3585 SbUnoClass* pUnoClass = findUnoClass( aName );
3586 if( pUnoClass )
3587 {
3588 pElem = new SbxVariable( t );
3589 SbxValues aRes( SbxOBJECT );
3590 aRes.pObj = pUnoClass;
3591 pElem->SbxVariable::Put( aRes );
3592 }
3593 }
3594
3595 // #62939 If a uno-class has been found, the wrapper
3596 // object has to be held, because the uno-class, e. g.
3597 // "stardiv", has to be read out of the registry
3598 // every time again otherwise
3599 if( pElem )
3600 {
3601 // #63774 May not be saved too!!!
3604
3605 // #72382 save locally, all variables that have been declared
3606 // implicit would become global automatically otherwise!
3607 if ( bSetName )
3608 {
3609 pElem->SetName( aName );
3610 }
3611 refLocals->Put(pElem, refLocals->Count());
3612 }
3613 }
3614
3615 if( !pElem )
3616 {
3617 // not there and not in the object?
3618 // don't establish if that thing has parameters!
3619 if( nOp1 & 0x8000 )
3620 {
3621 bFatalError = true;
3622 }
3623
3624 // else, if there are parameters, use different error code
3625 if( !bLocal || pImg->IsFlag( SbiImageFlags::EXPLICIT ) )
3626 {
3627 // #39108 if explicit and as ELEM always a fatal error
3628 bFatalError = true;
3629
3630
3631 if( !( nOp1 & 0x8000 ) && nNotFound == ERRCODE_BASIC_PROC_UNDEFINED )
3632 {
3633 nNotFound = ERRCODE_BASIC_VAR_UNDEFINED;
3634 }
3635 }
3636 if( bFatalError )
3637 {
3638 // #39108 use dummy variable instead of fatal error
3639 if( !xDummyVar.is() )
3640 {
3642 }
3643 pElem = xDummyVar.get();
3644
3646
3647 Error( nNotFound, aName );
3648 }
3649 else
3650 {
3651 if ( bStatic )
3652 {
3653 pElem = StepSTATIC_Impl( aName, t, 0 );
3654 }
3655 if ( !pElem )
3656 {
3657 pElem = new SbxVariable( t );
3658 if( t != SbxVARIANT )
3659 {
3660 pElem->SetFlag( SbxFlagBits::Fixed );
3661 }
3662 pElem->SetName( aName );
3663 refLocals->Put(pElem, refLocals->Count());
3664 }
3665 }
3666 }
3667 }
3668 // #39108 Args can already be deleted!
3669 if( !bFatalError )
3670 {
3671 SetupArgs( pElem, nOp1 );
3672 }
3673 // because a particular call-type is requested
3674 if (SbxMethod* pMethod = dynamic_cast<SbxMethod*>(pElem))
3675 {
3676 // shall the type be converted?
3677 SbxDataType t2 = pElem->GetType();
3678 bool bSet = false;
3679 if( (pElem->GetFlags() & SbxFlagBits::Fixed) == SbxFlagBits::NONE )
3680 {
3681 if( t != SbxVARIANT && t != t2 &&
3682 t >= SbxINTEGER && t <= SbxSTRING )
3683 {
3684 pElem->SetType( t );
3685 bSet = true;
3686 }
3687 }
3688 // assign pElem to a Ref, to delete a temp-var if applicable
3689 SbxVariableRef xDeleteRef = pElem;
3690
3691 // remove potential rests of the last call of the SbxMethod
3692 // free Write before, so that there's no error
3693 SbxFlagBits nSavFlags = pElem->GetFlags();
3695 pElem->SbxValue::Clear();
3696 pElem->SetFlags( nSavFlags );
3697
3698 // don't touch before setting, as e. g. LEFT()
3699 // has to know the difference between Left$() and Left()
3700
3701 // because the methods' parameters are cut away in PopVar()
3702 SbxVariable* pNew = new SbxMethod(*pMethod);
3703 //OLD: SbxVariable* pNew = new SbxVariable( *pElem );
3704
3705 pElem->SetParameters(nullptr);
3707
3708 if( bSet )
3709 {
3710 pElem->SetType( t2 );
3711 }
3712 pElem = pNew;
3713 }
3714 // consider index-access for UnoObjects
3715 // definitely we want this for VBA where properties are often
3716 // collections ( which need index access ), but lets only do
3717 // this if we actually have params following
3718 else if( bVBAEnabled && dynamic_cast<const SbUnoProperty*>( pElem) != nullptr && pElem->GetParameters() )
3719 {
3720 SbxVariableRef xDeleteRef = pElem;
3721
3722 // dissolve the notify while copying variable
3723 SbxVariable* pNew = new SbxVariable( *pElem );
3724 pElem->SetParameters( nullptr );
3725 pElem = pNew;
3726 }
3727 }
3728 return CheckArray( pElem );
3729}
3730
3731// for current scope (e. g. query from BASIC-IDE)
3733{
3734 // don't expect pMeth to be != 0, as there are none set
3735 // in the RunInit yet
3736
3737 SbxVariable* pElem = nullptr;
3738 if( !pMod || rName.isEmpty() )
3739 {
3740 return nullptr;
3741 }
3742 if( refLocals.is() )
3743 {
3744 pElem = refLocals->Find( rName, SbxClassType::DontCare );
3745 }
3746 if ( !pElem && pMeth )
3747 {
3748 const OUString aMethName = pMeth->GetName();
3749 // tdf#57308 - check if the name is the current method instance
3750 if (pMeth->GetName() == rName)
3751 {
3752 pElem = pMeth;
3753 }
3754 else
3755 {
3756 // for statics, set the method's name in front
3757 pElem = pMod->Find(aMethName + ":" + rName, SbxClassType::DontCare);
3758 }
3759 }
3760
3761
3762 // search in parameter list
3763 if( !pElem && pMeth )
3764 {
3765 SbxInfo* pInfo = pMeth->GetInfo();
3766 if( pInfo && refParams.is() )
3767 {
3768 sal_uInt32 nParamCount = refParams->Count();
3769 assert(nParamCount <= std::numeric_limits<sal_uInt16>::max());
3770 sal_uInt16 j = 1;
3771 const SbxParamInfo* pParam = pInfo->GetParam( j );
3772 while( pParam )
3773 {
3774 if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
3775 {
3776 if( j >= nParamCount )
3777 {
3778 // Parameter is missing
3779 pElem = new SbxVariable( SbxSTRING );
3780 pElem->PutString( "<missing parameter>");
3781 }
3782 else
3783 {
3784 pElem = refParams->Get(j);
3785 }
3786 break;
3787 }
3788 pParam = pInfo->GetParam( ++j );
3789 }
3790 }
3791 }
3792
3793 // search in module
3794 if( !pElem )
3795 {
3796 bool bSave = rBasic.bNoRtl;
3797 rBasic.bNoRtl = true;
3798 pElem = pMod->Find( rName, SbxClassType::DontCare );
3799 rBasic.bNoRtl = bSave;
3800 }
3801 return pElem;
3802}
3803
3804
3805void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 )
3806{
3807 if( nOp1 & 0x8000 )
3808 {
3809 if( !refArgv.is() )
3810 {
3812 }
3813 bool bHasNamed = false;
3814 sal_uInt32 i;
3815 sal_uInt32 nArgCount = refArgv->Count();
3816 for( i = 1 ; i < nArgCount ; i++ )
3817 {
3818 if (!refArgv->GetAlias(i).isEmpty())
3819 {
3820 bHasNamed = true; break;
3821 }
3822 }
3823 if( bHasNamed )
3824 {
3825 SbxInfo* pInfo = p->GetInfo();
3826 if( !pInfo )
3827 {
3828 bool bError_ = true;
3829
3830 SbUnoMethod* pUnoMethod = dynamic_cast<SbUnoMethod*>( p );
3831 SbUnoProperty* pUnoProperty = dynamic_cast<SbUnoProperty*>( p );
3832 if( pUnoMethod || pUnoProperty )
3833 {
3834 SbUnoObject* pParentUnoObj = dynamic_cast<SbUnoObject*>( p->GetParent() );
3835 if( pParentUnoObj )
3836 {
3837 Any aUnoAny = pParentUnoObj->getUnoAny();
3839 aUnoAny >>= xInvocation;
3840 if( xInvocation.is() ) // TODO: if( xOLEAutomation.is() )
3841 {
3842 bError_ = false;
3843
3844 sal_uInt32 nCurPar = 1;
3846 new AutomationNamedArgsSbxArray( nArgCount );
3847 OUString* pNames = pArg->getNames().getArray();
3848 for( i = 1 ; i < nArgCount ; i++ )
3849 {
3850 SbxVariable* pVar = refArgv->Get(i);
3851 OUString aName = refArgv->GetAlias(i);
3852 if (!aName.isEmpty())
3853 {
3854 pNames[i] = aName;
3855 }
3856 pArg->Put(pVar, nCurPar++);
3857 }
3858 refArgv = pArg;
3859 }
3860 }
3861 }
3862 else if( bVBAEnabled && p->GetType() == SbxOBJECT && (dynamic_cast<const SbxMethod*>( p) == nullptr || !p->IsBroadcaster()) )
3863 {
3864 // Check for default method with named parameters
3865 SbxBaseRef xObj = p->GetObject();
3866 if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( xObj.get() ))
3867 {
3868 Any aAny = pUnoObj->getUnoAny();
3869
3870 if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
3871 {
3872 Reference< XDefaultMethod > xDfltMethod( aAny, UNO_QUERY );
3873
3874 OUString sDefaultMethod;
3875 if ( xDfltMethod.is() )
3876 {
3877 sDefaultMethod = xDfltMethod->getDefaultMethodName();
3878 }
3879 if ( !sDefaultMethod.isEmpty() )
3880 {
3881 SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxClassType::Method );
3882 if( meth != nullptr )
3883 {
3884 pInfo = meth->GetInfo();
3885 }
3886 if( pInfo )
3887 {
3888 bError_ = false;
3889 }
3890 }
3891 }
3892 }
3893 }
3894 if( bError_ )
3895 {
3897 }
3898 }
3899 else
3900 {
3901 sal_uInt32 nCurPar = 1;
3902 SbxArray* pArg = new SbxArray;
3903 for( i = 1 ; i < nArgCount ; i++ )
3904 {
3905 SbxVariable* pVar = refArgv->Get(i);
3906 OUString aName = refArgv->GetAlias(i);
3907 if (!aName.isEmpty())
3908 {
3909 // nCurPar is set to the found parameter
3910 sal_uInt16 j = 1;
3911 const SbxParamInfo* pParam = pInfo->GetParam( j );
3912 while( pParam )
3913 {
3914 if( pParam->aName.equalsIgnoreAsciiCase( aName ) )
3915 {
3916 nCurPar = j;
3917 break;
3918 }
3919 pParam = pInfo->GetParam( ++j );
3920 }
3921 if( !pParam )
3922 {
3924 }
3925 }
3926 pArg->Put(pVar, nCurPar++);
3927 }
3928 refArgv = pArg;
3929 }
3930 }
3931 // own var as parameter 0
3932 refArgv->Put(p, 0);
3933 p->SetParameters( refArgv.get() );
3934 PopArgv();
3935 }
3936 else
3937 {
3938 p->SetParameters( nullptr );
3939 }
3940}
3941
3942// getting an array element
3943
3945{
3946 SbxArray* pPar;
3947 if( ( pElem->GetType() & SbxARRAY ) && refRedim.get() != pElem )
3948 {
3949 SbxBase* pElemObj = pElem->GetObject();
3950 SbxDimArray* pDimArray = dynamic_cast<SbxDimArray*>( pElemObj );
3951 pPar = pElem->GetParameters();
3952 if( pDimArray )
3953 {
3954 // parameters may be missing, if an array is
3955 // passed as an argument
3956 if( pPar )
3957 pElem = pDimArray->Get( pPar );
3958 }
3959 else
3960 {
3961 SbxArray* pArray = dynamic_cast<SbxArray*>( pElemObj );
3962 if( pArray )
3963 {
3964 if( !pPar )
3965 {
3967 pElem = new SbxVariable;
3968 }
3969 else
3970 {
3971 pElem = pArray->Get(pPar->Get(1)->GetInteger());
3972 }
3973 }
3974 }
3975
3976 // #42940, set parameter 0 to NULL so that var doesn't contain itself
3977 if( pPar )
3978 {
3979 pPar->Put(nullptr, 0);
3980 }
3981 }
3982 // consider index-access for UnoObjects
3983 else if( pElem->GetType() == SbxOBJECT &&
3984 dynamic_cast<const SbxMethod*>( pElem) == nullptr &&
3985 ( !bVBAEnabled || dynamic_cast<const SbxProperty*>( pElem) == nullptr ) )
3986 {
3987 pPar = pElem->GetParameters();
3988 if ( pPar )
3989 {
3990 // is it a uno-object?
3991 SbxBaseRef pObj = pElem->GetObject();
3992 if( pObj.is() )
3993 {
3994 if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>( pObj.get()))
3995 {
3996 Any aAny = pUnoObj->getUnoAny();
3997
3998 if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
3999 {
4000 Reference< XIndexAccess > xIndexAccess( aAny, UNO_QUERY );
4001 if ( !bVBAEnabled )
4002 {
4003 if( xIndexAccess.is() )
4004 {
4005 sal_uInt32 nParamCount = pPar->Count() - 1;
4006 if( nParamCount != 1 )
4007 {
4009 return pElem;
4010 }
4011
4012 // get index
4013 sal_Int32 nIndex = pPar->Get(1)->GetLong();
4015 try
4016 {
4017 Any aAny2 = xIndexAccess->getByIndex( nIndex );
4018 aAny2 >>= xRet;
4019 }
4020 catch (const IndexOutOfBoundsException&)
4021 {
4022 // usually expect converting problem
4024 }
4025
4026 // #57847 always create a new variable, else error
4027 // due to PutObject(NULL) at ReadOnly-properties
4028 pElem = new SbxVariable( SbxVARIANT );
4029 if( xRet.is() )
4030 {
4031 aAny <<= xRet;
4032
4033 // #67173 don't specify a name so that the real class name is entered
4034 SbxObjectRef xWrapper = static_cast<SbxObject*>(new SbUnoObject( OUString(), aAny ));
4035 pElem->PutObject( xWrapper.get() );
4036 }
4037 else
4038 {
4039 pElem->PutObject( nullptr );
4040 }
4041 }
4042 }
4043 else
4044 {
4045 // check if there isn't a default member between the current variable
4046 // and the params, e.g.
4047 // Dim rst1 As New ADODB.Recordset
4048 // "
4049 // val = rst1("FirstName")
4050 // has the default 'Fields' member between rst1 and '("FirstName")'
4051 Any x = aAny;
4052 SbxVariable* pDflt = getDefaultProp( pElem );
4053 if ( pDflt )
4054 {
4055 pDflt->Broadcast( SfxHintId::BasicDataWanted );
4056 SbxBaseRef pDfltObj = pDflt->GetObject();
4057 if( pDfltObj.is() )
4058 {
4059 if (SbUnoObject* pSbObj = dynamic_cast<SbUnoObject*>(pDfltObj.get()))
4060 {
4061 pUnoObj = pSbObj;
4062 Any aUnoAny = pUnoObj->getUnoAny();
4063
4064 if( aUnoAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
4065 x = aUnoAny;
4066 pElem = pDflt;
4067 }
4068 }
4069 }
4070 OUString sDefaultMethod;
4071
4072 Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
4073
4074 if ( xDfltMethod.is() )
4075 {
4076 sDefaultMethod = xDfltMethod->getDefaultMethodName();
4077 }
4078 else if( xIndexAccess.is() )
4079 {
4080 sDefaultMethod = "getByIndex";
4081 }
4082 if ( !sDefaultMethod.isEmpty() )
4083 {
4084 SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxClassType::Method );
4085 SbxVariableRef refTemp = meth;
4086 if ( refTemp.is() )
4087 {
4088 meth->SetParameters( pPar );
4089 SbxVariable* pNew = new SbxMethod( *static_cast<SbxMethod*>(meth) );
4090 pElem = pNew;
4091 }
4092 }
4093 }
4094 }
4095
4096 // #42940, set parameter 0 to NULL so that var doesn't contain itself
4097 pPar->Put(nullptr, 0);
4098 }
4099 else if (BasicCollection* pCol = dynamic_cast<BasicCollection*>(pObj.get()))
4100 {
4101 pElem = new SbxVariable( SbxVARIANT );
4102 pPar->Put(pElem, 0);
4103 pCol->CollItem( pPar );
4104 }
4105 }
4106 else if( bVBAEnabled ) // !pObj
4107 {
4108 SbxArray* pParam = pElem->GetParameters();
4109 if( pParam != nullptr && !pElem->IsSet( SbxFlagBits::VarToDim ) )
4110 {
4112 }
4113 }
4114 }
4115 }
4116
4117 return pElem;
4118}
4119
4120// loading an element from the runtime-library (+StringID+type)
4121
4122void SbiRuntime::StepRTL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4123{
4124 PushVar( FindElement( rBasic.pRtl.get(), nOp1, nOp2, ERRCODE_BASIC_PROC_UNDEFINED, false ) );
4125}
4126
4127void SbiRuntime::StepFIND_Impl( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
4128 ErrCode nNotFound, bool bStatic )
4129{
4130 if( !refLocals.is() )
4131 {
4132 refLocals = new SbxArray;
4133 }
4134 PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, true/*bLocal*/, bStatic ) );
4135}
4136// loading a local/global variable (+StringID+type)
4137
4138void SbiRuntime::StepFIND( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4139{
4141}
4142
4143// Search inside a class module (CM) to enable global search in time
4144void SbiRuntime::StepFIND_CM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4145{
4146
4147 SbClassModuleObject* pClassModuleObject = dynamic_cast<SbClassModuleObject*>( pMod );
4148 if( pClassModuleObject )
4149 {
4151 }
4153
4154 if( pClassModuleObject )
4155 {
4157 }
4158}
4159
4160void SbiRuntime::StepFIND_STATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4161{
4162 StepFIND_Impl( pMod, nOp1, nOp2, ERRCODE_BASIC_PROC_UNDEFINED, true );
4163}
4164
4165// loading an object-element (+StringID+type)
4166// the object lies on TOS
4167
4168void SbiRuntime::StepELEM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4169{
4170 SbxVariableRef pObjVar = PopVar();
4171
4172 SbxObject* pObj = dynamic_cast<SbxObject*>( pObjVar.get() );
4173 if( !pObj )
4174 {
4175 SbxBase* pObjVarObj = pObjVar->GetObject();
4176 pObj = dynamic_cast<SbxObject*>( pObjVarObj );
4177 }
4178
4179 // #56368 save reference at StepElem, otherwise objects could
4180 // lose their reference too early in qualification chains like
4181 // ActiveComponent.Selection(0).Text
4182 // #74254 now per list
4183 if( pObj )
4184 {
4185 aRefSaved.emplace_back(pObj );
4186 }
4187 PushVar( FindElement( pObj, nOp1, nOp2, ERRCODE_BASIC_NO_METHOD, false ) );
4188}
4189
4202void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4203{
4204 sal_uInt16 nIdx = static_cast<sal_uInt16>( nOp1 & 0x7FFF );
4205 SbxDataType eType = static_cast<SbxDataType>(nOp2);
4206 SbxVariable* pVar;
4207
4208 // #57915 solve missing in a cleaner way
4209 sal_uInt32 nParamCount = refParams->Count();
4210 if( nIdx >= nParamCount )
4211 {
4212 sal_uInt16 iLoop = nIdx;
4213 while( iLoop >= nParamCount )
4214 {
4215 pVar = new SbxVariable();
4216 pVar->PutErr( 448 ); // like in VB: Error-Code 448 (ERRCODE_BASIC_NAMED_NOT_FOUND)
4217 // tdf#79426, tdf#125180 - add additional information about a missing parameter
4218 SetIsMissing( pVar );
4219 refParams->Put(pVar, iLoop);
4220 iLoop--;
4221 }
4222 }
4223 pVar = refParams->Get(nIdx);
4224
4225 // tdf#79426, tdf#125180 - check for optionals only if the parameter is actually missing
4226 if( pVar->GetType() == SbxERROR && IsMissing( pVar, 1 ) && nIdx )
4227 {
4228 // if there's a parameter missing, it can be OPTIONAL
4229 bool bOpt = false;
4230 if( pMeth )
4231 {
4232 SbxInfo* pInfo = pMeth->GetInfo();
4233 if ( pInfo )
4234 {
4235 const SbxParamInfo* pParam = pInfo->GetParam( nIdx );
4236 if( pParam && ( pParam->nFlags & SbxFlagBits::Optional ) )
4237 {
4238 // tdf#136143 - reset SbxFlagBits::Fixed in order to prevent type conversion errors
4240 // Default value?
4241 sal_uInt16 nDefaultId = static_cast<sal_uInt16>(pParam->nUserData & 0x0ffff);
4242 if( nDefaultId > 0 )
4243 {
4244 // tdf#143707 - check if the data type character was added after the string
4245 // termination symbol, and convert the variable if it was present. The
4246 // data type character was added in basic/source/comp/symtbl.cxx.
4247 SbxDataType eTypeStr;
4248 OUString aDefaultStr = pImg->GetString( nDefaultId, &eTypeStr );
4249 pVar = new SbxVariable(pParam-> eType);
4250 pVar->PutString( aDefaultStr );
4251 if (eTypeStr != SbxSTRING)
4252 pVar->Convert(eTypeStr);
4253 refParams->Put(pVar, nIdx);
4254 }
4255 else if ( SbiRuntime::isVBAEnabled() && eType != SbxVARIANT )
4256 {
4257 // tdf#36737 - initialize the parameter with the default value of its type
4258 pVar = new SbxVariable( pParam->eType );
4259 refParams->Put(pVar, nIdx);
4260 }
4261 bOpt = true;
4262 }
4263 }
4264 }
4265 if( !bOpt )
4266 {
4268 }
4269 }
4270 else if( eType != SbxVARIANT && static_cast<SbxDataType>(pVar->GetType() & 0x0FFF ) != eType )
4271 {
4272 // tdf#43003 - convert parameter to the requested type
4273 pVar->Convert(eType);
4274 }
4275 SetupArgs( pVar, nOp1 );
4276 PushVar( CheckArray( pVar ) );
4277}
4278
4279// Case-Test (+True-Target+Test-Opcode)
4280
4281void SbiRuntime::StepCASEIS( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4282{
4283 if (!refCaseStk.is() || !refCaseStk->Count())
4284 {
4286 }
4287 else
4288 {
4289 SbxVariableRef xComp = PopVar();
4290 SbxVariableRef xCase = refCaseStk->Get(refCaseStk->Count() - 1);
4291 if( xCase->Compare( static_cast<SbxOperator>(nOp2), *xComp ) )
4292 {
4293 StepJUMP( nOp1 );
4294 }
4295 }
4296}
4297
4298// call of a DLL-procedure (+StringID+type)
4299// the StringID's MSB shows that Argv is occupied
4300
4301void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4302{
4303 OUString aName = pImg->GetString( nOp1 & 0x7FFF );
4304 SbxArray* pArgs = nullptr;
4305 if( nOp1 & 0x8000 )
4306 {
4307 pArgs = refArgv.get();
4308 }
4309 DllCall( aName, aLibName, pArgs, static_cast<SbxDataType>(nOp2), false );
4310 aLibName.clear();
4311 if( nOp1 & 0x8000 )
4312 {
4313 PopArgv();
4314 }
4315}
4316
4317// call of a DLL-procedure after CDecl (+StringID+type)
4318
4319void SbiRuntime::StepCALLC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4320{
4321 OUString aName = pImg->GetString( nOp1 & 0x7FFF );
4322 SbxArray* pArgs = nullptr;
4323 if( nOp1 & 0x8000 )
4324 {
4325 pArgs = refArgv.get();
4326 }
4327 DllCall( aName, aLibName, pArgs, static_cast<SbxDataType>(nOp2), true );
4328 aLibName.clear();
4329 if( nOp1 & 0x8000 )
4330 {
4331 PopArgv();
4332 }
4333}
4334
4335
4336// beginning of a statement (+Line+Col)
4337
4338void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4339{
4340 // If the Expr-Stack at the beginning of a statement contains a variable,
4341 // some fool has called X as a function, although it's a variable!
4342 bool bFatalExpr = false;
4343 OUString sUnknownMethodName;
4344 if( nExprLvl > 1 )
4345 {
4346 bFatalExpr = true;
4347 }
4348 else if( nExprLvl )
4349 {
4350 SbxVariable* p = refExprStk->Get(0);
4351 if( p->GetRefCount() > 1 &&
4352 refLocals.is() && refLocals->Find( p->GetName(), p->GetClass() ) )
4353 {
4354 sUnknownMethodName = p->GetName();
4355 bFatalExpr = true;
4356 }
4357 }
4358
4360
4361 aRefSaved.clear();
4362
4363 // We have to cancel hard here because line and column
4364 // would be wrong later otherwise!
4365 if( bFatalExpr)
4366 {
4367 StarBASIC::FatalError( ERRCODE_BASIC_NO_METHOD, sUnknownMethodName );
4368 return;
4369 }
4370 pStmnt = pCode - 9;
4371 sal_uInt16 nOld = nLine;
4372 nLine = static_cast<short>( nOp1 );
4373
4374 // #29955 & 0xFF, to filter out for-loop-level
4375 nCol1 = static_cast<short>( nOp2 & 0xFF );
4376
4377 // find the next STMNT-command to set the final column
4378 // of this statement
4379
4380 nCol2 = 0xffff;
4381 sal_uInt16 n1, n2;
4382 const sal_uInt8* p = pMod->FindNextStmnt( pCode, n1, n2 );
4383 if( p )
4384 {
4385 if( n1 == nOp1 )
4386 {
4387 // #29955 & 0xFF, to filter out for-loop-level
4388 nCol2 = (n2 & 0xFF) - 1;
4389 }
4390 }
4391
4392 // #29955 correct for-loop-level, #67452 NOT in the error-handler
4393 if( !bInError )
4394 {
4395 // (there's a difference here in case of a jump out of a loop)
4396 sal_uInt16 nExpectedForLevel = static_cast<sal_uInt16>( nOp2 / 0x100 );
4397 if( !pGosubStk.empty() )
4398 {
4399 nExpectedForLevel = nExpectedForLevel + pGosubStk.back().nStartForLvl;
4400 }
4401
4402 // if the actual for-level is too small it'd jump out
4403 // of a loop -> corrected
4404 while( nForLvl > nExpectedForLevel )
4405 {
4406 PopFor();
4407 }
4408 }
4409
4410 // 16.10.96: #31460 new concept for StepInto/Over/Out
4411 // see explanation at SbiInstance::CalcBreakCallLevel
4413 {
4414 StarBASIC* pStepBasic = GetCurrentBasic( &rBasic );
4415 BasicDebugFlags nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 );
4416
4417 pInst->CalcBreakCallLevel( nNewFlags );
4418 }
4419
4420 // break points only at STMNT-commands in a new line!
4421 else if( ( nOp1 != nOld )
4423 && pMod->IsBP( static_cast<sal_uInt16>( nOp1 ) ) )
4424 {
4425 StarBASIC* pBreakBasic = GetCurrentBasic( &rBasic );
4426 BasicDebugFlags nNewFlags = pBreakBasic->BreakPoint( nLine, nCol1, nCol2 );
4427
4428 pInst->CalcBreakCallLevel( nNewFlags );
4429 }
4430}
4431
4432// (+StreamMode+Flags)
4433// Stack: block length
4434// channel number
4435// file name
4436
4437void SbiRuntime::StepOPEN( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4438{
4440 SbxVariableRef pChan = PopVar();
4441 SbxVariableRef pLen = PopVar();
4442 short nBlkLen = pLen->GetInteger();
4443 short nChan = pChan->GetInteger();
4444 OString aName(OUStringToOString(pName->GetOUString(), osl_getThreadTextEncoding()));
4445 pIosys->Open( nChan, aName, static_cast<StreamMode>( nOp1 ),
4446 static_cast<SbiStreamFlags>( nOp2 ), nBlkLen );
4447 Error( pIosys->GetError() );
4448}
4449
4450// create object (+StringID+StringID)
4451
4452void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4453{
4454 OUString aClass( pImg->GetString( nOp2 ) );
4455 SbxObjectRef pObj = SbxBase::CreateObject( aClass );
4456 if( !pObj )
4457 {
4459 }
4460 else
4461 {
4462 OUString aName( pImg->GetString( nOp1 ) );
4463 pObj->SetName( aName );
4464 // the object must be able to call the BASIC
4465 pObj->SetParent( &rBasic );
4466 SbxVariableRef pNew = new SbxVariable;
4467 pNew->PutObject( pObj.get() );
4468 PushVar( pNew.get() );
4469 }
4470}
4471
4472void SbiRuntime::StepDCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4473{
4474 StepDCREATE_IMPL( nOp1, nOp2 );
4475}
4476
4477void SbiRuntime::StepDCREATE_REDIMP( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4478{
4479 StepDCREATE_IMPL( nOp1, nOp2 );
4480}
4481
4482// #56204 create object array (+StringID+StringID), DCREATE == Dim-Create
4483void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4484{
4485 SbxVariableRef refVar = PopVar();
4486
4487 DimImpl( refVar );
4488
4489 // fill the array with instances of the requested class
4490 SbxBase* pObj = refVar->GetObject();
4491 if (!pObj)
4492 {
4494 return;
4495 }
4496
4497 SbxDimArray* pArray = dynamic_cast<SbxDimArray*>(pObj);
4498 if (!pArray)
4499 return;
4500
4501 const sal_Int32 nDims = pArray->GetDims();
4502 sal_Int32 nTotalSize = nDims > 0 ? 1 : 0;
4503
4504 // must be a one-dimensional array
4505 sal_Int32 nLower, nUpper;
4506 for( sal_Int32 i = 0 ; i < nDims ; ++i )
4507 {
4508 pArray->GetDim(i + 1, nLower, nUpper);
4509 const sal_Int32 nSize = nUpper - nLower + 1;
4510 nTotalSize *= nSize;
4511 }
4512
4513 // Optimization: pre-allocate underlying container
4514 if (nTotalSize > 0)
4515 pArray->SbxArray::GetRef(nTotalSize - 1);
4516
4517 // First, fill those parts of the array that are preserved
4518 bool bWasError = false;
4519 const bool bRestored = implRestorePreservedArray(pArray, refRedimpArray, &bWasError);
4520 if (bWasError)
4521 nTotalSize = 0; // on error, don't create objects
4522
4523 // create objects and insert them into the array
4524 OUString aClass( pImg->GetString( nOp2 ) );
4525 OUString aName;
4526 for( sal_Int32 i = 0 ; i < nTotalSize ; ++i )
4527 {
4528 if (!bRestored || !pArray->SbxArray::GetRef(i)) // For those left unset after preserve
4529 {
4530 SbxObjectRef pClassObj = SbxBase::CreateObject(aClass);
4531 if (!pClassObj)
4532 {
4534 break;
4535 }
4536 else
4537 {
4538 if (aName.isEmpty())
4539 aName = pImg->GetString(nOp1);
4540 pClassObj->SetName(aName);
4541 // the object must be able to call the basic
4542 pClassObj->SetParent(&rBasic);
4543 pArray->SbxArray::Put(pClassObj.get(), i);
4544 }
4545 }
4546 }
4547}
4548
4549void SbiRuntime::StepTCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4550{
4551 OUString aName( pImg->GetString( nOp1 ) );
4552 OUString aClass( pImg->GetString( nOp2 ) );
4553
4554 SbxObjectRef pCopyObj = createUserTypeImpl( aClass );
4555 if( pCopyObj )
4556 {
4557 pCopyObj->SetName( aName );
4558 }
4559 SbxVariableRef pNew = new SbxVariable;
4560 pNew->PutObject( pCopyObj.get() );
4561 pNew->SetDeclareClassName( aClass );
4562 PushVar( pNew.get() );
4563}
4564
4566{
4567 bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0);
4568 if( bWithEvents )
4569 {
4571 }
4572 bool bDimAsNew = ((nOp2 & SBX_TYPE_DIM_AS_NEW_FLAG) != 0);
4573 if( bDimAsNew )
4574 {
4576 }
4577 bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0);
4578 if( bFixedString )
4579 {
4580 sal_uInt16 nCount = static_cast<sal_uInt16>( nOp2 >> 17 ); // len = all bits above 0x10000
4581 OUStringBuffer aBuf(nCount);
4583 pVar->PutString(aBuf.makeStringAndClear());
4584 }
4585
4586 bool bVarToDim = ((nOp2 & SBX_TYPE_VAR_TO_DIM_FLAG) != 0);
4587 if( bVarToDim )
4588 {
4590 }
4591}
4592
4593// establishing a local variable (+StringID+type)
4594
4595void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4596{
4597 if( !refLocals.is() )
4598 {
4599 refLocals = new SbxArray;
4600 }
4601 OUString aName( pImg->GetString( nOp1 ) );
4602 if( refLocals->Find( aName, SbxClassType::DontCare ) == nullptr )
4603 {
4604 SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff);
4605 SbxVariable* p = new SbxVariable( t );
4606 p->SetName( aName );
4607 implHandleSbxFlags( p, t, nOp2 );
4608 refLocals->Put(p, refLocals->Count());
4609 }
4610}
4611
4612// establishing a module-global variable (+StringID+type)
4613
4614void SbiRuntime::StepPUBLIC_Impl( sal_uInt32 nOp1, sal_uInt32 nOp2, bool bUsedForClassModule )
4615{
4616 OUString aName( pImg->GetString( nOp1 ) );
4617 SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff);
4618 bool bFlag = pMod->IsSet( SbxFlagBits::NoModify );
4621 if( p.is() )
4622 {
4623 pMod->Remove (p.get());
4624 }
4625 SbProperty* pProp = pMod->GetProperty( aName, t );
4626 if( !bUsedForClassModule )
4627 {
4628 pProp->SetFlag( SbxFlagBits::Private );
4629 }
4630 if( !bFlag )
4631 {
4633 }
4634 if( pProp )
4635 {
4637 // from 2.7.1996: HACK because of 'reference can't be saved'
4639
4640 implHandleSbxFlags( pProp, t, nOp2 );
4641 }
4642}
4643
4644void SbiRuntime::StepPUBLIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4645{
4646 StepPUBLIC_Impl( nOp1, nOp2, false );
4647}
4648
4649void SbiRuntime::StepPUBLIC_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4650{
4651 // Creates module variable that isn't reinitialised when
4652 // between invocations ( for VBASupport & document basic only )
4653 if( pMod->pImage->bFirstInit )
4654 {
4655 bool bUsedForClassModule = pImg->IsFlag( SbiImageFlags::CLASSMODULE );
4656 StepPUBLIC_Impl( nOp1, nOp2, bUsedForClassModule );
4657 }
4658}
4659
4660// establishing a global variable (+StringID+type)
4661
4662void SbiRuntime::StepGLOBAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4663{
4665 {
4666 StepPUBLIC_Impl( nOp1, nOp2, true );
4667 }
4668 OUString aName( pImg->GetString( nOp1 ) );
4669 SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff);
4670
4671 // Store module scope variables at module scope
4672 // in non vba mode these are stored at the library level :/
4673 // not sure if this really should not be enabled for ALL basic
4674 SbxObject* pStorage = &rBasic;
4676 {
4677 pStorage = pMod;
4678 pMod->AddVarName( aName );
4679 }
4680
4681 bool bFlag = pStorage->IsSet( SbxFlagBits::NoModify );
4684 if( p.is() )
4685 {
4686 pStorage->Remove (p.get());
4687 }
4688 p = pStorage->Make( aName, SbxClassType::Property, t );
4689 if( !bFlag )
4690 {
4691 pStorage->ResetFlag( SbxFlagBits::NoModify );
4692 }
4693 if( p.is() )
4694 {
4695 p->SetFlag( SbxFlagBits::DontStore );
4696 // from 2.7.1996: HACK because of 'reference can't be saved'
4697 p->SetFlag( SbxFlagBits::NoModify);
4698 }
4699}
4700
4701
4702// Creates global variable that isn't reinitialised when
4703// basic is restarted, P=PERSIST (+StringID+Typ)
4704
4705void SbiRuntime::StepGLOBAL_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4706{
4707 if( pMod->pImage->bFirstInit )
4708 {
4709 StepGLOBAL( nOp1, nOp2 );
4710 }
4711}
4712
4713
4714// Searches for global variable, behavior depends on the fact
4715// if the variable is initialised for the first time
4716
4717void SbiRuntime::StepFIND_G( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4718{
4719 if( pMod->pImage->bFirstInit )
4720 {
4721 // Behave like always during first init
4722 StepFIND( nOp1, nOp2 );
4723 }
4724 else
4725 {
4726 // Return dummy variable
4727 SbxDataType t = static_cast<SbxDataType>(nOp2);
4728 OUString aName( pImg->GetString( nOp1 & 0x7FFF ) );
4729
4730 SbxVariable* pDummyVar = new SbxVariable( t );
4731 pDummyVar->SetName( aName );
4732 PushVar( pDummyVar );
4733 }
4734}
4735
4736
4738 OUString const & aName, SbxDataType t, sal_uInt32 nOp2 )
4739{
4740 SbxVariable* p = nullptr;
4741 if ( pMeth )
4742 {
4743 SbxArray* pStatics = pMeth->GetStatics();
4744 if( pStatics && ( pStatics->Find( aName, SbxClassType::DontCare ) == nullptr ) )
4745 {
4746 p = new SbxVariable( t );
4747 if( t != SbxVARIANT )
4748 {
4749 p->SetFlag( SbxFlagBits::Fixed );
4750 }
4751 p->SetName( aName );
4752 implHandleSbxFlags( p, t, nOp2 );
4753 pStatics->Put(p, pStatics->Count());
4754 }
4755 }
4756 return p;
4757}
4758// establishing a static variable (+StringID+type)
4759void SbiRuntime::StepSTATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
4760{
4761 OUString aName( pImg->GetString( nOp1 ) );
4762 SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff);
4763 StepSTATIC_Impl( aName, t, nOp2 );
4764}
4765
4766/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
const char * pName
const LanguageTag & GetLanguageTag() const
static const AllSettings & GetSettings()
static bool Reschedule(bool bHandleAllCurrentEvents=false)
css::uno::Sequence< OUString > & getNames()
Definition: sbunoobj.hxx:320
SbxArrayRef xItemArray
Definition: sbunoobj.hxx:347
static bool IsExtendedTypeDeclaration()
ErrCode IgnoreWarning() const
LanguageType getLanguageType(bool bResolveSystem=true) const
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
DateOrder getDateOrder() const
virtual SbxInfo * GetInfo() override
Definition: sbxmod.cxx:2046
SbxVariable * mCaller
Definition: sbmeth.hxx:40
BasicDebugFlags GetDebugFlags() const
Definition: sbmeth.hxx:59
SbxArray * GetStatics()
Definition: sbxmod.cxx:1970
SAL_DLLPRIVATE const sal_uInt8 * FindNextStmnt(const sal_uInt8 *, sal_uInt16 &, sal_uInt16 &) const
Definition: sbxmod.cxx:1444
SAL_DLLPRIVATE bool IsBP(sal_uInt16 nLine) const
Definition: sbxmod.cxx:1507
virtual SAL_DLLPRIVATE SbxVariable * Find(const OUString &, SbxClassType) override
Definition: sbxmod.cxx:626
SAL_DLLPRIVATE SbProperty * GetProperty(const OUString &, SbxDataType)
Definition: sbxmod.cxx:532
std::unique_ptr< SbiImage > pImage
Definition: sbmod.hxx:66
SAL_DLLPRIVATE void AddVarName(const OUString &aName)
Definition: sbxmod.cxx:1268
std::unique_ptr< SbClassData > pClassData
Definition: sbmod.hxx:68
bool IsVBASupport() const
Definition: sbmod.hxx:126
void setSet(bool bSet)
Definition: sbprop.hxx:56
css::uno::Any getUnoAny()
Definition: sbunoobj.cxx:2823
const StructRefInfo & getStructInfo() const
Definition: sbunoobj.hxx:86
css::uno::Any getUnoAny()
Definition: sbunoobj.cxx:4738
ErrCode Call(std::u16string_view function, std::u16string_view library, SbxArray *arguments, SbxVariable &result, bool cdeclConvention)
Definition: dllmgr-none.cxx:94
OUString GetString(sal_uInt32 nId, SbxDataType *eType=nullptr) const
Definition: image.cxx:618
const sal_uInt8 * GetCode() const
Definition: image.hxx:85
sal_uInt16 GetBase() const
Definition: image.hxx:87
sal_uInt32 GetCodeSize() const
Definition: image.hxx:86
bool IsFlag(SbiImageFlags n) const
Definition: image.hxx:94
sal_uInt16 nBreakCallLvl
Definition: runtime.hxx:159
std::shared_ptr< SvNumberFormatter > pNumberFormatter
Definition: runtime.hxx:140
sal_uInt16 nCallLvl
Definition: runtime.hxx:158
void Error(ErrCode)
Definition: runtime.cxx:490
void Stop()
Definition: runtime.cxx:474
const OUString & GetErrorMsg() const
Definition: runtime.hxx:175
sal_Int32 nErl
Definition: runtime.hxx:148
void CalcBreakCallLevel(BasicDebugFlags nFlags)
Definition: runtime.cxx:304
SbiIoSystem * GetIoSystem()
Definition: runtime.hxx:187
void FatalError(ErrCode)
Definition: runtime.cxx:534
SbiRuntime * pRun
Definition: runtime.hxx:154
bool IsReschedule() const
Definition: runtime.hxx:178
SbModule * GetActiveModule()
Definition: runtime.cxx:565
bool IsCompatibility() const
Definition: runtime.hxx:180
void ErrorVB(sal_Int32 nVBNumber, const OUString &rMsg)
Definition: runtime.cxx:504
sal_uInt32 nStdDateTimeIdx
Definition: runtime.hxx:144
static std::shared_ptr< SvNumberFormatter > PrepareNumberFormatter(sal_uInt32 &rnStdDateIdx, sal_uInt32 &rnStdTimeIdx, sal_uInt32 &rnStdDateTimeIdx, LanguageType const *peFormatterLangType=nullptr, DateOrder const *peFormatterDateOrder=nullptr)
Definition: runtime.cxx:404
SbiInstance(StarBASIC *)
Definition: runtime.cxx:323
std::unique_ptr< SbiDllMgr > pDllMgr
Definition: runtime.hxx:139
OUString aErrorMsg
Definition: runtime.hxx:147
std::shared_ptr< SvNumberFormatter > const & GetNumberFormatter()
Definition: runtime.cxx:380
LanguageType meFormatterLangType
Definition: runtime.hxx:142
ComponentVector_t ComponentVector
Definition: runtime.hxx:152
void Abort()
Definition: runtime.cxx:544
SbiDllMgr * GetDllMgr()
Definition: runtime.cxx:370
DateOrder meFormatterDateOrder
Definition: runtime.hxx:143
sal_uInt32 nStdDateIdx
Definition: runtime.hxx:144
void setErrorVB(sal_Int32 nVBNumber)
Definition: runtime.cxx:520
StarBASIC * pBasic
Definition: runtime.hxx:141
sal_uInt32 nStdTimeIdx
Definition: runtime.hxx:144
ErrCode nErr
Definition: runtime.hxx:146
SbMethod * GetCaller(sal_uInt16)
Definition: runtime.cxx:577
void Write(std::u16string_view)
Definition: iosys.cxx:741
void SetPrompt(const OString &r)
Definition: iosys.hxx:97
short GetChannel() const
Definition: iosys.hxx:99
void SetChannel(short n)
Definition: iosys.hxx:98
ErrCode GetError()
Definition: iosys.cxx:622
void Shutdown()
Definition: iosys.cxx:674
void Open(short, std::string_view, StreamMode, SbiStreamFlags, short)
Definition: iosys.cxx:629
void Close()
Definition: iosys.cxx:654
void Read(OString &)
Definition: iosys.cxx:701
void ResetChannel()
Definition: iosys.hxx:100
void FatalError(ErrCode)
Definition: runtime.cxx:952
void StepPRCHAR(sal_uInt32)
Definition: runtime.cxx:3324
void(SbiRuntime::* pStep0)()
Definition: runtime.hxx:211
void StepSTOP()
Definition: runtime.cxx:2597
void StepENDCASE()
Definition: runtime.cxx:2649
SbiInstance * pInst
Definition: runtime.hxx:219
void StepPRINTF()
Definition: runtime.cxx:2721
void StepGLOBAL_P(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4705
void StepSET()
Definition: runtime.cxx:2024
void StepARGC()
Definition: runtime.cxx:2439
void SetupArgs(SbxVariable *, sal_uInt32)
Definition: runtime.cxx:3805
SbxVariable * CheckArray(SbxVariable *)
Definition: runtime.cxx:3944
void StepPUT()
Definition: runtime.cxx:1692
std::vector< SbiArgv > pArgvStk
Definition: runtime.hxx:256
void StepDIM()
Definition: runtime.cxx:2129
void DllCall(std::u16string_view, std::u16string_view, SbxArray *, SbxDataType, bool)
Definition: runtime.cxx:1261
void PushForEach()
Definition: runtime.cxx:1140
void StepGLOBAL(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4662
void StepJUMP(sal_uInt32)
Definition: runtime.cxx:2991
void TOSMakeTemp()
Definition: runtime.cxx:1039
SbxVariableRef xDummyVar
Definition: runtime.hxx:228
static bool isVBAEnabled()
Definition: runtime.cxx:115
void PopFor()
Definition: runtime.cxx:1221
void PushFor()
Definition: runtime.cxx:1122
static sal_Int32 translateErrorToVba(ErrCode nError, OUString &rMsg)
Definition: runtime.cxx:964
void StepVBASETCLASS(sal_uInt32)
Definition: runtime.cxx:3431
SbMethod * pMeth
Definition: runtime.hxx:221
void StepERASE_CLEAR()
Definition: runtime.cxx:2406
void StepPRINT()
Definition: runtime.cxx:2707
bool bError
Definition: runtime.hxx:246
const sal_uInt8 * pError
Definition: runtime.hxx:235
void StepLE()
Definition: runtime.cxx:1432
SbiForStack * FindForStackItemForCollection(class BasicCollection const *pCollection)
Definition: runtime.cxx:1241
void StepREDIMP()
Definition: runtime.cxx:2296
void PopGosub()
Definition: runtime.cxx:1078
void StepIDIV()
Definition: runtime.cxx:1414
SbxBase * FindElementExtern(const OUString &rName)
Definition: runtime.cxx:3732
void StepCHANNEL0()
Definition: runtime.cxx:2702
sal_uInt16 nForLvl
Definition: runtime.hxx:232
bool EvaluateTopOfStackAsBool()
Definition: runtime.cxx:3002
SbxVariable * StepSTATIC_Impl(OUString const &aName, SbxDataType t, sal_uInt32 nOp2)
Definition: runtime.cxx:4737
void StepCAT()
Definition: runtime.cxx:1418
void StepLINPUT()
Definition: runtime.cxx:2586
sal_Int32 nLine
Definition: runtime.hxx:351
void StepCLOSE(sal_uInt32)
Definition: runtime.cxx:3305
sal_uInt16 nOps
Definition: runtime.hxx:252
void StepCASETO(sal_uInt32)
Definition: runtime.cxx:3246
void StepAND()
Definition: runtime.cxx:1419
void StepEMPTY()
Definition: runtime.cxx:2798
void StepPLUS()
Definition: runtime.cxx:1416
void StepREDIMP_ERASE()
Definition: runtime.cxx:2313
static void SetIsMissing(SbxVariable *)
Definition: runtime.cxx:627
void StepRENAME()
Definition: runtime.cxx:2763
sal_uInt16 GetBase() const
Definition: runtime.cxx:1282
static const pStep2 aStep2[]
Definition: runtime.hxx:216
void StepRSET()
Definition: runtime.cxx:2078
void StepNOP()
Definition: runtime.cxx:1287
void StepSTATIC(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4759
sal_Int32 nCol2
Definition: runtime.hxx:351
void StepDCREATE(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4472
void SetVBAEnabled(bool bEnabled)
Definition: runtime.cxx:610
void StepEXP()
Definition: runtime.cxx:1411
void StepFIND_G(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4717
void StepPUTC()
Definition: runtime.cxx:2116
StarBASIC & rBasic
Definition: runtime.hxx:218
void StepIMP()
Definition: runtime.cxx:1423
void StepARGTYP(sal_uInt32)
Definition: runtime.cxx:2924
SbxArrayRef refRedimpArray
Definition: runtime.hxx:226
void StepNE()
Definition: runtime.cxx:1429
void StepOR()
Definition: runtime.cxx:1420
void StepMINUS()
Definition: runtime.cxx:1417
void StepCREATE(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4452
void PopArgv()
Definition: runtime.cxx:1100
SbiForStack * pForStk
Definition: runtime.hxx:230
void SetParameters(SbxArray *)
Definition: runtime.cxx:644
void StepGOSUB(sal_uInt32)
Definition: runtime.cxx:3077
void StepLIB(sal_uInt32)
Definition: runtime.cxx:3455
void StepFIND_CM(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4144
void StepDCREATE_IMPL(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4483
BasicDebugFlags nFlags
Definition: runtime.hxx:250
void ClearArgvStack()
Definition: runtime.cxx:1111
void StepNEG()
Definition: runtime.cxx:1425
void StepARRAYACCESS()
Definition: runtime.cxx:2411
static void implHandleSbxFlags(SbxVariable *pVar, SbxDataType t, sal_uInt32 nOp2)
Definition: runtime.cxx:4565
void DimImpl(const SbxVariableRef &refVar)
Definition: runtime.cxx:2136
SbxArrayRef refArgv
Definition: runtime.hxx:242
sal_uInt16 nExprLvl
Definition: runtime.hxx:231
void StepLT()
Definition: runtime.cxx:1430
void StepINPUT()
Definition: runtime.cxx:2473
void StepMUL()
Definition: runtime.cxx:1412
void StepSETCLASS(sal_uInt32)
Definition: runtime.cxx:3436
void StepPUBLIC(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4644
void PushVar(SbxVariable *)
Definition: runtime.cxx:985
bool checkClass_Impl(const SbxVariableRef &refVal, const OUString &aClass, bool bRaiseErrors, bool bDefault)
Definition: runtime.cxx:3360
void StepCompare(SbxOperator)
Definition: runtime.cxx:1323
void StepTESTCLASS(sal_uInt32)
Definition: runtime.cxx:3441
void StepWRITE()
Definition: runtime.cxx:2736
void StepEQV()
Definition: runtime.cxx:1422
void StepNOERROR()
Definition: runtime.cxx:2672
void StepPUBLIC_Impl(sal_uInt32, sal_uInt32, bool bUsedForClassModule)
Definition: runtime.cxx:4614
void StepARGV()
Definition: runtime.cxx:2448
ErrCode nError
Definition: runtime.hxx:251
SbxArrayRef refLocals
Definition: runtime.hxx:241
const sal_uInt8 * pErrStmnt
Definition: runtime.hxx:238
void StepERROR()
Definition: runtime.cxx:2813
void StepINITFOR()
Definition: runtime.cxx:2603
bool Step()
Definition: runtime.cxx:764
bool bVBAEnabled
Definition: runtime.hxx:249
bool bBlocked
Definition: runtime.hxx:248
void StepFIND_STATIC(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4160
void StepCALLC(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4319
void StepCASE()
Definition: runtime.cxx:2637
void StepTESTFOR(sal_uInt32)
Definition: runtime.cxx:3096
static bool implIsClass(SbxObject const *pObj, const OUString &aClass)
Definition: runtime.cxx:3333
const sal_uInt8 * pCode
Definition: runtime.hxx:233
void StepDIV()
Definition: runtime.cxx:1413
void StepNEXT()
Definition: runtime.cxx:2615
void Error(ErrCode, bool bVBATranslationAlreadyDone=false)
Definition: runtime.cxx:913
void StepGE()
Definition: runtime.cxx:1433
void StepUnary(SbxOperator)
Definition: runtime.cxx:1310
void StepVBASET()
Definition: runtime.cxx:2031
void StepELEM(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4168
SbxVariable * mpExtCaller
Definition: runtime.hxx:229
void StepLOADNC(sal_uInt32)
Definition: runtime.cxx:2830
const SbiImage * pImg
Definition: runtime.hxx:223
void StepJUMPF(sal_uInt32)
Definition: runtime.cxx:3044
std::vector< SbxVariableRef > aRefSaved
Definition: runtime.hxx:254
static const pStep0 aStep0[]
Definition: runtime.hxx:214
void StepXOR()
Definition: runtime.cxx:1421
void StepFIND_Impl(SbxObject *pObj, sal_uInt32 nOp1, sal_uInt32 nOp2, ErrCode, bool bStatic=false)
Definition: runtime.cxx:4127
OUString aLibName
Definition: runtime.hxx:239
void StepCASEIS(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4281
void StepPARAM(sal_uInt32, sal_uInt32)
Loading of a parameter (+offset+type) If the data type is wrong, create a copy and search for optiona...
Definition: runtime.cxx:4202
void StepBASED(sal_uInt32)
Definition: runtime.cxx:3464
static const pStep1 aStep1[]
Definition: runtime.hxx:215
void StepCALL(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4301
void StepFIND(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4138
void StepREDIM()
Definition: runtime.cxx:2201
void StepSTMNT(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4338
SbiRuntime * pNext
Definition: runtime.hxx:352
void PushGosub(const sal_uInt8 *)
Definition: runtime.cxx:1069
SbxVariableRef refRedim
Definition: runtime.hxx:227
void StepEQ()
Definition: runtime.cxx:1428
void StepRETURN(sal_uInt32)
Definition: runtime.cxx:3087
void StepSET_Impl(SbxVariableRef &refVal, SbxVariableRef &refVar, bool bDefaultHandling=false)
Definition: runtime.cxx:1805
void StepArith(SbxOperator)
Definition: runtime.cxx:1290
const sal_uInt8 * pStmnt
Definition: runtime.hxx:234
void StepRESTART()
Definition: runtime.cxx:2791
SbxVariableRef PopVar()
Definition: runtime.cxx:993
void PushArgv()
Definition: runtime.cxx:1093
void StepMOD()
Definition: runtime.cxx:1415
bool IsImageFlag(SbiImageFlags n) const
Definition: runtime.cxx:1277
SbiRuntime(SbModule *, SbMethod *, sal_uInt32)
Definition: runtime.cxx:591
void StepCHANNEL()
Definition: runtime.cxx:2694
SbxArrayRef refExprStk
Definition: runtime.hxx:224
void StepLOADI(sal_uInt32)
Definition: runtime.cxx:2888
void StepGET()
Definition: runtime.cxx:1606
void StepERRHDL(sal_uInt32)
Definition: runtime.cxx:3261
void StepERASE()
Definition: runtime.cxx:2400
void StepIS()
Definition: runtime.cxx:1575
void StepINITFOREACH()
Definition: runtime.cxx:2608
void StepJUMPT(sal_uInt32)
Definition: runtime.cxx:3034
const sal_uInt8 * pRestart
Definition: runtime.hxx:236
bool bInError
Definition: runtime.hxx:247
SbxArrayRef refParams
Definition: runtime.hxx:240
static bool IsMissing(SbxVariable *, sal_uInt16)
Definition: runtime.cxx:635
SbModule * GetModule()
Definition: runtime.hxx:370
void StepONJUMP(sal_uInt32)
Definition: runtime.cxx:3060
bool bRun
Definition: runtime.hxx:245
short nArgc
Definition: runtime.hxx:244
void StepRESUME(sal_uInt32)
Definition: runtime.cxx:3276
SbxArrayRef refCaseStk
Definition: runtime.hxx:225
const sal_uInt8 * pErrCode
Definition: runtime.hxx:237
void StepSETCLASS_impl(sal_uInt32 nOp1, bool bHandleDflt)
Definition: runtime.cxx:3418
void StepARGN(sal_uInt32)
Definition: runtime.cxx:2897
SbiIoSystem * pIosys
Definition: runtime.hxx:222
SbModule * pMod
Definition: runtime.hxx:220
void(SbiRuntime::* pStep1)(sal_uInt32 nOp1)
Definition: runtime.hxx:212
void StepLEAVE()
Definition: runtime.cxx:2684
void StepRTL(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4122
void StepLOADSC(sal_uInt32)
Definition: runtime.cxx:2878
void StepLOCAL(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4595
std::vector< SbiGosub > pGosubStk
Definition: runtime.hxx:255
void StepPUBLIC_P(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4649
void StepLSET()
Definition: runtime.cxx:2040
void StepPROMPT()
Definition: runtime.cxx:2782
void ClearExprStack()
Definition: runtime.cxx:1012
void StepPAD(sal_uInt32)
Definition: runtime.cxx:2969
void StepGT()
Definition: runtime.cxx:1431
void StepLIKE()
Definition: runtime.cxx:1539
void StepSTDERROR()
Definition: runtime.cxx:2662
void StepOPEN(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4437
void ClearForStack()
Definition: runtime.cxx:1233
void StepTCREATE(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4549
sal_Int32 nCol1
Definition: runtime.hxx:351
void StepDCREATE_REDIMP(sal_uInt32, sal_uInt32)
Definition: runtime.cxx:4477
SbxVariable * GetTOS()
Definition: runtime.cxx:1025
void(SbiRuntime::* pStep2)(sal_uInt32 nOp1, sal_uInt32 nOp2)
Definition: runtime.hxx:213
void StepNOT()
Definition: runtime.cxx:1426
SbxVariable * FindElement(SbxObject *pObj, sal_uInt32 nOp1, sal_uInt32 nOp2, ErrCode, bool bLocal, bool bStatic=false)
Definition: runtime.cxx:3488
void StepBYVAL()
Definition: runtime.cxx:2423
Definition: sbx.hxx:95
SbxVariable * Find(const OUString &, SbxClassType)
Definition: sbxarray.cxx:275
sal_uInt32 Count() const
Definition: sbxarray.cxx:87
virtual void Clear() override
Definition: sbxarray.cxx:82
SbxVariable * Get(sal_uInt32)
Definition: sbxarray.cxx:108
void Put(SbxVariable *, sal_uInt32)
Definition: sbxarray.cxx:123
static void SetError(ErrCode)
Definition: sbxbase.cxx:116
void SetFlags(SbxFlagBits n)
Definition: sbxcore.hxx:102
static ErrCode const & GetError()
Definition: sbxbase.cxx:96
bool IsSet(SbxFlagBits n) const
Definition: sbxcore.hxx:114
void SetFlag(SbxFlagBits n)
Definition: sbxcore.hxx:108
SbxFlagBits GetFlags() const
Definition: sbxcore.hxx:105
static SbxObjectRef CreateObject(const OUString &)
Definition: sbxbase.cxx:185
static bool IsError()
Definition: sbxbase.cxx:123
static void ResetError()
Definition: sbxbase.cxx:128
void ResetFlag(SbxFlagBits n)
Definition: sbxcore.hxx:111
virtual void Clear() override
Definition: sbxarray.cxx:420
bool GetDim(sal_Int32, sal_Int32 &, sal_Int32 &) const
Definition: sbxarray.cxx:458
SbxVariable * Get(SbxArray *)
Definition: sbxarray.cxx:538
void AddDim(sal_Int32, sal_Int32)
Definition: sbxarray.cxx:445
sal_Int32 GetDims() const
Definition: sbx.hxx:160
bool hasFixedSize() const
Definition: sbx.hxx:164
void setHasFixedSize(bool bHasFixedSize)
Definition: sbx.hxx:165
void unoAddDim(sal_Int32, sal_Int32)
Definition: sbxarray.cxx:450
void Put(SbxVariable *, const sal_Int32 *)
Definition: sbxarray.cxx:499
void setNumberAndDescription(::sal_Int32 _number, const OUString &_description)
Definition: errobject.cxx:211
static SbxVariableRef const & getErrObject()
Definition: errobject.cxx:198
static css::uno::Reference< ooo::vba::XErrObject > const & getUnoErrObject()
Definition: errobject.cxx:191
virtual SbxVariable * Find(const OUString &, SbxClassType)
Definition: sbxobj.cxx:182
const OUString & GetClassName() const
Definition: sbxobj.hxx:56
void SetClassName(const OUString &rNew)
Definition: sbxobj.hxx:57
void Remove(const OUString &, SbxClassType)
Definition: sbxobj.cxx:499
SbxVariable * Make(const OUString &, SbxClassType, SbxDataType, bool bIsRuntimeFunction=false)
Definition: sbxobj.cxx:347
virtual bool IsClass(const OUString &) const
Definition: sbxobj.cxx:177
bool Compute(SbxOperator, const SbxValue &)
Definition: sbxvalue.cxx:774
bool PutString(const OUString &)
Definition: sbxvalue.cxx:585
SbxBase * GetObject() const
Definition: sbxvar.hxx:157
bool PutBool(bool)
Definition: sbxvalue.cxx:543
bool PutInteger(sal_Int16)
bool PutObject(SbxBase *)
bool Convert(SbxDataType)
Definition: sbxvalue.cxx:729
sal_Int32 GetLong() const
Definition: sbxvar.hxx:142
void PutErr(sal_uInt16)
Definition: sbxvalue.cxx:599
sal_Int16 GetInteger() const
Definition: sbxvar.hxx:141
bool SetType(SbxDataType)
Definition: sbxvalue.cxx:674
const SbxObject * GetParent() const
Definition: sbxvar.hxx:296
void SetName(const OUString &)
Definition: sbxvar.cxx:192
virtual void Broadcast(SfxHintId nHintId) override
Definition: sbxvar.cxx:120
void SetInfo(SbxInfo *p)
Definition: sbxvar.cxx:173
void SetParameters(SbxArray *p)
Definition: sbxvar.cxx:178
virtual SbxDataType GetType() const override
Definition: sbxvar.cxx:321
SbxArray * GetParameters() const
Definition: sbxvar.cxx:111
const OUString & GetName(SbxNameType=SbxNameType::NONE) const
Definition: sbxvar.cxx:199
virtual SbxInfo * GetInfo()
Definition: sbxvar.cxx:160
virtual void SetParent(SbxObject *)
Definition: sbxvar.cxx:355
bool bNoRtl
Definition: sbstar.hxx:52
static void Stop()
Definition: sb.cxx:1357
BASIC_DLLPRIVATE BasicDebugFlags StepPoint(sal_Int32 nLine, sal_Int32 nCol1, sal_Int32 nCol2)
Definition: sb.cxx:1407
static ErrCode GetSfxFromVBError(sal_uInt16 nError)
Definition: sb.cxx:1482
SbxObjectRef pRtl
Definition: sbstar.hxx:46
static SbModule * GetActiveModule()
Definition: sb.cxx:1381
static const OUString & GetErrorText()
Definition: sb.cxx:1433
BASIC_DLLPRIVATE BasicDebugFlags BreakPoint(sal_Int32 nLine, sal_Int32 nCol1, sal_Int32 nCol2)
Definition: sb.cxx:1393
static void Error(ErrCode, const OUString &rMsg={})
Definition: sb.cxx:1683
BASIC_DLLPRIVATE bool RTError(ErrCode, const OUString &rMsg, sal_Int32, sal_Int32, sal_Int32)
Definition: sb.cxx:1642
bool bDocBasic
Definition: sbstar.hxx:54
bool bVBAEnabled
Definition: sbstar.hxx:55
bool isVBAEnabled() const
Definition: runtime.cxx:129
static void MakeErrorText(ErrCode, std::u16string_view aMsg)
Definition: sb.cxx:1544
static void FatalError(ErrCode)
Definition: sb.cxx:1691
void SetVBAEnabled(bool bEnabled)
Definition: runtime.cxx:121
static sal_uInt16 GetVBErrorCode(ErrCode nError)
Definition: sb.cxx:1443
SbxVariable * VBAFind(const OUString &rName, SbxClassType t)
Definition: sb.cxx:259
void setValue(const css::uno::Any &)
Definition: sbunoobj.cxx:4590
unsigned int GetRefCount() const
void AddFirstRef()
const LocaleDataWrapper & GetLocaleData() const
SbxVariable * getVBAConstant(const OUString &rName)
Definition: sbunoobj.cxx:3279
static VBAConstantHelper & instance()
Definition: sbunoobj.cxx:3212
T * get() const
bool is() const
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
#define PARAM_INFO_WITHBRACKETS
Definition: codegen.hxx:84
#define PARAM_INFO_PARAMARRAY
Definition: codegen.hxx:83
Any value
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
float v
float u
float x
#define ERRCODE_NONE
DocumentType eType
OUString sName
SbiImageFlags
Definition: image.hxx:33
sal_Int32 nIndex
OUString aName
SbiStreamFlags
Definition: iosys.hxx:36
void * p
sal_Int64 n
#define LANGUAGE_DONTKNOW
#define LANGUAGE_ENGLISH_US
DateOrder
#define SAL_INFO_IF(condition, area, stream)
aStr
aBuf
int n2
int n1
NONE
err
@ Exception
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill='\0')
OUStringBuffer & truncateToLength(OUStringBuffer &rBuffer, sal_Int32 nLength)
Reference< XComponentContext > getProcessComponentContext()
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
end
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
SbiOpcode
Definition: opcodes.hxx:25
Reference< XInvocation2 > xInvocation
QPRO_FUNC_TYPE nType
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
static void implCopyDimArray(SbxDimArray *pNewArray, SbxDimArray *pOldArray, sal_Int32 nMaxDimIndex, sal_Int32 nActualDim, sal_Int32 *pActualIndices, sal_Int32 *pLowerBounds, sal_Int32 *pUpperBounds)
Definition: runtime.cxx:2210
static void lcl_clearImpl(SbxVariableRef const &refVar, SbxDataType const &eType)
Definition: runtime.cxx:2338
void removeDimAsNewRecoverItem(SbxVariable *pVar)
Definition: runtime.cxx:1790
void setBasicWatchMode(bool bOn)
Definition: runtime.cxx:485
static bool bWatchMode
Definition: runtime.cxx:483
static bool implRestorePreservedArray(SbxDimArray *pNewArray, SbxArrayRef &rrefRedimpArray, bool *pbWasError=nullptr)
Definition: runtime.cxx:2233
std::unordered_map< SbxVariable *, DimAsNewRecoverItem, SbxVariablePtrHash > DimAsNewRecoverHash
Definition: runtime.cxx:1782
constexpr OUStringLiteral pCollectionStr
Definition: runtime.cxx:1803
StarBASIC * GetCurrentBasic(StarBASIC *pRTBasic)
Definition: runtime.cxx:552
static bool checkUnoStructCopy(bool bVBA, SbxVariableRef const &refVal, SbxVariableRef const &refVar)
Definition: runtime.cxx:1613
static void lcl_eraseImpl(SbxVariableRef const &refVar, bool bVBAEnabled)
Definition: runtime.cxx:2347
#define MAXRECURSION
Definition: runtime.hxx:90
bool hasUno()
Definition: iosys.cxx:133
void implStepRenameUCB(const OUString &aSource, const OUString &aDest)
@ EachCollection
@ EachXIndexAccess
@ EachXEnumeration
void implStepRenameOSL(const OUString &aSource, const OUString &aDest)
SbAttributes
Definition: runtime.hxx:92
void checkArithmeticOverflow(double d)
Definition: runtime.hxx:383
SbxObjectRef createUserTypeImpl(const OUString &rClassName)
Definition: sb.cxx:600
BasicDebugFlags
Definition: sbdef.hxx:46
#define ERRCODE_BASIC_USER_ABORT
Definition: sberrors.hxx:61
#define ERRCODE_BASIC_INVALID_OBJECT
Definition: sberrors.hxx:41
#define ERRCODE_BASIC_NO_METHOD
Definition: sberrors.hxx:42
#define ERRCODE_BASIC_BAD_PARAMETERS
Definition: sberrors.hxx:142
#define ERRCODE_BASIC_NO_OBJECT
Definition: sberrors.hxx:34
#define ERRCODE_BASIC_BAD_PARAMETER
Definition: sberrors.hxx:31
#define ERRCODE_BASIC_PROC_UNDEFINED
Definition: sberrors.hxx:32
#define ERRCODE_BASIC_OUT_OF_RANGE
Definition: sberrors.hxx:28
#define ERRCODE_BASIC_NO_GOSUB
Definition: sberrors.hxx:55
#define ERRCODE_BASIC_VAR_UNDEFINED
Definition: sberrors.hxx:60
#define ERRCODE_BASIC_COMPAT
Definition: sberrors.hxx:166
#define ERRCODE_BASIC_NAMED_NOT_FOUND
Definition: sberrors.hxx:50
#define ERRCODE_BASIC_CONVERSION
Definition: sberrors.hxx:30
#define ERRCODE_BASIC_BAD_ARGUMENT
Definition: sberrors.hxx:26
#define ERRCODE_BASIC_INTERNAL_ERROR
Definition: sberrors.hxx:33
#define ERRCODE_BASIC_BAD_RESUME
Definition: sberrors.hxx:62
#define ERRCODE_BASIC_NOT_OPTIONAL
Definition: sberrors.hxx:51
#define ERRCODE_BASIC_NO_NAMED_ARGS
Definition: sberrors.hxx:48
#define ERRCODE_BASIC_NEEDS_OBJECT
Definition: sberrors.hxx:108
#define ERRCODE_BASIC_STACK_OVERFLOW
Definition: sberrors.hxx:63
#define ERRCODE_BASIC_INVALID_USAGE_OBJECT
Definition: sberrors.hxx:43
SbiGlobals * GetSbData()
Definition: sbintern.cxx:26
SbUnoClass * findUnoClass(const OUString &rName)
Definition: sbunoobj.cxx:3298
void unoToSbxValue(SbxVariable *pVar, const Any &aValue)
Definition: sbunoobj.cxx:610
SbxVariable * getDefaultProp(SbxVariable *pRef)
Definition: sbunoobj.cxx:126
Reference< XInterface > createComListener(const Any &aControlAny, const OUString &aVBAType, std::u16string_view aPrefix, const SbxObjectRef &xScopeObj)
Definition: sbunoobj.cxx:4361
bool checkUnoObjectType(SbUnoObject &rUnoObj, const OUString &rClass)
Definition: sbunoobj.cxx:1644
SbxBOOL
Definition: sbxdef.hxx:215
const sal_uInt32 SBX_TYPE_DIM_AS_NEW_FLAG
Definition: sbxdef.hxx:88
const sal_uInt32 SBX_TYPE_WITH_EVENTS_FLAG
Definition: sbxdef.hxx:87
const sal_uInt32 SBX_TYPE_VAR_TO_DIM_FLAG
Definition: sbxdef.hxx:90
SbxOperator
Definition: sbxdef.hxx:92
@ SbxMOD
Definition: sbxdef.hxx:97
@ SbxAND
Definition: sbxdef.hxx:104
@ SbxGT
Definition: sbxdef.hxx:118
@ SbxGE
Definition: sbxdef.hxx:120
@ SbxEQ
Definition: sbxdef.hxx:115
@ SbxLT
Definition: sbxdef.hxx:117
@ SbxNEG
Definition: sbxdef.hxx:100
@ SbxMUL
Definition: sbxdef.hxx:95
@ SbxPLUS
Definition: sbxdef.hxx:98
@ SbxIMP
Definition: sbxdef.hxx:108
@ SbxXOR
Definition: sbxdef.hxx:106
@ SbxCAT
Definition: sbxdef.hxx:112
@ SbxOR
Definition: sbxdef.hxx:105
@ SbxEQV
Definition: sbxdef.hxx:107
@ SbxIDIV
Definition: sbxdef.hxx:101
@ SbxNE
Definition: sbxdef.hxx:116
@ SbxNOT
Definition: sbxdef.hxx:109
@ SbxMINUS
Definition: sbxdef.hxx:99
@ SbxDIV
Definition: sbxdef.hxx:96
@ SbxLE
Definition: sbxdef.hxx:119
@ SbxEXP
Definition: sbxdef.hxx:94
const sal_uInt32 SBX_FIXED_LEN_STRING_FLAG
Definition: sbxdef.hxx:89
SbxDataType
Definition: sbxdef.hxx:37
@ SbxOBJECT
Definition: sbxdef.hxx:47
@ SbxLONG
Definition: sbxdef.hxx:41
@ SbxARRAY
Definition: sbxdef.hxx:80
@ SbxEMPTY
Definition: sbxdef.hxx:38
@ SbxMISSING
Definition: sbxdef.hxx:84
@ SbxERROR
Definition: sbxdef.hxx:48
@ SbxDATE
Definition: sbxdef.hxx:45
@ SbxCURRENCY
Definition: sbxdef.hxx:44
@ SbxVARIANT
Definition: sbxdef.hxx:51
@ SbxSINGLE
Definition: sbxdef.hxx:42
@ SbxBYREF
Definition: sbxdef.hxx:81
@ SbxSTRING
Definition: sbxdef.hxx:46
@ SbxINTEGER
Definition: sbxdef.hxx:40
@ SbxDOUBLE
Definition: sbxdef.hxx:43
SbxFlagBits
Definition: sbxdef.hxx:131
StreamMode
SbxArrayRef mxIfaces
Definition: sbintern.hxx:51
short nArgc
Definition: runtime.cxx:136
SbxArrayRef refArgv
Definition: runtime.cxx:135
SbiArgv(SbxArrayRef refArgv_, short nArgc_)
Definition: runtime.cxx:138
SbxVariableRef refVar
Definition: runtime.hxx:67
sal_Int32 nCurCollectionIndex
Definition: runtime.hxx:73
SbxVariableRef refInc
Definition: runtime.hxx:69
ForType eForType
Definition: runtime.hxx:72
SbxVariableRef refEnd
Definition: runtime.hxx:68
SbiInstance * pInst
Definition: sbintern.hxx:108
StarBASIC * pMSOMacroRuntimLib
Definition: sbintern.hxx:136
SbiGosub(const sal_uInt8 *pCode_, sal_uInt16 nStartForLvl_)
Definition: runtime.cxx:147
const sal_uInt8 * pCode
Definition: runtime.cxx:144
sal_uInt16 nStartForLvl
Definition: runtime.cxx:145
SbxDataType eType
Definition: sbx.hxx:42
const OUString aName
Definition: sbx.hxx:41
SbxFlagBits nFlags
Definition: sbx.hxx:43
sal_uInt32 nUserData
Definition: sbx.hxx:44
SbxBase * pObj
Definition: sbxvar.hxx:61
TransliterationFlags transliterateFlags
css::lang::Locale Locale
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
SvNumFormatType
NF_EVALDATEFORMAT_FORMAT