/**************************************************************
 *
 * 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"
#include "image.hxx"
#include <limits>
#include <com/sun/star/script/ModuleType.hpp>

// nInc ist die Inkrementgroesse der Puffer

SbiCodeGen::SbiCodeGen( SbModule& r, SbiParser* p, short nInc )
		 : rMod( r ), aCode( p, nInc )
{
	pParser = p;
	bStmnt = sal_False;
	nLine = 0;
	nCol = 0;
	nForLevel = 0;
}

sal_uInt32 SbiCodeGen::GetPC()
{
	return aCode.GetSize();
}

// Statement merken

void SbiCodeGen::Statement()
{
	bStmnt = sal_True;

	nLine = pParser->GetLine();
	nCol  = pParser->GetCol1();

	// #29955 Information der for-Schleifen-Ebene
	// in oberen Byte der Spalte speichern
	nCol = (nCol & 0xff) + 0x100 * nForLevel;
}

// Anfang eines Statements markieren

void SbiCodeGen::GenStmnt()
{
	if( bStmnt )
	{
		bStmnt = sal_False;
		Gen( _STMNT, nLine, nCol );
	}
}

// Die Gen-Routinen returnen den Offset des 1. Operanden,
// damit Jumps dort ihr Backchain versenken koennen

sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode )
{
#ifdef DBG_UTIL
	if( eOpcode < SbOP0_START || eOpcode > SbOP0_END )
		pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE1" );
#endif
	GenStmnt();
	aCode += (sal_uInt8) eOpcode;
	return GetPC();
}

sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd )
{
#ifdef DBG_UTIL
	if( eOpcode < SbOP1_START || eOpcode > SbOP1_END )
		pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE2" );
#endif
	GenStmnt();
	aCode += (sal_uInt8) eOpcode;
	sal_uInt32 n = GetPC();
	aCode += nOpnd;
	return n;
}

sal_uInt32 SbiCodeGen::Gen( SbiOpcode eOpcode, sal_uInt32 nOpnd1, sal_uInt32 nOpnd2 )
{
#ifdef DBG_UTIL
	if( eOpcode < SbOP2_START || eOpcode > SbOP2_END )
		pParser->Error( SbERR_INTERNAL_ERROR, "OPCODE3" );
#endif
	GenStmnt();
	aCode += (sal_uInt8) eOpcode;
	sal_uInt32 n = GetPC();
	aCode += nOpnd1;
	aCode += nOpnd2;
	return n;
}

// Abspeichern des erzeugten Images im Modul

void SbiCodeGen::Save()
{
	SbiImage* p = new SbiImage;
	rMod.StartDefinitions();
	// OPTION BASE-Wert:
	p->nDimBase = pParser->nBase;
	// OPTION EXPLICIT-Flag uebernehmen
	if( pParser->bExplicit )
		p->SetFlag( SBIMG_EXPLICIT );

	int nIfaceCount = 0;
	if( rMod.mnType == com::sun::star::script::ModuleType::CLASS )
	{
                OSL_TRACE("COdeGen::save() classmodule processing");
		rMod.bIsProxyModule = true;
		p->SetFlag( SBIMG_CLASSMODULE );
		pCLASSFAC->AddClassModule( &rMod );

		nIfaceCount = pParser->aIfaceVector.size();
		if( !rMod.pClassData )
			rMod.pClassData = new SbClassData;
		if( nIfaceCount )
		{
			for( int i = 0 ; i < nIfaceCount ; i++ )
			{
				const String& rIfaceName = pParser->aIfaceVector[i];
				SbxVariable* pIfaceVar = new SbxVariable( SbxVARIANT );
				pIfaceVar->SetName( rIfaceName );
				SbxArray* pIfaces = rMod.pClassData->mxIfaces;
				pIfaces->Insert( pIfaceVar, pIfaces->Count() );
			}
		}

		rMod.pClassData->maRequiredTypes = pParser->aRequiredTypes;
	}
	else
	{
		pCLASSFAC->RemoveClassModule( &rMod );
		// Only a ClassModule can revert to Normal
                if ( rMod.mnType == com::sun::star::script::ModuleType::CLASS )
			rMod.mnType = com::sun::star::script::ModuleType::NORMAL;
		rMod.bIsProxyModule = false;
	}

	if( pParser->bText )
		p->SetFlag( SBIMG_COMPARETEXT );
	// GlobalCode-Flag
	if( pParser->HasGlobalCode() )
		p->SetFlag( SBIMG_INITCODE );
	// Die Entrypoints:
	for( SbiSymDef* pDef = pParser->aPublics.First(); pDef;
				   pDef = pParser->aPublics.Next() )
	{
		SbiProcDef* pProc = pDef->GetProcDef();
		if( pProc && pProc->IsDefined() )
		{
			String aProcName = pProc->GetName();
			String aIfaceProcName;
			String aIfaceName;
			sal_uInt16 nPassCount = 1;
			if( nIfaceCount )
			{
				int nPropPrefixFound =
					aProcName.Search( String( RTL_CONSTASCII_USTRINGPARAM("Property ") ) );
				String aPureProcName = aProcName;
				String aPropPrefix;
				if( nPropPrefixFound == 0 )
				{
					aPropPrefix = aProcName.Copy( 0, 13 );		// 13 == Len( "Property ?et " )
					aPureProcName = aProcName.Copy( 13 );
				}
				for( int i = 0 ; i < nIfaceCount ; i++ )
				{
					const String& rIfaceName = pParser->aIfaceVector[i];
					int nFound = aPureProcName.Search( rIfaceName );
					if( nFound == 0 && '_' == aPureProcName.GetChar( rIfaceName.Len() ) )
					{
						if( nPropPrefixFound == 0 )
							aIfaceProcName += aPropPrefix;
						aIfaceProcName += aPureProcName.Copy( rIfaceName.Len() + 1 );
						aIfaceName = rIfaceName;
						nPassCount = 2;
						break;
					}
				}
			}
			SbMethod* pMeth = NULL;
			for( sal_uInt16 nPass = 0 ; nPass < nPassCount ; nPass++ )
			{
				if( nPass == 1 )
					aProcName = aIfaceProcName;

				PropertyMode ePropMode = pProc->getPropertyMode();
				if( ePropMode != PROPERTY_MODE_NONE )
				{
					SbxDataType ePropType = SbxEMPTY;
					switch( ePropMode )
					{
						case PROPERTY_MODE_GET:
							ePropType = pProc->GetType();
							break;
						case PROPERTY_MODE_LET:
						{
							// type == type of first parameter
							ePropType = SbxVARIANT;		// Default
							SbiSymPool* pPool = &pProc->GetParams();
							if( pPool->GetSize() > 1 )
							{
								SbiSymDef* pPar = pPool->Get( 1 );
								if( pPar )
									ePropType = pPar->GetType();
							}
							break;
						}
						case PROPERTY_MODE_SET:
							ePropType = SbxOBJECT;
							break;
						case PROPERTY_MODE_NONE:
							DBG_ERROR( "Illegal PropertyMode PROPERTY_MODE_NONE" );
							break;
					}
					String aPropName = pProc->GetPropName();
					if( nPass == 1 )
						aPropName = aPropName.Copy( aIfaceName.Len() + 1 );
					SbProcedureProperty* pProcedureProperty = NULL;
					pProcedureProperty = rMod.GetProcedureProperty( aPropName, ePropType );
				}
				if( nPass == 1 )
				{
					SbIfaceMapperMethod* pMapperMeth = NULL;
					pMapperMeth = rMod.GetIfaceMapperMethod( aProcName, pMeth );
				}
				else
				{
					pMeth = rMod.GetMethod( aProcName, pProc->GetType() );

					// #110004
					if( !pProc->IsPublic() )
						pMeth->SetFlag( SBX_PRIVATE );

					// Declare? -> Hidden
					if( pProc->GetLib().Len() > 0 )
						pMeth->SetFlag( SBX_HIDDEN );

					pMeth->nStart = pProc->GetAddr();
					pMeth->nLine1 = pProc->GetLine1();
					pMeth->nLine2 = pProc->GetLine2();
					// Die Parameter:
					SbxInfo* pInfo = pMeth->GetInfo();
					String aHelpFile, aComment;
					sal_uIntPtr nHelpId = 0;
					if( pInfo )
					{
						// Die Zusatzdaten retten
						aHelpFile = pInfo->GetHelpFile();
						aComment  = pInfo->GetComment();
						nHelpId	  = pInfo->GetHelpId();
					}
					// Und die Parameterliste neu aufbauen
					pInfo = new SbxInfo( aHelpFile, nHelpId );
					pInfo->SetComment( aComment );
					SbiSymPool* pPool = &pProc->GetParams();
					// Das erste Element ist immer der Funktionswert!
					for( sal_uInt16 i = 1; i < pPool->GetSize(); i++ )
					{
						SbiSymDef* pPar = pPool->Get( i );
						SbxDataType t = pPar->GetType();
						if( !pPar->IsByVal() )
							t = (SbxDataType) ( t | SbxBYREF );
						if( pPar->GetDims() )
							t = (SbxDataType) ( t | SbxARRAY );
						// #33677 Optional-Info durchreichen
						sal_uInt16 nFlags = SBX_READ;
						if( pPar->IsOptional() )
							nFlags |= SBX_OPTIONAL;

						pInfo->AddParam( pPar->GetName(), t, nFlags );

						sal_uInt32 nUserData = 0;
						sal_uInt16 nDefaultId = pPar->GetDefaultId();
						if( nDefaultId )
							nUserData |= nDefaultId;
						if( pPar->IsParamArray() )
							nUserData |= PARAM_INFO_PARAMARRAY;
						if( pPar->IsWithBrackets() )
							nUserData |= PARAM_INFO_WITHBRACKETS;
						if( nUserData )
						{
							SbxParamInfo* pParam = (SbxParamInfo*)pInfo->GetParam( i );
							pParam->nUserData = nUserData;
						}
					}
					pMeth->SetInfo( pInfo );
				}

			}	// for( iPass...
		}
	}
	// Der Code
	p->AddCode( aCode.GetBuffer(), aCode.GetSize() );

	// Der globale StringPool. 0 ist nicht belegt.
	SbiStringPool* pPool = &pParser->aGblStrings;
	sal_uInt16 nSize = pPool->GetSize();
	p->MakeStrings( nSize );
	sal_uInt16 i;
	for( i = 1; i <= nSize; i++ )
		p->AddString( pPool->Find( i ) );

	// Typen einfuegen
	sal_uInt16 nCount = pParser->rTypeArray->Count();
	for (i = 0; i < nCount; i++)
		 p->AddType((SbxObject *)pParser->rTypeArray->Get(i));

	// Insert enum objects
	nCount = pParser->rEnumArray->Count();
	for (i = 0; i < nCount; i++)
		 p->AddEnum((SbxObject *)pParser->rEnumArray->Get(i));

	if( !p->IsError() )
		rMod.pImage = p;
	else
		delete p;

	rMod.EndDefinitions();
}

template < class T >
class PCodeVisitor
{
public:
	virtual ~PCodeVisitor();

	virtual void start( sal_uInt8* pStart ) = 0;
	virtual void processOpCode0( SbiOpcode eOp ) = 0;
	virtual void processOpCode1( SbiOpcode eOp, T nOp1 ) = 0;
	virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 ) = 0;
	virtual bool processParams() = 0;
	virtual void end() = 0;
};

template <class T> PCodeVisitor< T >::~PCodeVisitor()
{}

template <class T>
class PCodeBufferWalker
{
private:
	T  m_nBytes;
	sal_uInt8* m_pCode;
	T readParam( sal_uInt8*& pCode )
	{
		short nBytes = sizeof( T );
		T nOp1=0;
		for ( int i=0; i<nBytes; ++i )
			nOp1 |= *pCode++ << ( i * 8);
		return nOp1;
	}
public:
	PCodeBufferWalker( sal_uInt8* pCode, T nBytes ): m_nBytes( nBytes ), m_pCode( pCode )
	{
	}
	void visitBuffer( PCodeVisitor< T >& visitor )
	{
		sal_uInt8* pCode = m_pCode;
		if ( !pCode )
			return;
		sal_uInt8* pEnd = pCode + m_nBytes;
		visitor.start( m_pCode );
		T nOp1 = 0, nOp2 = 0;
		for( ; pCode < pEnd; )
		{
			SbiOpcode eOp = (SbiOpcode)(*pCode++);

			if ( eOp <= SbOP0_END )
				visitor.processOpCode0( eOp );
			else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
			{
				if ( visitor.processParams() )
					nOp1 = readParam( pCode );
				else
					pCode += sizeof( T );
				visitor.processOpCode1( eOp, nOp1 );
			}
			else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
			{
				if ( visitor.processParams() )
				{
					nOp1 = readParam( pCode );
					nOp2 = readParam( pCode );
				}
				else
					pCode += ( sizeof( T ) * 2 );
				visitor.processOpCode2( eOp, nOp1, nOp2 );
			}
		}
		visitor.end();
	}
};

template < class T, class S >
class OffSetAccumulator : public PCodeVisitor< T >
{
	T m_nNumOp0;
	T m_nNumSingleParams;
	T m_nNumDoubleParams;
public:

	OffSetAccumulator() : m_nNumOp0(0), m_nNumSingleParams(0), m_nNumDoubleParams(0){}
	virtual void start( sal_uInt8* /*pStart*/ ){}
	virtual void processOpCode0( SbiOpcode /*eOp*/ ){ ++m_nNumOp0; }
	virtual void processOpCode1( SbiOpcode /*eOp*/, T /*nOp1*/ ){  ++m_nNumSingleParams; }
	virtual void processOpCode2( SbiOpcode /*eOp*/, T /*nOp1*/, T /*nOp2*/ ) { ++m_nNumDoubleParams; }
	virtual void end(){}
	S offset()
	{
		T result = 0 ;
		static const S max = std::numeric_limits< S >::max();
		result = m_nNumOp0 + ( ( sizeof(S) + 1 ) * m_nNumSingleParams ) + ( (( sizeof(S) * 2 )+ 1 )  * m_nNumDoubleParams );
		if ( result > max )
			return max;

		return static_cast<S>(result);
	}
   virtual bool processParams(){ return false; }
};



template < class T, class S >

class BufferTransformer : public PCodeVisitor< T >
{
	sal_uInt8* m_pStart;
	SbiBuffer m_ConvertedBuf;
public:
	BufferTransformer():m_pStart(NULL), m_ConvertedBuf( NULL, 1024 ) {}
	virtual void start( sal_uInt8* pStart ){ m_pStart = pStart; }
	virtual void processOpCode0( SbiOpcode eOp )
	{
		m_ConvertedBuf += (sal_uInt8)eOp;
	}
	virtual void processOpCode1( SbiOpcode eOp, T nOp1 )
	{
		m_ConvertedBuf += (sal_uInt8)eOp;
		switch( eOp )
		{
			case _JUMP:
			case _JUMPT:
			case _JUMPF:
			case _GOSUB:
			case _CASEIS:
			case _RETURN:
			case _ERRHDL:
			case _TESTFOR:
				nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
				break;
			case _RESUME:
				if ( nOp1 > 1 )
					nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
				break;
			default:
				break; //

		}
		m_ConvertedBuf += (S)nOp1;
	}
	virtual void processOpCode2( SbiOpcode eOp, T nOp1, T nOp2 )
	{
		m_ConvertedBuf += (sal_uInt8)eOp;
		if ( eOp == _CASEIS )
				if ( nOp1 )
					nOp1 = static_cast<T>( convertBufferOffSet(m_pStart, nOp1) );
		m_ConvertedBuf += (S)nOp1;
		m_ConvertedBuf += (S)nOp2;

	}
	virtual bool processParams(){ return true; }
	virtual void end() {}
	// yeuch, careful here, you can only call
	// GetBuffer on the returned SbiBuffer once, also
	// you (as the caller) get to own the memory
	SbiBuffer& buffer()
	{
		return m_ConvertedBuf;
	}
	static S convertBufferOffSet( sal_uInt8* pStart, T nOp1 )
	{
		PCodeBufferWalker< T > aBuff( pStart, nOp1);
		OffSetAccumulator< T, S > aVisitor;
		aBuff.visitBuffer( aVisitor );
		return aVisitor.offset();
	}
};

sal_uInt32
SbiCodeGen::calcNewOffSet( sal_uInt8* pCode, sal_uInt16 nOffset )
{
	return BufferTransformer< sal_uInt16, sal_uInt32 >::convertBufferOffSet( pCode, nOffset );
}

sal_uInt16
SbiCodeGen::calcLegacyOffSet( sal_uInt8* pCode, sal_uInt32 nOffset )
{
	return BufferTransformer< sal_uInt32, sal_uInt16 >::convertBufferOffSet( pCode, nOffset );
}

template <class T, class S>
void
PCodeBuffConvertor<T,S>::convert()
{
	PCodeBufferWalker< T > aBuf( m_pStart, m_nSize );
	BufferTransformer< T, S > aTrnsfrmer;
	aBuf.visitBuffer( aTrnsfrmer );
	m_pCnvtdBuf = (sal_uInt8*)aTrnsfrmer.buffer().GetBuffer();
	m_nCnvtdSize = static_cast<S>( aTrnsfrmer.buffer().GetSize() );
}

template class PCodeBuffConvertor< sal_uInt16, sal_uInt32 >;
template class PCodeBuffConvertor< sal_uInt32, sal_uInt16 >;
