summaryrefslogtreecommitdiff
path: root/basic/source/comp/dim.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
commitcb1a7c1869062c789c65bc55285e6b18fcf378e0 (patch)
treea084b702d7cce826b3b68cb69be833eeedd6bedb /basic/source/comp/dim.cxx
initial import
Diffstat (limited to 'basic/source/comp/dim.cxx')
-rw-r--r--basic/source/comp/dim.cxx792
1 files changed, 792 insertions, 0 deletions
diff --git a/basic/source/comp/dim.cxx b/basic/source/comp/dim.cxx
new file mode 100644
index 0000000000..4fc9eb6560
--- /dev/null
+++ b/basic/source/comp/dim.cxx
@@ -0,0 +1,792 @@
+/*************************************************************************
+ *
+ * $RCSfile: dim.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:12:10 $
+ *
+ * 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): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <svtools/sbx.hxx>
+#include "sbcomp.hxx"
+#pragma hdrstop
+
+#include "segmentc.hxx"
+#pragma SW_SEGMENT_CLASS( SBCOMP, SBCOMP_CODE )
+
+// Deklaration einer Variablen
+// Bei Fehlern wird bis zum Komma oder Newline geparst.
+// Returnwert: eine neue Instanz, die eingefuegt und dann geloescht wird.
+// Array-Indexe werden als SbiDimList zurueckgegeben
+
+SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, BOOL bStatic, BOOL bConst )
+{
+ if( !TestSymbol() ) return NULL;
+ SbxDataType t = eScanType;
+ SbiSymDef* pDef = bConst ? new SbiConstDef( aSym ) : new SbiSymDef( aSym );
+ SbiDimList* pDim = NULL;
+ // Klammern?
+ if( Peek() == LPAREN )
+ pDim = new SbiDimList( this );
+ pDef->SetType( t );
+ if( bStatic )
+ pDef->SetStatic();
+ TypeDecl( *pDef );
+ if( !ppDim && pDim )
+ {
+ if(pDim->GetDims() )
+ Error( SbERR_EXPECTED, "()" );
+ delete pDim;
+ }
+ else if( ppDim )
+ *ppDim = pDim;
+ return pDef;
+}
+
+// Aufloesen einer AS-Typdeklaration
+// Der Datentyp wird in die uebergebene Variable eingetragen
+
+void SbiParser::TypeDecl( SbiSymDef& rDef )
+{
+ SbxDataType eType = rDef.GetType();
+ short nSize = 0;
+ if( Peek() == AS )
+ {
+#ifdef VBSCRIPT_TEST
+ Error( ERRCODE_BASIC_NOT_IN_VBSCRIPT );
+#endif
+ Next();
+ rDef.SetDefinedAs();
+ String aType;
+ SbiToken eTok = Next();
+ if( eTok == NEW )
+ {
+ rDef.SetNew();
+ eTok = Next();
+ }
+ switch( eTok )
+ {
+ case ANY:
+ if( rDef.IsNew() )
+ Error( SbERR_SYNTAX );
+ eType = SbxVARIANT; break;
+ case TINTEGER:
+ case TLONG:
+ case TSINGLE:
+ case TDOUBLE:
+ case TCURRENCY:
+ case TDATE:
+ case TSTRING:
+ case TOBJECT:
+ case _ERROR_:
+ case TBOOLEAN:
+ case TVARIANT:
+ if( rDef.IsNew() )
+ Error( SbERR_SYNTAX );
+ eType = SbxDataType( eTok - TINTEGER + SbxINTEGER );
+ if( eType == SbxSTRING )
+ {
+ // STRING*n ?
+ if( Peek() == MUL )
+ { // fixed size!
+ Next();
+ SbiConstExpression aSize( this );
+ nSize = aSize.GetShortValue();
+ if( nSize < 0 )
+ Error( SbERR_OUT_OF_RANGE );
+ }
+ }
+ break;
+ case SYMBOL: // kann nur ein TYPE oder eine Objektklasse sein!
+ if( eScanType != SbxVARIANT )
+ Error( SbERR_SYNTAX );
+ else
+ {
+ String aCompleteName = aSym;
+
+ // #52709 DIM AS NEW fuer Uno mit voll-qualifizierten Namen
+ if( Peek() == DOT )
+ {
+ String aDotStr( '.' );
+ while( Peek() == DOT )
+ {
+ aCompleteName += aDotStr;
+ Next();
+ if( Peek() == SYMBOL )
+ {
+ Next();
+ aCompleteName += aSym;
+ }
+ else
+ {
+ Next();
+ Error( SbERR_UNEXPECTED, SYMBOL );
+ break;
+ }
+ }
+ }
+
+ // In den String-Pool uebernehmen
+ rDef.SetTypeId( aGblStrings.Add( aCompleteName ) );
+ }
+ eType = SbxOBJECT;
+ break;
+ default:
+ Error( SbERR_UNEXPECTED, eTok );
+ Next();
+ }
+ // Die Variable koennte mit Suffix deklariert sein
+ if( rDef.GetType() != SbxVARIANT )
+ {
+ if( rDef.GetType() != eType )
+ Error( SbERR_VAR_DEFINED, rDef.GetName() );
+ else if( eType == SbxSTRING && rDef.GetLen() != nSize )
+ Error( SbERR_VAR_DEFINED, rDef.GetName() );
+ }
+ rDef.SetType( eType );
+ rDef.SetLen( nSize );
+ }
+}
+
+// Hier werden Variable, Arrays und Strukturen definiert.
+// DIM/PRIVATE/PUBLIC/GLOBAL
+
+void SbiParser::Dim()
+{
+ DefVar( _DIM, FALSE );
+}
+
+void SbiParser::DefVar( SbiOpcode eOp, BOOL bStatic )
+{
+ SbiSymPool* pOldPool = pPool;
+ BOOL bSwitchPool = FALSE;
+ if( pProc && ( eCurTok == GLOBAL || eCurTok == PUBLIC || eCurTok == PRIVATE ) )
+ Error( SbERR_NOT_IN_SUBR, eCurTok );
+ if( eCurTok == PUBLIC || eCurTok == GLOBAL )
+ bSwitchPool = TRUE; // im richtigen Moment auf globalen Pool schalten
+ //pPool = &aGlobals;
+ // PRIVATE ist Synonym fuer DIM
+ // _CONST_?
+ BOOL bConst = FALSE;
+ if( eCurTok == _CONST_ )
+ bConst = TRUE;
+ else if( Peek() == _CONST_ )
+ Next(), bConst = TRUE;
+#ifdef SHARED
+#define tmpSHARED
+#undef SHARED
+#endif
+ // SHARED wird ignoriert
+ if( Peek() == SHARED ) Next();
+#ifdef tmpSHARED
+#define SHARED
+#undef tmpSHARED
+#endif
+ // PRESERVE nur bei REDIM
+ if( Peek() == PRESERVE )
+ {
+ Next();
+ if( eOp == _REDIM )
+ eOp = _REDIMP;
+ else
+ Error( SbERR_UNEXPECTED, eCurTok );
+ }
+ SbiSymDef* pDef;
+ SbiDimList* pDim;
+
+ // AB 9.7.97, #40689, Statics -> Modul-Initialisierung, in Sub ueberspringen
+ USHORT nEndOfStaticLbl;
+ if( bStatic )
+ {
+ nEndOfStaticLbl = aGen.Gen( _JUMP, 0 );
+ aGen.Statement(); // bei static hier nachholen
+ }
+
+ BOOL bDefined = FALSE;
+ while( ( pDef = VarDecl( &pDim, bStatic, bConst ) ) != NULL )
+ {
+ EnableErrors();
+ // Variable suchen:
+ if( bSwitchPool )
+ pPool = &aGlobals;
+ SbiSymDef* pOld = pPool->Find( pDef->GetName() );
+ // AB 31.3.1996, #25651#, auch in Runtime-Library suchen
+ BOOL bRtlSym = FALSE;
+ if( !pOld )
+ {
+ pOld = CheckRTLForSym( pDef->GetName(), SbxVARIANT );
+ if( pOld )
+ bRtlSym = TRUE;
+ }
+ if( pOld )
+ {
+ bDefined = TRUE;
+ // Bei RTL-Symbol immer Fehler
+ if( !bRtlSym && (eOp == _REDIM || eOp == _REDIMP) )
+ {
+ // Bei REDIM die Attribute vergleichen
+ if( pOld->IsStatic() || pOld->GetType() != pDef->GetType() )
+ Error( SbERR_VAR_DEFINED, pDef->GetName() );
+ }
+ else
+ Error( SbERR_VAR_DEFINED, pDef->GetName() );
+ delete pDef; pDef = pOld;
+ }
+ else
+ pPool->Add( pDef );
+
+ // #36374: Variable vor Unterscheidung IsNew() anlegen
+ // Sonst Error bei Dim Identifier As New Type und option explicit
+ if( !bDefined && ( !bConst || pDef->GetScope() == SbGLOBAL ) )
+ {
+ // Variable oder globale Konstante deklarieren
+ SbiOpcode eOp;
+ switch ( pDef->GetScope() )
+ {
+ case SbGLOBAL: eOp = _GLOBAL; goto global;
+ case SbPUBLIC: eOp = _PUBLIC;
+ // AB 9.7.97, #40689, kein eigener Opcode mehr
+ /*
+ if( bStatic )
+ {
+ eOp = _STATIC;
+ break;
+ }
+ */
+ global: aGen.BackChain( nGblChain );
+ nGblChain = 0;
+ bGblDefs = bNewGblDefs = TRUE;
+ break;
+ default: eOp = _LOCAL;
+ }
+ aGen.Gen( eOp, pDef->GetId(), pDef->GetType() );
+ }
+
+ // Initialisierung fuer selbstdefinierte Datentypen
+ // und per NEW angelegte Variable
+ if( pDef->GetType() == SbxOBJECT
+ && pDef->GetTypeId()
+ && pDef->IsNew() )
+// && ( pDef->IsNew() || pDef->HabIchAlsTypeDefiniert() ) )
+ {
+ if( bConst )
+ {
+ Error( SbERR_SYNTAX );
+ }
+
+ if( pDim )
+ {
+ pDef->SetDims( pDim->GetDims() );
+ SbiExpression aExpr( this, *pDef, pDim );
+ aExpr.Gen();
+ aGen.Gen( _DCREATE, pDef->GetId(), pDef->GetTypeId() );
+ }
+ else
+ {
+ SbiExpression aExpr( this, *pDef );
+ aExpr.Gen();
+ SbiOpcode eOp = pDef->IsNew() ? _CREATE : _TCREATE;
+ aGen.Gen( eOp, pDef->GetId(), pDef->GetTypeId() );
+ aGen.Gen( _SET );
+ }
+ }
+ else
+ {
+ if( bConst )
+ {
+ // Konstanten-Definition
+ if( pDim )
+ {
+ Error( SbERR_SYNTAX );
+ delete pDim;
+ }
+ SbiExpression aVar( this, *pDef );
+ if( !TestToken( EQ ) )
+ goto MyBreak; // AB 24.6.1996 (s.u.)
+ SbiConstExpression aExpr( this );
+ if( !bDefined && aExpr.IsValid() )
+ {
+ if( pDef->GetScope() == SbGLOBAL )
+ {
+ // Nur Code fuer globale Konstante erzeugen!
+ aVar.Gen();
+ aExpr.Gen();
+ aGen.Gen( _PUTC );
+ }
+ SbiConstDef* pConst = pDef->GetConstDef();
+ if( aExpr.GetType() == SbxSTRING )
+ pConst->Set( aExpr.GetString() );
+ else
+ pConst->Set( aExpr.GetValue(), aExpr.GetType() );
+ }
+ }
+ else if( pDim )
+ {
+ // Die Variable dimensionieren
+ // Bei REDIM die Var vorher loeschen
+ if( eOp == _REDIM )
+ {
+ SbiExpression aExpr( this, *pDef, NULL );
+ aExpr.Gen();
+ aGen.Gen( _ERASE );
+ }
+ pDef->SetDims( pDim->GetDims() );
+ SbiExpression aExpr( this, *pDef, pDim );
+ aExpr.Gen();
+ aGen.Gen( (eOp == _STATIC) ? _DIM : eOp );
+ }
+ }
+ if( !TestComma() )
+ goto MyBreak; // AB 24.6.1996 (s.u.)
+
+ // #27963# AB, 24.6.1996
+ // Einfuehrung bSwitchPool (s.o.): pPool darf beim VarDecl-Aufruf
+ // noch nicht auf &aGlobals gesetzt sein.
+ // Ansonsten soll das Verhalten aber absolut identisch bleiben,
+ // d.h. pPool muss immer am Schleifen-Ende zurueckgesetzt werden.
+ // auch bei break
+ pPool = pOldPool;
+ continue; // MyBreak überspingen
+ MyBreak:
+ pPool = pOldPool;
+ break;
+ }
+
+ // AB 9.7.97, #40689, Sprung ueber Statics-Deklaration abschliessen
+ if( bStatic )
+ {
+ // globalen Chain pflegen
+ nGblChain = aGen.Gen( _JUMP, 0 );
+ bGblDefs = bNewGblDefs = TRUE;
+
+ // fuer Sub Sprung auf Ende der statics eintragen
+ aGen.BackChain( nEndOfStaticLbl );
+ }
+
+ //pPool = pOldPool;
+}
+
+// Hier werden Arrays redimensioniert.
+
+void SbiParser::ReDim()
+{
+ DefVar( _REDIM, FALSE );
+}
+
+// ERASE array, ...
+
+void SbiParser::Erase()
+{
+ while( !bAbort )
+ {
+ if( !TestSymbol() ) return;
+ String aName( aSym );
+ SbxDataType eType = eScanType;
+ SbiSymDef* pDef = pPool->Find( aName );
+ if( !pDef )
+ {
+ if( bExplicit )
+ Error( SbERR_UNDEF_VAR, aName );
+ pDef = pPool->AddSym( aName );
+ pDef->SetType( eType );
+ }
+ SbiExpression aExpr( this, *pDef );
+ aExpr.Gen();
+ aGen.Gen( _ERASE );
+ if( !TestComma() ) break;
+ }
+}
+
+// Deklaration eines Datentyps
+
+void SbiParser::Type()
+{
+ // Neues Token lesen, es muss ein Symbol sein
+ if (!TestSymbol())
+ return;
+
+ if (rTypeArray->Find(aSym,SbxCLASS_OBJECT))
+ {
+ Error( SbERR_VAR_DEFINED, aSym );
+ return;
+ }
+
+ SbxObject *pType = new SbxObject(aSym);
+
+ SbiSymDef* pElem;
+ SbiDimList* pDim;
+ BOOL bDone = FALSE;
+
+ while( !bDone && !IsEof() )
+ {
+ switch (Next())
+ {
+ case ENDTYPE :
+ pElem = NULL;
+ bDone = TRUE;
+ break;
+
+ case EOLN :
+ pElem = NULL;
+ break;
+
+ default:
+ pDim = NULL;
+ pElem = VarDecl(&pDim,FALSE,FALSE);
+ if( pDim )
+ {
+ // HOT FIX, to be updated
+ delete pDim;
+ Error( SbERR_NO_STRINGS_ARRAYS );
+ }
+
+ }
+ if( pElem )
+ {
+ SbxArray *pTypeMembers = pType -> GetProperties();
+ if (pTypeMembers -> Find (pElem->GetName(),SbxCLASS_DONTCARE))
+ Error (SbERR_VAR_DEFINED);
+ else
+ {
+ SbxProperty *pTypeElem = new SbxProperty (pElem->GetName(),pElem->GetType());
+ pTypeMembers -> Insert (pTypeElem,pTypeMembers->Count());
+ }
+ delete pElem;
+ }
+ }
+ rTypeArray->Insert (pType,rTypeArray->Count());
+}
+/**********************************************************
+ // Variablennamen einlesen:
+ if( !TestSymbol() ) return;
+ String aName( aSym );
+ if( pDEFS->Find( aName ) )
+ {
+ Error( SbERR_VAR_DEFINED, aName ); return;
+ }
+ SbTypeDef* pDef = pDEFS->AddTypeDef( aName );
+ TestEoln();
+
+ // Deklarationen parsen:
+ SbiSymDef* pElem;
+ SbiDimList* pDim;
+ BOOL bDone = FALSE;
+ while( !IsEof() && !bDone )
+ {
+ switch( Next() )
+ {
+ case SUB:
+ case FUNCTION:
+ pElem = ProcDecl( TRUE ); break;
+ case END:
+ pElem = NULL;
+ bDone = TRUE;
+ if( Next() != TYPE )
+ Error( SbERR_EXPECTED, TYPE );
+ break;
+ default:
+ pElem = VarDecl( &pDim );
+ if( pDim )
+ {
+ // HOT FIX, to be updated
+ delete pDim;
+ Error( SbERR_NO_STRINGS_ARRAYS );
+ }
+ }
+ if( pElem )
+ pDef->GetPool().Add( *pElem );
+ delete pElem;
+ }
+}
+************************************************/
+
+// Prozedur-Deklaration
+// das erste Token ist bereits eingelesen (SUB/FUNCTION)
+// xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]
+
+SbiProcDef* SbiParser::ProcDecl( BOOL bDecl )
+{
+ BOOL bFunc = BOOL( eCurTok == FUNCTION );
+ if( !TestSymbol() ) return NULL;
+ String aName( aSym );
+ SbxDataType eType = eScanType;
+ SbiProcDef* pDef = new SbiProcDef( this, aName );
+ pDef->SetType( eType );
+ if( Peek() == _CDECL_ )
+ {
+ Next(); pDef->SetCdecl();
+ }
+ if( Peek() == LIB )
+ {
+ Next();
+ if( Next() == FIXSTRING )
+ pDef->GetLib() = aSym;
+ else
+ Error( SbERR_SYNTAX );
+ }
+ if( Peek() == ALIAS )
+ {
+ Next();
+ if( Next() == FIXSTRING )
+ pDef->GetAlias() = aSym;
+ else
+ Error( SbERR_SYNTAX );
+ }
+ if( !bDecl )
+ {
+ // CDECL, LIB und ALIAS sind unzulaessig
+ if( pDef->GetLib().Len() )
+ Error( SbERR_UNEXPECTED, LIB );
+ if( pDef->GetAlias().Len() )
+ Error( SbERR_UNEXPECTED, ALIAS );
+ if( pDef->IsCdecl() )
+ Error( SbERR_UNEXPECTED, _CDECL_ );
+ pDef->SetCdecl( FALSE );
+ pDef->GetLib().Erase();
+ pDef->GetAlias().Erase();
+ }
+ else if( !pDef->GetLib().Len() )
+ {
+ // ALIAS und CDECL nur zusammen mit LIB
+ if( pDef->GetAlias().Len() )
+ Error( SbERR_UNEXPECTED, ALIAS );
+ if( pDef->IsCdecl() )
+ Error( SbERR_UNEXPECTED, _CDECL_ );
+ pDef->SetCdecl( FALSE );
+ pDef->GetAlias().Erase();
+ }
+ // Klammern?
+ if( Peek() == LPAREN )
+ {
+ Next();
+ if( Peek() == RPAREN )
+ Next();
+ else
+ for(;;) {
+ BOOL bByVal = FALSE;
+ BOOL bOptional = FALSE;
+ while( Peek() == BYVAL || Peek() == _OPTIONAL_ )
+ {
+ if ( Peek() == BYVAL ) Next(), bByVal = TRUE;
+ else if ( Peek() == _OPTIONAL_ ) Next(), bOptional = TRUE;
+ }
+ SbiSymDef* pPar = VarDecl( NULL, FALSE, FALSE );
+ if( !pPar )
+ break;
+ if( bByVal )
+ pPar->SetByVal();
+ if( bOptional )
+ pPar->SetOptional();
+ pDef->GetParams().Add( pPar );
+ SbiToken eTok = Next();
+ if( eTok != COMMA && eTok != RPAREN )
+ {
+ Error( SbERR_EXPECTED, RPAREN );
+ break;
+ }
+ if( eTok == RPAREN )
+ break;
+ }
+ }
+ TypeDecl( *pDef );
+ if( eType != SbxVARIANT && pDef->GetType() != eType )
+ Error( SbERR_BAD_DECLARATION, aName );
+// if( pDef->GetType() == SbxOBJECT )
+// pDef->SetType( SbxVARIANT ),
+// Error( SbERR_SYNTAX );
+ if( pDef->GetType() == SbxVARIANT && !bFunc )
+ pDef->SetType( SbxEMPTY );
+ return pDef;
+}
+
+// DECLARE
+
+void SbiParser::Declare()
+{
+ Next();
+ if( eCurTok != SUB && eCurTok != FUNCTION )
+ Error( SbERR_UNEXPECTED, eCurTok );
+ else
+ {
+ SbiProcDef* pDef = ProcDecl( TRUE );
+ if( pDef )
+ {
+ if( !pDef->GetLib().Len() )
+ Error( SbERR_EXPECTED, LIB );
+ // gibts den schon?
+ SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
+ if( pOld )
+ {
+ SbiProcDef* p = pOld->GetProcDef();
+ if( !p )
+ {
+ // Als Variable deklariert
+ Error( SbERR_BAD_DECLARATION, pDef->GetName() );
+ delete pDef;
+ }
+ else
+ pDef->Match( p );
+ }
+ else
+ aPublics.Add( pDef );
+ }
+ }
+}
+
+// Aufruf einer SUB oder FUNCTION
+
+void SbiParser::Call()
+{
+ String aName( aSym );
+ SbiExpression aVar( this, SbSYMBOL );
+ aVar.Gen();
+ aGen.Gen( _GET );
+}
+
+// SUB/FUNCTION
+
+void SbiParser::SubFunc()
+{
+ DefProc( FALSE );
+}
+
+// Einlesen einer Prozedur
+
+void SbiParser::DefProc( BOOL bStatic )
+{
+ USHORT l1 = nLine, l2 = nLine;
+ BOOL bSub = BOOL( eCurTok == SUB );
+ SbiToken eExit = eCurTok;
+ SbiProcDef* pDef = ProcDecl( FALSE );
+ if( !pDef )
+ return;
+
+ // Ist die Proc bereits deklariert?
+ SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
+ if( pOld )
+ {
+ pProc = pOld->GetProcDef();
+ if( !pProc )
+ {
+ // Als Variable deklariert
+ Error( SbERR_BAD_DECLARATION, pDef->GetName() );
+ delete pDef;
+ pProc = NULL;
+ }
+ else
+ {
+ pDef->Match( pProc );
+ pProc = pDef;
+ }
+ }
+ else
+ aPublics.Add( pDef ), pProc = pDef;
+
+ if( !pProc )
+ return;
+
+ // Nun setzen wir die Suchhierarchie fuer Symbole sowie die aktuelle
+ // Prozedur.
+ aPublics.SetProcId( pProc->GetId() );
+ pProc->GetParams().SetParent( &aPublics );
+ if( !bStatic )
+ {
+ // Normalfall: Lokale Variable->Parameter->Globale Variable
+ pProc->GetLocals().SetParent( &pProc->GetParams() );
+ pPool = &pProc->GetLocals();
+ }
+ else
+ {
+ Error( SbERR_NOT_IMPLEMENTED ); // STATIC SUB ...
+ }
+
+ pProc->Define();
+ OpenBlock( eExit );
+ StmntBlock( bSub ? ENDSUB : ENDFUNC );
+ l2 = nLine;
+ pProc->SetLine1( l1 );
+ pProc->SetLine2( l2 );
+ pPool = &aPublics;
+ aPublics.SetProcId( 0 );
+ // Offene Labels?
+ pProc->GetLabels().CheckRefs();
+ CloseBlock();
+ aGen.Gen( _LEAVE );
+ pProc = NULL;
+}
+
+// STATIC variable|procedure
+
+void SbiParser::Static()
+{
+ switch( Peek() )
+ {
+ case SUB:
+ case FUNCTION:
+ Next();
+ DefProc( TRUE );
+ break;
+ default: {
+ if( !pProc )
+ Error( SbERR_NOT_IN_SUBR );
+ // Pool umsetzen, damit STATIC-Deklarationen im globalen
+ // Pool landen
+ SbiSymPool* p = pPool; pPool = &aPublics;
+ DefVar( _STATIC, TRUE );
+ pPool = p;
+ } break;
+ }
+}
+