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: step1.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"
35 #include <rtl/math.hxx>
36 #include "runtime.hxx"
37 #include "sbintern.hxx"
40 #include "sbunoobj.hxx"
41 #include "errobject.hxx"
43 bool checkUnoObjectType( SbUnoObject
* refVal
,
44 const String
& aClass
);
46 // Laden einer numerischen Konstanten (+ID)
48 void SbiRuntime::StepLOADNC( UINT32 nOp1
)
50 SbxVariable
* p
= new SbxVariable( SbxDOUBLE
);
52 // #57844 Lokalisierte Funktion benutzen
53 String aStr
= pImg
->GetString( static_cast<short>( nOp1
) );
54 // Auch , zulassen !!!
55 USHORT iComma
= aStr
.Search( ',' );
56 if( iComma
!= STRING_NOTFOUND
)
58 String aStr1
= aStr
.Copy( 0, iComma
);
59 String aStr2
= aStr
.Copy( iComma
+ 1 );
64 double n
= ::rtl::math::stringToDouble( aStr
, '.', ',', NULL
, NULL
);
70 // Laden einer Stringkonstanten (+ID)
72 void SbiRuntime::StepLOADSC( UINT32 nOp1
)
74 SbxVariable
* p
= new SbxVariable
;
75 p
->PutString( pImg
->GetString( static_cast<short>( nOp1
) ) );
79 // Immediate Load (+Wert)
81 void SbiRuntime::StepLOADI( UINT32 nOp1
)
83 SbxVariable
* p
= new SbxVariable
;
84 p
->PutInteger( static_cast<INT16
>( nOp1
) );
88 // Speichern eines named Arguments in Argv (+Arg-Nr ab 1!)
90 void SbiRuntime::StepARGN( UINT32 nOp1
)
93 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
96 String
aAlias( pImg
->GetString( static_cast<short>( nOp1
) ) );
97 SbxVariableRef pVal
= PopVar();
98 if( bVBAEnabled
&& ( pVal
->ISA(SbxMethod
) || pVal
->ISA(SbUnoProperty
) || pVal
->ISA(SbProcedureProperty
) ) )
100 // named variables ( that are Any especially properties ) can be empty at this point and need a broadcast
101 if ( pVal
->GetType() == SbxEMPTY
)
102 pVal
->Broadcast( SBX_HINT_DATAWANTED
);
103 // Methoden und Properties evaluieren!
104 SbxVariable
* pRes
= new SbxVariable( *pVal
);
107 refArgv
->Put( pVal
, nArgc
);
108 refArgv
->PutAlias( aAlias
, nArgc
++ );
112 // Konvertierung des Typs eines Arguments in Argv fuer DECLARE-Fkt. (+Typ)
114 void SbiRuntime::StepARGTYP( UINT32 nOp1
)
117 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
120 BOOL bByVal
= (nOp1
& 0x8000) != 0; // Ist BYVAL verlangt?
121 SbxDataType t
= (SbxDataType
) (nOp1
& 0x7FFF);
122 SbxVariable
* pVar
= refArgv
->Get( refArgv
->Count() - 1 ); // letztes Arg
125 if( pVar
->GetRefCount() > 2 ) // 2 ist normal für BYVAL
127 // Parameter ist eine Referenz
130 // Call by Value ist verlangt -> Kopie anlegen
131 pVar
= new SbxVariable( *pVar
);
132 pVar
->SetFlag( SBX_READWRITE
);
133 refExprStk
->Put( pVar
, refArgv
->Count() - 1 );
136 pVar
->SetFlag( SBX_REFERENCE
); // Ref-Flag für DllMgr
140 // Parameter ist KEINE Referenz
142 pVar
->ResetFlag( SBX_REFERENCE
); // Keine Referenz -> OK
144 Error( SbERR_BAD_PARAMETERS
); // Referenz verlangt
147 if( pVar
->GetType() != t
)
149 // Variant, damit richtige Konvertierung
150 // Ausserdem Fehler, wenn SbxBYREF
151 pVar
->Convert( SbxVARIANT
);
157 // String auf feste Laenge bringen (+Laenge)
159 void SbiRuntime::StepPAD( UINT32 nOp1
)
161 SbxVariable
* p
= GetTOS();
162 String
& s
= (String
&)(const String
&) *p
;
164 s
.Erase( static_cast<xub_StrLen
>( nOp1
) );
166 s
.Expand( static_cast<xub_StrLen
>( nOp1
), ' ' );
171 void SbiRuntime::StepJUMP( UINT32 nOp1
)
174 // #QUESTION shouln't this be
175 // if( (BYTE*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() )
176 if( nOp1
>= pImg
->GetCodeSize() )
177 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
179 pCode
= (const BYTE
*) pImg
->GetCode() + nOp1
;
182 // TOS auswerten, bedingter Sprung (+Target)
184 void SbiRuntime::StepJUMPT( UINT32 nOp1
)
186 SbxVariableRef p
= PopVar();
191 // TOS auswerten, bedingter Sprung (+Target)
193 void SbiRuntime::StepJUMPF( UINT32 nOp1
)
195 SbxVariableRef p
= PopVar();
196 // In a test e.g. If Null then
197 // will evaluate Null will act as if False
198 if( ( bVBAEnabled
&& p
->IsNull() ) || !p
->GetBool() )
202 // TOS auswerten, Sprung in JUMP-Tabelle (+MaxVal)
208 //Falls im Operanden 0x8000 gesetzt ist, Returnadresse pushen (ON..GOSUB)
210 void SbiRuntime::StepONJUMP( UINT32 nOp1
)
212 SbxVariableRef p
= PopVar();
213 INT16 n
= p
->GetInteger();
217 //PushGosub( pCode + 3 * nOp1 );
218 PushGosub( pCode
+ 5 * nOp1
);
220 if( n
< 1 || static_cast<UINT32
>(n
) > nOp1
)
221 n
= static_cast<INT16
>( nOp1
+ 1 );
222 //nOp1 = (UINT32) ( (const char*) pCode - pImg->GetCode() ) + 3 * --n;
223 nOp1
= (UINT32
) ( (const char*) pCode
- pImg
->GetCode() ) + 5 * --n
;
227 // UP-Aufruf (+Target)
229 void SbiRuntime::StepGOSUB( UINT32 nOp1
)
232 if( nOp1
>= pImg
->GetCodeSize() )
233 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
234 pCode
= (const BYTE
*) pImg
->GetCode() + nOp1
;
237 // UP-Return (+0 oder Target)
239 void SbiRuntime::StepRETURN( UINT32 nOp1
)
246 // FOR-Variable testen (+Endlabel)
248 void unoToSbxValue( SbxVariable
* pVar
, const Any
& aValue
);
250 void SbiRuntime::StepTESTFOR( UINT32 nOp1
)
254 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
258 bool bEndLoop
= false;
259 switch( pForStk
->eForType
)
263 SbxOperator eOp
= ( pForStk
->refInc
->GetDouble() < 0 ) ? SbxLT
: SbxGT
;
264 if( pForStk
->refVar
->Compare( eOp
, *pForStk
->refEnd
) )
270 SbiForStack
* p
= pForStk
;
271 if( p
->pArrayCurIndices
== NULL
)
277 SbxDimArray
* pArray
= (SbxDimArray
*)(SbxVariable
*)p
->refEnd
;
278 short nDims
= pArray
->GetDims();
281 if( nDims
== 1 && p
->pArrayLowerBounds
[0] > p
->pArrayUpperBounds
[0] )
286 SbxVariable
* pVal
= pArray
->Get32( p
->pArrayCurIndices
);
287 *(p
->refVar
) = *pVal
;
289 bool bFoundNext
= false;
290 for( short i
= 0 ; i
< nDims
; i
++ )
292 if( p
->pArrayCurIndices
[i
] < p
->pArrayUpperBounds
[i
] )
295 p
->pArrayCurIndices
[i
]++;
296 for( short j
= i
- 1 ; j
>= 0 ; j
-- )
297 p
->pArrayCurIndices
[j
] = p
->pArrayLowerBounds
[j
];
303 delete[] p
->pArrayCurIndices
;
304 p
->pArrayCurIndices
= NULL
;
309 case FOR_EACH_COLLECTION
:
311 BasicCollection
* pCollection
= (BasicCollection
*)(SbxVariable
*)pForStk
->refEnd
;
312 SbxArrayRef xItemArray
= pCollection
->xItemArray
;
313 INT32 nCount
= xItemArray
->Count32();
314 if( pForStk
->nCurCollectionIndex
< nCount
)
316 SbxVariable
* pRes
= xItemArray
->Get32( pForStk
->nCurCollectionIndex
);
317 pForStk
->nCurCollectionIndex
++;
318 (*pForStk
->refVar
) = *pRes
;
326 case FOR_EACH_XENUMERATION
:
328 SbiForStack
* p
= pForStk
;
329 if( p
->xEnumeration
->hasMoreElements() )
331 Any aElem
= p
->xEnumeration
->nextElement();
332 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
333 unoToSbxValue( (SbxVariable
*)xVar
, aElem
);
334 (*pForStk
->refVar
) = *xVar
;
350 // Tos+1 <= Tos+2 <= Tos, 2xremove (+Target)
352 void SbiRuntime::StepCASETO( UINT32 nOp1
)
354 if( !refCaseStk
|| !refCaseStk
->Count() )
355 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
358 SbxVariableRef xTo
= PopVar();
359 SbxVariableRef xFrom
= PopVar();
360 SbxVariableRef xCase
= refCaseStk
->Get( refCaseStk
->Count() - 1 );
361 if( *xCase
>= *xFrom
&& *xCase
<= *xTo
)
368 void SbiRuntime::StepERRHDL( UINT32 nOp1
)
370 const BYTE
* p
= pCode
;
374 pInst
->aErrorMsg
= String();
378 SbxErrObject::getUnoErrObject()->Clear();
381 // Resume nach Fehlern (+0=statement, 1=next or Label)
383 void SbiRuntime::StepRESUME( UINT32 nOp1
)
385 // AB #32714 Resume ohne Error? -> Fehler
388 Error( SbERR_BAD_RESUME
);
393 // Code-Zeiger auf naechstes Statement setzen
395 pCode
= pMod
->FindNextStmnt( pErrCode
, n1
, n2
, TRUE
, pImg
);
399 if ( pError
) // current in error handler ( and got a Resume Next statment )
400 SbxErrObject::getUnoErrObject()->Clear();
404 pInst
->aErrorMsg
= String();
410 // Error-Stack loeschen
411 SbErrorStack
*& rErrStack
= GetSbData()->pErrStack
;
416 // Kanal schliessen (+Kanal, 0=Alle)
417 void SbiRuntime::StepCLOSE( UINT32 nOp1
)
424 err
= pIosys
->GetError();
430 err
= pIosys
->GetError();
434 // Zeichen ausgeben (+char)
436 void SbiRuntime::StepPRCHAR( UINT32 nOp1
)
438 ByteString
s( (char) nOp1
);
440 Error( pIosys
->GetError() );
443 // Check, ob TOS eine bestimmte Objektklasse ist (+StringID)
445 bool SbiRuntime::implIsClass( SbxObject
* pObj
, const String
& aClass
)
449 if( aClass
.Len() != 0 )
451 bRet
= pObj
->IsClass( aClass
);
453 bRet
= aClass
.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("object") ) );
456 String aObjClass
= pObj
->GetClassName();
457 SbModule
* pClassMod
= pCLASSFAC
->FindClass( aObjClass
);
458 SbClassData
* pClassData
;
459 if( pClassMod
&& (pClassData
=pClassMod
->pClassData
) != NULL
)
461 SbxVariable
* pClassVar
=
462 pClassData
->mxIfaces
->Find( aClass
, SbxCLASS_DONTCARE
);
463 bRet
= (pClassVar
!= NULL
);
470 bool SbiRuntime::checkClass_Impl( const SbxVariableRef
& refVal
,
471 const String
& aClass
, bool bRaiseErrors
)
475 SbxDataType t
= refVal
->GetType();
479 SbxVariable
* pVal
= (SbxVariable
*)refVal
;
480 if( pVal
->IsA( TYPE(SbxObject
) ) )
481 pObj
= (SbxObject
*) pVal
;
484 pObj
= (SbxObject
*) refVal
->GetObject();
485 if( pObj
&& !pObj
->IsA( TYPE(SbxObject
) ) )
490 if( !implIsClass( pObj
, aClass
) )
492 if ( bVBAEnabled
&& pObj
->IsA( TYPE(SbUnoObject
) ) )
494 SbUnoObject
* pUnoObj
= PTR_CAST(SbUnoObject
,pObj
);
495 bOk
= checkUnoObjectType( pUnoObj
, aClass
);
502 Error( SbERR_INVALID_USAGE_OBJECT
);
507 SbClassModuleObject
* pClassModuleObject
= PTR_CAST(SbClassModuleObject
,pObj
);
508 if( pClassModuleObject
!= NULL
)
509 pClassModuleObject
->triggerInitializeEvent();
518 Error( SbERR_NEEDS_OBJECT
);
525 void SbiRuntime::StepSETCLASS_impl( UINT32 nOp1
, bool bHandleDflt
)
527 SbxVariableRef refVal
= PopVar();
528 SbxVariableRef refVar
= PopVar();
529 String
aClass( pImg
->GetString( static_cast<short>( nOp1
) ) );
531 bool bOk
= checkClass_Impl( refVal
, aClass
, true );
533 StepSET_Impl( refVal
, refVar
, bHandleDflt
); // don't do handle dflt prop for a "proper" set
536 void SbiRuntime::StepVBASETCLASS( UINT32 nOp1
)
538 StepSETCLASS_impl( nOp1
, false );
541 void SbiRuntime::StepSETCLASS( UINT32 nOp1
)
543 StepSETCLASS_impl( nOp1
, true );
546 void SbiRuntime::StepTESTCLASS( UINT32 nOp1
)
548 SbxVariableRef xObjVal
= PopVar();
549 String
aClass( pImg
->GetString( static_cast<short>( nOp1
) ) );
550 bool bOk
= checkClass_Impl( xObjVal
, aClass
, false );
552 SbxVariable
* pRet
= new SbxVariable
;
553 pRet
->PutBool( bOk
);
557 // Library fuer anschliessenden Declare-Call definieren
559 void SbiRuntime::StepLIB( UINT32 nOp1
)
561 aLibName
= pImg
->GetString( static_cast<short>( nOp1
) );
564 // TOS wird um BASE erhoeht, BASE davor gepusht (+BASE)
565 // Dieser Opcode wird vor DIM/REDIM-Anweisungen gepusht,
566 // wenn nur ein Index angegeben wurde.
568 void SbiRuntime::StepBASED( UINT32 nOp1
)
570 SbxVariable
* p1
= new SbxVariable
;
571 SbxVariableRef x2
= PopVar();
573 // #109275 Check compatiblity mode
574 bool bCompatible
= ((nOp1
& 0x8000) != 0);
575 USHORT uBase
= static_cast<USHORT
>(nOp1
& 1); // Can only be 0 or 1
576 p1
->PutInteger( uBase
);
578 x2
->Compute( SbxPLUS
, *p1
);
579 PushVar( x2
); // erst die Expr
580 PushVar( p1
); // dann die Base