diff options
Diffstat (limited to 'basic/source/runtime/runtime.cxx')
-rw-r--r-- | basic/source/runtime/runtime.cxx | 691 |
1 files changed, 383 insertions, 308 deletions
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index 87cef46cffbe..b2f493689c0b 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -36,21 +36,20 @@ #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> -#include <rtl/instance.hxx> #include <rtl/math.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/character.hxx> +#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_) {} }; @@ -289,9 +280,9 @@ const SbiRuntime::pStep2 SbiRuntime::aStep2[] = {// all opcodes with two operand // SbiRTLData SbiRTLData::SbiRTLData() + : nDirFlags(SbAttributes::NONE) + , nCurDirPos(0) { - nDirFlags = SbAttributes::NONE; - nCurDirPos = 0; } SbiRTLData::~SbiRTLData() @@ -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 ), 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 ); } @@ -671,10 +647,10 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) { refParams = new SbxArray; // for the return value - refParams->Put32( pMeth, 0 ); + refParams->Put(pMeth, 0); SbxInfo* pInfo = pMeth ? pMeth->GetInfo() : nullptr; - sal_uInt32 nParamCount = pParams ? pParams->Count32() : 1; + sal_uInt32 nParamCount = pParams ? pParams->Count() : 1; assert(nParamCount <= std::numeric_limits<sal_uInt16>::max()); if( nParamCount > 1 ) { @@ -687,25 +663,25 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) { SbxDimArray* pArray = new SbxDimArray( SbxVARIANT ); sal_uInt32 nParamArrayParamCount = nParamCount - i; - pArray->unoAddDim32( 0, nParamArrayParamCount - 1 ); + pArray->unoAddDim(0, nParamArrayParamCount - 1); for (sal_uInt32 j = i; j < nParamCount ; ++j) { - SbxVariable* v = pParams->Get32( j ); + SbxVariable* v = pParams->Get(j); sal_Int32 aDimIndex[1]; aDimIndex[0] = j - i; - pArray->Put32(v, aDimIndex); + pArray->Put(v, aDimIndex); } SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT ); pArrayVar->SetFlag( SbxFlagBits::ReadWrite ); pArrayVar->PutObject( pArray ); - refParams->Put32( pArrayVar, i ); + refParams->Put(pArrayVar, i); // Block ParamArray for missing parameter pInfo = nullptr; break; } - SbxVariable* v = pParams->Get32( i ); + SbxVariable* v = pParams->Get(i); // methods are always byval! bool bByVal = dynamic_cast<const SbxMethod *>(v) != nullptr; SbxDataType t = v->GetType(); @@ -742,7 +718,7 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) SetIsMissing( v2 ); } *v2 = *v; - refParams->Put32( v2, i ); + refParams->Put(v2, i); } else { @@ -758,11 +734,11 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) v->Convert( t ); } } - refParams->Put32( v, i ); + refParams->Put(v, i); } if( p ) { - refParams->PutAlias32( p->aName, i ); + refParams->PutAlias(p->aName, i); } } } @@ -776,11 +752,11 @@ void SbiRuntime::SetParameters( SbxArray* pParams ) if( p && (p->nUserData & PARAM_INFO_PARAMARRAY) != 0 ) { SbxDimArray* pArray = new SbxDimArray( SbxVARIANT ); - pArray->unoAddDim32( 0, -1 ); + pArray->unoAddDim(0, -1); SbxVariable* pArrayVar = new SbxVariable( SbxVARIANT ); pArrayVar->SetFlag( SbxFlagBits::ReadWrite ); pArrayVar->PutObject( pArray ); - refParams->Put32( pArrayVar, nParamCount ); + refParams->Put(pArrayVar, nParamCount); } } @@ -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(); } } @@ -991,15 +970,9 @@ sal_Int32 SbiRuntime::translateErrorToVba( ErrCode nError, OUString& rMsg ) // if there is an error defined it more than likely // is not the one you want ( some are the same though ) // we really need a new vba compatible error list - if ( rMsg.isEmpty() ) - { - StarBASIC::MakeErrorText( nError, rMsg ); - rMsg = StarBASIC::GetErrorText(); - if ( rMsg.isEmpty() ) // no message for err no, need localized resource here - { - rMsg = "Internal Object Error:"; - } - } + // tdf#123144 - always translate an error number to a vba error message + StarBASIC::MakeErrorText( nError, rMsg ); + rMsg = StarBASIC::GetErrorText(); // no num? most likely then it *is* really a vba err sal_uInt16 nVBErrorCode = StarBASIC::GetVBErrorCode( nError ); sal_Int32 nVBAErrorNumber = ( nVBErrorCode == 0 ) ? sal_uInt32(nError) : nVBErrorCode; @@ -1015,7 +988,7 @@ void SbiRuntime::PushVar( SbxVariable* pVar ) { if( pVar ) { - refExprStk->Put32( pVar, nExprLvl++ ); + refExprStk->Put(pVar, nExprLvl++); } } @@ -1028,7 +1001,7 @@ SbxVariableRef SbiRuntime::PopVar() return new SbxVariable; } #endif - SbxVariableRef xVar = refExprStk->Get32( --nExprLvl ); + SbxVariableRef xVar = refExprStk->Get(--nExprLvl); SAL_INFO_IF( xVar->GetName() == "Cells", "basic", "PopVar: Name equals 'Cells'" ); // methods hold themselves in parameter 0 if( dynamic_cast<const SbxMethod *>(xVar.get()) != nullptr ) @@ -1061,13 +1034,13 @@ SbxVariable* SbiRuntime::GetTOS() return new SbxVariable; } #endif - return refExprStk->Get32( static_cast<sal_uInt32>(n) ); + return refExprStk->Get(static_cast<sal_uInt32>(n)); } void SbiRuntime::TOSMakeTemp() { - SbxVariable* p = refExprStk->Get32( nExprLvl - 1 ); + SbxVariable* p = refExprStk->Get(nExprLvl - 1); if ( p->GetType() == SbxEMPTY ) { p->Broadcast( SfxHintId::BasicDataWanted ); @@ -1084,13 +1057,13 @@ void SbiRuntime::TOSMakeTemp() pDflt->SetParent( nullptr ); p = new SbxVariable( *pDflt ); p->SetFlag( SbxFlagBits::ReadWrite ); - refExprStk->Put32( p, nExprLvl - 1 ); + refExprStk->Put(p, nExprLvl - 1); } else if( p->GetRefCount() != 1 ) { SbxVariable* pNew = new SbxVariable( *p ); pNew->SetFlag( SbxFlagBits::ReadWrite ); - refExprStk->Put32( pNew, nExprLvl - 1 ); + refExprStk->Put(pNew, nExprLvl - 1); } } @@ -1175,20 +1148,28 @@ 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)) { p->refEnd = reinterpret_cast<SbxVariable*>(pArray); - sal_Int32 nDims = pArray->GetDims32(); + sal_Int32 nDims = pArray->GetDims(); p->pArrayLowerBounds.reset( new sal_Int32[nDims] ); p->pArrayUpperBounds.reset( new sal_Int32[nDims] ); p->pArrayCurIndices.reset( new sal_Int32[nDims] ); sal_Int32 lBound, uBound; for( sal_Int32 i = 0 ; i < nDims ; i++ ) { - pArray->GetDim32( i+1, lBound, uBound ); + pArray->GetDim(i + 1, lBound, uBound); p->pArrayCurIndices[i] = p->pArrayLowerBounds[i] = lBound; p->pArrayUpperBounds[i] = uBound; } @@ -1201,14 +1182,22 @@ void SbiRuntime::PushForEach() } else if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj)) { - // XEnumerationAccess? + // XEnumerationAccess or XIndexAccess? Any aAny = pUnoObj->getUnoAny(); + Reference<XIndexAccess> xIndexAccess; Reference< XEnumerationAccess > xEnumerationAccess; if( aAny >>= xEnumerationAccess ) { p->xEnumeration = xEnumerationAccess->createEnumeration(); p->eForType = ForType::EachXEnumeration; } + // tdf#130307 - support for each loop for objects exposing XIndexAccess + else if (aAny >>= xIndexAccess) + { + p->eForType = ForType::EachXIndexAccess; + p->xIndexAccess = xIndexAccess; + p->nCurCollectionIndex = 0; + } else if ( isVBAEnabled() && pUnoObj->isNativeCOMObject() ) { uno::Reference< script::XInvocation > xInvocation; @@ -1277,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 ); @@ -1308,6 +1295,14 @@ void SbiRuntime::StepArith( SbxOperator eOp ) TOSMakeTemp(); SbxVariable* p2 = GetTOS(); + // tdf#144353 - do not compute any operation with a missing optional variable + if ((p1->GetType() == SbxERROR && IsMissing(p1.get(), 1)) + || (p2->GetType() == SbxERROR && IsMissing(p2, 1))) + { + Error(ERRCODE_BASIC_NOT_OPTIONAL); + return; + } + p2->ResetFlag( SbxFlagBits::Fixed ); p2->Compute( eOp, *p1 ); @@ -1318,6 +1313,12 @@ void SbiRuntime::StepUnary( SbxOperator eOp ) { TOSMakeTemp(); SbxVariable* p = GetTOS(); + // tdf#144353 - do not compute any operation with a missing optional variable + if (p->GetType() == SbxERROR && IsMissing(p, 1)) + { + Error(ERRCODE_BASIC_NOT_OPTIONAL); + return; + } p->Compute( eOp, *p ); } @@ -1326,6 +1327,14 @@ void SbiRuntime::StepCompare( SbxOperator eOp ) SbxVariableRef p1 = PopVar(); SbxVariableRef p2 = PopVar(); + // tdf#144353 - do not compare a missing optional variable + if ((p1->GetType() == SbxERROR && SbiRuntime::IsMissing(p1.get(), 1)) + || (p2->GetType() == SbxERROR && SbiRuntime::IsMissing(p2.get(), 1))) + { + SbxBase::SetError(ERRCODE_BASIC_NOT_OPTIONAL); + return; + } + // Make sure objects with default params have // values ( and type ) set as appropriate SbxDataType p1Type = p1->GetType(); @@ -1371,7 +1380,7 @@ void SbiRuntime::StepCompare( SbxOperator eOp ) // I dumbly follow the pattern :-/ if ( bVBAEnabled && ( p1->IsNull() || p2->IsNull() ) ) { - static SbxVariable* pNULL = [&]() { + static SbxVariable* pNULL = []() { SbxVariable* p = new SbxVariable; p->PutNull(); p->AddFirstRef(); @@ -1427,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(); } @@ -1532,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() ); @@ -1548,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 ); @@ -1606,6 +1596,13 @@ static bool checkUnoStructCopy( bool bVBA, SbxVariableRef const & refVal, SbxVar SbxDataType eVarType = refVar->GetType(); SbxDataType eValType = refVal->GetType(); + // tdf#144353 - do not assign a missing optional variable to a property + if (refVal->GetType() == SbxERROR && SbiRuntime::IsMissing(refVal.get(), 1)) + { + SbxBase::SetError(ERRCODE_BASIC_NOT_OPTIONAL); + return true; + } + if ( ( bVBA && ( eVarType == SbxEMPTY ) ) || !refVar->CanWrite() ) return false; @@ -1635,40 +1632,39 @@ static bool checkUnoStructCopy( bool bVBA, SbxVariableRef const & refVal, SbxVar aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny(); else return false; - if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT ) - { - refVar->SetType( SbxOBJECT ); - ErrCode eOldErr = SbxBase::GetError(); - // There are some circumstances when calling GetObject - // will trigger an error, we need to squash those here. - // Alternatively it is possible that the same scenario - // could overwrite and existing error. Lets prevent that - SbxObjectRef xVarObj = static_cast<SbxObject*>(refVar->GetObject()); - if ( eOldErr != ERRCODE_NONE ) - SbxBase::SetError( eOldErr ); - else - SbxBase::ResetError(); + if ( aAny.getValueType().getTypeClass() != TypeClass_STRUCT ) + return false; - SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>( xVarObj.get() ); + refVar->SetType( SbxOBJECT ); + ErrCode eOldErr = SbxBase::GetError(); + // There are some circumstances when calling GetObject + // will trigger an error, we need to squash those here. + // Alternatively it is possible that the same scenario + // could overwrite and existing error. Lets prevent that + SbxObjectRef xVarObj = static_cast<SbxObject*>(refVar->GetObject()); + if ( eOldErr != ERRCODE_NONE ) + SbxBase::SetError( eOldErr ); + else + SbxBase::ResetError(); - OUString sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName(); - OUString sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName(); + SbUnoStructRefObject* pUnoStructObj = dynamic_cast<SbUnoStructRefObject*>( xVarObj.get() ); - if ( pUnoStructObj ) - { - StructRefInfo aInfo = pUnoStructObj->getStructInfo(); - aInfo.setValue( aAny ); - } - else - { - SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny ); - // #70324: adopt ClassName - pNewUnoObj->SetClassName( sClassName ); - refVar->PutObject( pNewUnoObj ); - } - return true; + OUString sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName(); + OUString sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName(); + + if ( pUnoStructObj ) + { + StructRefInfo aInfo = pUnoStructObj->getStructInfo(); + aInfo.setValue( aAny ); } - return false; + else + { + SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny ); + // #70324: adopt ClassName + pNewUnoObj->SetClassName( sClassName ); + refVar->PutObject( pNewUnoObj ); + } + return true; } @@ -1744,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 ) {} @@ -1768,17 +1764,16 @@ typedef std::unordered_map< SbxVariable*, DimAsNewRecoverItem, namespace { -class GaDimAsNewRecoverHash : public rtl::Static<DimAsNewRecoverHash, GaDimAsNewRecoverHash> {}; +DimAsNewRecoverHash gaDimAsNewRecoverHash; } void removeDimAsNewRecoverItem( SbxVariable* pVar ) { - DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get(); - DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( pVar ); - if( it != rDimAsNewRecoverHash.end() ) + DimAsNewRecoverHash::iterator it = gaDimAsNewRecoverHash.find( pVar ); + if( it != gaDimAsNewRecoverHash.end() ) { - rDimAsNewRecoverHash.erase( it ); + gaDimAsNewRecoverHash.erase( it ); } } @@ -1786,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 ) { @@ -1949,9 +1944,8 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b if( xPrevVarObj.is() ) { // Object is overwritten with NULL, instantiate init object - DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get(); - DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( refVar.get() ); - if( it != rDimAsNewRecoverHash.end() ) + DimAsNewRecoverHash::iterator it = gaDimAsNewRecoverHash.find( refVar.get() ); + if( it != gaDimAsNewRecoverHash.end() ) { const DimAsNewRecoverItem& rItem = it->second; if( rItem.m_pClassModule != nullptr ) @@ -1984,16 +1978,15 @@ void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, b OUString aObjClass = pValObj->GetClassName(); SbClassModuleObject* pClassModuleObj = dynamic_cast<SbClassModuleObject*>( pValObjBase ); - DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get(); if( pClassModuleObj != nullptr ) { SbModule* pClassModule = pClassModuleObj->getClassModule(); - rDimAsNewRecoverHash[refVar.get()] = + gaDimAsNewRecoverHash[refVar.get()] = DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule ); } else if( aObjClass.equalsIgnoreAsciiCase( "Collection" ) ) { - rDimAsNewRecoverHash[refVar.get()] = + gaDimAsNewRecoverHash[refVar.get()] = DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), nullptr ); } } @@ -2091,7 +2084,7 @@ void SbiRuntime::StepRSET() } else { - aNewStr.append(std::u16string_view(aRefValString).substr(0, nVarStrLen)); + aNewStr.append(aRefValString.subView(0, nVarStrLen)); } refVar->PutString(aNewStr.makeStringAndClear()); @@ -2139,7 +2132,7 @@ void SbiRuntime::DimImpl(const SbxVariableRef& refVar) SbxArray* pDims = refVar->GetParameters(); // must have an even number of arguments // have in mind that Arg[0] does not count! - if( pDims && !( pDims->Count32() & 1 ) ) + if (pDims && !(pDims->Count() & 1)) { StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR ); } @@ -2152,16 +2145,16 @@ void SbiRuntime::DimImpl(const SbxVariableRef& refVar) { refVar->ResetFlag( SbxFlagBits::VarToDim ); - for( sal_uInt32 i = 1; i < pDims->Count32(); ) + for (sal_uInt32 i = 1; i < pDims->Count();) { - sal_Int32 lb = pDims->Get32( i++ )->GetLong(); - sal_Int32 ub = pDims->Get32( i++ )->GetLong(); + sal_Int32 lb = pDims->Get(i++)->GetLong(); + sal_Int32 ub = pDims->Get(i++)->GetLong(); if( ub < lb ) { Error( ERRCODE_BASIC_OUT_OF_RANGE ); ub = lb; } - pArray->AddDim32( lb, ub ); + pArray->AddDim(lb, ub); if ( lb != ub ) { pArray->setHasFixedSize( true ); @@ -2172,7 +2165,7 @@ void SbiRuntime::DimImpl(const SbxVariableRef& refVar) { // #62867 On creating an array of the length 0, create // a dimension (like for Uno-Sequences of the length 0) - pArray->unoAddDim32( 0, -1 ); + pArray->unoAddDim(0, -1); } SbxFlagBits nSavFlags = refVar->GetFlags(); refVar->ResetFlag( SbxFlagBits::Fixed ); @@ -2208,11 +2201,11 @@ static void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, sa } else { - SbxVariable* pSource = pOldArray->Get32( pActualIndices ); + SbxVariable* pSource = pOldArray->Get(pActualIndices); if (pSource && pOldArray->GetRefCount() > 1) // tdf#134692: old array will stay alive after the redim - we need to copy deep pSource = new SbxVariable(*pSource); - pNewArray->Put32(pSource, pActualIndices); + pNewArray->Put(pSource, pActualIndices); } } } @@ -2227,8 +2220,8 @@ static bool implRestorePreservedArray(SbxDimArray* pNewArray, SbxArrayRef& rrefR if (rrefRedimpArray) { SbxDimArray* pOldArray = static_cast<SbxDimArray*>(rrefRedimpArray.get()); - const sal_Int32 nDimsNew = pNewArray->GetDims32(); - const sal_Int32 nDimsOld = pOldArray->GetDims32(); + const sal_Int32 nDimsNew = pNewArray->GetDims(); + const sal_Int32 nDimsOld = pOldArray->GetDims(); if (nDimsOld != nDimsNew) { @@ -2249,8 +2242,8 @@ static bool implRestorePreservedArray(SbxDimArray* pNewArray, SbxArrayRef& rrefR { sal_Int32 lBoundNew, uBoundNew; sal_Int32 lBoundOld, uBoundOld; - pNewArray->GetDim32(i, lBoundNew, uBoundNew); - pOldArray->GetDim32(i, lBoundOld, uBoundOld); + pNewArray->GetDim(i, lBoundNew, uBoundNew); + pOldArray->GetDim(i, lBoundOld, uBoundOld); lBoundNew = std::max(lBoundNew, lBoundOld); uBoundNew = std::min(uBoundNew, uBoundOld); sal_Int32 j = i - 1; @@ -2262,7 +2255,7 @@ static bool implRestorePreservedArray(SbxDimArray* pNewArray, SbxArrayRef& rrefR // Optimization: pre-allocate underlying container if (bNeedsPreallocation) - pNewArray->Put32(nullptr, pUpperBounds.get()); + pNewArray->Put(nullptr, pUpperBounds.get()); // Copy data from old array by going recursively through all dimensions // (It would be faster to work on the flat internal data array of an @@ -2452,7 +2445,7 @@ void SbiRuntime::StepARGV() SbxVariable* pRes = new SbxVariable( *pVal ); pVal = pRes; } - refArgv->Put32( pVal.get(), nArgc++ ); + refArgv->Put(pVal.get(), nArgc++); } } @@ -2629,20 +2622,20 @@ void SbiRuntime::StepCASE() refCaseStk = new SbxArray; } SbxVariableRef xVar = PopVar(); - refCaseStk->Put32( xVar.get(), refCaseStk->Count32() ); + refCaseStk->Put(xVar.get(), refCaseStk->Count()); } // end CASE: free variable void SbiRuntime::StepENDCASE() { - if( !refCaseStk.is() || !refCaseStk->Count32() ) + if (!refCaseStk.is() || !refCaseStk->Count()) { StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR ); } else { - refCaseStk->Remove( refCaseStk->Count32() - 1 ); + refCaseStk->Remove(refCaseStk->Count() - 1); } } @@ -2717,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() ); } @@ -2737,12 +2730,12 @@ void SbiRuntime::StepWRITE() // write TOS OUString s; if( ch ) { - s += OUString(ch); + s += OUStringChar(ch); } s += p->GetOUString(); if( ch ) { - s += OUString(ch); + s += OUStringChar(ch); } pIosys->Write( s ); Error( pIosys->GetError() ); @@ -2817,13 +2810,15 @@ void SbiRuntime::StepERROR() 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 ) ); + OUString aStr = pImg->GetString(nOp1, &eTypeStr); // also allow , !!! sal_Int32 iComma = aStr.indexOf(','); if( iComma >= 0 ) { - aStr = aStr.replaceAt(iComma, 1, "."); + aStr = aStr.replaceAt(iComma, 1, u"."); } sal_Int32 nParseEnd = 0; rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; @@ -2833,6 +2828,8 @@ void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 ) SbxDataType eType = SbxDOUBLE; if ( nParseEnd < aStr.getLength() ) { + // tdf#143707 - Check if there was a data type character after the numeric constant, + // added by older versions of the fix of the default values for strings. switch ( aStr[nParseEnd] ) { // See GetSuffixType in basic/source/comp/scanner.cxx for type characters @@ -2840,8 +2837,16 @@ void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 ) case '&': eType = SbxLONG; break; case '!': eType = SbxSINGLE; break; case '@': eType = SbxCURRENCY; break; + // tdf#142460 - properly handle boolean values in string pool + case 'b': eType = SbxBOOL; break; } } + // tdf#143707 - if the data type character is different from the default value, it was added + // in basic/source/comp/symtbl.cxx. Hence, change the type of the numeric constant to be loaded. + else if (eTypeStr != SbxSTRING) + { + eType = eTypeStr; + } SbxVariable* p = new SbxVariable( eType ); p->PutDouble( n ); // tdf#133913 - create variable with Variant/Type in order to prevent type conversion errors @@ -2854,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 ); } @@ -2876,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 @@ -2890,8 +2895,8 @@ void SbiRuntime::StepARGN( sal_uInt32 nOp1 ) SbxVariable* pRes = new SbxVariable( *pVal ); pVal = pRes; } - refArgv->Put32( pVal.get(), nArgc ); - refArgv->PutAlias32( aAlias, nArgc++ ); + refArgv->Put(pVal.get(), nArgc); + refArgv->PutAlias(aAlias, nArgc++); } } @@ -2905,7 +2910,7 @@ void SbiRuntime::StepARGTYP( sal_uInt32 nOp1 ) { bool bByVal = (nOp1 & 0x8000) != 0; // Is BYVAL requested? SbxDataType t = static_cast<SbxDataType>(nOp1 & 0x7FFF); - SbxVariable* pVar = refArgv->Get32( refArgv->Count32() - 1 ); // last Arg + SbxVariable* pVar = refArgv->Get(refArgv->Count() - 1); // last Arg // check BYVAL if( pVar->GetRefCount() > 2 ) // 2 is normal for BYVAL @@ -2916,7 +2921,7 @@ void SbiRuntime::StepARGTYP( sal_uInt32 nOp1 ) // Call by Value is requested -> create a copy pVar = new SbxVariable( *pVar ); pVar->SetFlag( SbxFlagBits::ReadWrite ); - refExprStk->Put32( pVar, refArgv->Count32() - 1 ); + refExprStk->Put(pVar, refArgv->Count() - 1); } else pVar->SetFlag( SbxFlagBits::Reference ); // Ref-Flag for DllMgr @@ -2975,24 +2980,54 @@ void SbiRuntime::StepJUMP( sal_uInt32 nOp1 ) pCode = pImg->GetCode() + nOp1; } +bool SbiRuntime::EvaluateTopOfStackAsBool() +{ + SbxVariableRef tos = PopVar(); + // In a test e.g. If Null then + // will evaluate Null will act as if False + if ( bVBAEnabled && tos->IsNull() ) + { + 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 + //the underlying value as Bool. Here, we're checking rather that + //it is not null + return tos->GetObject(); + } + else + { + return tos->GetBool(); + } +} + // evaluate TOS, conditional jump (+target) void SbiRuntime::StepJUMPT( sal_uInt32 nOp1 ) { - SbxVariableRef p = PopVar(); - if( p->GetBool() ) + if ( EvaluateTopOfStackAsBool() ) + { StepJUMP( nOp1 ); + } } // evaluate TOS, conditional jump (+target) void SbiRuntime::StepJUMPF( sal_uInt32 nOp1 ) { - SbxVariableRef p = PopVar(); - // In a test e.g. If Null then - // will evaluate Null will act as if False - if( ( bVBAEnabled && p->IsNull() ) || !p->GetBool() ) + if ( !EvaluateTopOfStackAsBool() ) + { StepJUMP( nOp1 ); + } } // evaluate TOS, jump into JUMP-table (+MaxVal) @@ -3074,7 +3109,7 @@ void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 ) else { SbxDimArray* pArray = reinterpret_cast<SbxDimArray*>(p->refEnd.get()); - sal_Int32 nDims = pArray->GetDims32(); + sal_Int32 nDims = pArray->GetDims(); // Empty array? if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] ) @@ -3082,7 +3117,7 @@ void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 ) bEndLoop = true; break; } - SbxVariable* pVal = pArray->Get32( p->pArrayCurIndices.get() ); + SbxVariable* pVal = pArray->Get(p->pArrayCurIndices.get()); *(p->refVar) = *pVal; bool bFoundNext = false; @@ -3115,10 +3150,10 @@ void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 ) BasicCollection* pCollection = static_cast<BasicCollection*>(pForStk->refEnd.get()); SbxArrayRef xItemArray = pCollection->xItemArray; - sal_Int32 nCount = xItemArray->Count32(); + sal_Int32 nCount = xItemArray->Count(); if( pForStk->nCurCollectionIndex < nCount ) { - SbxVariable* pRes = xItemArray->Get32( pForStk->nCurCollectionIndex ); + SbxVariable* pRes = xItemArray->Get(pForStk->nCurCollectionIndex); pForStk->nCurCollectionIndex++; (*pForStk->refVar) = *pRes; } @@ -3149,6 +3184,29 @@ void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 ) } break; } + // tdf#130307 - support for each loop for objects exposing XIndexAccess + case ForType::EachXIndexAccess: + { + SbiForStack* p = pForStk; + if (!p->xIndexAccess) + { + SbxBase::SetError(ERRCODE_BASIC_CONVERSION); + pForStk->eForType = ForType::Error; // terminate loop at the next iteration + } + else if (pForStk->nCurCollectionIndex < p->xIndexAccess->getCount()) + { + Any aElem = p->xIndexAccess->getByIndex(pForStk->nCurCollectionIndex); + pForStk->nCurCollectionIndex++; + SbxVariableRef xVar = new SbxVariable(SbxVARIANT); + unoToSbxValue(xVar.get(), aElem); + (*pForStk->refVar) = *xVar; + } + else + { + bEndLoop = true; + } + break; + } case ForType::Error: { // We are in Resume Next mode after failed loop initialization @@ -3168,13 +3226,13 @@ void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 ) void SbiRuntime::StepCASETO( sal_uInt32 nOp1 ) { - if( !refCaseStk.is() || !refCaseStk->Count32() ) + if (!refCaseStk.is() || !refCaseStk->Count()) StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR ); else { SbxVariableRef xTo = PopVar(); SbxVariableRef xFrom = PopVar(); - SbxVariableRef xCase = refCaseStk->Get32( refCaseStk->Count32() - 1 ); + SbxVariableRef xCase = refCaseStk->Get(refCaseStk->Count() - 1); if( *xCase >= *xFrom && *xCase <= *xTo ) StepJUMP( nOp1 ); } @@ -3342,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 ) @@ -3364,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 ); @@ -3377,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) @@ -3431,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("[") ) @@ -3531,7 +3589,7 @@ SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt { pElem->SetName( aName ); } - refLocals->Put32( pElem, refLocals->Count32() ); + refLocals->Put(pElem, refLocals->Count()); } } @@ -3583,7 +3641,7 @@ SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt pElem->SetFlag( SbxFlagBits::Fixed ); } pElem->SetName( aName ); - refLocals->Put32( pElem, refLocals->Count32() ); + refLocals->Put(pElem, refLocals->Count()); } } } @@ -3668,18 +3726,27 @@ SbxBase* SbiRuntime::FindElementExtern( const OUString& rName ) } if ( !pElem && pMeth ) { - // for statics, set the method's name in front - OUString aMethName = pMeth->GetName() + ":" + rName; - pElem = pMod->Find(aMethName, SbxClassType::DontCare); + const OUString aMethName = pMeth->GetName(); + // tdf#57308 - check if the name is the current method instance + if (pMeth->GetName() == rName) + { + pElem = pMeth; + } + else + { + // for statics, set the method's name in front + pElem = pMod->Find(aMethName + ":" + rName, SbxClassType::DontCare); + } } + // search in parameter list if( !pElem && pMeth ) { SbxInfo* pInfo = pMeth->GetInfo(); if( pInfo && refParams.is() ) { - sal_uInt32 nParamCount = refParams->Count32(); + sal_uInt32 nParamCount = refParams->Count(); assert(nParamCount <= std::numeric_limits<sal_uInt16>::max()); sal_uInt16 j = 1; const SbxParamInfo* pParam = pInfo->GetParam( j ); @@ -3695,7 +3762,7 @@ SbxBase* SbiRuntime::FindElementExtern( const OUString& rName ) } else { - pElem = refParams->Get32( j ); + pElem = refParams->Get(j); } break; } @@ -3726,10 +3793,10 @@ void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 ) } bool bHasNamed = false; sal_uInt32 i; - sal_uInt32 nArgCount = refArgv->Count32(); + sal_uInt32 nArgCount = refArgv->Count(); for( i = 1 ; i < nArgCount ; i++ ) { - if( !refArgv->GetAlias32(i).isEmpty() ) + if (!refArgv->GetAlias(i).isEmpty()) { bHasNamed = true; break; } @@ -3761,13 +3828,13 @@ void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 ) OUString* pNames = pArg->getNames().getArray(); for( i = 1 ; i < nArgCount ; i++ ) { - SbxVariable* pVar = refArgv->Get32( i ); - OUString aName = refArgv->GetAlias32(i); + SbxVariable* pVar = refArgv->Get(i); + OUString aName = refArgv->GetAlias(i); if (!aName.isEmpty()) { pNames[i] = aName; } - pArg->Put32( pVar, nCurPar++ ); + pArg->Put(pVar, nCurPar++); } refArgv = pArg; } @@ -3816,8 +3883,8 @@ void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 ) SbxArray* pArg = new SbxArray; for( i = 1 ; i < nArgCount ; i++ ) { - SbxVariable* pVar = refArgv->Get32( i ); - OUString aName = refArgv->GetAlias32(i); + SbxVariable* pVar = refArgv->Get(i); + OUString aName = refArgv->GetAlias(i); if (!aName.isEmpty()) { // nCurPar is set to the found parameter @@ -3837,13 +3904,13 @@ void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 ) Error( ERRCODE_BASIC_NAMED_NOT_FOUND ); break; } } - pArg->Put32( pVar, nCurPar++ ); + pArg->Put(pVar, nCurPar++); } refArgv = pArg; } } // own var as parameter 0 - refArgv->Put32( p, 0 ); + refArgv->Put(p, 0); p->SetParameters( refArgv.get() ); PopArgv(); } @@ -3882,7 +3949,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) } else { - pElem = pArray->Get32( pPar->Get32( 1 )->GetInteger() ); + pElem = pArray->Get(pPar->Get(1)->GetInteger()); } } } @@ -3890,7 +3957,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) // #42940, set parameter 0 to NULL so that var doesn't contain itself if( pPar ) { - pPar->Put32( nullptr, 0 ); + pPar->Put(nullptr, 0); } } // consider index-access for UnoObjects @@ -3916,7 +3983,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) { if( xIndexAccess.is() ) { - sal_uInt32 nParamCount = pPar->Count32() - 1; + sal_uInt32 nParamCount = pPar->Count() - 1; if( nParamCount != 1 ) { StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT ); @@ -3924,7 +3991,7 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) } // get index - sal_Int32 nIndex = pPar->Get32( 1 )->GetLong(); + sal_Int32 nIndex = pPar->Get(1)->GetLong(); Reference< XInterface > xRet; try { @@ -4008,12 +4075,12 @@ SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) } // #42940, set parameter 0 to NULL so that var doesn't contain itself - pPar->Put32( nullptr, 0 ); + pPar->Put(nullptr, 0); } else if (BasicCollection* pCol = dynamic_cast<BasicCollection*>(pObj.get())) { pElem = new SbxVariable( SbxVARIANT ); - pPar->Put32( pElem, 0 ); + pPar->Put(pElem, 0); pCol->CollItem( pPar ); } } @@ -4120,7 +4187,7 @@ void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 ) SbxVariable* pVar; // #57915 solve missing in a cleaner way - sal_uInt32 nParamCount = refParams->Count32(); + sal_uInt32 nParamCount = refParams->Count(); if( nIdx >= nParamCount ) { sal_uInt16 iLoop = nIdx; @@ -4130,11 +4197,11 @@ void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 ) pVar->PutErr( 448 ); // like in VB: Error-Code 448 (ERRCODE_BASIC_NAMED_NOT_FOUND) // tdf#79426, tdf#125180 - add additional information about a missing parameter SetIsMissing( pVar ); - refParams->Put32( pVar, iLoop ); + refParams->Put(pVar, iLoop); iLoop--; } } - pVar = refParams->Get32( nIdx ); + pVar = refParams->Get(nIdx); // tdf#79426, tdf#125180 - check for optionals only if the parameter is actually missing if( pVar->GetType() == SbxERROR && IsMissing( pVar, 1 ) && nIdx ) @@ -4155,16 +4222,22 @@ void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 ) sal_uInt16 nDefaultId = static_cast<sal_uInt16>(pParam->nUserData & 0x0ffff); if( nDefaultId > 0 ) { - OUString aDefaultStr = pImg->GetString( nDefaultId ); + // tdf#143707 - check if the data type character was added after the string + // termination symbol, and convert the variable if it was present. The + // data type character was added in basic/source/comp/symtbl.cxx. + SbxDataType eTypeStr; + OUString aDefaultStr = pImg->GetString( nDefaultId, &eTypeStr ); pVar = new SbxVariable(pParam-> eType); pVar->PutString( aDefaultStr ); - refParams->Put32( pVar, nIdx ); + if (eTypeStr != SbxSTRING) + pVar->Convert(eTypeStr); + refParams->Put(pVar, nIdx); } else if ( SbiRuntime::isVBAEnabled() && eType != SbxVARIANT ) { // tdf#36737 - initialize the parameter with the default value of its type pVar = new SbxVariable( pParam->eType ); - refParams->Put32( pVar, nIdx ); + refParams->Put(pVar, nIdx); } bOpt = true; } @@ -4188,14 +4261,14 @@ void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 ) void SbiRuntime::StepCASEIS( sal_uInt32 nOp1, sal_uInt32 nOp2 ) { - if( !refCaseStk.is() || !refCaseStk->Count32() ) + if (!refCaseStk.is() || !refCaseStk->Count()) { StarBASIC::FatalError( ERRCODE_BASIC_INTERNAL_ERROR ); } else { SbxVariableRef xComp = PopVar(); - SbxVariableRef xCase = refCaseStk->Get32( refCaseStk->Count32() - 1 ); + SbxVariableRef xCase = refCaseStk->Get(refCaseStk->Count() - 1); if( xCase->Compare( static_cast<SbxOperator>(nOp2), *xComp ) ) { StepJUMP( nOp1 ); @@ -4208,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 ) { @@ -4226,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 ) { @@ -4255,7 +4328,7 @@ void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 ) } else if( nExprLvl ) { - SbxVariable* p = refExprStk->Get32( 0 ); + SbxVariable* p = refExprStk->Get(0); if( p->GetRefCount() > 1 && refLocals.is() && refLocals->Find( p->GetName(), p->GetClass() ) ) { @@ -4316,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 ); @@ -4359,21 +4432,21 @@ 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 ) ) ); - SbxObject *pObj = SbxBase::CreateObject( aClass ); + OUString aClass( pImg->GetString( nOp2 ) ); + SbxObjectRef pObj = SbxBase::CreateObject( aClass ); if( !pObj ) { Error( ERRCODE_BASIC_INVALID_OBJECT ); } 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 ); - SbxVariable* pNew = new SbxVariable; - pNew->PutObject( pObj ); - PushVar( pNew ); + SbxVariableRef pNew = new SbxVariable; + pNew->PutObject( pObj.get() ); + PushVar( pNew.get() ); } } @@ -4406,21 +4479,21 @@ void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) if (!pArray) return; - const sal_Int32 nDims = pArray->GetDims32(); + const sal_Int32 nDims = pArray->GetDims(); sal_Int32 nTotalSize = nDims > 0 ? 1 : 0; // must be a one-dimensional array sal_Int32 nLower, nUpper; for( sal_Int32 i = 0 ; i < nDims ; ++i ) { - pArray->GetDim32( i+1, nLower, nUpper ); + pArray->GetDim(i + 1, nLower, nUpper); const sal_Int32 nSize = nUpper - nLower + 1; nTotalSize *= nSize; } // Optimization: pre-allocate underlying container if (nTotalSize > 0) - pArray->SbxArray::GetRef32(nTotalSize - 1); + pArray->SbxArray::GetRef(nTotalSize - 1); // First, fill those parts of the array that are preserved bool bWasError = false; @@ -4429,13 +4502,13 @@ 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 ) { - if (!bRestored || !pArray->SbxArray::GetRef32(i)) // For those left unset after preserve + if (!bRestored || !pArray->SbxArray::GetRef(i)) // For those left unset after preserve { - SbxObject* pClassObj = SbxBase::CreateObject(aClass); + SbxObjectRef pClassObj = SbxBase::CreateObject(aClass); if (!pClassObj) { Error(ERRCODE_BASIC_INVALID_OBJECT); @@ -4444,11 +4517,11 @@ 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); - pArray->SbxArray::Put32(pClassObj, i); + pArray->SbxArray::Put(pClassObj.get(), i); } } } @@ -4456,18 +4529,18 @@ 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 ) ); - SbxObject* pCopyObj = createUserTypeImpl( aClass ); + SbxObjectRef pCopyObj = createUserTypeImpl( aClass ); if( pCopyObj ) { pCopyObj->SetName( aName ); } - SbxVariable* pNew = new SbxVariable; - pNew->PutObject( pCopyObj ); + SbxVariableRef pNew = new SbxVariable; + pNew->PutObject( pCopyObj.get() ); pNew->SetDeclareClassName( aClass ); - PushVar( pNew ); + PushVar( pNew.get() ); } void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt32 nOp2 ) @@ -4486,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()); } @@ -4506,14 +4579,14 @@ 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); SbxVariable* p = new SbxVariable( t ); p->SetName( aName ); implHandleSbxFlags( p, t, nOp2 ); - refLocals->Put32( p, refLocals->Count32() ); + refLocals->Put(p, refLocals->Count()); } } @@ -4521,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 ); @@ -4573,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 @@ -4633,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 ); @@ -4658,7 +4731,7 @@ SbxVariable* SbiRuntime::StepSTATIC_Impl( } p->SetName( aName ); implHandleSbxFlags( p, t, nOp2 ); - pStatics->Put32( p, pStatics->Count32() ); + pStatics->Put(p, pStatics->Count()); } } return p; @@ -4666,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: */ |