Files
harbour-core/harbour/source/rtl/codebloc.c
1999-06-29 05:07:16 +00:00

195 lines
5.1 KiB
C

/*
* $Id$
*/
/* The Harbour implementation of codeblocks */
#include <extend.h>
#include <string.h>
extern STACK stack;
#define FALSE 0
#define TRUE 1
/* Uncomment this to trace codeblocks activity
#define CODEBLOCKDEBUG
*/
/* Creates the codeblock structure
*
* The buffer should contain:
* +0 bytes -> number of referenced local variables
* +2 bytes -> table of referenced local variables
* +2 + 2 *(number of referenced variables) -> codeblock pcode
*/
HB_CODEBLOCK_PTR CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols,
int iStaticsBase, WORD wStackBase )
{
HB_CODEBLOCK_PTR pCBlock;
WORD wVars;
pCBlock =( HB_CODEBLOCK_PTR ) hb_xgrab( sizeof(HB_CODEBLOCK) );
/* Check the number of referenced local variables
*/
wVars = * ( (WORD *) pBuffer );
wSize -= ( wVars + 1 ) * 2;
pBuffer +=2;
pCBlock->wLocals =wVars;
if( wVars )
{
WORD w = 0;
/* Create the table with references to local variables
* If this codeblock will be exported from a function then
* all references will be replaced with current values of
* these variables
*/
pCBlock->pItems =(PHB_ITEM) hb_xgrab( sizeof(HB_ITEM) * wVars );
while( wVars-- )
{
pCBlock->pItems[ w ].type =IT_BYREF; /* not really integer */
pCBlock->pItems[ w ].item.asRefer.value = * ( (WORD*) pBuffer );
++w;
pBuffer +=2;
}
}
else
pCBlock->pItems =NULL;
/* the codeblock initally contains references to local variables
*/
pCBlock->wDetached =FALSE;
/*
* pcode is stored in static segment now.
* The only allowed operation on a codeblock is evaluating it then
* there is no need to duplicate its pcode -just store the pointer to it
*/
pCBlock->pCode = pBuffer;
pCBlock->pSymbols =pSymbols;
pCBlock->wDetached =FALSE;
pCBlock->lCounter =1;
pCBlock->iStatBase =iStaticsBase;
/*
* wStackBase is stack base of function where the codeblock was defined
* We need it because stack.pBase points to a stack base of EVAL function
* at the time of codeblock evaluation.
*/
pCBlock->wRefBase =wStackBase;
#ifdef CODEBLOCKDEBUG
printf( "codeblock created (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
return pCBlock;
}
/* Delete a codeblock
*/
void CodeblockDelete( HB_CODEBLOCK_PTR pCBlock )
{
#ifdef CODEBLOCKDEBUG
printf( "delete a codeblock (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
if( --pCBlock->lCounter == 0 )
{
WORD w = 0;
/* free space allocated for local variables
*/
if( pCBlock->pItems )
{
while( w < pCBlock->wLocals )
ItemRelease( &pCBlock->pItems[ w++ ] );
hb_xfree( pCBlock->pItems );
}
/* free space allocated for a CODEBLOCK structure
*/
hb_xfree( pCBlock );
#ifdef CODEBLOCKDEBUG
printf( "codeblock deleted (%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
}
}
/* Function to unlink variables referenced in a codeblock from a function
* where this codeblock was created
*/
void CodeblockDetach( HB_CODEBLOCK_PTR pCBlock )
{
if( pCBlock->wLocals && !pCBlock->wDetached )
{
/* this codeblock refers to local variables */
WORD w = 0;
PHB_ITEM pItem;
while( w < pCBlock->wLocals )
{
/* replace the position of local variable on the stack with
* it's current value
* stack.pBase still points to a stack frame of function
* where this codeblock was defined
*/
pItem =pCBlock->pItems + w;
pItem =stack.pBase +pItem->item.asRefer.value + 1;
if( IS_BYREF( pItem ) )
pItem =stack.pItems +pItem->item.asRefer.value;
ItemCopy( pCBlock->pItems + w, pItem );
++w;
}
pCBlock->wDetached =TRUE;
}
#ifdef CODEBLOCKDEBUG
printf( "codeblock detached(%li) %lx\n", pCBlock->lCounter, pCBlock );
#endif
}
/* Evaluate passed codeblock
* wStackBase is stack base of function where the codeblock was defined
* We need it because stack.pBase points to a stack base of EVAL function
*/
void CodeblockEvaluate( HB_CODEBLOCK_PTR pCBlock )
{
int iStatics = stack.iStatics;
stack.iStatics = pCBlock->iStatBase;
VirtualMachine( pCBlock->pCode, pCBlock->pSymbols );
stack.iStatics = iStatics;
}
/* Get local variable referenced in a codeblock
*/
PHB_ITEM CodeblockGetVar( PHB_ITEM pItem, LONG iItemPos )
{
HB_CODEBLOCK_PTR pCBlock = pItem->item.asBlock.value;
PHB_ITEM pLocalVar;
pLocalVar =&pCBlock->pItems[ -iItemPos -1 ];
/* if a codeblock have detached local variables then it stores their value */
if( !pCBlock->wDetached )
{
/* when variables are not detached then a codeblock stores the variable's
* position on the stack
*/
pLocalVar =stack.pItems +pCBlock->wRefBase +pLocalVar->item.asRefer.value + 1;
}
return pLocalVar;
}
/* Copy the codeblock
* TODO: check if such simple pointer coping will allow to evaluate
* codeblocks recursively
*/
void CodeblockCopy( PHB_ITEM pDest, PHB_ITEM pSource )
{
pDest->item.asBlock.value =pSource->item.asBlock.value;
pDest->item.asBlock.value->lCounter++;
#ifdef CODEBLOCKDEBUG
printf( "copy a codeblock (%li) %lx\n", pDest->item.asBlock.valuevalue->lCounter, pDest->item.asBlock.valuevalue);
#endif
}