#ifndef VIRTUAL_MACHINE_H_INCLUDED
#define VIRTUAL_MACHINE_H_INCLUDED
/*****************************************************************************/
/* HEADER FILE */
/*****************************************************************************/
/*
$Archive: $
$Revision: $
$Date: $
$Author: $
Description: Declaration of the MemoryManager class for the InterPiler
project.
TOOL And XML FORMS License
==========================
Except where otherwise noted, all of the documentation
and software included in the TOOL package is
copyrighted by Michael Swartzendruber.
Copyright (C) 2005 Michael John Swartzendruber.
All rights reserved.
Access to this code, whether intentional or accidental,
does NOT IMPLY any transfer of rights.
This software is provided "as-is," without any express
or implied warranty. In no event shall the author be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to
alter and redistribute it, provided that the following
conditions are met:
1. All redistributions of source code files must retain
all copyright notices that are currently in place,
and this list of conditions without modification.
2. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
3. If you use this software in another product, an acknowledgment
in the product documentation would be appreciated but is
not required.
4. Modified versions in source or binary form must be plainly
marked as such, and must not be misrepresented as being
the original software.
*/
/*****************************************************************************/
#include <vector>
#include "./APIClasses/VMByteArray.h"
#include "./Collections/VMQueue.h"
#include "./Collections/VMStack.h"
#include "VMCoreGlobal.h"
#include "VMCoreScreenInfo.h"
#include "VMCoreVirtualChip.h"
#include "VMCoreInterpreter.h"
#pragma warning( disable : 4786 )
#include "VMCoreCmdLineOptions.h"
///////////////////////////////////////////////////////////////////////////////
//
// declaration of a value container that can be used to pass variables between
// the application context and the scripting engine
//
class CAppContextVariant
{
public:
enum eValueType
{
eString,
eLong,
eBool,
eDouble,
eDWORD,
eDateTime,
eBytes,
eNullType,
};
CAppContextVariant::eValueType GetValueType( void ) const { return( m_eType ); };
CAppContextVariant( const char* pchValue );
CAppContextVariant( long lValue );
CAppContextVariant( bool bValue );
CAppContextVariant( double dblValue );
CAppContextVariant( DWORD roValue );
CAppContextVariant( SYSTEMTIME xValue );
CAppContextVariant( VMByteArray& roValue );
~CAppContextVariant( void );
bool GetValue( char* pchOutput, int& iOutBufferSize ) const;
bool GetValue( long& rlOutput ) const;
bool GetValue( bool& rbOutput ) const;
bool GetValue( double& rdblOutput ) const;
bool GetValue( DWORD& rdwOutput ) const;
bool GetValue( SYSTEMTIME& rxOutput ) const;
bool GetValue( VMByteArray& roOutput ) const;
CAppContextVariant* Clone( void );
int AsString( char* pchOutput ) const;
private:
char* m_pchValue;
long m_lValue;
bool m_bValue;
double m_dblValue;
SYSTEMTIME m_xTimeValue;
VMByteArray m_oBytesValue;
DWORD m_dwValue;
eValueType m_eType;
};
///////////////////////////////////////////////////////////////////////////////
//
// define the collection that is passed between the application context and
// the scripting context for data I/O
//
typedef std::map< std::string, CAppContextVariant* > SCRIPT_ARGUMENTS;
typedef SCRIPT_ARGUMENTS::iterator SCRIPT_ARGUMENTS_ITER;
///////////////////////////////////////////////////////////////////////////////
//
// The Application Context class is used to provide a loosely coupled interface
// that allows the interpiler to be easily integrated into an application's
// design and implementation
//
///////////////////////////////////////////////////////////////////////////////
class CAppContext
{
public:
CAppContext( void ) {;};
virtual ~CAppContext( void ) {;};
virtual bool SetFieldByName( const char* pchFieldName,
const CAppContextVariant* poFieldValue ) = 0;
virtual const CAppContextVariant* GetFieldByName( const char* pchFieldName ) = 0;
virtual bool WriteDirectToTemplateContext( const char* pchToWrite ) = 0;
};
///////////////////////////////////////////////////////////////////////////////
//
// Thread Safe Implementation of an Application Context class
//
///////////////////////////////////////////////////////////////////////////////
class CThreadSafeAppContext : public CAppContext
{
friend class VMFacade;
friend class VMVirtualOpSys;
public:
CThreadSafeAppContext( SCRIPT_ARGUMENTS* poScriptArguments = NULL ) : CAppContext()
{
InitializeCriticalSection( &m_xCriticalSection );
m_poScriptArguments = poScriptArguments;
m_bThisOwnsCriticalSection = true;
};
virtual ~CThreadSafeAppContext( void )
{
if ( m_bThisOwnsCriticalSection == true )
{
DeleteCriticalSection( &m_xCriticalSection );
}
};
virtual bool SetFieldByName( const char* pchFieldName,
const CAppContextVariant* poFieldValue )
{
bool bResult = true;
EnterCriticalSection( &m_xCriticalSection );
if ( NULL != m_poScriptArguments )
{
bResult = true;
SCRIPT_ARGUMENTS_ITER oIter = m_poScriptArguments->find( std::string( pchFieldName ) );
if ( oIter != m_poScriptArguments->end() )
{
m_poScriptArguments->erase( oIter );
}
m_poScriptArguments->insert( SCRIPT_ARGUMENTS::value_type( std::string( pchFieldName ),
const_cast<CAppContextVariant*>( poFieldValue ) ) );
}
else
{
bResult = false;
}
LeaveCriticalSection( &m_xCriticalSection );
return( bResult );
};
virtual const CAppContextVariant* GetFieldByName( const char* pchFieldName )
{
CAppContextVariant* poResult = NULL;
EnterCriticalSection( &m_xCriticalSection );
if ( NULL != m_poScriptArguments )
{
SCRIPT_ARGUMENTS_ITER oIter = m_poScriptArguments->find( std::string( pchFieldName ) );
if ( oIter != m_poScriptArguments->end() )
{
poResult = (*oIter).second;
}
}
LeaveCriticalSection( &m_xCriticalSection );
return( poResult );
};
void ClearAllVars( void )
{
EnterCriticalSection( &m_xCriticalSection );
if ( m_poScriptArguments )
{
SCRIPT_ARGUMENTS_ITER oIter;
for ( oIter = m_poScriptArguments->begin();
oIter != m_poScriptArguments->end();
oIter++ )
{
delete (*oIter).second;
}
m_poScriptArguments->clear();
}
LeaveCriticalSection( &m_xCriticalSection );
};
void CloneArguments( SCRIPT_ARGUMENTS* poArguments, bool bOverWrite )
{
EnterCriticalSection( &m_xCriticalSection );
if ( m_poScriptArguments && bOverWrite )
{
SCRIPT_ARGUMENTS_ITER oIter;
for ( oIter = m_poScriptArguments->begin();
oIter != m_poScriptArguments->end();
oIter++ )
{
delete (*oIter).second;
}
m_poScriptArguments->clear();
}
else
{
m_poScriptArguments = new SCRIPT_ARGUMENTS;
}
if ( poArguments )
{
SCRIPT_ARGUMENTS_ITER oIter;
for ( oIter = poArguments->begin();
oIter != poArguments->end();
oIter++ )
{
std::string oKey = (*oIter).first;
CAppContextVariant* poValue = (*oIter).second->Clone();
m_poScriptArguments->insert( SCRIPT_ARGUMENTS::value_type( oKey, poValue ) );
}
}
LeaveCriticalSection( &m_xCriticalSection );
};
protected:
SCRIPT_ARGUMENTS* m_poScriptArguments;
CRITICAL_SECTION m_xCriticalSection;
bool m_bThisOwnsCriticalSection;
// copy and assignment construction not allowed
//
CThreadSafeAppContext( const CThreadSafeAppContext& roOther );
virtual CThreadSafeAppContext& operator=( const CThreadSafeAppContext& roOther ){ return( *this ); };
};
///////////////////////////////////////////////////////////////////////////////
//
// define the basic allocation unit
//
typedef char* AUNIT;
// block flags
//
#define MARK 1
// size of each type of memory segment
//
#define VSSIZE 10000 // number of LVAL's per vector segment
// vector segment structure
//
typedef struct vsegment
{
struct vsegment* vs_next; // next vector segment
AUNIT* vs_free; // next free location in this segment
AUNIT* vs_top; // top of segment (plus one)
AUNIT vs_data[1]; // segment data
} VSEGMENT;
// forward declarations
//
class VMCompiler;
class VMInterpreter;
class VMVirtualOpSys;
class VMCmdLineOptions;
class VMVirtualMachine : public VMScreenInfo
{
public:
VMVirtualMachine()
{
m_psVectorSegmentList = NULL;
m_psCurrentVectorSegment = NULL;
m_psNextFreeLocation = NULL;
m_psTopCurrentSegment = NULL;
m_bShowCallResults = false;
};
virtual ~VMVirtualMachine( void );
// this is the only method that the virtual
// operating system needs to over ride
//
virtual int InitVirtualMachine( int smax, int cmax );
void SetCompiler( VMCompiler& roCompiler ){ m_poCompiler = &roCompiler; };
void SetDataSpace( VMVirtualChip& roVirtualChip ){ m_poVirtualChip = &roVirtualChip; };
void SetInterpreter( VMInterpreter& roInterpreter ){ m_poInterpreter = &roInterpreter; };
void MarkReachableBlocks( VMVARIANT *val );
char* GetCStyleString( char* buf, int max, VMVARIANT* str );
VMCLASS* AllocateNewClass( char* name, VMVARIANT* base );
VMDICT_ENTRY* AddDictionaryEntry( VMVARIANT* dict, char* key, int type );
VMDICT_ENTRY* FindDictionaryEntry( VMVARIANT* dict, char* key );
// mjs: new runtime strings
//
VMSTRING* AllocateNewString( int n, bool bRunTimeAlloc );
VMOBJECT* AllocateNewObject( VMVARIANT* pxClass );
VMVECTOR* AllocateNewVector( int n );
VMSTRING* MakeVMString( char* str );
void PrintOneArg( FILE* fp, int qflag, VMVARIANT *val );
void PrintOneArg( VMVARIANT* ios, int qflag, VMVARIANT* val );
void ConvertToString( char *buf, VMVARIANT *val );
void SetArguments(int iArgc, char *argv[] );
void IllegalConstantAssignment( void );
void SetServerContext( CThreadSafeAppContext* poServerContext ){ m_poServerContext = poServerContext; };
protected:
VMDICTIONARY* CreateNewDictionary( VMVARIANT* pxClass );
VMDICT_ENTRY* AllocateDictionaryEntry( VMVARIANT* dict, char* key, int type );
VMHDR* AllocateMemory( int type, int size );
int FindVectorMemory( int size );
int CheckVectorMemory( int size );
int MakeVectorMemory( int size );
int ExpandVectorSpace( int size );
VSEGMENT* CreateNewVectorSegment( unsigned int n );
void RunGarbageCollection( void );
void MarkClass( VMCLASS* pxClass );
void MarkDictionary( VMDICTIONARY* dict );
void MarkEntry( VMDICT_ENTRY* entry );
void MarkObject( VMOBJECT* obj );
void MarkVector( VMVECTOR* vect );
void CompactMemory( void );
int GetBlockSize( VMHDR* hdr );
void CompactVectorSegment( VSEGMENT* vseg );
void ConfigureBuiltInFunction( char *name, int (VMVirtualOpSys::*fcn)(int) );
void ConfigureBuiltInFileType( char* name, FILE* fp );
void ConfigureStandardStream( char* name, FILE* fp, VMVARIANT* pval );
VMIOSTREAM* CreateNewStream( VMIODISPATCH* pxDispatch, void* pData );
int NotEnoughArguments( void );
int TooManyArguments( void );
void VerifyRunLineArguments( int iCount, int iRequired );
void PushToStack( void* pToPush, int iType );
short VerifyElementType( int iOffset, int iType );
short VerifySubElementType( int iControl, int iCompare );
void VerifyStackDepth( int iRequired );
void FreeVectorSegments( VSEGMENT* pxRoot );
protected:
VMInterpreter* m_poInterpreter;
VMCompiler* m_poCompiler;
VMVirtualChip* m_poVirtualChip;
CThreadSafeAppContext* m_poServerContext;
VMCmdLineOptions m_oCmdLine;
char** m_pchArgv;
int m_iArgc;
bool m_bShowCallResults;
TRACKED_ALLOCS m_oTrackedAllocs;
private:
VSEGMENT* m_psVectorSegmentList; // list of vector segments
VSEGMENT* m_psCurrentVectorSegment; // current vector segment
AUNIT* m_psNextFreeLocation; // next free location in current segment
AUNIT* m_psTopCurrentSegment; // top of current segment
};
#endif
/*****************************************************************************/
/* Check-in history */
/*
*$Log: $
*/
/*****************************************************************************/