1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: step2.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #include "runtime.hxx"
39 #include "sbintern.hxx"
40 #include "sbunoobj.hxx"
41 #include "opcodes.hxx"
43 #include <com/sun/star/container/XIndexAccess.hpp>
44 #include <com/sun/star/script/XDefaultMethod.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/uno/Any.hxx>
47 #include <comphelper/processfactory.hxx>
49 using namespace com::sun::star::uno
;
50 using namespace com::sun::star::container
;
51 using namespace com::sun::star::lang
;
52 using namespace com::sun::star::beans
;
53 using namespace com::sun::star::script
;
55 using com::sun::star::uno::Reference
;
57 // Suchen eines Elements
58 // Die Bits im String-ID:
59 // 0x8000 - Argv ist belegt
61 SbxVariable
* SbiRuntime::FindElement
62 ( SbxObject
* pObj
, UINT32 nOp1
, UINT32 nOp2
, SbError nNotFound
, BOOL bLocal
, BOOL bStatic
)
64 bool bIsVBAInterOp
= SbiRuntime::isVBAEnabled();
67 StarBASIC
* pMSOMacroRuntimeLib
= GetSbData()->pMSOMacroRuntimLib
;
68 if( pMSOMacroRuntimeLib
!= NULL
)
69 pMSOMacroRuntimeLib
->ResetFlag( SBX_EXTSEARCH
);
72 SbxVariable
* pElem
= NULL
;
75 Error( SbERR_NO_OBJECT
);
76 pElem
= new SbxVariable
;
80 BOOL bFatalError
= FALSE
;
81 SbxDataType t
= (SbxDataType
) nOp2
;
82 String
aName( pImg
->GetString( static_cast<short>( nOp1
& 0x7FFF ) ) );
83 // Hacky capture of Evaluate [] syntax
84 // this should be tackled I feel at the pcode level
85 if ( bIsVBAInterOp
&& aName
.Search('[') == 0 )
90 String sArg
= aName
.Copy( 1, aName
.Len() - 2 );
91 SbxVariable
* p
= new SbxVariable
;
96 nOp1
= nOp1
| 0x8000; // indicate params are present
97 aName
= String::CreateFromAscii("Evaluate");
104 pElem
= pMeth
->GetStatics()->Find( aName
, SbxCLASS_DONTCARE
);
108 pElem
= refLocals
->Find( aName
, SbxCLASS_DONTCARE
);
112 // Die RTL brauchen wir nicht mehr zu durchsuchen!
113 BOOL bSave
= rBasic
.bNoRtl
;
114 rBasic
.bNoRtl
= TRUE
;
115 pElem
= pObj
->Find( aName
, SbxCLASS_DONTCARE
);
117 // #110004, #112015: Make private really private
118 if( bLocal
&& pElem
) // Local as flag for global search
120 if( pElem
->IsSet( SBX_PRIVATE
) )
122 SbiInstance
* pInst_
= pINST
;
123 if( pInst_
&& pInst_
->IsCompatibility() && pObj
!= pElem
->GetParent() )
124 pElem
= NULL
; // Found but in wrong module!
126 // Interfaces: Use SBX_EXTFOUND
129 rBasic
.bNoRtl
= bSave
;
131 // Ist es ein globaler Uno-Bezeichner?
132 if( bLocal
&& !pElem
)
134 bool bSetName
= true; // preserve normal behaviour
136 // i#i68894# if VBAInterOp favour searching vba globals
137 // over searching for uno classess
140 // Try Find in VBA symbols space
141 pElem
= rBasic
.VBAFind( aName
, SbxCLASS_DONTCARE
);
143 bSetName
= false; // don't overwrite uno name
145 pElem
= VBAConstantHelper::instance().getVBAConstant( aName
);
147 // #72382 VORSICHT! Liefert jetzt wegen unbekannten
148 // Modulen IMMER ein Ergebnis!
149 SbUnoClass
* pUnoClass
= findUnoClass( aName
);
152 pElem
= new SbxVariable( t
);
153 SbxValues
aRes( SbxOBJECT
);
154 aRes
.pObj
= pUnoClass
;
155 pElem
->SbxVariable::Put( aRes
);
158 // #62939 Wenn eine Uno-Klasse gefunden wurde, muss
159 // das Wrapper-Objekt gehalten werden, da sonst auch
160 // die Uno-Klasse, z.B. "stardiv" immer wieder neu
161 // aus der Registry gelesen werden muss
164 // #63774 Darf nicht mit gespeichert werden!!!
165 pElem
->SetFlag( SBX_DONTSTORE
);
166 pElem
->SetFlag( SBX_NO_MODIFY
);
168 // #72382 Lokal speichern, sonst werden alle implizit
169 // deklarierten Vars automatisch global !
171 pElem
->SetName( aName
);
172 refLocals
->Put( pElem
, refLocals
->Count() );
178 // Nicht da und nicht im Objekt?
179 // Hat das Ding Parameter, nicht einrichten!
182 // ALT: StarBASIC::FatalError( nNotFound );
184 // Sonst, falls keine Parameter sind, anderen Error Code verwenden
185 if( !bLocal
|| pImg
->GetFlag( SBIMG_EXPLICIT
) )
187 // #39108 Bei explizit und als ELEM immer ein Fatal Error
190 // Falls keine Parameter sind, anderen Error Code verwenden
191 if( !( nOp1
& 0x8000 ) && nNotFound
== SbERR_PROC_UNDEFINED
)
192 nNotFound
= SbERR_VAR_UNDEFINED
;
196 // #39108 Statt FatalError zu setzen, Dummy-Variable liefern
197 if( !xDummyVar
.Is() )
198 xDummyVar
= new SbxVariable( SbxVARIANT
);
201 // Parameter von Hand loeschen
204 // Normalen Error setzen
205 Error( nNotFound
, aName
);
210 pElem
= StepSTATIC_Impl( aName
, t
);
213 // Sonst Variable neu anlegen
214 pElem
= new SbxVariable( t
);
215 if( t
!= SbxVARIANT
)
216 pElem
->SetFlag( SBX_FIXED
);
217 pElem
->SetName( aName
);
218 refLocals
->Put( pElem
, refLocals
->Count() );
223 // #39108 Args koennen schon geloescht sein!
225 SetupArgs( pElem
, nOp1
);
226 // Ein bestimmter Call-Type wurde gewuenscht, daher muessen
227 // wir hier den Typ setzen und das Ding anfassen, um den
228 // korrekten Returnwert zu erhalten!
229 if( pElem
->IsA( TYPE(SbxMethod
) ) )
231 // Soll der Typ konvertiert werden?
232 SbxDataType t2
= pElem
->GetType();
234 if( !( pElem
->GetFlags() & SBX_FIXED
) )
236 if( t
!= SbxVARIANT
&& t
!= t2
&&
237 t
>= SbxINTEGER
&& t
<= SbxSTRING
)
238 pElem
->SetType( t
), bSet
= TRUE
;
240 // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen
241 SbxVariableRef refTemp
= pElem
;
243 // Moegliche Reste vom letzten Aufruf der SbxMethod beseitigen
244 // Vorher Schreiben freigeben, damit kein Error gesetzt wird.
245 USHORT nSavFlags
= pElem
->GetFlags();
246 pElem
->SetFlag( SBX_READWRITE
| SBX_NO_BROADCAST
);
247 pElem
->SbxValue::Clear();
248 pElem
->SetFlags( nSavFlags
);
250 // Erst nach dem Setzen anfassen, da z.B. LEFT()
251 // den Unterschied zwischen Left$() und Left() kennen muss
253 // AB 12.8.96: Da in PopVar() die Parameter von Methoden weggehauen
254 // werden, muessen wir hier explizit eine neue SbxMethod anlegen
255 SbxVariable
* pNew
= new SbxMethod( *((SbxMethod
*)pElem
) ); // das ist der Call!
256 //ALT: SbxVariable* pNew = new SbxVariable( *pElem ); // das ist der Call!
258 pElem
->SetParameters(0); // sonst bleibt Ref auf sich selbst
259 pNew
->SetFlag( SBX_READWRITE
);
261 // den Datentypen zuruecksetzen?
263 pElem
->SetType( t2
);
266 // Index-Access bei UnoObjekten beruecksichtigen
267 // definitely we want this for VBA where properties are often
268 // collections ( which need index access ), but lets only do
269 // this if we actually have params following
270 else if( bVBAEnabled
&& pElem
->ISA(SbUnoProperty
) && pElem
->GetParameters() )
272 // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen
273 SbxVariableRef refTemp
= pElem
;
275 // Variable kopieren und dabei den Notify aufloesen
276 SbxVariable
* pNew
= new SbxVariable( *((SbxVariable
*)pElem
) ); // das ist der Call!
277 pElem
->SetParameters( NULL
); // sonst bleibt Ref auf sich selbst
281 return CheckArray( pElem
);
284 // Find-Funktion ueber Name fuer aktuellen Scope (z.B. Abfrage aus BASIC-IDE)
285 SbxBase
* SbiRuntime::FindElementExtern( const String
& rName
)
287 // Hinweis zu #35281#: Es darf nicht davon ausgegangen werden, dass
288 // pMeth != null, da im RunInit noch keine gesetzt ist.
290 SbxVariable
* pElem
= NULL
;
291 if( !pMod
|| !rName
.Len() )
296 pElem
= refLocals
->Find( rName
, SbxCLASS_DONTCARE
);
299 if ( !pElem
&& pMeth
)
301 // Bei Statics, Name der Methode davor setzen
302 String aMethName
= pMeth
->GetName();
305 pElem
= pMod
->Find(aMethName
, SbxCLASS_DONTCARE
);
308 // In Parameter-Liste suchen
309 if( !pElem
&& pMeth
)
311 SbxInfo
* pInfo
= pMeth
->GetInfo();
312 if( pInfo
&& refParams
)
314 USHORT nParamCount
= refParams
->Count();
316 const SbxParamInfo
* pParam
= pInfo
->GetParam( j
);
319 if( pParam
->aName
.EqualsIgnoreCaseAscii( rName
) )
321 if( j
>= nParamCount
)
323 // Parameter is missing
324 pElem
= new SbxVariable( SbxSTRING
);
325 pElem
->PutString( String( RTL_CONSTASCII_USTRINGPARAM("<missing parameter>" ) ) );
329 pElem
= refParams
->Get( j
);
333 pParam
= pInfo
->GetParam( ++j
);
341 // RTL nicht durchsuchen!
342 BOOL bSave
= rBasic
.bNoRtl
;
343 rBasic
.bNoRtl
= TRUE
;
344 pElem
= pMod
->Find( rName
, SbxCLASS_DONTCARE
);
345 rBasic
.bNoRtl
= bSave
;
351 // Argumente eines Elements setzen
352 // Dabei auch die Argumente umsetzen, falls benannte Parameter
355 void SbiRuntime::SetupArgs( SbxVariable
* p
, UINT32 nOp1
)
360 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
361 BOOL bHasNamed
= FALSE
;
363 USHORT nArgCount
= refArgv
->Count();
364 for( i
= 1 ; i
< nArgCount
; i
++ )
366 if( refArgv
->GetAlias( i
).Len() )
368 bHasNamed
= TRUE
; break;
373 // Wir haben mindestens einen benannten Parameter!
374 // Wir muessen also umsortieren
375 // Gibt es Parameter-Infos?
376 SbxInfo
* pInfo
= p
->GetInfo();
381 SbUnoMethod
* pUnoMethod
= PTR_CAST(SbUnoMethod
,p
);
382 SbUnoProperty
* pUnoProperty
= PTR_CAST(SbUnoProperty
,p
);
383 if( pUnoMethod
|| pUnoProperty
)
385 SbUnoObject
* pParentUnoObj
= PTR_CAST( SbUnoObject
,p
->GetParent() );
388 Any aUnoAny
= pParentUnoObj
->getUnoAny();
389 Reference
< XInvocation
> xInvocation
;
390 aUnoAny
>>= xInvocation
;
391 if( xInvocation
.is() ) // TODO: if( xOLEAutomation.is() )
396 AutomationNamedArgsSbxArray
* pArg
=
397 new AutomationNamedArgsSbxArray( nArgCount
);
398 ::rtl::OUString
* pNames
= pArg
->getNames().getArray();
399 for( i
= 1 ; i
< nArgCount
; i
++ )
401 SbxVariable
* pVar
= refArgv
->Get( i
);
402 const String
& rName
= refArgv
->GetAlias( i
);
405 pArg
->Put( pVar
, nCurPar
++ );
412 Error( SbERR_NO_NAMED_ARGS
);
417 SbxArray
* pArg
= new SbxArray
;
418 for( i
= 1 ; i
< nArgCount
; i
++ )
420 SbxVariable
* pVar
= refArgv
->Get( i
);
421 const String
& rName
= refArgv
->GetAlias( i
);
424 // nCurPar wird auf den gefundenen Parameter gesetzt
426 const SbxParamInfo
* pParam
= pInfo
->GetParam( j
);
429 if( pParam
->aName
.EqualsIgnoreCaseAscii( rName
) )
434 pParam
= pInfo
->GetParam( ++j
);
438 Error( SbERR_NAMED_NOT_FOUND
); break;
441 pArg
->Put( pVar
, nCurPar
++ );
446 // Eigene Var als Parameter 0
447 refArgv
->Put( p
, 0 );
448 p
->SetParameters( refArgv
);
452 p
->SetParameters( NULL
);
455 // Holen eines Array-Elements
457 SbxVariable
* SbiRuntime::CheckArray( SbxVariable
* pElem
)
459 // Falls wir ein Array haben, wollen wir bitte das Array-Element!
461 if( ( pElem
->GetType() & SbxARRAY
) && (SbxVariable
*)refRedim
!= pElem
)
463 SbxBase
* pElemObj
= pElem
->GetObject();
464 SbxDimArray
* pDimArray
= PTR_CAST(SbxDimArray
,pElemObj
);
465 pPar
= pElem
->GetParameters();
468 // Die Parameter koennen fehlen, wenn ein Array als
469 // Argument uebergeben wird.
471 pElem
= pDimArray
->Get( pPar
);
475 SbxArray
* pArray
= PTR_CAST(SbxArray
,pElemObj
);
480 Error( SbERR_OUT_OF_RANGE
);
481 pElem
= new SbxVariable
;
484 pElem
= pArray
->Get( pPar
->Get( 1 )->GetInteger() );
488 // #42940, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt
490 pPar
->Put( NULL
, 0 );
492 // Index-Access bei UnoObjekten beruecksichtigen
493 else if( pElem
->GetType() == SbxOBJECT
&& !pElem
->ISA(SbxMethod
) )
495 pPar
= pElem
->GetParameters();
498 // Ist es ein Uno-Objekt?
499 SbxBaseRef pObj
= (SbxBase
*)pElem
->GetObject();
502 if( pObj
->ISA(SbUnoObject
) )
504 SbUnoObject
* pUnoObj
= (SbUnoObject
*)(SbxBase
*)pObj
;
505 Any aAny
= pUnoObj
->getUnoAny();
507 if( aAny
.getValueType().getTypeClass() == TypeClass_INTERFACE
)
509 Reference
< XInterface
> x
= *(Reference
< XInterface
>*)aAny
.getValue();
510 Reference
< XIndexAccess
> xIndexAccess( x
, UNO_QUERY
);
513 // Haben wir Index-Access?
514 if( xIndexAccess
.is() )
516 UINT32 nParamCount
= (UINT32
)pPar
->Count() - 1;
517 if( nParamCount
!= 1 )
519 StarBASIC::Error( SbERR_BAD_ARGUMENT
);
524 INT32 nIndex
= pPar
->Get( 1 )->GetLong();
525 Reference
< XInterface
> xRet
;
528 Any aAny2
= xIndexAccess
->getByIndex( nIndex
);
529 TypeClass eType
= aAny2
.getValueType().getTypeClass();
530 if( eType
== TypeClass_INTERFACE
)
531 xRet
= *(Reference
< XInterface
>*)aAny2
.getValue();
533 catch (IndexOutOfBoundsException
&)
535 // Bei Exception erstmal immer von Konvertierungs-Problem ausgehen
536 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
539 // #57847 Immer neue Variable anlegen, sonst Fehler
540 // durch PutObject(NULL) bei ReadOnly-Properties.
541 pElem
= new SbxVariable( SbxVARIANT
);
546 // #67173 Kein Namen angeben, damit echter Klassen-Namen eintragen wird
548 SbxObjectRef xWrapper
= (SbxObject
*)new SbUnoObject( aName
, aAny
);
549 pElem
->PutObject( xWrapper
);
553 pElem
->PutObject( NULL
);
559 rtl::OUString sDefaultMethod
;
561 Reference
< XDefaultMethod
> xDfltMethod( x
, UNO_QUERY
);
563 if ( xDfltMethod
.is() )
564 sDefaultMethod
= xDfltMethod
->getDefaultMethodName();
565 else if( xIndexAccess
.is() )
566 sDefaultMethod
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getByIndex" ) );
568 if ( sDefaultMethod
.getLength() )
570 SbxVariable
* meth
= pUnoObj
->Find( sDefaultMethod
, SbxCLASS_METHOD
);
571 SbxVariableRef refTemp
= meth
;
574 meth
->SetParameters( pPar
);
575 SbxVariable
* pNew
= new SbxMethod( *(SbxMethod
*)meth
);
582 // #42940, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt
583 pPar
->Put( NULL
, 0 );
585 else if( pObj
->ISA(BasicCollection
) )
587 BasicCollection
* pCol
= (BasicCollection
*)(SbxBase
*)pObj
;
588 pElem
= new SbxVariable( SbxVARIANT
);
589 pPar
->Put( pElem
, 0 );
590 pCol
->CollItem( pPar
);
599 // Laden eines Elements aus der Runtime-Library (+StringID+Typ)
601 void SbiRuntime::StepRTL( UINT32 nOp1
, UINT32 nOp2
)
603 PushVar( FindElement( rBasic
.pRtl
, nOp1
, nOp2
, SbERR_PROC_UNDEFINED
, FALSE
) );
607 SbiRuntime::StepFIND_Impl( SbxObject
* pObj
, UINT32 nOp1
, UINT32 nOp2
, SbError nNotFound
, BOOL bLocal
, BOOL bStatic
)
610 refLocals
= new SbxArray
;
611 PushVar( FindElement( pObj
, nOp1
, nOp2
, nNotFound
, bLocal
, bStatic
) );
613 // Laden einer lokalen/globalen Variablen (+StringID+Typ)
615 void SbiRuntime::StepFIND( UINT32 nOp1
, UINT32 nOp2
)
617 StepFIND_Impl( pMod
, nOp1
, nOp2
, SbERR_PROC_UNDEFINED
, TRUE
);
620 // Search inside a class module (CM) to enable global search in time
621 void SbiRuntime::StepFIND_CM( UINT32 nOp1
, UINT32 nOp2
)
624 SbClassModuleObject
* pClassModuleObject
= PTR_CAST(SbClassModuleObject
,pMod
);
625 if( pClassModuleObject
)
626 pMod
->SetFlag( SBX_GBLSEARCH
);
628 StepFIND_Impl( pMod
, nOp1
, nOp2
, SbERR_PROC_UNDEFINED
, TRUE
);
630 if( pClassModuleObject
)
631 pMod
->ResetFlag( SBX_GBLSEARCH
);
634 void SbiRuntime::StepFIND_STATIC( UINT32 nOp1
, UINT32 nOp2
)
636 StepFIND_Impl( pMod
, nOp1
, nOp2
, SbERR_PROC_UNDEFINED
, TRUE
, TRUE
);
639 // Laden eines Objekt-Elements (+StringID+Typ)
640 // Das Objekt liegt auf TOS
642 void SbiRuntime::StepELEM( UINT32 nOp1
, UINT32 nOp2
)
644 // Liegt auf dem TOS ein Objekt?
645 SbxVariableRef pObjVar
= PopVar();
647 SbxObject
* pObj
= PTR_CAST(SbxObject
,(SbxVariable
*) pObjVar
);
650 SbxBase
* pObjVarObj
= pObjVar
->GetObject();
651 pObj
= PTR_CAST(SbxObject
,pObjVarObj
);
654 // #56368 Bei StepElem Referenz sichern, sonst koennen Objekte
655 // in Qualifizierungsketten wie ActiveComponent.Selection(0).Text
656 // zu fueh die Referenz verlieren
657 // #74254 Jetzt per Liste
659 SaveRef( (SbxVariable
*)pObj
);
661 PushVar( FindElement( pObj
, nOp1
, nOp2
, SbERR_NO_METHOD
, FALSE
) );
664 // Laden eines Parameters (+Offset+Typ)
665 // Wenn der Datentyp nicht stimmen sollte, eine Kopie anlegen
666 // Der Datentyp SbxEMPTY zeigt an, daa kein Parameter angegeben ist.
667 // Get( 0 ) darf EMPTY sein
669 void SbiRuntime::StepPARAM( UINT32 nOp1
, UINT32 nOp2
)
671 USHORT i
= static_cast<USHORT
>( nOp1
& 0x7FFF );
672 SbxDataType t
= (SbxDataType
) nOp2
;
675 // #57915 Missing sauberer loesen
676 USHORT nParamCount
= refParams
->Count();
677 if( i
>= nParamCount
)
680 while( iLoop
>= nParamCount
)
682 p
= new SbxVariable();
683 p
->PutErr( 448 ); // Wie in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND)
684 refParams
->Put( p
, iLoop
);
688 p
= refParams
->Get( i
);
690 if( p
->GetType() == SbxERROR
&& ( i
) )
691 //if( p->GetType() == SbxEMPTY && ( i ) )
693 // Wenn ein Parameter fehlt, kann er OPTIONAL sein
697 SbxInfo
* pInfo
= pMeth
->GetInfo();
700 const SbxParamInfo
* pParam
= pInfo
->GetParam( i
);
701 if( pParam
&& ( (pParam
->nFlags
& SBX_OPTIONAL
) != 0 ) )
704 USHORT nDefaultId
= sal::static_int_cast
< USHORT
>(
705 pParam
->nUserData
& 0xffff );
708 String aDefaultStr
= pImg
->GetString( nDefaultId
);
709 p
= new SbxVariable();
710 p
->PutString( aDefaultStr
);
711 refParams
->Put( p
, i
);
718 Error( SbERR_NOT_OPTIONAL
);
720 else if( t
!= SbxVARIANT
&& (SbxDataType
)(p
->GetType() & 0x0FFF ) != t
)
722 SbxVariable
* q
= new SbxVariable( t
);
727 refParams
->Put( p
, i
);
729 SetupArgs( p
, nOp1
);
730 PushVar( CheckArray( p
) );
733 // Case-Test (+True-Target+Test-Opcode)
735 void SbiRuntime::StepCASEIS( UINT32 nOp1
, UINT32 nOp2
)
737 if( !refCaseStk
|| !refCaseStk
->Count() )
738 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
741 SbxVariableRef xComp
= PopVar();
742 SbxVariableRef xCase
= refCaseStk
->Get( refCaseStk
->Count() - 1 );
743 if( xCase
->Compare( (SbxOperator
) nOp2
, *xComp
) )
748 // Aufruf einer DLL-Prozedur (+StringID+Typ)
749 // Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist
751 void SbiRuntime::StepCALL( UINT32 nOp1
, UINT32 nOp2
)
753 String aName
= pImg
->GetString( static_cast<short>( nOp1
& 0x7FFF ) );
754 SbxArray
* pArgs
= NULL
;
757 DllCall( aName
, aLibName
, pArgs
, (SbxDataType
) nOp2
, FALSE
);
763 // Aufruf einer DLL-Prozedur nach CDecl (+StringID+Typ)
764 // Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist
766 void SbiRuntime::StepCALLC( UINT32 nOp1
, UINT32 nOp2
)
768 String aName
= pImg
->GetString( static_cast<short>( nOp1
& 0x7FFF ) );
769 SbxArray
* pArgs
= NULL
;
772 DllCall( aName
, aLibName
, pArgs
, (SbxDataType
) nOp2
, TRUE
);
779 // Beginn eines Statements (+Line+Col)
781 void SbiRuntime::StepSTMNT( UINT32 nOp1
, UINT32 nOp2
)
783 // Wenn der Expr-Stack am Anfang einen Statements eine Variable enthaelt,
784 // hat ein Trottel X als Funktion aufgerufen, obwohl es eine Variable ist!
785 BOOL bFatalExpr
= FALSE
;
786 String sUnknownMethodName
;
791 SbxVariable
* p
= refExprStk
->Get( 0 );
792 if( p
->GetRefCount() > 1
793 && refLocals
.Is() && refLocals
->Find( p
->GetName(), p
->GetClass() ) )
795 sUnknownMethodName
= p
->GetName();
799 // Der Expr-Stack ist nun nicht mehr notwendig
802 // #56368 Kuenstliche Referenz fuer StepElem wieder freigeben,
803 // damit sie nicht ueber ein Statement hinaus erhalten bleibt
805 // #74254 Jetzt per Liste
808 // Wir muessen hier hart abbrechen, da sonst Zeile und Spalte nicht mehr
812 StarBASIC::FatalError( SbERR_NO_METHOD
, sUnknownMethodName
);
817 nLine
= static_cast<short>( nOp1
);
819 // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern
820 nCol1
= static_cast<short>( nOp2
& 0xFF );
822 // Suchen des naechsten STMNT-Befehls,
823 // um die End-Spalte dieses Statements zu setzen
824 // Searches of the next STMNT instruction,
825 // around the final column of this statement to set
829 const BYTE
* p
= pMod
->FindNextStmnt( pCode
, n1
, n2
);
834 // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern
835 nCol2
= (n2
& 0xFF) - 1;
839 // #29955 for-Schleifen-Ebene korrigieren, #67452 NICHT im Error-Handler sonst Chaos
842 // (Bei Sprüngen aus Schleifen tritt hier eine Differenz auf)
843 USHORT nExspectedForLevel
= static_cast<USHORT
>( nOp2
/ 0x100 );
845 nExspectedForLevel
= nExspectedForLevel
+ pGosubStk
->nStartForLvl
;
847 // Wenn der tatsaechliche For-Level zu klein ist, wurde aus
848 // einer Schleife heraus gesprungen -> korrigieren
849 while( nForLvl
> nExspectedForLevel
)
853 // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out
854 // Erklärung siehe bei _ImplGetBreakCallLevel.
855 if( pInst
->nCallLvl
<= pInst
->nBreakCallLvl
)
856 //if( nFlags & SbDEBUG_STEPINTO )
858 StarBASIC
* pStepBasic
= GetCurrentBasic( &rBasic
);
859 USHORT nNewFlags
= pStepBasic
->StepPoint( nLine
, nCol1
, nCol2
);
861 // Neuen BreakCallLevel ermitteln
862 pInst
->CalcBreakCallLevel( nNewFlags
);
865 // Breakpoints nur bei STMNT-Befehlen in neuer Zeile!
866 else if( ( nOp1
!= nOld
)
867 && ( nFlags
& SbDEBUG_BREAK
)
868 && pMod
->IsBP( static_cast<USHORT
>( nOp1
) ) )
870 StarBASIC
* pBreakBasic
= GetCurrentBasic( &rBasic
);
871 USHORT nNewFlags
= pBreakBasic
->BreakPoint( nLine
, nCol1
, nCol2
);
873 // Neuen BreakCallLevel ermitteln
874 pInst
->CalcBreakCallLevel( nNewFlags
);
876 //if( nNewFlags != SbDEBUG_CONTINUE )
877 // nFlags = nNewFlags;
881 // (+SvStreamFlags+Flags)
882 // Stack: Blocklaenge
886 void SbiRuntime::StepOPEN( UINT32 nOp1
, UINT32 nOp2
)
888 SbxVariableRef pName
= PopVar();
889 SbxVariableRef pChan
= PopVar();
890 SbxVariableRef pLen
= PopVar();
891 short nBlkLen
= pLen
->GetInteger();
892 short nChan
= pChan
->GetInteger();
893 ByteString
aName( pName
->GetString(), gsl_getSystemTextEncoding() );
894 pIosys
->Open( nChan
, aName
, static_cast<short>( nOp1
),
895 static_cast<short>( nOp2
), nBlkLen
);
896 Error( pIosys
->GetError() );
899 // Objekt kreieren (+StringID+StringID)
901 void SbiRuntime::StepCREATE( UINT32 nOp1
, UINT32 nOp2
)
903 String
aClass( pImg
->GetString( static_cast<short>( nOp2
) ) );
904 SbxObject
*pObj
= SbxBase::CreateObject( aClass
);
906 Error( SbERR_INVALID_OBJECT
);
909 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
910 pObj
->SetName( aName
);
911 // Das Objekt muss BASIC rufen koennen
912 pObj
->SetParent( &rBasic
);
913 SbxVariable
* pNew
= new SbxVariable
;
914 pNew
->PutObject( pObj
);
919 void SbiRuntime::StepDCREATE( UINT32 nOp1
, UINT32 nOp2
)
921 StepDCREATE_IMPL( nOp1
, nOp2
);
924 void SbiRuntime::StepDCREATE_REDIMP( UINT32 nOp1
, UINT32 nOp2
)
926 StepDCREATE_IMPL( nOp1
, nOp2
);
930 // Helper function for StepDCREATE_IMPL / bRedimp = true
931 void implCopyDimArray_DCREATE( SbxDimArray
* pNewArray
, SbxDimArray
* pOldArray
, short nMaxDimIndex
,
932 short nActualDim
, sal_Int32
* pActualIndices
, sal_Int32
* pLowerBounds
, sal_Int32
* pUpperBounds
)
934 sal_Int32
& ri
= pActualIndices
[nActualDim
];
935 for( ri
= pLowerBounds
[nActualDim
] ; ri
<= pUpperBounds
[nActualDim
] ; ri
++ )
937 if( nActualDim
< nMaxDimIndex
)
939 implCopyDimArray_DCREATE( pNewArray
, pOldArray
, nMaxDimIndex
, nActualDim
+ 1,
940 pActualIndices
, pLowerBounds
, pUpperBounds
);
944 SbxVariable
* pSource
= pOldArray
->Get32( pActualIndices
);
945 pNewArray
->Put32( pSource
, pActualIndices
);
950 // #56204 Objekt-Array kreieren (+StringID+StringID), DCREATE == Dim-Create
951 void SbiRuntime::StepDCREATE_IMPL( UINT32 nOp1
, UINT32 nOp2
)
953 SbxVariableRef refVar
= PopVar();
957 // Das Array mit Instanzen der geforderten Klasse fuellen
958 SbxBaseRef xObj
= (SbxBase
*)refVar
->GetObject();
961 StarBASIC::Error( SbERR_INVALID_OBJECT
);
965 SbxDimArray
* pArray
= 0;
966 if( xObj
->ISA(SbxDimArray
) )
968 SbxBase
* pObj
= (SbxBase
*)xObj
;
969 pArray
= (SbxDimArray
*)pObj
;
971 // Dimensionen auswerten
972 short nDims
= pArray
->GetDims();
973 INT32 nTotalSize
= 0;
975 // es muss ein eindimensionales Array sein
976 INT32 nLower
, nUpper
, nSize
;
978 for( i
= 0 ; i
< nDims
; i
++ )
980 pArray
->GetDim32( i
+1, nLower
, nUpper
);
981 nSize
= nUpper
- nLower
+ 1;
988 // Objekte anlegen und ins Array eintragen
989 String
aClass( pImg
->GetString( static_cast<short>( nOp2
) ) );
990 for( i
= 0 ; i
< nTotalSize
; i
++ )
992 SbxObject
*pClassObj
= SbxBase::CreateObject( aClass
);
995 Error( SbERR_INVALID_OBJECT
);
1000 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
1001 pClassObj
->SetName( aName
);
1002 // Das Objekt muss BASIC rufen koennen
1003 pClassObj
->SetParent( &rBasic
);
1004 pArray
->SbxArray::Put32( pClassObj
, i
);
1009 SbxDimArray
* pOldArray
= (SbxDimArray
*)(SbxArray
*)refRedimpArray
;
1010 if( pArray
&& pOldArray
)
1012 short nDimsNew
= pArray
->GetDims();
1013 short nDimsOld
= pOldArray
->GetDims();
1014 short nDims
= nDimsNew
;
1015 BOOL bRangeError
= FALSE
;
1017 // Store dims to use them for copying later
1018 sal_Int32
* pLowerBounds
= new sal_Int32
[nDims
];
1019 sal_Int32
* pUpperBounds
= new sal_Int32
[nDims
];
1020 sal_Int32
* pActualIndices
= new sal_Int32
[nDims
];
1021 if( nDimsOld
!= nDimsNew
)
1028 for( short i
= 1 ; i
<= nDims
; i
++ )
1030 sal_Int32 lBoundNew
, uBoundNew
;
1031 sal_Int32 lBoundOld
, uBoundOld
;
1032 pArray
->GetDim32( i
, lBoundNew
, uBoundNew
);
1033 pOldArray
->GetDim32( i
, lBoundOld
, uBoundOld
);
1035 lBoundNew
= std::max( lBoundNew
, lBoundOld
);
1036 uBoundNew
= std::min( uBoundNew
, uBoundOld
);
1038 pActualIndices
[j
] = pLowerBounds
[j
] = lBoundNew
;
1039 pUpperBounds
[j
] = uBoundNew
;
1045 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
1049 // Copy data from old array by going recursively through all dimensions
1050 // (It would be faster to work on the flat internal data array of an
1051 // SbyArray but this solution is clearer and easier)
1052 implCopyDimArray_DCREATE( pArray
, pOldArray
, nDims
- 1,
1053 0, pActualIndices
, pLowerBounds
, pUpperBounds
);
1055 delete [] pUpperBounds
;
1056 delete [] pLowerBounds
;
1057 delete [] pActualIndices
;
1058 refRedimpArray
= NULL
;
1062 // Objekt aus User-Type kreieren (+StringID+StringID)
1064 SbxObject
* createUserTypeImpl( const String
& rClassName
); // sb.cxx
1066 void SbiRuntime::StepTCREATE( UINT32 nOp1
, UINT32 nOp2
)
1068 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
1069 String
aClass( pImg
->GetString( static_cast<short>( nOp2
) ) );
1071 SbxObject
* pCopyObj
= createUserTypeImpl( aClass
);
1073 pCopyObj
->SetName( aName
);
1074 SbxVariable
* pNew
= new SbxVariable
;
1075 pNew
->PutObject( pCopyObj
);
1080 // Einrichten einer lokalen Variablen (+StringID+Typ)
1082 void SbiRuntime::StepLOCAL( UINT32 nOp1
, UINT32 nOp2
)
1084 if( !refLocals
.Is() )
1085 refLocals
= new SbxArray
;
1086 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
1087 if( refLocals
->Find( aName
, SbxCLASS_DONTCARE
) == NULL
)
1089 SbxDataType t
= (SbxDataType
) nOp2
;
1090 SbxVariable
* p
= new SbxVariable( t
);
1091 p
->SetName( aName
);
1092 refLocals
->Put( p
, refLocals
->Count() );
1096 // Einrichten einer modulglobalen Variablen (+StringID+Typ)
1098 void SbiRuntime::StepPUBLIC_Impl( UINT32 nOp1
, UINT32 nOp2
, bool bUsedForClassModule
)
1100 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
1101 SbxDataType t
= (SbxDataType
) nOp2
;
1102 BOOL bFlag
= pMod
->IsSet( SBX_NO_MODIFY
);
1103 pMod
->SetFlag( SBX_NO_MODIFY
);
1104 SbxVariableRef p
= pMod
->Find( aName
, SbxCLASS_PROPERTY
);
1107 SbProperty
* pProp
= pMod
->GetProperty( aName
, t
);
1108 if( !bUsedForClassModule
)
1109 pProp
->SetFlag( SBX_PRIVATE
);
1111 pMod
->ResetFlag( SBX_NO_MODIFY
);
1114 pProp
->SetFlag( SBX_DONTSTORE
);
1115 // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
1116 pProp
->SetFlag( SBX_NO_MODIFY
);
1120 void SbiRuntime::StepPUBLIC( UINT32 nOp1
, UINT32 nOp2
)
1122 StepPUBLIC_Impl( nOp1
, nOp2
, false );
1125 void SbiRuntime::StepPUBLIC_P( UINT32 nOp1
, UINT32 nOp2
)
1127 // Creates module variable that isn't reinitialised when
1128 // between invocations ( for VBASupport & document basic only )
1129 if( pMod
->pImage
->bFirstInit
)
1130 StepPUBLIC( nOp1
, nOp2
);
1133 // Einrichten einer globalen Variablen (+StringID+Typ)
1135 void SbiRuntime::StepGLOBAL( UINT32 nOp1
, UINT32 nOp2
)
1137 if( pImg
->GetFlag( SBIMG_CLASSMODULE
) )
1138 StepPUBLIC_Impl( nOp1
, nOp2
, true );
1140 SbxObject
* pStorage
= &rBasic
;
1141 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
1142 // Store module scope variables at module scope
1143 // in non vba mode these are stored at the library level :/
1144 // not sure if this really should not be enabled for ALL basic
1145 if ( SbiRuntime::isVBAEnabled() )
1148 pMod
->AddVarName( aName
);
1151 SbxDataType t
= (SbxDataType
) nOp2
;
1152 BOOL bFlag
= pStorage
->IsSet( SBX_NO_MODIFY
);
1153 rBasic
.SetFlag( SBX_NO_MODIFY
);
1154 SbxVariableRef p
= pStorage
->Find( aName
, SbxCLASS_PROPERTY
);
1156 pStorage
->Remove (p
);
1157 p
= pStorage
->Make( aName
, SbxCLASS_PROPERTY
, t
);
1159 pStorage
->ResetFlag( SBX_NO_MODIFY
);
1162 p
->SetFlag( SBX_DONTSTORE
);
1163 // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
1164 p
->SetFlag( SBX_NO_MODIFY
);
1169 // Creates global variable that isn't reinitialised when
1170 // basic is restarted, P=PERSIST (+StringID+Typ)
1172 void SbiRuntime::StepGLOBAL_P( UINT32 nOp1
, UINT32 nOp2
)
1174 if( pMod
->pImage
->bFirstInit
)
1176 StepGLOBAL( nOp1
, nOp2
);
1181 // Searches for global variable, behavior depends on the fact
1182 // if the variable is initialised for the first time
1184 void SbiRuntime::StepFIND_G( UINT32 nOp1
, UINT32 nOp2
)
1186 if( pMod
->pImage
->bFirstInit
)
1188 // Behave like always during first init
1189 StepFIND( nOp1
, nOp2
);
1193 // Return dummy variable
1194 SbxDataType t
= (SbxDataType
) nOp2
;
1195 String
aName( pImg
->GetString( static_cast<short>( nOp1
& 0x7FFF ) ) );
1197 SbxVariable
* pDummyVar
= new SbxVariable( t
);
1198 pDummyVar
->SetName( aName
);
1199 PushVar( pDummyVar
);
1204 SbxVariable
* SbiRuntime::StepSTATIC_Impl( String
& aName
, SbxDataType
& t
)
1206 SbxVariable
* p
= NULL
;
1209 SbxArray
* pStatics
= pMeth
->GetStatics();
1210 if( pStatics
&& ( pStatics
->Find( aName
, SbxCLASS_DONTCARE
) == NULL
) )
1212 p
= new SbxVariable( t
);
1213 if( t
!= SbxVARIANT
)
1214 p
->SetFlag( SBX_FIXED
);
1215 p
->SetName( aName
);
1216 pStatics
->Put( p
, pStatics
->Count() );
1221 // Einrichten einer statischen Variablen (+StringID+Typ)
1222 void SbiRuntime::StepSTATIC( UINT32 nOp1
, UINT32 nOp2
)
1224 String
aName( pImg
->GetString( static_cast<short>( nOp1
) ) );
1225 SbxDataType t
= (SbxDataType
) nOp2
;
1226 StepSTATIC_Impl( aName
, t
);