diff options
Diffstat (limited to 'basic/source/runtime/runtime.cxx')
-rw-r--r-- | basic/source/runtime/runtime.cxx | 274 |
1 files changed, 125 insertions, 149 deletions
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index afc785e76b32..b2f493689c0b 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -36,8 +36,9 @@ #include <sal/log.hxx> #include <tools/wldcrd.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <vcl/settings.hxx> @@ -48,9 +49,7 @@ #include <svl/numformat.hxx> #include <svl/zforlist.hxx> -#include <i18nutil/searchopt.hxx> -#include <unotools/syslocale.hxx> -#include <unotools/textsearch.hxx> +#include <unicode/regex.h> #include <basic/sbuno.hxx> @@ -75,11 +74,12 @@ using com::sun::star::uno::Reference; using namespace com::sun::star::uno; using namespace com::sun::star::container; using namespace com::sun::star::lang; -using namespace com::sun::star::beans; using namespace com::sun::star::script; using namespace ::com::sun::star; +#if HAVE_FEATURE_SCRIPTING + static void lcl_clearImpl( SbxVariableRef const & refVar, SbxDataType const & eType ); static void lcl_eraseImpl( SbxVariableRef const & refVar, bool bVBAEnabled ); @@ -113,11 +113,8 @@ private: bool SbiRuntime::isVBAEnabled() { - bool bResult = false; SbiInstance* pInst = GetSbData()->pInst; - if ( pInst && GetSbData()->pInst->pRun ) - bResult = pInst->pRun->bVBAEnabled; - return bResult; + return pInst && pInst->pRun && pInst->pRun->bVBAEnabled; } void StarBASIC::SetVBAEnabled( bool bEnabled ) @@ -130,21 +127,15 @@ void StarBASIC::SetVBAEnabled( bool bEnabled ) bool StarBASIC::isVBAEnabled() const { - if ( bDocBasic ) - { - if( SbiRuntime::isVBAEnabled() ) - return true; - return bVBAEnabled; - } - return false; + return bDocBasic && (bVBAEnabled || SbiRuntime::isVBAEnabled()); } struct SbiArgv { // Argv stack: SbxArrayRef refArgv; // Argv short nArgc; // Argc - SbiArgv(SbxArrayRef const & refArgv_, short nArgc_) : - refArgv(refArgv_), + SbiArgv(SbxArrayRef refArgv_, short nArgc_) : + refArgv(std::move(refArgv_)), nArgc(nArgc_) {} }; @@ -384,6 +375,8 @@ SbiDllMgr* SbiInstance::GetDllMgr() return pDllMgr.get(); } +#endif + // #39629 create NumberFormatter with the help of a static method now std::shared_ptr<SvNumberFormatter> const & SbiInstance::GetNumberFormatter() { @@ -476,6 +469,7 @@ std::shared_ptr<SvNumberFormatter> SbiInstance::PrepareNumberFormatter( sal_uInt return pNumberFormatter; } +#if HAVE_FEATURE_SCRIPTING // Let engine run. If Flags == BasicDebugFlags::Continue, take Flags over @@ -598,32 +592,14 @@ SbMethod* SbiInstance::GetCaller( sal_uInt16 nLevel ) SbiRuntime::SbiRuntime( SbModule* pm, SbMethod* pe, sal_uInt32 nStart ) : rBasic( *static_cast<StarBASIC*>(pm->pParent) ), pInst( GetSbData()->pInst ), - pMod( pm ), pMeth( pe ), pImg( pMod->pImage.get() ), mpExtCaller(nullptr), m_nLastTime(0) + pMod( pm ), pMeth( pe ), pImg( pMod->pImage.get() ) { nFlags = pe ? pe->GetDebugFlags() : BasicDebugFlags::NONE; pIosys = pInst->GetIoSystem(); - pForStk = nullptr; - pError = nullptr; - pErrCode = - pErrStmnt = - pRestart = nullptr; - pNext = nullptr; pCode = pStmnt = pImg->GetCode() + nStart; - bRun = - bError = true; - bInError = false; - bBlocked = false; - nLine = 0; - nCol1 = 0; - nCol2 = 0; - nExprLvl = 0; - nArgc = 0; - nError = ERRCODE_NONE; - nForLvl = 0; - nOps = 0; refExprStk = new SbxArray; - SetVBAEnabled( pMod->IsVBACompat() ); + SetVBAEnabled( pMod->IsVBASupport() ); SetParameters( pe ? pe->GetParameters() : nullptr ); } @@ -791,23 +767,26 @@ bool SbiRuntime::Step() { if( bRun ) { + static sal_uInt32 nLastTime = osl_getGlobalTimer(); + // in any case check casually! if( !( ++nOps & 0xF ) && pInst->IsReschedule() ) { sal_uInt32 nTime = osl_getGlobalTimer(); - if (nTime - m_nLastTime > 5 ) // 20 ms + if (nTime - nLastTime > 5) // 20 ms { + nLastTime = nTime; Application::Reschedule(); - m_nLastTime = nTime; } } // #i48868 blocked by next call level? while( bBlocked ) { - if( pInst->IsReschedule() ) + if( pInst->IsReschedule() ) // And what if not? Busy loop? { Application::Reschedule(); + nLastTime = osl_getGlobalTimer(); } } @@ -1169,7 +1148,15 @@ void SbiRuntime::PushForEach() pForStk = p; SbxVariableRef xObjVar = PopVar(); - SbxBase* pObj = xObjVar && xObjVar->GetFullType() == SbxOBJECT ? xObjVar->GetObject() : nullptr; + SbxBase* pObj(nullptr); + if (xObjVar) + { + SbxValues v(SbxVARIANT); + // Here it may retrieve the value, and change the type from SbxEMPTY to SbxOBJECT + xObjVar->Get(v); + if (v.eType == SbxOBJECT) + pObj = v.pObj; + } if (SbxDimArray* pArray = dynamic_cast<SbxDimArray*>(pObj)) { @@ -1279,8 +1266,6 @@ void SbiRuntime::DllCall SbxDataType eResType, // return value bool bCDecl ) // true: according to C-conventions { - // NOT YET IMPLEMENTED - SbxVariable* pRes = new SbxVariable( eResType ); SbiDllMgr* pDllMgr = pInst->GetDllMgr(); ErrCode nErr = pDllMgr->Call( aFuncName, aDLLName, pArgs, *pRes, bCDecl ); @@ -1451,101 +1436,68 @@ void SbiRuntime::StepGE() { StepCompare( SbxGE ); } namespace { - bool NeedEsc(sal_Unicode cCode) - { - if(!rtl::isAscii(cCode)) - { - return false; - } - switch(cCode) - { - case '.': - case '^': - case '$': - case '+': - case '\\': - case '|': - case '{': - case '}': - case '(': - case ')': - return true; - default: - return false; - } - } - - OUString VBALikeToRegexp(const OUString &rIn) + OUString VBALikeToRegexp(std::u16string_view sIn) { - OUStringBuffer sResult; - const sal_Unicode *start = rIn.getStr(); - const sal_Unicode *end = start + rIn.getLength(); - - int seenright = 0; + OUStringBuffer sResult("\\A"); // Match at the beginning of the input - sResult.append('^'); - - while (start < end) + for (auto start = sIn.begin(), end = sIn.end(); start < end;) { - switch (*start) + switch (auto ch = *start++) { case '?': sResult.append('.'); - start++; break; case '*': sResult.append(".*"); - start++; break; case '#': sResult.append("[0-9]"); - start++; - break; - case ']': - sResult.append('\\'); - sResult.append(*start++); break; case '[': - sResult.append(*start++); - seenright = 0; - while (start < end && !seenright) + sResult.append(ch); + if (start < end) + { + if (*start == '!') + { + sResult.append('^'); + ++start; + } + else if (*start == '^') + sResult.append('\\'); + } + for (bool seenright = false; start < end && !seenright; ++start) { switch (*start) { case '[': - case '?': - case '*': + case '\\': sResult.append('\\'); - sResult.append(*start); break; case ']': - sResult.append(*start); - seenright = 1; - break; - case '!': - sResult.append('^'); - break; - default: - if (NeedEsc(*start)) - { - sResult.append('\\'); - } - sResult.append(*start); + seenright = true; break; } - start++; + sResult.append(*start); } break; + case '.': + case '^': + case '$': + case '+': + case '\\': + case '|': + case '{': + case '}': + case '(': + case ')': + sResult.append('\\'); + [[fallthrough]]; default: - if (NeedEsc(*start)) - { - sResult.append('\\'); - } - sResult.append(*start++); + sResult.append(ch); } } - sResult.append('$'); + sResult.append("\\z"); // Match if the current position is at the end of input return sResult.makeStringAndClear(); } @@ -1556,15 +1508,8 @@ void SbiRuntime::StepLIKE() SbxVariableRef refVar1 = PopVar(); SbxVariableRef refVar2 = PopVar(); - OUString pattern = VBALikeToRegexp(refVar1->GetOUString()); OUString value = refVar2->GetOUString(); - - i18nutil::SearchOptions2 aSearchOpt; - - aSearchOpt.AlgorithmType2 = css::util::SearchAlgorithms2::REGEXP; - - aSearchOpt.Locale = Application::GetSettings().GetLanguageTag().getLocale(); - aSearchOpt.searchString = pattern; + OUString regex = VBALikeToRegexp(refVar1->GetOUString()); bool bTextMode(true); bool bCompatibility = ( GetSbData()->pInst && GetSbData()->pInst->IsCompatibility() ); @@ -1572,14 +1517,35 @@ void SbiRuntime::StepLIKE() { bTextMode = IsImageFlag( SbiImageFlags::COMPARETEXT ); } + sal_uInt32 searchFlags = UREGEX_UWORD | UREGEX_DOTALL; // Dot matches newline if( bTextMode ) { - aSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE; + searchFlags |= UREGEX_CASE_INSENSITIVE; + } + + static sal_uInt32 cachedSearchFlags = 0; + static OUString cachedRegex; + static std::optional<icu::RegexMatcher> oRegexMatcher; + UErrorCode nIcuErr = U_ZERO_ERROR; + if (regex != cachedRegex || searchFlags != cachedSearchFlags || !oRegexMatcher) + { + cachedRegex = regex; + cachedSearchFlags = searchFlags; + icu::UnicodeString sRegex(false, reinterpret_cast<const UChar*>(cachedRegex.getStr()), + cachedRegex.getLength()); + oRegexMatcher.emplace(sRegex, cachedSearchFlags, nIcuErr); + } + + icu::UnicodeString sSource(false, reinterpret_cast<const UChar*>(value.getStr()), + value.getLength()); + oRegexMatcher->reset(sSource); + + bool bRes = oRegexMatcher->matches(nIcuErr); + if (nIcuErr) + { + Error(ERRCODE_BASIC_INTERNAL_ERROR); } SbxVariable* pRes = new SbxVariable; - utl::TextSearch aSearch( aSearchOpt); - sal_Int32 nStart=0, nEnd=value.getLength(); - bool bRes = aSearch.SearchForward(value, &nStart, &nEnd); pRes->PutBool( bRes ); PushVar( pRes ); @@ -1774,10 +1740,10 @@ struct DimAsNewRecoverItem , m_pClassModule( nullptr ) {} - DimAsNewRecoverItem( const OUString& rObjClass, const OUString& rObjName, + DimAsNewRecoverItem( OUString aObjClass, OUString aObjName, SbxObject* pObjParent, SbModule* pClassModule ) - : m_aObjClass( rObjClass ) - , m_aObjName( rObjName ) + : m_aObjClass(std::move( aObjClass )) + , m_aObjName(std::move( aObjName )) , m_pObjParent( pObjParent ) , m_pClassModule( pClassModule ) {} @@ -1815,7 +1781,7 @@ void removeDimAsNewRecoverItem( SbxVariable* pVar ) // saving object variable // not-object variables will cause errors -constexpr OUStringLiteral pCollectionStr = u"Collection"; +constexpr OUString pCollectionStr = u"Collection"_ustr; void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp ) { @@ -2744,7 +2710,7 @@ void SbiRuntime::StepPRINTF() // print TOS in field } s.append(s1); comphelper::string::padToLength(s, 14, ' '); - pIosys->Write( s.makeStringAndClear() ); + pIosys->Write( s ); Error( pIosys->GetError() ); } @@ -2847,7 +2813,7 @@ void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 ) // tdf#143707 - check if the data type character was added after the string termination symbol SbxDataType eTypeStr; // #57844 use localized function - OUString aStr = pImg->GetString(static_cast<short>(nOp1), &eTypeStr); + OUString aStr = pImg->GetString(nOp1, &eTypeStr); // also allow , !!! sal_Int32 iComma = aStr.indexOf(','); if( iComma >= 0 ) @@ -2893,7 +2859,7 @@ void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 ) void SbiRuntime::StepLOADSC( sal_uInt32 nOp1 ) { SbxVariable* p = new SbxVariable; - p->PutString( pImg->GetString( static_cast<short>( nOp1 ) ) ); + p->PutString( pImg->GetString( nOp1 ) ); PushVar( p ); } @@ -2915,7 +2881,7 @@ void SbiRuntime::StepARGN( sal_uInt32 nOp1 ) StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR ); else { - OUString aAlias( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aAlias( pImg->GetString( nOp1 ) ); SbxVariableRef pVal = PopVar(); if( bVBAEnabled && ( dynamic_cast<const SbxMethod*>( pVal.get()) != nullptr @@ -3023,6 +2989,14 @@ bool SbiRuntime::EvaluateTopOfStackAsBool() { return false; } + + // tdf#151503 - do not evaluate a missing optional variable to a boolean + if (tos->GetType() == SbxERROR && IsMissing(tos.get(), 1)) + { + Error(ERRCODE_BASIC_NOT_OPTIONAL); + return false; + } + if ( tos->IsObject() ) { //GetBool applied to an Object attempts to dereference and evaluate @@ -3426,7 +3400,7 @@ void SbiRuntime::StepSETCLASS_impl( sal_uInt32 nOp1, bool bHandleDflt ) { SbxVariableRef refVal = PopVar(); SbxVariableRef refVar = PopVar(); - OUString aClass( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aClass( pImg->GetString( nOp1 ) ); bool bOk = checkClass_Impl( refVal, aClass, true, true ); if( bOk ) @@ -3448,7 +3422,7 @@ void SbiRuntime::StepSETCLASS( sal_uInt32 nOp1 ) void SbiRuntime::StepTESTCLASS( sal_uInt32 nOp1 ) { SbxVariableRef xObjVal = PopVar(); - OUString aClass( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aClass( pImg->GetString( nOp1 ) ); bool bDefault = !bVBAEnabled; bool bOk = checkClass_Impl( xObjVal, aClass, false, bDefault ); @@ -3461,7 +3435,7 @@ void SbiRuntime::StepTESTCLASS( sal_uInt32 nOp1 ) void SbiRuntime::StepLIB( sal_uInt32 nOp1 ) { - aLibName = pImg->GetString( static_cast<short>( nOp1 ) ); + aLibName = pImg->GetString( nOp1 ); } // TOS is incremented by BASE, BASE is pushed before (+BASE) @@ -3515,7 +3489,7 @@ SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt { bool bFatalError = false; SbxDataType t = static_cast<SbxDataType>(nOp2); - OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) ); + OUString aName( pImg->GetString( nOp1 & 0x7FFF ) ); // Hacky capture of Evaluate [] syntax // this should be tackled I feel at the pcode level if ( bIsVBAInterOp && aName.startsWith("[") ) @@ -4307,7 +4281,7 @@ void SbiRuntime::StepCASEIS( sal_uInt32 nOp1, sal_uInt32 nOp2 ) void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { - OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ); + OUString aName = pImg->GetString( nOp1 & 0x7FFF ); SbxArray* pArgs = nullptr; if( nOp1 & 0x8000 ) { @@ -4325,7 +4299,7 @@ void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) void SbiRuntime::StepCALLC( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { - OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ); + OUString aName = pImg->GetString( nOp1 & 0x7FFF ); SbxArray* pArgs = nullptr; if( nOp1 & 0x8000 ) { @@ -4415,7 +4389,7 @@ void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 ) } // 16.10.96: #31460 new concept for StepInto/Over/Out - // see explanation at _ImplGetBreakCallLevel + // see explanation at SbiInstance::CalcBreakCallLevel if( pInst->nCallLvl <= pInst->nBreakCallLvl ) { StarBASIC* pStepBasic = GetCurrentBasic( &rBasic ); @@ -4458,7 +4432,7 @@ void SbiRuntime::StepOPEN( sal_uInt32 nOp1, sal_uInt32 nOp2 ) void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { - OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + OUString aClass( pImg->GetString( nOp2 ) ); SbxObjectRef pObj = SbxBase::CreateObject( aClass ); if( !pObj ) { @@ -4466,7 +4440,7 @@ void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 ) } else { - OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aName( pImg->GetString( nOp1 ) ); pObj->SetName( aName ); // the object must be able to call the BASIC pObj->SetParent( &rBasic ); @@ -4528,7 +4502,7 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) nTotalSize = 0; // on error, don't create objects // create objects and insert them into the array - OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + OUString aClass( pImg->GetString( nOp2 ) ); OUString aName; for( sal_Int32 i = 0 ; i < nTotalSize ; ++i ) { @@ -4543,7 +4517,7 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) else { if (aName.isEmpty()) - aName = pImg->GetString(static_cast<short>(nOp1)); + aName = pImg->GetString(nOp1); pClassObj->SetName(aName); // the object must be able to call the basic pClassObj->SetParent(&rBasic); @@ -4555,8 +4529,8 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) void SbiRuntime::StepTCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { - OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); - OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); + OUString aName( pImg->GetString( nOp1 ) ); + OUString aClass( pImg->GetString( nOp2 ) ); SbxObjectRef pCopyObj = createUserTypeImpl( aClass ); if( pCopyObj ) @@ -4585,7 +4559,7 @@ void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt3 if( bFixedString ) { sal_uInt16 nCount = static_cast<sal_uInt16>( nOp2 >> 17 ); // len = all bits above 0x10000 - OUStringBuffer aBuf; + OUStringBuffer aBuf(nCount); comphelper::string::padToLength(aBuf, nCount); pVar->PutString(aBuf.makeStringAndClear()); } @@ -4605,7 +4579,7 @@ void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { refLocals = new SbxArray; } - OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aName( pImg->GetString( nOp1 ) ); if( refLocals->Find( aName, SbxClassType::DontCare ) == nullptr ) { SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff); @@ -4620,7 +4594,7 @@ void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) void SbiRuntime::StepPUBLIC_Impl( sal_uInt32 nOp1, sal_uInt32 nOp2, bool bUsedForClassModule ) { - OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aName( pImg->GetString( nOp1 ) ); SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff); bool bFlag = pMod->IsSet( SbxFlagBits::NoModify ); pMod->SetFlag( SbxFlagBits::NoModify ); @@ -4672,7 +4646,7 @@ void SbiRuntime::StepGLOBAL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { StepPUBLIC_Impl( nOp1, nOp2, true ); } - OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aName( pImg->GetString( nOp1 ) ); SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff); // Store module scope variables at module scope @@ -4732,7 +4706,7 @@ void SbiRuntime::StepFIND_G( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { // Return dummy variable SbxDataType t = static_cast<SbxDataType>(nOp2); - OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) ); + OUString aName( pImg->GetString( nOp1 & 0x7FFF ) ); SbxVariable* pDummyVar = new SbxVariable( t ); pDummyVar->SetName( aName ); @@ -4765,9 +4739,11 @@ SbxVariable* SbiRuntime::StepSTATIC_Impl( // establishing a static variable (+StringID+type) void SbiRuntime::StepSTATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { - OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); + OUString aName( pImg->GetString( nOp1 ) ); SbxDataType t = static_cast<SbxDataType>(nOp2 & 0xffff); StepSTATIC_Impl( aName, t, nOp2 ); } +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |