/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basic.hxx"
#include <basic/sbx.hxx>
#include "sbcomp.hxx"

SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj );

// Deklaration einer Variablen
// Bei Fehlern wird bis zum Komma oder Newline geparst.
// Returnwert: eine neue Instanz, die eingefügt und dann gelöscht wird.
// Array-Indexe werden als SbiDimList zurückgegeben

SbiSymDef* SbiParser::VarDecl( SbiDimList** ppDim, sal_Bool bStatic, sal_Bool bConst )
{
	bool bWithEvents = false;
	if( Peek() == WITHEVENTS )
	{
		Next();
		bWithEvents = true;
	}
	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 );
		if( !pDim->GetDims() )
			pDef->SetWithBrackets();
	}
	pDef->SetType( t );
	if( bStatic )
		pDef->SetStatic();
	if( bWithEvents )
		pDef->SetWithEvents();
	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, sal_Bool bAsNewAlreadyParsed )
{
	SbxDataType eType = rDef.GetType();
	short nSize = 0;
	if( bAsNewAlreadyParsed || Peek() == AS )
	{
		if( !bAsNewAlreadyParsed )
			Next();
		rDef.SetDefinedAs();
		String aType;
		SbiToken eTok = Next();
		if( !bAsNewAlreadyParsed && 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:
			case TBYTE:
				if( rDef.IsNew() )
					Error( SbERR_SYNTAX );
				eType = (eTok==TBYTE) ? SbxBYTE : SbxDataType( eTok - TINTEGER + SbxINTEGER );
				if( eType == SbxSTRING )
				{
					// STRING*n ?
					if( Peek() == MUL )
					{		// fixed size!
						Next();
						SbiConstExpression aSize( this );
						nSize = aSize.GetShortValue();
						if( nSize < 0 || (bVBASupportOn && nSize <= 0) )
							Error( SbERR_OUT_OF_RANGE );
						else
							rDef.SetFixedStringLength( nSize );
					}
				}
				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();
							SbiToken ePeekTok = Peek();
							if( ePeekTok == SYMBOL || IsKwd( ePeekTok ) )
							{
								Next();
								aCompleteName += aSym;
							}
							else
							{
								Next();
								Error( SbERR_UNEXPECTED, SYMBOL );
								break;
							}
						}
					}
					else if( rEnumArray->Find( aCompleteName, SbxCLASS_OBJECT ) )
					{
						eType = SbxLONG;
						break;
					}

					// In den String-Pool uebernehmen
					rDef.SetTypeId( aGblStrings.Add( aCompleteName ) );

					if( rDef.IsNew() && pProc == NULL )
						aRequiredTypes.push_back( aCompleteName );
				}
				eType = SbxOBJECT;
				break;
			case FIXSTRING: // new syntax for complex UNO types
				rDef.SetTypeId( aGblStrings.Add( aSym ) );
				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, ( pProc && bVBASupportOn ) ? pProc->IsStatic() : sal_False );
}

void SbiParser::DefVar( SbiOpcode eOp, sal_Bool bStatic )
{
	SbiSymPool* pOldPool = pPool;
	sal_Bool bSwitchPool = sal_False;
	sal_Bool bPersistantGlobal = sal_False;
	SbiToken eFirstTok = eCurTok;
	if( pProc && ( eCurTok == GLOBAL || eCurTok == PUBLIC || eCurTok == PRIVATE ) )
		Error( SbERR_NOT_IN_SUBR, eCurTok );
	if( eCurTok == PUBLIC || eCurTok == GLOBAL )
	{
		bSwitchPool = sal_True;		// im richtigen Moment auf globalen Pool schalten
		if( eCurTok == GLOBAL )
			bPersistantGlobal = sal_True;
	}
	// behavior in VBA is that a module scope variable's lifetime is
	// tied to the document. e.g. a module scope variable is global
	if( GetBasic()->IsDocBasic() && bVBASupportOn && !pProc )
		bPersistantGlobal = sal_True;
	// PRIVATE ist Synonym fuer DIM
	// _CONST_?
	sal_Bool bConst = sal_False;
	if( eCurTok == _CONST_ )
		bConst = sal_True;
	else if( Peek() == _CONST_ )
		Next(), bConst = sal_True;

	// #110004 It can also be a sub/function
	if( !bConst && (eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY ||
					eCurTok == STATIC || eCurTok == ENUM || eCurTok == DECLARE || eCurTok == TYPE) )
	{
		// Next token is read here, because !bConst
		bool bPrivate = ( eFirstTok == PRIVATE );

		if( eCurTok == STATIC )
		{
			Next();
			DefStatic( bPrivate );
		}
		else if( eCurTok == SUB || eCurTok == FUNCTION || eCurTok == PROPERTY )
		{
			// End global chain if necessary (not done in
			// SbiParser::Parse() under these conditions
			if( bNewGblDefs && nGblChain == 0 )
			{
				nGblChain = aGen.Gen( _JUMP, 0 );
				bNewGblDefs = sal_False;
			}
			Next();
			DefProc( sal_False, bPrivate );
			return;
		}
		else if( eCurTok == ENUM )
		{
			Next();
			DefEnum( bPrivate );
			return;
		}
		else if( eCurTok == DECLARE )
		{
			Next();
			DefDeclare( bPrivate );
			return;
		}
		// #i109049
		else if( eCurTok == TYPE )
		{
			Next();
			DefType( bPrivate );
			return;
		}
	}

#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
	sal_uInt32 nEndOfStaticLbl = 0;
	if( !bVBASupportOn && bStatic )
	{
		nEndOfStaticLbl = aGen.Gen( _JUMP, 0 );
		aGen.Statement();	// bei static hier nachholen
	}

	sal_Bool bDefined = sal_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
		sal_Bool bRtlSym = sal_False;
		if( !pOld )
		{
			pOld = CheckRTLForSym( pDef->GetName(), SbxVARIANT );
			if( pOld )
				bRtlSym = sal_True;
		}
		if( pOld && !(eOp == _REDIM || eOp == _REDIMP) )
		{
			if( pDef->GetScope() == SbLOCAL && pOld->GetScope() != SbLOCAL )
				pOld = NULL;
		}
		if( pOld )
		{
			bDefined = sal_True;
			// Bei RTL-Symbol immer Fehler
			if( !bRtlSym && (eOp == _REDIM || eOp == _REDIMP) )
			{
				// Bei REDIM die Attribute vergleichen
				SbxDataType eDefType;
				bool bError_ = false;
				if( pOld->IsStatic() )
				{
					bError_ = true;
				}
				else if( pOld->GetType() != ( eDefType = pDef->GetType() ) )
				{
					if( !( eDefType == SbxVARIANT && !pDef->IsDefinedAs() ) )
						bError_ = true;
				}
				if( bError_ )
					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 && !(eOp == _REDIM || eOp == _REDIMP)
					  && ( !bConst || pDef->GetScope() == SbGLOBAL ) )
		{
			// Variable oder globale Konstante deklarieren
			SbiOpcode eOp2;
			switch ( pDef->GetScope() )
			{
				case SbGLOBAL:	eOp2 = bPersistantGlobal ? _GLOBAL_P : _GLOBAL;
								goto global;
				case SbPUBLIC:	eOp2 = bPersistantGlobal ? _PUBLIC_P : _PUBLIC;
								// AB 9.7.97, #40689, kein eigener Opcode mehr
								if( bVBASupportOn && bStatic )
								{
									eOp2 = _STATIC;
									break;
								}
				global:			aGen.BackChain( nGblChain );
								nGblChain = 0;
								bGblDefs = bNewGblDefs = sal_True;
								break;
				default:		eOp2 = _LOCAL;
			}
			sal_uInt32 nOpnd2 = sal::static_int_cast< sal_uInt16 >( pDef->GetType() );
			if( pDef->IsWithEvents() )
				nOpnd2 |= SBX_TYPE_WITH_EVENTS_FLAG;

			if( bCompatible && pDef->IsNew() )
				nOpnd2 |= SBX_TYPE_DIM_AS_NEW_FLAG;

			short nFixedStringLength = pDef->GetFixedStringLength();
			if( nFixedStringLength >= 0 )
				nOpnd2 |= (SBX_FIXED_LEN_STRING_FLAG + (sal_uInt32(nFixedStringLength) << 17));		// len = all bits above 0x10000

			if( pDim != NULL && pDim->GetDims() > 0 )
				nOpnd2 |= SBX_TYPE_VAR_TO_DIM_FLAG;

			aGen.Gen( eOp2, pDef->GetId(), nOpnd2 );
		}

		// Initialisierung fuer selbstdefinierte Datentypen
		// und per NEW angelegte Variable
		if( pDef->GetType() == SbxOBJECT
		 && pDef->GetTypeId() )
		{
			if( !bCompatible && !pDef->IsNew() )
			{
				String aTypeName( aGblStrings.Find( pDef->GetTypeId() ) );
				if( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) == NULL )
					Error( SbERR_UNDEF_TYPE, aTypeName );
			}

			if( bConst )
			{
				Error( SbERR_SYNTAX );
			}

			if( pDim )
			{
				if( eOp == _REDIMP )
				{
					SbiExpression aExpr( this, *pDef, NULL );
					aExpr.Gen();
					aGen.Gen( _REDIMP_ERASE );

					pDef->SetDims( pDim->GetDims() );
					SbiExpression aExpr2( this, *pDef, pDim );
					aExpr2.Gen();
					aGen.Gen( _DCREATE_REDIMP, pDef->GetId(), pDef->GetTypeId() );
				}
				else
				{
					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();
					if ( bVBASupportOn )
						// delete the array but
						// clear the variable ( this
						// allows the processing of
						// the param to happen as normal without errors ( ordinary ERASE just clears the array )
						aGen.Gen( _ERASE_CLEAR );
					else
						aGen.Gen( _ERASE );
				}
				else if( eOp == _REDIMP )
				{
					SbiExpression aExpr( this, *pDef, NULL );
					aExpr.Gen();
					aGen.Gen( _REDIMP_ERASE );
				}
				pDef->SetDims( pDim->GetDims() );
				if( bPersistantGlobal )
					pDef->SetGlobal( sal_True );
				SbiExpression aExpr( this, *pDef, pDim );
				aExpr.Gen();
				pDef->SetGlobal( sal_False );
				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( !bVBASupportOn && bStatic )
	{
		// globalen Chain pflegen
		nGblChain = aGen.Gen( _JUMP, 0 );
		bGblDefs = bNewGblDefs = sal_True;

		// fuer Sub Sprung auf Ende der statics eintragen
		aGen.BackChain( nEndOfStaticLbl );
	}

	//pPool = pOldPool;
}

// Hier werden Arrays redimensioniert.

void SbiParser::ReDim()
{
	DefVar( _REDIM, ( pProc && bVBASupportOn ) ? pProc->IsStatic() : sal_False );
}

// ERASE array, ...

void SbiParser::Erase()
{
	while( !bAbort )
	{
		SbiExpression aExpr( this, SbLVALUE );
		aExpr.Gen();
		aGen.Gen( _ERASE );
		if( !TestComma() ) break;
	}
}

// Deklaration eines Datentyps

void SbiParser::Type()
{
	DefType( sal_False );
}

void SbiParser::DefType( sal_Bool bPrivate )
{
	// TODO: Use bPrivate
	(void)bPrivate;

	// 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 = NULL;
	sal_Bool bDone = sal_False;

	while( !bDone && !IsEof() )
	{
		switch( Peek() )
		{
			case ENDTYPE :
				pElem = NULL;
				bDone = sal_True;
				Next();
			break;

			case EOLN :
			case REM :
				pElem = NULL;
				Next();
			break;

			default:
				pDim = NULL;
				pElem = VarDecl(&pDim,sal_False,sal_False);
				if( !pElem )
					bDone = sal_True;	// Error occurred
		}
		if( pElem )
		{
			SbxArray *pTypeMembers = pType->GetProperties();
			String aElemName = pElem->GetName();
			if( pTypeMembers->Find( aElemName, SbxCLASS_DONTCARE) )
				Error (SbERR_VAR_DEFINED);
			else
			{
				SbxDataType eElemType = pElem->GetType();
				SbxProperty *pTypeElem = new SbxProperty( aElemName, eElemType );
				if( pDim )
				{
					SbxDimArray* pArray = new SbxDimArray( pElem->GetType() );
					if ( pDim->GetSize() )
					{
						// Dimension the target array

						for ( short i=0; i<pDim->GetSize();++i )
						{
							sal_Int32 ub = -1;
							sal_Int32 lb = nBase;
							SbiExprNode* pNode = pDim->Get(i)->GetExprNode();
							ub = pNode->GetNumber();
							if ( !pDim->Get( i )->IsBased() ) // each dim is low/up
							{
								if ( ++i >= pDim->GetSize() ) // trouble
									StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
								pNode = pDim->Get(i)->GetExprNode();
								lb = ub;
								ub = pNode->GetNumber();
							}
							else if ( !bCompatible )
								ub += nBase;
							pArray->AddDim32( lb, ub );
						}
						pArray->setHasFixedSize( true );
					}
					else
						pArray->unoAddDim( 0, -1 ); // variant array
					sal_uInt16 nSavFlags = pTypeElem->GetFlags();
					// need to reset the FIXED flag
					// when calling PutObject ( because the type will not match Object )
					pTypeElem->ResetFlag( SBX_FIXED );
					pTypeElem->PutObject( pArray );
					pTypeElem->SetFlags( nSavFlags );
				}
				// Nested user type?
				if( eElemType == SbxOBJECT )
				{
					sal_uInt16 nElemTypeId = pElem->GetTypeId();
					if( nElemTypeId != 0 )
					{
						String aTypeName( aGblStrings.Find( nElemTypeId ) );
						SbxObject* pTypeObj = static_cast< SbxObject* >( rTypeArray->Find( aTypeName, SbxCLASS_OBJECT ) );
						if( pTypeObj != NULL )
						{
							SbxObject* pCloneObj = cloneTypeObjectImpl( *pTypeObj );
							pTypeElem->PutObject( pCloneObj );
						}
					}
				}
				delete pDim;
				pTypeMembers->Insert( pTypeElem, pTypeMembers->Count() );
			}
			delete pElem;
		}
	}

	pType->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
	pType->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );

	rTypeArray->Insert (pType,rTypeArray->Count());
}


// Declaration of Enum type

void SbiParser::Enum()
{
	DefEnum( sal_False );
}

void SbiParser::DefEnum( sal_Bool bPrivate )
{
	// Neues Token lesen, es muss ein Symbol sein
	if (!TestSymbol())
		return;

	String aEnumName = aSym;
	if( rEnumArray->Find(aEnumName,SbxCLASS_OBJECT) )
	{
		Error( SbERR_VAR_DEFINED, aSym );
		return;
	}

	SbxObject *pEnum = new SbxObject( aEnumName );
	if( bPrivate )
		pEnum->SetFlag( SBX_PRIVATE );

	SbiSymDef* pElem;
	SbiDimList* pDim;
	sal_Bool bDone = sal_False;

	// Starting with -1 to make first default value 0 after ++
	sal_Int32 nCurrentEnumValue = -1;
	while( !bDone && !IsEof() )
	{
		switch( Peek() )
		{
			case ENDENUM :
				pElem = NULL;
				bDone = sal_True;
				Next();
			break;

			case EOLN :
			case REM :
				pElem = NULL;
				Next();
			break;

			default:
			{
				// TODO: Check existing!
				sal_Bool bDefined = sal_False;

				pDim = NULL;
				pElem = VarDecl( &pDim, sal_False, sal_True );
				if( !pElem )
				{
					bDone = sal_True;	// Error occurred
					break;
				}
				else if( pDim )
				{
					delete pDim;
					Error( SbERR_SYNTAX );
					bDone = sal_True;	// Error occurred
					break;
				}

				SbiExpression aVar( this, *pElem );
				if( Peek() == EQ )
				{
					Next();

					SbiConstExpression aExpr( this );
					if( !bDefined && aExpr.IsValid() )
					{
						SbxVariableRef xConvertVar = new SbxVariable();
						if( aExpr.GetType() == SbxSTRING )
							xConvertVar->PutString( aExpr.GetString() );
						else
							xConvertVar->PutDouble( aExpr.GetValue() );

						nCurrentEnumValue = xConvertVar->GetLong();
					}
				}
				else
					nCurrentEnumValue++;

				SbiSymPool* pPoolToUse = bPrivate ? pPool : &aGlobals;

				SbiSymDef* pOld = pPoolToUse->Find( pElem->GetName() );
				if( pOld )
				{
					Error( SbERR_VAR_DEFINED, pElem->GetName() );
					bDone = sal_True;	// Error occurred
					break;
				}

				pPool->Add( pElem );

				if( !bPrivate )
				{
					SbiOpcode eOp = _GLOBAL;
					aGen.BackChain( nGblChain );
					nGblChain = 0;
					bGblDefs = bNewGblDefs = sal_True;
					aGen.Gen(
						eOp, pElem->GetId(),
						sal::static_int_cast< sal_uInt16 >( pElem->GetType() ) );

					aVar.Gen();
					sal_uInt16 nStringId = aGen.GetParser()->aGblStrings.Add( nCurrentEnumValue, SbxLONG );
					aGen.Gen( _NUMBER, nStringId );
					aGen.Gen( _PUTC );
				}

				SbiConstDef* pConst = pElem->GetConstDef();
				pConst->Set( nCurrentEnumValue, SbxLONG );
			}
		}
		if( pElem )
		{
			SbxArray *pEnumMembers = pEnum->GetProperties();
			SbxProperty *pEnumElem = new SbxProperty( pElem->GetName(), SbxLONG );
			pEnumElem->PutLong( nCurrentEnumValue );
			pEnumElem->ResetFlag( SBX_WRITE );
			pEnumElem->SetFlag( SBX_CONST );
			pEnumMembers->Insert( pEnumElem, pEnumMembers->Count() );
		}
	}

	pEnum->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_DONTCARE );
	pEnum->Remove( XubString( RTL_CONSTASCII_USTRINGPARAM("Parent") ), SbxCLASS_DONTCARE );

	rEnumArray->Insert( pEnum, rEnumArray->Count() );
}


// Prozedur-Deklaration
// das erste Token ist bereits eingelesen (SUB/FUNCTION)
// xxx Name [LIB "name"[ALIAS "name"]][(Parameter)][AS TYPE]

SbiProcDef* SbiParser::ProcDecl( sal_Bool bDecl )
{
	sal_Bool bFunc = sal_Bool( eCurTok == FUNCTION );
	sal_Bool bProp = sal_Bool( eCurTok == GET || eCurTok == SET || eCurTok == LET );
	if( !TestSymbol() ) return NULL;
	String aName( aSym );
	SbxDataType eType = eScanType;
	SbiProcDef* pDef = new SbiProcDef( this, aName, true );
	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( sal_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( sal_False );
		pDef->GetAlias().Erase();
	}
	// Klammern?
	if( Peek() == LPAREN )
	{
		Next();
		if( Peek() == RPAREN )
			Next();
		else
		  for(;;) {
			sal_Bool bByVal = sal_False;
			sal_Bool bOptional = sal_False;
			sal_Bool bParamArray = sal_False;
			while( Peek() == BYVAL || Peek() == BYREF || Peek() == _OPTIONAL_ )
			{
				if		( Peek() == BYVAL )		Next(), bByVal = sal_True;
				else if	( Peek() == BYREF )		Next(), bByVal = sal_False;
				else if	( Peek() == _OPTIONAL_ )	Next(), bOptional = sal_True;
			}
			if( bCompatible && Peek() == PARAMARRAY )
			{
				if( bByVal || bOptional )
					Error( SbERR_UNEXPECTED, PARAMARRAY );
				Next();
				bParamArray = sal_True;
			}
			SbiSymDef* pPar = VarDecl( NULL, sal_False, sal_False );
			if( !pPar )
				break;
			if( bByVal )
				pPar->SetByVal();
			if( bOptional )
				pPar->SetOptional();
			if( bParamArray )
				pPar->SetParamArray();
			pDef->GetParams().Add( pPar );
			SbiToken eTok = Next();
			if( eTok != COMMA && eTok != RPAREN )
			{
				sal_Bool bError2 = sal_True;
				if( bOptional && bCompatible && eTok == EQ )
				{
					SbiConstExpression* pDefaultExpr = new SbiConstExpression( this );
					SbxDataType eType2 = pDefaultExpr->GetType();

					sal_uInt16 nStringId;
					if( eType2 == SbxSTRING )
						nStringId = aGblStrings.Add( pDefaultExpr->GetString() );
					else
						nStringId = aGblStrings.Add( pDefaultExpr->GetValue(), eType2 );

					pPar->SetDefaultId( nStringId );
					delete pDefaultExpr;

					eTok = Next();
					if( eTok == COMMA || eTok == RPAREN )
						bError2 = sal_False;
				}
				if( bError2 )
				{
					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 || bProp ) )
		pDef->SetType( SbxEMPTY );
	return pDef;
}

// DECLARE

void SbiParser::Declare()
{
	DefDeclare( sal_False );
}

void SbiParser::DefDeclare( sal_Bool bPrivate )
{
	Next();
	if( eCurTok != SUB && eCurTok != FUNCTION )
	  Error( SbERR_UNEXPECTED, eCurTok );
	else
	{
		bool bFunction = (eCurTok == FUNCTION);

		SbiProcDef* pDef = ProcDecl( sal_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;
					pDef = NULL;
				}
				else
					pDef->Match( p );
			}
			else
				aPublics.Add( pDef );

			if ( pDef )
			{
				pDef->SetPublic( !bPrivate );

				// New declare handling
				if( pDef->GetLib().Len() > 0 )
				{
					if( bNewGblDefs && nGblChain == 0 )
					{
						nGblChain = aGen.Gen( _JUMP, 0 );
						bNewGblDefs = sal_False;
					}

					sal_uInt16 nSavLine = nLine;
					aGen.Statement();
					pDef->Define();
					pDef->SetLine1( nSavLine );
					pDef->SetLine2( nSavLine );

					SbiSymPool& rPool = pDef->GetParams();
					sal_uInt16 nParCount = rPool.GetSize();

					SbxDataType eType = pDef->GetType();
					if( bFunction )
						aGen.Gen( _PARAM, 0, sal::static_int_cast< sal_uInt16 >( eType ) );

					if( nParCount > 1 )
					{
						aGen.Gen( _ARGC );

						for( sal_uInt16 i = 1 ; i < nParCount ; ++i )
						{
							SbiSymDef* pParDef = rPool.Get( i );
							SbxDataType eParType = pParDef->GetType();

							aGen.Gen( _PARAM, i, sal::static_int_cast< sal_uInt16 >( eParType ) );
							aGen.Gen( _ARGV );

							sal_uInt16 nTyp = sal::static_int_cast< sal_uInt16 >( pParDef->GetType() );
							if( pParDef->IsByVal() )
							{
								// Reset to avoid additional byval in call to wrapper function
								pParDef->SetByVal( sal_False );
								nTyp |= 0x8000;
							}
							aGen.Gen( _ARGTYP, nTyp );
						}
					}

					aGen.Gen( _LIB, aGblStrings.Add( pDef->GetLib() ) );

					SbiOpcode eOp = pDef->IsCdecl() ? _CALLC : _CALL;
					sal_uInt16 nId = pDef->GetId();
					if( pDef->GetAlias().Len() )
						nId = ( nId & 0x8000 ) | aGblStrings.Add( pDef->GetAlias() );
					if( nParCount > 1 )
						nId |= 0x8000;
					aGen.Gen( eOp, nId, sal::static_int_cast< sal_uInt16 >( eType ) );

					if( bFunction )
						aGen.Gen( _PUT );

					aGen.Gen( _LEAVE );
				}
			}
		}
	}
}

// Aufruf einer SUB oder FUNCTION

void SbiParser::Call()
{
	String aName( aSym );
	SbiExpression aVar( this, SbSYMBOL );
	aVar.Gen( FORCE_CALL );
	aGen.Gen( _GET );
}

// SUB/FUNCTION

void SbiParser::SubFunc()
{
	DefProc( sal_False, sal_False );
}

// Einlesen einer Prozedur

sal_Bool runsInSetup( void );

void SbiParser::DefProc( sal_Bool bStatic, sal_Bool bPrivate )
{
	sal_uInt16 l1 = nLine, l2 = nLine;
	sal_Bool bSub = sal_Bool( eCurTok == SUB );
	sal_Bool bProperty = sal_Bool( eCurTok == PROPERTY );
	PropertyMode ePropertyMode = PROPERTY_MODE_NONE;
	if( bProperty )
	{
		Next();
		if( eCurTok == GET )
			ePropertyMode = PROPERTY_MODE_GET;
		else if( eCurTok == LET )
			ePropertyMode = PROPERTY_MODE_LET;
		else if( eCurTok == SET )
			ePropertyMode = PROPERTY_MODE_SET;
		else
			Error( SbERR_EXPECTED, "Get or Let or Set" );
	}

	SbiToken eExit = eCurTok;
	SbiProcDef* pDef = ProcDecl( sal_False );
	if( !pDef )
		return;
	pDef->setPropertyMode( ePropertyMode );

	// Ist die Proc bereits deklariert?
	SbiSymDef* pOld = aPublics.Find( pDef->GetName() );
	if( pOld )
	{
		bool bError_ = false;

		pProc = pOld->GetProcDef();
		if( !pProc )
		{
			// Als Variable deklariert
			Error( SbERR_BAD_DECLARATION, pDef->GetName() );
			delete pDef;
			pProc = NULL;
			bError_ = true;
		}
		// #100027: Multiple declaration -> Error
		// #112787: Not for setup, REMOVE for 8
		else if( !runsInSetup() && pProc->IsUsedForProcDecl() )
		{
			PropertyMode ePropMode = pDef->getPropertyMode();
			if( ePropMode == PROPERTY_MODE_NONE || ePropMode == pProc->getPropertyMode() )
			{
				Error( SbERR_PROC_DEFINED, pDef->GetName() );
				delete pDef;
				pProc = NULL;
				bError_ = true;
			}
		}

		if( !bError_ )
		{
			pDef->Match( pProc );
			pProc = pDef;
		}
	}
	else
		aPublics.Add( pDef ), pProc = pDef;

	if( !pProc )
		return;
	pProc->SetPublic( !bPrivate );

	// Nun setzen wir die Suchhierarchie fuer Symbole sowie die aktuelle
	// Prozedur.
	aPublics.SetProcId( pProc->GetId() );
	pProc->GetParams().SetParent( &aPublics );
	if( bStatic )
		{
		if ( bVBASupportOn )
			pProc->SetStatic( sal_True );
		else
			Error( SbERR_NOT_IMPLEMENTED ); // STATIC SUB ...
		}
 	else
	{
		pProc->SetStatic( sal_False );
		}
	// Normalfall: Lokale Variable->Parameter->Globale Variable
	pProc->GetLocals().SetParent( &pProc->GetParams() );
	pPool = &pProc->GetLocals();

	pProc->Define();
	OpenBlock( eExit );
	StmntBlock( bSub ? ENDSUB : (bProperty ? ENDPROPERTY : 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()
{
	DefStatic( sal_False );
}

void SbiParser::DefStatic( sal_Bool bPrivate )
{
	switch( Peek() )
	{
		case SUB:
		case FUNCTION:
		case PROPERTY:
			// End global chain if necessary (not done in
			// SbiParser::Parse() under these conditions
			if( bNewGblDefs && nGblChain == 0 )
			{
				nGblChain = aGen.Gen( _JUMP, 0 );
				bNewGblDefs = sal_False;
			}
			Next();
			DefProc( sal_True, bPrivate );
			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, sal_True );
			pPool = p;
			} break;
	}
}

/* vim: set noet sw=4 ts=4: */
