summaryrefslogtreecommitdiff
path: root/basic/source/runtime/runtime.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/runtime/runtime.cxx')
-rw-r--r--basic/source/runtime/runtime.cxx691
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: */