summaryrefslogtreecommitdiff
path: root/basic/source/runtime/runtime.cxx
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 15:18:56 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 15:18:56 +0000
commitc25ec0608a167bcf1d891043f02273761c351701 (patch)
tree32c3e19f0b663e37ad1910e8fddeac200ad3856d /basic/source/runtime/runtime.cxx
initial import
Diffstat (limited to 'basic/source/runtime/runtime.cxx')
-rw-r--r--basic/source/runtime/runtime.cxx934
1 files changed, 934 insertions, 0 deletions
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
new file mode 100644
index 000000000000..587c59ffeb9e
--- /dev/null
+++ b/basic/source/runtime/runtime.cxx
@@ -0,0 +1,934 @@
+/*************************************************************************
+ *
+ * $RCSfile: runtime.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:12:11 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _FSYS_HXX //autogen
+#include <tools/fsys.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX //autogen
+#include <vcl/svapp.hxx>
+#endif
+#ifndef _INTN_HXX //autogen
+#include <tools/intn.hxx>
+#endif
+
+#ifndef _ZFORLIST_HXX //autogen
+#include <svtools/zforlist.hxx>
+#endif
+#include <svtools/sbx.hxx>
+#include "runtime.hxx"
+#pragma hdrstop
+#include "sbintern.hxx"
+#include "opcodes.hxx"
+#include "iosys.hxx"
+#include "image.hxx"
+#include "ddectrl.hxx"
+#include "dllmgr.hxx"
+
+// Makro MEMBER()
+#include <macfix.hxx>
+
+#include "segmentc.hxx"
+#pragma SW_SEGMENT_CLASS( SBRUNTIME, SBRUNTIME_CODE )
+
+struct SbiGosubStack { // GOSUB-Stack:
+ SbiGosubStack* pNext; // Chain
+ const BYTE* pCode; // Return-Pointer
+};
+
+struct SbiArgvStack { // Argv stack:
+ SbiArgvStack* pNext; // Stack Chain
+ SbxArrayRef refArgv; // Argv
+ short nArgc; // Argc
+};
+
+SbiRuntime::pStep0 SbiRuntime::aStep0[] = { // Alle Opcodes ohne Operanden
+ MEMBER(SbiRuntime::StepNOP),
+ MEMBER(SbiRuntime::StepEXP),
+ MEMBER(SbiRuntime::StepMUL),
+ MEMBER(SbiRuntime::StepDIV),
+ MEMBER(SbiRuntime::StepMOD),
+ MEMBER(SbiRuntime::StepPLUS),
+ MEMBER(SbiRuntime::StepMINUS),
+ MEMBER(SbiRuntime::StepNEG),
+ MEMBER(SbiRuntime::StepEQ),
+ MEMBER(SbiRuntime::StepNE),
+ MEMBER(SbiRuntime::StepLT),
+ MEMBER(SbiRuntime::StepGT),
+ MEMBER(SbiRuntime::StepLE),
+ MEMBER(SbiRuntime::StepGE),
+ MEMBER(SbiRuntime::StepIDIV),
+ MEMBER(SbiRuntime::StepAND),
+ MEMBER(SbiRuntime::StepOR),
+ MEMBER(SbiRuntime::StepXOR),
+ MEMBER(SbiRuntime::StepEQV),
+ MEMBER(SbiRuntime::StepIMP),
+ MEMBER(SbiRuntime::StepNOT),
+ MEMBER(SbiRuntime::StepCAT),
+
+ MEMBER(SbiRuntime::StepLIKE),
+ MEMBER(SbiRuntime::StepIS),
+ // Laden/speichern
+ MEMBER(SbiRuntime::StepARGC), // neuen Argv einrichten
+ MEMBER(SbiRuntime::StepARGV), // TOS ==> aktueller Argv
+ MEMBER(SbiRuntime::StepINPUT), // Input ==> TOS
+ MEMBER(SbiRuntime::StepLINPUT), // Line Input ==> TOS
+ MEMBER(SbiRuntime::StepGET), // TOS anfassen
+ MEMBER(SbiRuntime::StepSET), // Speichern Objekt TOS ==> TOS-1
+ MEMBER(SbiRuntime::StepPUT), // TOS ==> TOS-1
+ MEMBER(SbiRuntime::StepPUTC), // TOS ==> TOS-1, dann ReadOnly
+ MEMBER(SbiRuntime::StepDIM), // DIM
+ MEMBER(SbiRuntime::StepREDIM), // REDIM
+ MEMBER(SbiRuntime::StepREDIMP), // REDIM PRESERVE
+ MEMBER(SbiRuntime::StepERASE), // TOS loeschen
+ // Verzweigen
+ MEMBER(SbiRuntime::StepSTOP), // Programmende
+ MEMBER(SbiRuntime::StepINITFOR), // FOR-Variable initialisieren
+ MEMBER(SbiRuntime::StepNEXT), // FOR-Variable inkrementieren
+ MEMBER(SbiRuntime::StepCASE), // Anfang CASE
+ MEMBER(SbiRuntime::StepENDCASE), // Ende CASE
+ MEMBER(SbiRuntime::StepSTDERROR), // Standard-Fehlerbehandlung
+ MEMBER(SbiRuntime::StepNOERROR), // keine Fehlerbehandlung
+ MEMBER(SbiRuntime::StepLEAVE), // UP verlassen
+ // E/A
+ MEMBER(SbiRuntime::StepCHANNEL), // TOS = Kanalnummer
+ MEMBER(SbiRuntime::StepPRINT), // print TOS
+ MEMBER(SbiRuntime::StepPRINTF), // print TOS in field
+ MEMBER(SbiRuntime::StepWRITE), // write TOS
+ MEMBER(SbiRuntime::StepRENAME), // Rename Tos+1 to Tos
+ MEMBER(SbiRuntime::StepPROMPT), // Input Prompt aus TOS definieren
+ MEMBER(SbiRuntime::StepRESTART), // Set restart point
+ MEMBER(SbiRuntime::StepCHANNEL0), // E/A-Kanal 0 einstellen
+ MEMBER(SbiRuntime::StepEMPTY), // Leeren Ausdruck auf Stack
+ MEMBER(SbiRuntime::StepERROR), // TOS = Fehlercode
+ MEMBER(SbiRuntime::StepLSET), // Speichern Objekt TOS ==> TOS-1
+ MEMBER(SbiRuntime::StepRSET) // Speichern Objekt TOS ==> TOS-1
+};
+
+SbiRuntime::pStep1 SbiRuntime::aStep1[] = { // Alle Opcodes mit einem Operanden
+ MEMBER(SbiRuntime::StepLOADNC), // Laden einer numerischen Konstanten (+ID)
+ MEMBER(SbiRuntime::StepLOADSC), // Laden einer Stringkonstanten (+ID)
+ MEMBER(SbiRuntime::StepLOADI), // Immediate Load (+Wert)
+ MEMBER(SbiRuntime::StepARGN), // Speichern eines named Args in Argv (+StringID)
+ MEMBER(SbiRuntime::StepPAD), // String auf feste Laenge bringen (+Laenge)
+ // Verzweigungen
+ MEMBER(SbiRuntime::StepJUMP), // Sprung (+Target)
+ MEMBER(SbiRuntime::StepJUMPT), // TOS auswerten), bedingter Sprung (+Target)
+ MEMBER(SbiRuntime::StepJUMPF), // TOS auswerten), bedingter Sprung (+Target)
+ MEMBER(SbiRuntime::StepONJUMP), // TOS auswerten), Sprung in JUMP-Tabelle (+MaxVal)
+ MEMBER(SbiRuntime::StepGOSUB), // UP-Aufruf (+Target)
+ MEMBER(SbiRuntime::StepRETURN), // UP-Return (+0 oder Target)
+ MEMBER(SbiRuntime::StepTESTFOR), // FOR-Variable testen), inkrementieren (+Endlabel)
+ MEMBER(SbiRuntime::StepCASETO), // Tos+1 <= Case <= Tos), 2xremove (+Target)
+ MEMBER(SbiRuntime::StepERRHDL), // Fehler-Handler (+Offset)
+ MEMBER(SbiRuntime::StepRESUME), // Resume nach Fehlern (+0 or 1 or Label)
+ // E/A
+ MEMBER(SbiRuntime::StepCLOSE), // (+Kanal/0)
+ MEMBER(SbiRuntime::StepPRCHAR), // (+char)
+ // Verwaltung
+ MEMBER(SbiRuntime::StepCLASS), // Klassennamen testen (+StringId)
+ MEMBER(SbiRuntime::StepLIB), // Lib fuer Declare-Call (+StringId)
+ MEMBER(SbiRuntime::StepBASED), // TOS wird um BASE erhoeht, BASE davor gepusht
+ MEMBER(SbiRuntime::StepARGTYP), // Letzten Parameter in Argv konvertieren (+Typ)
+};
+
+SbiRuntime::pStep2 SbiRuntime::aStep2[] = {// Alle Opcodes mit zwei Operanden
+ MEMBER(SbiRuntime::StepRTL), // Laden aus RTL (+StringID+Typ)
+ MEMBER(SbiRuntime::StepFIND), // Laden (+StringID+Typ)
+ MEMBER(SbiRuntime::StepELEM), // Laden Element (+StringID+Typ)
+ MEMBER(SbiRuntime::StepPARAM), // Parameter (+Offset+Typ)
+ // Verzweigen
+ MEMBER(SbiRuntime::StepCALL), // Declare-Call (+StringID+Typ)
+ MEMBER(SbiRuntime::StepCALLC), // CDecl-Declare-Call (+StringID+Typ)
+ MEMBER(SbiRuntime::StepCASEIS), // Case-Test (+Test-Opcode+False-Target)
+ // Verwaltung
+ MEMBER(SbiRuntime::StepSTMNT), // Beginn eines Statements (+Line+Col)
+ // E/A
+ MEMBER(SbiRuntime::StepOPEN), // (+SvStreamFlags+Flags)
+ // Objekte
+ MEMBER(SbiRuntime::StepLOCAL), // Lokale Variable definieren (+StringId+Typ)
+ MEMBER(SbiRuntime::StepPUBLIC), // Modulglobale Variable (+StringID+Typ)
+ MEMBER(SbiRuntime::StepGLOBAL), // Globale Variable definieren (+StringID+Typ)
+ MEMBER(SbiRuntime::StepCREATE), // Objekt kreieren (+StringId+StringId)
+ MEMBER(SbiRuntime::StepSTATIC), // Statische Variable (+StringId+StringId)
+ MEMBER(SbiRuntime::StepTCREATE), // User Defined Objekte (+StringId+StringId)
+ MEMBER(SbiRuntime::StepDCREATE), // Objekt-Array kreieren (+StringID+StringID)
+};
+
+//////////////////////////////////////////////////////////////////////////
+// SbiRTLData //
+//////////////////////////////////////////////////////////////////////////
+
+SbiRTLData::SbiRTLData()
+{
+ pDir = 0;
+ nDirFlags = 0;
+ nCurDirPos = 0;
+}
+
+SbiRTLData::~SbiRTLData()
+{
+ delete pDir;
+ pDir = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// SbiInstance //
+//////////////////////////////////////////////////////////////////////////
+
+// 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out
+// Die Entscheidung, ob StepPoint aufgerufen werden soll, wird anhand des
+// CallLevels getroffen. Angehalten wird, wenn der aktuelle CallLevel <=
+// nBreakCallLvl ist. Der aktuelle CallLevel kann niemals kleiner als 1
+// sein, da er beim Aufruf einer Methode (auch main) inkrementiert wird.
+// Daher bedeutet ein BreakCallLvl von 0, dass das Programm gar nicht
+// angehalten wird.
+// (siehe auch step2.cxx, SbiRuntime::StepSTMNT() )
+
+// Hilfsfunktion, um den BreakCallLevel gemaess der der Debug-Flags zu ermitteln
+void SbiInstance::CalcBreakCallLevel( USHORT nFlags )
+{
+ // Break-Flag wegfiltern
+ nFlags &= ~((USHORT)SbDEBUG_BREAK);
+
+ USHORT nRet;
+ switch( nFlags )
+ {
+ case SbDEBUG_STEPINTO:
+ nRet = nCallLvl + 1; // CallLevel+1 wird auch angehalten
+ break;
+ case SbDEBUG_STEPOVER | SbDEBUG_STEPINTO:
+ nRet = nCallLvl; // Aktueller CallLevel wird angehalten
+ break;
+ case SbDEBUG_STEPOUT:
+ nRet = nCallLvl - 1; // Kleinerer CallLevel wird angehalten
+ break;
+ case SbDEBUG_CONTINUE:
+ // Basic-IDE liefert 0 statt SbDEBUG_CONTINUE, also auch default=continue
+ default:
+ nRet = 0; // CallLevel ist immer >0 -> kein StepPoint
+ }
+ nBreakCallLvl = nRet; // Ergebnis uebernehmen
+}
+
+SbiInstance::SbiInstance( StarBASIC* p )
+{
+ pBasic = p;
+ pNext = NULL;
+ pRun = NULL;
+ pIosys = new SbiIoSystem;
+ pDdeCtrl = new SbiDdeControl;
+ pDllMgr = 0; // on demand
+ pNumberFormatter = 0; // on demand
+ nCallLvl = 0;
+ nBreakCallLvl = 0;
+ nErr =
+ nErl = 0;
+ bReschedule = TRUE;
+}
+
+SbiInstance::~SbiInstance()
+{
+ while( pRun )
+ {
+ SbiRuntime* p = pRun->pNext;
+ delete pRun;
+ pRun = p;
+ }
+ delete pIosys;
+ delete pDdeCtrl;
+ delete pDllMgr;
+ delete pNumberFormatter;
+}
+
+SbiDllMgr* SbiInstance::GetDllMgr()
+{
+ if( !pDllMgr )
+ pDllMgr = new SbiDllMgr;
+ return pDllMgr;
+}
+
+// #39629 NumberFormatter jetzt ueber statische Methode anlegen
+SvNumberFormatter* SbiInstance::GetNumberFormatter()
+{
+ if( !pNumberFormatter )
+ PrepareNumberFormatter( pNumberFormatter, nStdDateIdx, nStdTimeIdx, nStdDateTimeIdx );
+ return pNumberFormatter;
+}
+
+// #39629 NumberFormatter auch statisch anbieten
+void SbiInstance::PrepareNumberFormatter( SvNumberFormatter*& rpNumberFormatter,
+ ULONG &rnStdDateIdx, ULONG &rnStdTimeIdx, ULONG &rnStdDateTimeIdx )
+{
+ const International& rInter = GetpApp()->GetAppInternational();
+ LanguageType eLangType = rInter.GetLanguage();
+ rpNumberFormatter = new SvNumberFormatter( eLangType );
+ xub_StrLen nCheckPos = 0; short nType;
+ rnStdTimeIdx = rpNumberFormatter->GetStandardFormat( NUMBERFORMAT_TIME, eLangType );
+
+ // Standard-Vorlagen des Formatters haben nur zweistellige
+ // Jahreszahl. Deshalb eigenes Format registrieren
+
+ // HACK, da der Numberformatter in PutandConvertEntry die Platzhalter
+ // fuer Monat, Tag, Jahr nicht entsprechend der Systemeinstellung
+ // austauscht. Problem: Print Year(Date) unter engl. BS
+ // siehe auch svtools\source\sbx\sbxdate.cxx
+
+ DateFormat eDate = rInter.GetDateFormat();
+ String aDateStr;
+ switch( eDate )
+ {
+ case MDY: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("MM.TT.JJJJ") ); break;
+ case DMY: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("TT.MM.JJJJ") ); break;
+ case YMD: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("JJJJ.MM.TT") ); break;
+ default: aDateStr = String( RTL_CONSTASCII_USTRINGPARAM("MM.TT.JJJJ") );
+ }
+ String aStr( aDateStr );
+ rpNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
+ rnStdDateIdx, LANGUAGE_GERMAN, eLangType );
+ nCheckPos = 0;
+ String aStrHHMMSS( RTL_CONSTASCII_USTRINGPARAM(" HH:MM:SS") );
+ aStr = aDateStr;
+ aStr += aStrHHMMSS;
+ rpNumberFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
+ rnStdDateTimeIdx, LANGUAGE_GERMAN, eLangType );
+}
+
+
+
+// Engine laufenlassen. Falls Flags == SbDEBUG_CONTINUE, Flags uebernehmen
+
+void SbiInstance::Stop()
+{
+ for( SbiRuntime* p = pRun; p; p = p->pNext )
+ p->Stop();
+}
+
+void SbiInstance::Error( SbError n )
+{
+ Error( n, String() );
+}
+
+void SbiInstance::Error( SbError n, const String& rMsg )
+{
+ aErrorMsg = rMsg;
+ pRun->Error( n );
+}
+
+void SbiInstance::FatalError( SbError n )
+{
+ pRun->FatalError( n );
+}
+
+void SbiInstance::Abort()
+{
+ // Basic suchen, in dem der Fehler auftrat
+ StarBASIC* pErrBasic = GetCurrentBasic( pBasic );
+ pErrBasic->RTError( nErr, aErrorMsg, pRun->nLine, pRun->nCol1, pRun->nCol2 );
+ pBasic->Stop();
+}
+
+// Hilfsfunktion, um aktives Basic zu finden, kann ungleich pRTBasic sein
+StarBASIC* GetCurrentBasic( StarBASIC* pRTBasic )
+{
+ StarBASIC* pCurBasic = pRTBasic;
+ SbModule* pActiveModule = pRTBasic->GetActiveModule();
+ if( pActiveModule )
+ {
+ SbxObject* pParent = pActiveModule->GetParent();
+ if( pParent && pParent->ISA(StarBASIC) )
+ pCurBasic = (StarBASIC*)pParent;
+ }
+ return pCurBasic;
+}
+
+SbModule* SbiInstance::GetActiveModule()
+{
+ if( pRun )
+ return pRun->GetModule();
+ else
+ return NULL;
+}
+
+SbMethod* SbiInstance::GetCaller( USHORT nLevel )
+{
+ SbiRuntime* p = pRun;
+ while( nLevel-- && p )
+ p = p->pNext;
+ if( p )
+ return p->GetCaller();
+ else
+ return NULL;
+}
+
+SbxArray* SbiInstance::GetLocals( SbMethod* pMeth )
+{
+ SbiRuntime* p = pRun;
+ while( p && p->GetMethod() != pMeth )
+ p = p->pNext;
+ if( p )
+ return p->GetLocals();
+ else
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// SbiInstance //
+//////////////////////////////////////////////////////////////////////////
+
+// Achtung: pMeth kann auch NULL sein (beim Aufruf des Init-Codes)
+
+SbiRuntime::SbiRuntime( SbModule* pm, SbMethod* pe, USHORT nStart )
+ : pMeth( pe ), pMod( pm ), pImg( pMod->pImage ),
+ rBasic( *(StarBASIC*)pm->pParent ), pInst( pINST )
+{
+ nFlags = pe ? pe->GetDebugFlags() : 0;
+ pIosys = pInst->pIosys;
+ pArgvStk = NULL;
+ pGosubStk = NULL;
+ pForStk = NULL;
+ pError = NULL;
+ pErrCode =
+ pErrStmnt =
+ pRestart = NULL;
+ pNext = NULL;
+ pCode =
+ pStmnt = (const BYTE* ) pImg->GetCode() + nStart;
+ bRun =
+ bError = TRUE;
+ bInError = FALSE;
+ nLine =
+ nCol1 =
+ nCol2 =
+ nExprLvl =
+ nArgc =
+ nError =
+ nGosubLvl =
+ nOps = 0;
+ refExprStk = new SbxArray;
+#if defined GCC
+ SetParameters( pe ? pe->GetParameters() : (class SbxArray *)NULL );
+#else
+ SetParameters( pe ? pe->GetParameters() : NULL );
+#endif
+ pRefSaveList = NULL;
+ pItemStoreList = NULL;
+}
+
+SbiRuntime::~SbiRuntime()
+{
+ ClearGosubStack();
+ ClearArgvStack();
+ ClearForStack();
+
+ // #74254 Items zum Sichern temporaere Referenzen freigeben
+ ClearRefs();
+ while( pItemStoreList )
+ {
+ RefSaveItem* pToDeleteItem = pItemStoreList;
+ pItemStoreList = pToDeleteItem->pNext;
+ delete pToDeleteItem;
+ }
+}
+
+// Aufbau der Parameterliste. Alle ByRef-Parameter werden direkt
+// uebernommen; von ByVal-Parametern werden Kopien angelegt. Falls
+// ein bestimmter Datentyp verlangt wird, wird konvertiert.
+
+void SbiRuntime::SetParameters( SbxArray* pParams )
+{
+ refParams = new SbxArray;
+ // fuer den Returnwert
+ refParams->Put( pMeth, 0 );
+ if( pParams )
+ {
+ SbxInfo* pInfo = pMeth->GetInfo();
+ for( USHORT i = 1; i < pParams->Count(); i++ )
+ {
+ const SbxParamInfo* p = pInfo ? pInfo->GetParam( i ) : NULL;
+ SbxVariable* v = pParams->Get( i );
+ // Methoden sind immer byval!
+ BOOL bByVal = v->IsA( TYPE(SbxMethod) );
+ SbxDataType t = v->GetType();
+ if( p )
+ {
+ bByVal |= BOOL( ( p->eType & SbxBYREF ) == 0 );
+ t = (SbxDataType) ( p->eType & 0x0FFF );
+ }
+ if( bByVal )
+ {
+ SbxVariable* v2 = new SbxVariable( t );
+ v2->SetFlag( SBX_READWRITE );
+ *v2 = *v;
+ refParams->Put( v2, i );
+ }
+ else
+ {
+ if( t != SbxVARIANT && t != ( v->GetType() & 0x0FFF ) )
+ {
+ // Array konvertieren??
+ if( p && (p->eType & SbxARRAY) )
+ Error( SbERR_CONVERSION );
+ else
+ v->Convert( t );
+ }
+ refParams->Put( v, i );
+ }
+ if( p )
+ refParams->PutAlias( p->aName, i );
+ }
+ }
+}
+
+// Einen P-Code ausfuehren
+
+BOOL SbiRuntime::Step()
+{
+ if( bRun )
+ {
+ // Unbedingt gelegentlich die Kontrolle abgeben!
+ if( pInst->IsReschedule() && !( ++nOps & 0x1F ) )
+ Application::Reschedule();
+
+ SbiOpcode eOp = (SbiOpcode ) ( *pCode++ );
+ USHORT nOp1, nOp2;
+ if( eOp <= SbOP0_END )
+ {
+ (this->*( aStep0[ eOp ] ) )();
+ }
+ else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
+ {
+ nOp1 = *pCode++; nOp1 |= *pCode++ << 8;
+ (this->*( aStep1[ eOp - SbOP1_START ] ) )( nOp1 );
+ }
+ else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
+ {
+ nOp1 = *pCode++; nOp1 |= *pCode++ << 8;
+ nOp2 = *pCode++; nOp2 |= *pCode++ << 8;
+ (this->*( aStep2[ eOp - SbOP2_START ] ) )( nOp1, nOp2 );
+ }
+ else
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+
+ // SBX-Fehler aufgetreten?
+ SbError nSbError = SbxBase::GetError();
+ Error( ERRCODE_TOERROR(nSbError) ); // Warnings rausfiltern
+
+ // AB 13.2.1997, neues Error-Handling:
+ // ACHTUNG: Hier kann nError auch dann gesetzt sein, wenn !nSbError,
+ // da nError jetzt auch von anderen RT-Instanzen gesetzt werden kann
+
+ if( nError )
+ SbxBase::ResetError();
+
+ // AB,15.3.96: Fehler nur anzeigen, wenn BASIC noch aktiv
+ // (insbesondere nicht nach Compiler-Fehlern zur Laufzeit)
+ if( nError && bRun )
+ {
+ SbError err = nError;
+ ClearExprStack();
+ nError = 0;
+ // Im Error Handler? Dann Std-Error
+ if( bInError )
+ {
+ StepSTDERROR();
+ pInst->Abort();
+ }
+ else
+ {
+ bInError = TRUE;
+
+ pInst->nErr = err;
+ pInst->nErl = nLine;
+ pErrCode = pCode;
+ pErrStmnt = pStmnt;
+ if( !bError ) // On Error Resume Next
+ StepRESUME( 1 );
+ else if( pError ) // On Error Goto ...
+ pCode = pError;
+ else // Standard-Fehlerbehandlung
+ {
+ // AB 13.2.1997, neues Error-Handling:
+ // Uebergeordnete Error-Handler beruecksichtigen
+
+ // Wir haben keinen Error-Handler -> weiter oben suchen
+ SbiRuntime* pRtErrHdl = NULL;
+ SbiRuntime* pRt = this;
+ while( NULL != (pRt = pRt->pNext) )
+ {
+ // Gibt es einen Error-Handler?
+ if( pRt->bError == FALSE || pRt->pError != NULL )
+ {
+ pRtErrHdl = pRt;
+ break;
+ }
+ }
+
+ // Error-Hdl gefunden?
+ if( pRtErrHdl )
+ {
+ // (Neuen) Error-Stack anlegen
+ SbErrorStack*& rErrStack = GetSbData()->pErrStack;
+ if( rErrStack )
+ delete rErrStack;
+ rErrStack = new SbErrorStack();
+
+ // Alle im Call-Stack darunter stehenden RTs manipulieren
+ pRt = this;
+ do
+ {
+ // Fehler setzen
+ pRt->nError = err;
+ if( pRt != pRtErrHdl )
+ pRt->bRun = FALSE;
+
+ // In Error-Stack eintragen
+ SbErrorStackEntry *pEntry = new SbErrorStackEntry
+ ( pRt->pMeth, pRt->nLine, pRt->nCol1, pRt->nCol2 );
+ rErrStack->C40_INSERT(SbErrorStackEntry, pEntry, rErrStack->Count() );
+
+ // Nach RT mit Error-Handler aufhoeren
+ if( pRt == pRtErrHdl )
+ break;
+ }
+ while( pRt = pRt->pNext );
+ }
+ // Kein Error-Hdl gefunden -> altes Vorgehen
+ else
+ {
+ pInst->Abort();
+ }
+
+ // ALT: Nur
+ // pInst->Abort();
+ }
+ }
+ }
+ }
+ return bRun;
+}
+
+void SbiRuntime::Error( SbError n )
+{
+ if( n )
+ nError = n;
+}
+
+void SbiRuntime::FatalError( SbError n )
+{
+ StepSTDERROR();
+ Error( n );
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Parameter, Locals, Caller
+//
+//////////////////////////////////////////////////////////////////////////
+
+SbMethod* SbiRuntime::GetCaller()
+{
+ return pMeth;
+}
+
+SbxArray* SbiRuntime::GetLocals()
+{
+ return refLocals;
+}
+
+SbxArray* SbiRuntime::GetParams()
+{
+ return refParams;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Stacks
+//
+//////////////////////////////////////////////////////////////////////////
+
+// Der Expression-Stack steht fuer die laufende Auswertung von Expressions
+// zur Verfuegung.
+
+void SbiRuntime::PushVar( SbxVariable* pVar )
+{
+ if( pVar )
+ refExprStk->Put( pVar, nExprLvl++ );
+}
+
+SbxVariableRef SbiRuntime::PopVar()
+{
+#ifndef PRODUCT
+ if( !nExprLvl )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return new SbxVariable;
+ }
+#endif
+ SbxVariableRef xVar = refExprStk->Get( --nExprLvl );
+#ifdef DBG_UTIL
+ if ( xVar->GetName().EqualsAscii( "Cells" ) )
+ DBG_TRACE( "" );
+#endif
+ // Methods halten im 0.Parameter sich selbst, also weghauen
+ if( xVar->IsA( TYPE(SbxMethod) ) )
+ xVar->SetParameters(0);
+ return xVar;
+}
+
+BOOL SbiRuntime::ClearExprStack()
+{
+ // #74732 Hier kann ein Fehler gesetzt werden
+ BOOL bErrorSet = FALSE;
+
+ // Achtung: Clear() reicht nicht, da Methods geloescht werden muessen
+ while ( nExprLvl )
+ {
+ SbxVariableRef xVar = PopVar();
+ if( !nError && xVar->ISA( UnoClassMemberVariable ) )
+ {
+ Error( SbERR_NO_METHOD );
+ bErrorSet = TRUE;
+ }
+ }
+ refExprStk->Clear();
+ return bErrorSet;
+}
+
+// Variable auf dem Expression-Stack holen, ohne sie zu entfernen
+// n zaehlt ab 0.
+
+SbxVariable* SbiRuntime::GetTOS( short n )
+{
+ n = nExprLvl - n - 1;
+#ifndef PRODUCT
+ if( n < 0 )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return new SbxVariable;
+ }
+#endif
+ return refExprStk->Get( (USHORT) n );
+}
+
+// Sicherstellen, dass TOS eine temporaere Variable ist
+
+void SbiRuntime::TOSMakeTemp()
+{
+ SbxVariable* p = refExprStk->Get( nExprLvl - 1 );
+ if( p->GetRefCount() != 1 )
+ {
+ // #74573 UnoClassSbxVariable spezialbehandeln
+ SbxVariable* pNew;
+ if( p->ISA( UnoClassSbxVariable ) )
+ pNew = new UnoClassSbxVariable( *(UnoClassSbxVariable*)p );
+ else
+ pNew = new SbxVariable( *p );
+ pNew->SetFlag( SBX_READWRITE );
+ refExprStk->Put( pNew, nExprLvl - 1 );
+ }
+}
+
+// Der GOSUB-Stack nimmt Returnadressen fuer GOSUBs auf
+
+void SbiRuntime::PushGosub( const BYTE* pc )
+{
+ if( ++nGosubLvl > MAXRECURSION )
+ StarBASIC::FatalError( SbERR_STACK_OVERFLOW );
+ SbiGosubStack* p = new SbiGosubStack;
+ p->pCode = pc;
+ p->pNext = pGosubStk;
+ pGosubStk = p;
+}
+
+void SbiRuntime::PopGosub()
+{
+ if( !pGosubStk )
+ Error( SbERR_NO_GOSUB );
+ else
+ {
+ SbiGosubStack* p = pGosubStk;
+ pCode = p->pCode;
+ pGosubStk = p->pNext;
+ delete p;
+ nGosubLvl--;
+ }
+}
+
+// Entleeren des GOSUB-Stacks
+
+void SbiRuntime::ClearGosubStack()
+{
+ SbiGosubStack* p;
+ while(( p = pGosubStk ) != NULL )
+ pGosubStk = p->pNext, delete p;
+ nGosubLvl = 0;
+}
+
+// Der Argv-Stack nimmt aktuelle Argument-Vektoren auf
+
+void SbiRuntime::PushArgv()
+{
+ SbiArgvStack* p = new SbiArgvStack;
+ p->refArgv = refArgv;
+ p->nArgc = nArgc;
+ nArgc = 1;
+ refArgv.Clear();
+ p->pNext = pArgvStk;
+ pArgvStk = p;
+}
+
+void SbiRuntime::PopArgv()
+{
+ if( pArgvStk )
+ {
+ SbiArgvStack* p = pArgvStk;
+ pArgvStk = p->pNext;
+ refArgv = p->refArgv;
+ nArgc = p->nArgc;
+ delete p;
+ }
+}
+
+// Entleeren des Argv-Stacks
+
+void SbiRuntime::ClearArgvStack()
+{
+ while( pArgvStk )
+ PopArgv();
+}
+
+// Push des For-Stacks. Der Stack hat Inkrement, Ende, Beginn und Variable.
+// Nach Aufbau des Stack-Elements ist der Stack leer.
+
+void SbiRuntime::PushFor()
+{
+ SbiForStack* p = new SbiForStack;
+ p->pNext = pForStk;
+ pForStk = p;
+ // Der Stack ist wie folgt aufgebaut:
+ p->refInc = PopVar();
+ p->refEnd = PopVar();
+ SbxVariableRef xBgn = PopVar();
+ p->refVar = PopVar();
+ *(p->refVar) = *xBgn;
+}
+
+// Poppen des FOR-Stacks
+
+void SbiRuntime::PopFor()
+{
+ if( pForStk )
+ {
+ SbiForStack* p = pForStk;
+ pForStk = p->pNext;
+ delete p;
+ }
+}
+
+// Entleeren des FOR-Stacks
+
+void SbiRuntime::ClearForStack()
+{
+ while( pForStk )
+ PopFor();
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// DLL-Aufrufe
+//
+//////////////////////////////////////////////////////////////////////////
+
+void SbiRuntime::DllCall
+ ( const String& aFuncName, // Funktionsname
+ const String& aDLLName, // Name der DLL
+ SbxArray* pArgs, // Parameter (ab Index 1, kann NULL sein)
+ SbxDataType eResType, // Returnwert
+ BOOL bCDecl ) // TRUE: nach C-Konventionen
+{
+ // No DllCall for "virtual" portal users
+ if( needSecurityRestrictions() )
+ {
+ StarBASIC::Error(SbERR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ // MUSS NOCH IMPLEMENTIERT WERDEN
+ /*
+ String aMsg;
+ aMsg = "FUNC=";
+ aMsg += pFunc;
+ aMsg += " DLL=";
+ aMsg += pDLL;
+ MessBox( NULL, WB_OK, String( "DLL-CALL" ), aMsg ).Execute();
+ Error( SbERR_NOT_IMPLEMENTED );
+ */
+
+ SbxVariable* pRes = new SbxVariable( eResType );
+ SbiDllMgr* pDllMgr = pInst->GetDllMgr();
+ ByteString aByteFuncName( aFuncName, gsl_getSystemTextEncoding() );
+ ByteString aByteDLLName( aDLLName, gsl_getSystemTextEncoding() );
+ SbError nErr = pDllMgr->Call( aByteFuncName.GetBuffer(), aByteDLLName.GetBuffer(), pArgs, *pRes, bCDecl );
+ if( nErr )
+ Error( nErr );
+ PushVar( pRes );
+}
+