merge the formfield patch from ooo-build
[ooovba.git] / basic / source / runtime / step1.cxx
blob669ada99da1e0dd55e13de61d8b97357ed89ac92
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: step1.cxx,v $
10 * $Revision: 1.18 $
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 <stdlib.h>
35 #include <rtl/math.hxx>
36 #include "runtime.hxx"
37 #include "sbintern.hxx"
38 #include "iosys.hxx"
39 #include "image.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 );
60 aStr = aStr1;
61 aStr += '.';
62 aStr += aStr2;
64 double n = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
66 p->PutDouble( n );
67 PushVar( p );
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 ) ) );
76 PushVar( p );
79 // Immediate Load (+Wert)
81 void SbiRuntime::StepLOADI( UINT32 nOp1 )
83 SbxVariable* p = new SbxVariable;
84 p->PutInteger( static_cast<INT16>( nOp1 ) );
85 PushVar( p );
88 // Speichern eines named Arguments in Argv (+Arg-Nr ab 1!)
90 void SbiRuntime::StepARGN( UINT32 nOp1 )
92 if( !refArgv )
93 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
94 else
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 );
105 pVal = pRes;
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 )
116 if( !refArgv )
117 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
118 else
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
124 // BYVAL prüfen
125 if( pVar->GetRefCount() > 2 ) // 2 ist normal für BYVAL
127 // Parameter ist eine Referenz
128 if( bByVal )
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 );
135 else
136 pVar->SetFlag( SBX_REFERENCE ); // Ref-Flag für DllMgr
138 else
140 // Parameter ist KEINE Referenz
141 if( bByVal )
142 pVar->ResetFlag( SBX_REFERENCE ); // Keine Referenz -> OK
143 else
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 );
152 pVar->Convert( t );
157 // String auf feste Laenge bringen (+Laenge)
159 void SbiRuntime::StepPAD( UINT32 nOp1 )
161 SbxVariable* p = GetTOS();
162 String& s = (String&)(const String&) *p;
163 if( s.Len() > nOp1 )
164 s.Erase( static_cast<xub_StrLen>( nOp1 ) );
165 else
166 s.Expand( static_cast<xub_StrLen>( nOp1 ), ' ' );
169 // Sprung (+Target)
171 void SbiRuntime::StepJUMP( UINT32 nOp1 )
173 #ifndef PRODUCT
174 // #QUESTION shouln't this be
175 // if( (BYTE*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() )
176 if( nOp1 >= pImg->GetCodeSize() )
177 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
178 #endif
179 pCode = (const BYTE*) pImg->GetCode() + nOp1;
182 // TOS auswerten, bedingter Sprung (+Target)
184 void SbiRuntime::StepJUMPT( UINT32 nOp1 )
186 SbxVariableRef p = PopVar();
187 if( p->GetBool() )
188 StepJUMP( nOp1 );
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() )
199 StepJUMP( nOp1 );
202 // TOS auswerten, Sprung in JUMP-Tabelle (+MaxVal)
203 // Sieht so aus:
204 // ONJUMP 2
205 // JUMP target1
206 // JUMP target2
207 // ...
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();
214 if( nOp1 & 0x8000 )
216 nOp1 &= 0x7FFF;
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;
224 StepJUMP( nOp1 );
227 // UP-Aufruf (+Target)
229 void SbiRuntime::StepGOSUB( UINT32 nOp1 )
231 PushGosub( pCode );
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 )
241 PopGosub();
242 if( nOp1 )
243 StepJUMP( nOp1 );
246 // FOR-Variable testen (+Endlabel)
248 void unoToSbxValue( SbxVariable* pVar, const Any& aValue );
250 void SbiRuntime::StepTESTFOR( UINT32 nOp1 )
252 if( !pForStk )
254 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
255 return;
258 bool bEndLoop = false;
259 switch( pForStk->eForType )
261 case FOR_TO:
263 SbxOperator eOp = ( pForStk->refInc->GetDouble() < 0 ) ? SbxLT : SbxGT;
264 if( pForStk->refVar->Compare( eOp, *pForStk->refEnd ) )
265 bEndLoop = true;
266 break;
268 case FOR_EACH_ARRAY:
270 SbiForStack* p = pForStk;
271 if( p->pArrayCurIndices == NULL )
273 bEndLoop = true;
275 else
277 SbxDimArray* pArray = (SbxDimArray*)(SbxVariable*)p->refEnd;
278 short nDims = pArray->GetDims();
280 // Empty array?
281 if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] )
283 bEndLoop = true;
284 break;
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] )
294 bFoundNext = true;
295 p->pArrayCurIndices[i]++;
296 for( short j = i - 1 ; j >= 0 ; j-- )
297 p->pArrayCurIndices[j] = p->pArrayLowerBounds[j];
298 break;
301 if( !bFoundNext )
303 delete[] p->pArrayCurIndices;
304 p->pArrayCurIndices = NULL;
307 break;
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;
320 else
322 bEndLoop = true;
324 break;
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;
336 else
338 bEndLoop = true;
340 break;
343 if( bEndLoop )
345 PopFor();
346 StepJUMP( nOp1 );
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 );
356 else
358 SbxVariableRef xTo = PopVar();
359 SbxVariableRef xFrom = PopVar();
360 SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
361 if( *xCase >= *xFrom && *xCase <= *xTo )
362 StepJUMP( nOp1 );
366 // Fehler-Handler
368 void SbiRuntime::StepERRHDL( UINT32 nOp1 )
370 const BYTE* p = pCode;
371 StepJUMP( nOp1 );
372 pError = pCode;
373 pCode = p;
374 pInst->aErrorMsg = String();
375 pInst->nErr = 0;
376 pInst->nErl = 0;
377 nError = 0;
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
386 if( !bInError )
388 Error( SbERR_BAD_RESUME );
389 return;
391 if( nOp1 )
393 // Code-Zeiger auf naechstes Statement setzen
394 USHORT n1, n2;
395 pCode = pMod->FindNextStmnt( pErrCode, n1, n2, TRUE, pImg );
397 else
398 pCode = pErrStmnt;
399 if ( pError ) // current in error handler ( and got a Resume Next statment )
400 SbxErrObject::getUnoErrObject()->Clear();
402 if( nOp1 > 1 )
403 StepJUMP( nOp1 );
404 pInst->aErrorMsg = String();
405 pInst->nErr = 0;
406 pInst->nErl = 0;
407 nError = 0;
408 bInError = FALSE;
410 // Error-Stack loeschen
411 SbErrorStack*& rErrStack = GetSbData()->pErrStack;
412 delete rErrStack;
413 rErrStack = NULL;
416 // Kanal schliessen (+Kanal, 0=Alle)
417 void SbiRuntime::StepCLOSE( UINT32 nOp1 )
419 SbError err;
420 if( !nOp1 )
421 pIosys->Shutdown();
422 else
424 err = pIosys->GetError();
425 if( !err )
427 pIosys->Close();
430 err = pIosys->GetError();
431 Error( err );
434 // Zeichen ausgeben (+char)
436 void SbiRuntime::StepPRCHAR( UINT32 nOp1 )
438 ByteString s( (char) nOp1 );
439 pIosys->Write( s );
440 Error( pIosys->GetError() );
443 // Check, ob TOS eine bestimmte Objektklasse ist (+StringID)
445 bool SbiRuntime::implIsClass( SbxObject* pObj, const String& aClass )
447 bool bRet = true;
449 if( aClass.Len() != 0 )
451 bRet = pObj->IsClass( aClass );
452 if( !bRet )
453 bRet = aClass.EqualsIgnoreCaseAscii( String( RTL_CONSTASCII_USTRINGPARAM("object") ) );
454 if( !bRet )
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);
467 return bRet;
470 bool SbiRuntime::checkClass_Impl( const SbxVariableRef& refVal,
471 const String& aClass, bool bRaiseErrors )
473 bool bOk = true;
475 SbxDataType t = refVal->GetType();
476 if( t == SbxOBJECT )
478 SbxObject* pObj;
479 SbxVariable* pVal = (SbxVariable*)refVal;
480 if( pVal->IsA( TYPE(SbxObject) ) )
481 pObj = (SbxObject*) pVal;
482 else
484 pObj = (SbxObject*) refVal->GetObject();
485 if( pObj && !pObj->IsA( TYPE(SbxObject) ) )
486 pObj = NULL;
488 if( pObj )
490 if( !implIsClass( pObj, aClass ) )
492 if ( bVBAEnabled && pObj->IsA( TYPE(SbUnoObject) ) )
494 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
495 bOk = checkUnoObjectType( pUnoObj, aClass );
497 else
498 bOk = false;
499 if ( !bOk )
501 if( bRaiseErrors )
502 Error( SbERR_INVALID_USAGE_OBJECT );
505 else
507 SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pObj);
508 if( pClassModuleObject != NULL )
509 pClassModuleObject->triggerInitializeEvent();
513 else
515 if ( !bVBAEnabled )
517 if( bRaiseErrors )
518 Error( SbERR_NEEDS_OBJECT );
519 bOk = false;
522 return bOk;
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 );
532 if( bOk )
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 );
554 PushVar( pRet );
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 );
577 if( !bCompatible )
578 x2->Compute( SbxPLUS, *p1 );
579 PushVar( x2 ); // erst die Expr
580 PushVar( p1 ); // dann die Base