2006-08-19 01:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/include/hbapi.h
    * moved HB_STACK_STATE declaration from hbstack.h to hbapi.h
      it's covered by _HB_API_INTERNAL_ macro so it should not
      effect 3-rd party code
    * modified hb_struSymbol structure:
         LONG stackbase
      replaced by:
         PHB_STACK_STATE stackstate
      this modification allows to keepadditional information bound with
      function call stack accessible from different HVM modules.
      Now it's used by memvars code to keep/update PRIVATE variables
      stack pointers. I plan to store in HB_STACK_STATE structure
      information additional information for classes code like super
      casting or instance variables offsets in new OOP model I'm working on.
      It can be also used by debugger code to retrieve some informations
      about executed functions without active updating by main HVM loop.
    + added hb_memvarsClear() - cleanly clears all PRIVATE and PUBLIC
      variables
    + added hb_memvarUpdatePrivatesBase() - updates PRIVATE stack base
      offset so PRIVATE variables created in current function/procedure
      will not be removed when it returns
    - removed hb_memvarsRelease() and hb_memvarValueNew()

  * harbour/include/hbstack.h
    + added hb_stackClearMevarsBase() - helper function for hb_memvarsClear()
      clears PRIVATE stack offsets in executed functions
    * changed to static offset from int to long - in different places we
      were using int or long in HVM so I cleaned the HVM code to always
      operate on the same type

  * harbour/source/vm/estack.c
    * set/restore PRIVATE stack base offset in hb_stackNewFrame()/
      hb_stackOldFrame()
    * updated for new HB_IT_SYMBOL structure

  * harbour/source/vm/hvm.c
    ! removed setting/restoring PRIVATE stack base offset in hb_vmExecute()
      It make code like:
         eval(&("{||VAR:=1}"))
      Clipper compatible
    * updated for new HB_IT_SYMBOL structure
    * changed order of execution exit procedures for clean memvars removing
      and future destructors execution. I'll describe it better when I'll
      add destructors.

  * harbour/source/vm/memvars.c
    ! fixed CLEAR MEMORY - now this function should be safe in Harbour
      It's not exactly compatible with Clipper because I intentionally
      didn't replicated some Clipper bugs like possible memory corruption.
    + added hb_memvarsClear() - cleanly clears all PRIVATE and PUBLIC
      variables
    + added hb_memvarUpdatePrivatesBase() - updates PRIVATE stack base
      offset so PRIVATE variables created in current function/procedure
      will not be removed when it returns
    ! fixed releasing PUBLIC and PRIVATE variables which were passed by
      reference and are still active on HVM stack or in codeblocks as
      detached locals (see: hb_memvarDetachDynSym())
    * modified hb_memvarFindSymbol() to be more Clipper compatible
    % optimized hb_memvarRelease() to operate or PHB_DYNS instead of
      string comparison and not make linear dynamic symbol scan for
      PUBLIC or not existing symbols
    - removed hb_memvarReleasePublic()

  * harbour/include/hbvmpub.h
  * harbour/include/hbxvm.h
  * harbour/source/compiler/gencc.c
  * harbour/source/vm/classes.c
  * harbour/source/vm/debug.c
  * harbour/source/vm/itemapi.c
  * harbour/source/vm/pcount.c
  * harbour/source/vm/proc.c
  * harbour/source/vm/pvalue.c
    * updated for the above modifications

  * harbour/source/rtl/memvarbl.prg
  * harbour/source/rtl/menuto.prg
    * use __mvEXIST( cMemvar ) instead of __mvSCOPE( cMemvar ) > HB_MV_ERROR
      __mvEXIST() is much faster function

  * harbour/source/rtl/type.c
    * execute hb_memvarUpdatePrivatesBase() after macro type checking.
      This should not be necessary but we are not Clipper compatible here
      and this is work around for difference in our TYPE() implementation.
      Clipper for:
         ? TYPE("VAR:=1")
      create PUBLIC variable VAR when [x]Harbour PRIVATE one.
      Should we try to make it Clipper compatible?

   The above should fix problems reported with memvars. We are not 100%
   Clipper compatible but unlike in Clipper we cannot break VM internals
   using some operation on references to memvars and detached locals
   and/or RELEASE.../ CLEAR MEMORY. This modifications should be intensively
   tested. If you will find any problems with current code please inform me.
   I'd like to hear your opinions about memvars created by TYPE() (see above).
   Should we change it? It may not be very easy operation - we will have to
   change macro compiler and add new PCODE for that.
This commit is contained in:
Przemyslaw Czerpak
2006-08-18 23:12:38 +00:00
parent 68cb7f510b
commit 8bef490815
18 changed files with 401 additions and 355 deletions

View File

@@ -8,6 +8,104 @@
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
2006-08-19 01:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbapi.h
* moved HB_STACK_STATE declaration from hbstack.h to hbapi.h
it's covered by _HB_API_INTERNAL_ macro so it should not
effect 3-rd party code
* modified hb_struSymbol structure:
LONG stackbase
replaced by:
PHB_STACK_STATE stackstate
this modification allows to keepadditional information bound with
function call stack accessible from different HVM modules.
Now it's used by memvars code to keep/update PRIVATE variables
stack pointers. I plan to store in HB_STACK_STATE structure
information additional information for classes code like super
casting or instance variables offsets in new OOP model I'm working on.
It can be also used by debugger code to retrieve some informations
about executed functions without active updating by main HVM loop.
+ added hb_memvarsClear() - cleanly clears all PRIVATE and PUBLIC
variables
+ added hb_memvarUpdatePrivatesBase() - updates PRIVATE stack base
offset so PRIVATE variables created in current function/procedure
will not be removed when it returns
- removed hb_memvarsRelease() and hb_memvarValueNew()
* harbour/include/hbstack.h
+ added hb_stackClearMevarsBase() - helper function for hb_memvarsClear()
clears PRIVATE stack offsets in executed functions
* changed to static offset from int to long - in different places we
were using int or long in HVM so I cleaned the HVM code to always
operate on the same type
* harbour/source/vm/estack.c
* set/restore PRIVATE stack base offset in hb_stackNewFrame()/
hb_stackOldFrame()
* updated for new HB_IT_SYMBOL structure
* harbour/source/vm/hvm.c
! removed setting/restoring PRIVATE stack base offset in hb_vmExecute()
It make code like:
eval(&("{||VAR:=1}"))
Clipper compatible
* updated for new HB_IT_SYMBOL structure
* changed order of execution exit procedures for clean memvars removing
and future destructors execution. I'll describe it better when I'll
add destructors.
* harbour/source/vm/memvars.c
! fixed CLEAR MEMORY - now this function should be safe in Harbour
It's not exactly compatible with Clipper because I intentionally
didn't replicated some Clipper bugs like possible memory corruption.
+ added hb_memvarsClear() - cleanly clears all PRIVATE and PUBLIC
variables
+ added hb_memvarUpdatePrivatesBase() - updates PRIVATE stack base
offset so PRIVATE variables created in current function/procedure
will not be removed when it returns
! fixed releasing PUBLIC and PRIVATE variables which were passed by
reference and are still active on HVM stack or in codeblocks as
detached locals (see: hb_memvarDetachDynSym())
* modified hb_memvarFindSymbol() to be more Clipper compatible
% optimized hb_memvarRelease() to operate or PHB_DYNS instead of
string comparison and not make linear dynamic symbol scan for
PUBLIC or not existing symbols
- removed hb_memvarReleasePublic()
* harbour/include/hbvmpub.h
* harbour/include/hbxvm.h
* harbour/source/compiler/gencc.c
* harbour/source/vm/classes.c
* harbour/source/vm/debug.c
* harbour/source/vm/itemapi.c
* harbour/source/vm/pcount.c
* harbour/source/vm/proc.c
* harbour/source/vm/pvalue.c
* updated for the above modifications
* harbour/source/rtl/memvarbl.prg
* harbour/source/rtl/menuto.prg
* use __mvEXIST( cMemvar ) instead of __mvSCOPE( cMemvar ) > HB_MV_ERROR
__mvEXIST() is much faster function
* harbour/source/rtl/type.c
* execute hb_memvarUpdatePrivatesBase() after macro type checking.
This should not be necessary but we are not Clipper compatible here
and this is work around for difference in our TYPE() implementation.
Clipper for:
? TYPE("VAR:=1")
create PUBLIC variable VAR when [x]Harbour PRIVATE one.
Should we try to make it Clipper compatible?
The above should fix problems reported with memvars. We are not 100%
Clipper compatible but unlike in Clipper we cannot break VM internals
using some operation on references to memvars and detached locals
and/or RELEASE.../ CLEAR MEMORY. This modifications should be intensively
tested. If you will find any problems with current code please inform me.
I'd like to hear your opinions about memvars created by TYPE() (see above).
Should we change it? It may not be very easy operation - we will have to
change macro compiler and add new PCODE for that.
2006-08-17 12:40 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/rdd_ads/ads1.c
* harbour/include/hbapi.h

View File

@@ -224,6 +224,14 @@ struct _HB_BASEARRAY;
struct _HB_ITEM;
struct _HB_VALUE;
typedef struct _HB_STACK_STATE
{
LONG lBaseItem; /* stack base offset of previous func/proc */
LONG lStatics; /* statics offset of previous func/proc */
ULONG ulPrivateBase; /* memvars base offset of previous func/proc */
} HB_STACK_STATE, * PHB_STACK_STATE; /* used to save/restore stack state in hb_vmDo)_ */
/* Internal structures that holds data */
struct hb_struArray
{
@@ -308,10 +316,10 @@ struct hb_struString
struct hb_struSymbol
{
LONG stackbase;
USHORT lineno;
USHORT paramcnt;
PHB_SYMB value;
PHB_SYMB value;
PHB_STACK_STATE stackstate; /* function stack state */
USHORT lineno;
USHORT paramcnt;
};
/* items hold at the virtual machine stack */
@@ -717,9 +725,8 @@ extern PHB_ITEM hb_codeblockGetRef( HB_CODEBLOCK_PTR pCBlock, PHB_ITEM p
extern void hb_codeblockEvaluate( HB_ITEM_PTR pItem ); /* evaluate a codeblock */
/* memvars subsystem */
extern HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar ); /* create a new global value */
extern void hb_memvarsInit( void ); /* initialize the memvar API system */
extern void hb_memvarsRelease( void ); /* clear all PUBLIC and PRIVATE variables */
extern void hb_memvarsClear( void ); /* clear all PUBLIC and PRIVATE variables */
extern void hb_memvarsFree( void ); /* release the memvar API system */
extern void hb_memvarValueIncRef( HB_HANDLE hValue ); /* increase the reference count of a global value */
extern void hb_memvarValueDecRef( HB_HANDLE hValue ); /* decrease the reference count of a global value */
@@ -729,6 +736,7 @@ extern void hb_memvarGetValue( HB_ITEM_PTR pItem, PHB_SYMB pMemvarSymb );
extern void hb_memvarGetRefer( HB_ITEM_PTR pItem, PHB_SYMB pMemvarSymb ); /* copy a reference to a symbol value into an item, with error trapping */
extern ULONG hb_memvarGetPrivatesBase( void ); /* retrieve current PRIVATE variables stack base */
extern void hb_memvarSetPrivatesBase( ULONG ulBase ); /* release PRIVATE variables created after specified base */
extern void hb_memvarUpdatePrivatesBase( void ); /* Update PRIVATE base ofsset so they will not be removed when function return */
extern void hb_memvarNewParameter( PHB_SYMB pSymbol, PHB_ITEM pValue );
extern char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen );
extern void hb_memvarCreateFromItem( PHB_ITEM pMemvar, BYTE bScope, PHB_ITEM pValue );

View File

@@ -74,19 +74,13 @@ typedef struct
HB_ITEM Return; /* latest returned value */
PHB_ITEM * pBase; /* stack frame position for the current function call */
PHB_ITEM * pEvalBase; /* stack frame position for the evaluated codeblock */
int iStatics; /* statics base for the current function call */
LONG lStatics; /* statics base for the current function call */
LONG lWithObject; /* stack offset to base current WITH OBJECT item */
char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */
} HB_STACK;
extern HB_STACK hb_stack;
typedef struct
{
LONG lBaseItem;
LONG iStatics;
} HB_STACK_STATE; /* used to save/restore stack state in hb_vmDo)_ */
#endif
extern HB_ITEM_PTR hb_stackItemFromTop( int nFromTop );
@@ -99,8 +93,8 @@ extern HB_ITEM_PTR hb_stackSelfItem( void );
extern HB_ITEM_PTR hb_stackItem( LONG iItemPos );
extern HB_ITEM_PTR hb_stackReturnItem( void );
extern char * hb_stackDateBuffer( void );
extern void hb_stackSetStaticsBase( int iBase );
extern int hb_stackGetStaticsBase( void );
extern void hb_stackSetStaticsBase( LONG lBase );
extern LONG hb_stackGetStaticsBase( void );
extern PHB_ITEM ** hb_stackItemBasePtr( void );
extern PHB_ITEM hb_stackWithObjectItem( void );
extern LONG hb_stackWithObjectOffset( void );
@@ -128,6 +122,7 @@ extern void hb_stackIncrease( void ); /* increase the stack size */
extern void hb_stackDecrease( ULONG ulItems );
extern HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams );
extern void hb_stackOldFrame( HB_STACK_STATE * pStack );
extern void hb_stackClearMevarsBase( void );
#endif
#if defined(HB_STACK_MACROS)
@@ -142,8 +137,8 @@ extern void hb_stackOldFrame( HB_STACK_STATE * pStack );
#define hb_stackItem( iItemPos ) ( * ( hb_stack.pItems + ( iItemPos ) ) )
#define hb_stackReturnItem( ) ( &hb_stack.Return )
#define hb_stackDateBuffer( ) ( hb_stack.szDate )
#define hb_stackGetStaticsBase( ) ( hb_stack.iStatics )
#define hb_stackSetStaticsBase( n ) do { hb_stack.iStatics = ( n ); } while ( 0 )
#define hb_stackGetStaticsBase( ) ( hb_stack.lStatics )
#define hb_stackSetStaticsBase( n ) do { hb_stack.lStatics = ( n ); } while ( 0 )
#define hb_stackItemBasePtr( ) ( &hb_stack.pItems )
#define hb_stackWithObjectItem( ) ( hb_stack.lWithObject ? * ( hb_stack.pItems + hb_stack.lWithObject ) : NULL )
#define hb_stackWithObjectOffset( ) ( hb_stack.lWithObject )

View File

@@ -167,7 +167,7 @@ typedef struct _HB_SYMB
{
PHB_FUNC pFunPtr; /* machine code function address for function symbol table entries */
PHB_PCODEFUNC pCodeFunc; /* PCODE function address */
int iStaticsBase; /* base offset to array of statics */
LONG lStaticsBase; /* base offset to array of statics */
} value;
PHB_DYNS pDynSym; /* pointer to its dynamic symbol if defined */
} HB_SYMB, * PHB_SYMB;

View File

@@ -73,7 +73,7 @@ HB_EXTERN_BEGIN
* to check HVM state so they are simply declared as void.
*/
extern HB_EXPORT void hb_xvmExitProc( ULONG ulPrivateBase );
extern HB_EXPORT void hb_xvmExitProc( void );
extern HB_EXPORT void hb_xvmSeqBegin( void );
extern HB_EXPORT BOOL hb_xvmSeqEnd( void );
extern HB_EXPORT BOOL hb_xvmSeqEndTest( void );

View File

@@ -1742,7 +1742,6 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc )
}
fprintf( yyc, "{\n" );
fprintf( yyc, " ULONG ulPrivateBase = hb_memvarGetPrivatesBase();\n" );
if( label_info.fCondJump )
fprintf( yyc, " BOOL fValue;\n" );
fprintf( yyc, " do {\n" );
@@ -1750,7 +1749,7 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc )
hb_compPCodeEval( pFunc, ( HB_PCODE_FUNC_PTR * ) s_verbose_table, ( void * ) &label_info );
fprintf( yyc, " } while ( 0 );\n" );
fprintf( yyc, " hb_xvmExitProc( ulPrivateBase );\n" );
fprintf( yyc, " hb_xvmExitProc();\n" );
fprintf( yyc, "}\n" );
if( label_info.pulLabels )

View File

@@ -56,7 +56,7 @@
FUNCTION MEMVARBLOCK( cMemvar )
IF ISCHARACTER( cMemvar ) .AND. __mvSCOPE( cMemvar ) > HB_MV_ERROR
IF ISCHARACTER( cMemvar ) .AND. __mvEXIST( cMemvar )
RETURN {| x | iif( x == NIL, __mvGET( cMemvar ), __mvPUT( cMemvar, x ) ) }
ENDIF

View File

@@ -67,12 +67,9 @@ function __MenuTo( bBlock, cVariable )
local cFrontColor
// Detect if a memvar was passed
if __mvSCOPE( cVariable ) <= HB_MV_ERROR
lDeclared := !__mvEXIST( cVariable )
if lDeclared
__mvPUBLIC( cVariable )
lDeclared := .T.
else
lDeclared := .F.
endif
n := eval( bBlock )

View File

@@ -58,7 +58,10 @@ HB_FUNC( TYPE )
HB_ITEM_PTR pItem = hb_param( 1, HB_IT_STRING );
if( pItem )
{
hb_retc( hb_macroGetType( pItem ) );
hb_memvarUpdatePrivatesBase();
}
else
hb_errRT_BASE_SubstR( EG_ARG, 1121, NULL, "TYPE", 1, hb_paramError( 1 ) );
}

View File

@@ -510,28 +510,28 @@ static void hb_clsScope( PHB_ITEM pObject, PMETHOD pMethod )
szSelfNameRealClass = hb_objGetRealClsName( pObject, pMessage->pSymbol->szName );
while( iLevel-- > 0 && lOffset > 1 )
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1;
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName;
/* Is it an inline ? if so back one more ... */
if( strcmp( szCallerNameMsg, "__EVAL" ) == 0 && lOffset > 1 )
{
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1;
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName;
}
/* Is it an eval ? if so back another one more ... */
if( ( strcmp( szCallerNameMsg, "EVAL" ) == 0 ) && lOffset > 1 )
{
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1;
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName;
}
/* Is it an Aeval ? if so back another one more ... */
if ( ( strcmp( szCallerNameMsg, "AEVAL" ) == 0 ) && lOffset > 1 )
{
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1;
lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName;
}
@@ -2234,7 +2234,7 @@ HB_FUNC( __CLASSSEL )
/* to be used from Classes ERROR HANDLER method */
HB_FUNC( __GETMESSAGE )
{
hb_retc( hb_stackItem( hb_stackBaseItem()->item.asSymbol.stackbase )->item.asSymbol.value->szName );
hb_retc( hb_stackItem( hb_stackBaseItem()->item.asSymbol.stackstate->lBaseItem )->item.asSymbol.value->szName );
}
HB_FUNC( __CLSPARENT )
@@ -2250,7 +2250,7 @@ HB_FUNC( __SENDER )
while( iLevel > 0 && lOffset > 1 )
{
lOffset = hb_stackItem( lOffset )->item.asSymbol.stackbase;
lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem;
oSender = hb_stackItem( lOffset + 1 );
if( ( iLevel-- == 2 && oSender->type != HB_IT_BLOCK ) || oSender->type == HB_IT_NIL )
@@ -2270,11 +2270,9 @@ HB_FUNC( __SENDER )
*/
HB_FUNC( __CLASSH )
{
PHB_ITEM pObject = hb_itemParam( 1 );
PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT );
hb_retni( HB_IS_OBJECT( pObject ) ? pObject->item.asArray.value->uiClass : 0 );
hb_itemRelease( pObject );
hb_retni( pObject ? pObject->item.asArray.value->uiClass : 0 );
}
/*

View File

@@ -120,11 +120,11 @@ static LONG hb_stackLen( int iLevel )
lBaseOffset = hb_stackBaseOffset();
while( --iLevel > 0 && lBaseOffset > 1 )
lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase + 1;
lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
if( lBaseOffset > 1 )
{
lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase;
lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem;
lLen = lBaseOffset - lPrevOffset - 3;
}
else
@@ -160,7 +160,7 @@ HB_FUNC( HB_DBG_VMSTKLLIST )
LONG lBaseOffset, lPrevOffset;
lBaseOffset = hb_stackBaseOffset();
lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase;
lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem;
ulLen = lBaseOffset - lPrevOffset - 3;
pReturn = hb_itemArrayNew( ulLen ); /* Create a transfer array */
@@ -190,7 +190,7 @@ HB_FUNC( HB_DBG_VMVARLGET )
lBaseOffset = hb_stackBaseOffset();
while( iLevel-- > 0 && lBaseOffset > 1 )
lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase + 1;
lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
if( iLevel < 0 )
{
@@ -215,7 +215,7 @@ HB_FUNC( HB_DBG_VMVARLSET )
lBaseOffset = hb_stackBaseOffset();
while( iLevel-- > 0 && lBaseOffset > 1 )
lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase + 1;
lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1;
if( iLevel < 0 )
{

View File

@@ -229,8 +229,10 @@ void hb_stackRemove( LONG lUntilPos )
HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams )
{
HB_ITEM_PTR pItem;
pItem = hb_stackItemFromTop( - uiParams - 2 ); /* procedure name */
HB_ITEM_PTR * pBase, pItem;
pBase = hb_stack.pPos - uiParams - 2;
pItem = * pBase; /* procedure symbol */
if( ! HB_IS_SYMBOL( pItem ) )
{
@@ -240,12 +242,12 @@ HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams )
}
pStack->lBaseItem = hb_stack.pBase - hb_stack.pItems;
pStack->iStatics = hb_stack.iStatics;
pStack->lStatics = hb_stack.lStatics;
pStack->ulPrivateBase = hb_memvarGetPrivatesBase();
pItem->item.asSymbol.stackstate = pStack;
pItem->item.asSymbol.lineno = 0;
pItem->item.asSymbol.paramcnt = uiParams;
hb_stack.pBase = hb_stack.pItems + pItem->item.asSymbol.stackbase;
pItem->item.asSymbol.stackbase = pStack->lBaseItem;
hb_stack.pBase = pBase;
return pItem;
}
@@ -260,7 +262,8 @@ void hb_stackOldFrame( HB_STACK_STATE * pStack )
}
hb_stack.pBase = hb_stack.pItems + pStack->lBaseItem;
hb_stack.iStatics = pStack->iStatics;
hb_stack.lStatics = pStack->lStatics;
hb_memvarSetPrivatesBase( pStack->ulPrivateBase );
}
#undef hb_stackItem
@@ -278,7 +281,7 @@ HB_ITEM_PTR hb_stackItemFromTop( int nFromTop )
if( nFromTop > 0 )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
return ( * ( hb_stack.pPos + nFromTop ) );
return * ( hb_stack.pPos + nFromTop );
}
#undef hb_stackItemFromBase
@@ -287,7 +290,7 @@ HB_ITEM_PTR hb_stackItemFromBase( int nFromBase )
if( nFromBase <= 0 )
hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL );
return ( * ( hb_stack.pBase + nFromBase + 1 ) );
return * ( hb_stack.pBase + nFromBase + 1 );
}
#undef hb_stackBaseItem
@@ -337,15 +340,15 @@ char * hb_stackDateBuffer( void )
}
#undef hb_stackGetStaticsBase
int hb_stackGetStaticsBase( void )
LONG hb_stackGetStaticsBase( void )
{
return hb_stack.iStatics;
return hb_stack.lStatics;
}
#undef hb_stackSetStaticsBase
void hb_stackSetStaticsBase( int iBase )
void hb_stackSetStaticsBase( LONG lBase )
{
hb_stack.iStatics = iBase;
hb_stack.lStatics = lBase;
}
#undef hb_stackWithObjectItem
@@ -373,6 +376,22 @@ PHB_ITEM ** hb_stackItemBasePtr( void )
return &hb_stack.pItems;
}
void hb_stackClearMevarsBase( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_stackClearMevarsBase()"));
if( hb_stack.pBase > hb_stack.pPos )
{
PHB_ITEM pBase = * hb_stack.pBase;
while( pBase->item.asSymbol.stackstate->ulPrivateBase != 0 )
{
pBase->item.asSymbol.stackstate->ulPrivateBase = 0;
pBase = * ( hb_stack.pItems + pBase->item.asSymbol.stackstate->lBaseItem );
}
}
}
int hb_stackCallDepth( void )
{
LONG lOffset = hb_stack.pBase - hb_stack.pItems;
@@ -380,7 +399,7 @@ int hb_stackCallDepth( void )
while( lOffset > 0 )
{
lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackbase;
lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackstate->lBaseItem;
++iLevel;
}
@@ -392,7 +411,7 @@ LONG hb_stackBaseProcOffset( int iLevel )
LONG lOffset = hb_stack.pBase - hb_stack.pItems;
while( iLevel-- > 0 && lOffset > 0 )
lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackbase;
lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackstate->lBaseItem;
if( iLevel < 0 )
return lOffset;
@@ -503,7 +522,7 @@ void hb_stackDispCall( void )
{
char buffer[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 32 ];
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackbase;
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
if( ( *( pBase + 1 ) )->type == HB_IT_ARRAY )
sprintf( buffer, HB_I_("Called from %s:%s(%i)"), hb_objGetClsName( *(pBase + 1) ),
@@ -573,7 +592,7 @@ LONG WINAPI hb_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionI
strcat( msg, buffer );
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackbase;
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
}
while( pBase != hb_stack.pItems );
@@ -617,7 +636,7 @@ ULONG _System OS2TermHandler(PEXCEPTIONREPORTRECORD p1,
( *pBase )->item.asSymbol.value->szName,
( *pBase )->item.asSymbol.lineno );
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackbase;
pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem;
}
while( pBase != hb_stack.pItems );
}

View File

@@ -538,24 +538,28 @@ HB_EXPORT int hb_vmQuit( void )
hb_vmCleanModuleFunctions();
/* release all known items stored in subsystems */
hb_itemClear( hb_stackReturnItem() );
hb_stackRemove( 0 ); /* clear stack items */
hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */
/* intentionally here to allow executing object destructors for all
* cross references items before we release classy subsystem
*/
hb_gcCollectAll();
hb_rddShutDown();
hb_idleShutDown();
hb_errExit();
hb_clsReleaseAll();
hb_vmReleaseLocalSymbols(); /* releases the local modules linked list */
hb_dynsymRelease(); /* releases the dynamic symbol table */
hb_conRelease(); /* releases Console */
hb_setRelease(); /* releases Sets */
hb_cdpReleaseAll(); /* releases codepages */
hb_itemClear( &s_aStatics );
/* release all remaining items */
hb_stackRemove( 0 );
hb_itemClear( hb_stackReturnItem() );
hb_itemClear( &s_aStatics );
hb_memvarsRelease(); /* clear all PUBLIC variables */
/* release all known garbage */
/* hb_gcReleaseAll(); */
hb_conRelease(); /* releases Console */
hb_setRelease(); /* releases Sets */
hb_vmReleaseLocalSymbols(); /* releases the local modules linked list */
hb_dynsymRelease(); /* releases the dynamic symbol table */
hb_cdpReleaseAll(); /* releases codepages */
/* release all known garbage */
if( hb_xquery( HB_MEM_USEDMAX ) ) /* check if fmstat is ON */
@@ -575,7 +579,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
{
LONG w = 0;
BOOL bCanRecover = FALSE;
ULONG ulPrivateBase;
BOOL bDynCode = pSymbols == NULL || ( pSymbols->scope.value & HB_FS_DYNCODE ) != 0;
#ifndef HB_NO_PROFILER
ULONG ulLastOpcode = 0; /* opcodes profiler support */
@@ -587,14 +590,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
HB_TRACE(HB_TR_DEBUG, ("hb_vmExecute(%p, %p)", pCode, pSymbols));
/* NOTE: if pSymbols == NULL then hb_vmExecute is called from macro
* evaluation. In this case all PRIVATE variables created during
* macro evaluation belong to a function/procedure where macro
* compiler was called.
*/
/* NOTE: Initialization with 0 is needed to avoid GCC -O2 warning */
ulPrivateBase = pSymbols ? hb_memvarGetPrivatesBase() : 0;
#ifndef HB_NO_PROFILER
if( hb_bProfiler )
ulPastClock = ( ULONG ) clock();
@@ -1864,9 +1859,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols )
}
}
}
if( pSymbols )
hb_memvarSetPrivatesBase( ulPrivateBase );
}
/* ------------------------------- */
@@ -4298,7 +4290,7 @@ static void hb_vmSFrame( PHB_SYMB pSym ) /* sets the statics frame for a fu
HB_TRACE(HB_TR_DEBUG, ("hb_vmSFrame(%p)", pSym));
/* _INITSTATICS is now the statics frame. Statics() changed it! */
hb_stackSetStaticsBase( pSym->value.iStaticsBase );
hb_stackSetStaticsBase( pSym->value.lStaticsBase );
}
static void hb_vmStatics( PHB_SYMB pSym, USHORT uiStatics ) /* initializes the global aStatics array or redimensionates it */
@@ -4307,13 +4299,13 @@ static void hb_vmStatics( PHB_SYMB pSym, USHORT uiStatics ) /* initializes the g
if( HB_IS_NIL( &s_aStatics ) )
{
pSym->value.iStaticsBase = 0; /* statics frame for this PRG */
pSym->value.lStaticsBase = 0; /* statics frame for this PRG */
hb_arrayNew( &s_aStatics, uiStatics );
}
else
{
pSym->value.iStaticsBase = hb_arrayLen( &s_aStatics );
hb_arraySize( &s_aStatics, ( ULONG ) pSym->value.iStaticsBase + uiStatics );
pSym->value.lStaticsBase = hb_arrayLen( &s_aStatics );
hb_arraySize( &s_aStatics, ( ULONG ) pSym->value.lStaticsBase + uiStatics );
}
}
@@ -4616,7 +4608,7 @@ HB_EXPORT void hb_vmPushSymbol( PHB_SYMB pSym )
pItem->type = HB_IT_SYMBOL;
pItem->item.asSymbol.value = pSym;
pItem->item.asSymbol.stackbase = hb_stackTopOffset() - 1;
pItem->item.asSymbol.stackstate = NULL;
}
/* -3 -> HB_P_PUSHBLOCK
@@ -5950,12 +5942,10 @@ ULONG hb_vmFlagEnabled( ULONG flags )
#define HB_XVM_RETURN return ( s_uiActionRequest & \
( HB_ENDPROC_REQUESTED | HB_BREAK_REQUESTED | HB_QUIT_REQUESTED ) ) != 0;
HB_EXPORT void hb_xvmExitProc( ULONG ulPrivateBase )
HB_EXPORT void hb_xvmExitProc( void )
{
if( s_uiActionRequest & HB_ENDPROC_REQUESTED )
s_uiActionRequest = 0;
hb_memvarSetPrivatesBase( ulPrivateBase );
}
@@ -6281,7 +6271,7 @@ HB_EXPORT void hb_xvmPushFuncSymbol( PHB_SYMB pSym )
pItem = hb_stackAllocItem();
pItem->type = HB_IT_SYMBOL;
pItem->item.asSymbol.value = pSym;
pItem->item.asSymbol.stackbase = hb_stackTopOffset() - 1;
pItem->item.asSymbol.stackstate = NULL;
hb_stackAllocItem()->type = HB_IT_NIL;
}

View File

@@ -1135,10 +1135,10 @@ HB_EXPORT PHB_ITEM hb_itemPutSymbol( PHB_ITEM pItem, PHB_SYMB pSym )
pItem = hb_itemNew( NULL );
pItem->type = HB_IT_SYMBOL;
pItem->item.asSymbol.stackbase = 0;
pItem->item.asSymbol.lineno = 0;
pItem->item.asSymbol.paramcnt = 0;
pItem->item.asSymbol.value = pSym;
pItem->item.asSymbol.value = pSym;
pItem->item.asSymbol.stackstate = NULL;
pItem->item.asSymbol.lineno = 0;
pItem->item.asSymbol.paramcnt = 0;
return pItem;
}

View File

@@ -98,9 +98,6 @@ struct mv_PUBLIC_var_info
};
static void hb_memvarCreateFromDynSymbol( PHB_DYNS, BYTE, PHB_ITEM );
static void hb_memvarAddPrivate( PHB_DYNS );
static void hb_memvarReleasePublic( PHB_ITEM pMemVar );
static HB_DYNS_PTR hb_memvarFindSymbol( char *, ULONG );
void hb_memvarsInit( void )
{
@@ -116,29 +113,6 @@ void hb_memvarsInit( void )
s_privateStackCnt = s_privateStackBase = 0;
}
/* clear all variables except the detached ones
* Should be called at application exit only
*/
void hb_memvarsRelease( void )
{
ULONG ulCnt = s_globalLastFree;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarsClear()"));
if( s_globalTable )
{
while( --ulCnt )
{
if( s_globalTable[ ulCnt ].counter && s_globalTable[ ulCnt ].hPrevMemvar != ( HB_HANDLE )-1 )
{
hb_itemClear( s_globalTable[ ulCnt ].pVarItem );
hb_xfree( s_globalTable[ ulCnt ].pVarItem );
s_globalTable[ ulCnt ].counter = 0;
}
}
}
}
void hb_memvarsFree( void )
{
if( s_globalTable )
@@ -160,25 +134,27 @@ HB_VALUE_PTR *hb_memvarValueBaseAddress( void )
* This function creates new global value.
*
* pSource = item value that have to be stored or NULL
* bTrueMemvar = TRUE | FALSE
* FALSE if function is called to create memvar variable for a codeblock
* hPrevMemvar
* -1 if function is called to create memvar variable for a codeblock
* (to store detached local variable) - in this case we have to do
* exact copy of passed item (without duplicating its value and
* without reference decrementing)
* TRUE if we are creating regular memvar variable (PUBLI or PRIVATE)
* else we are creating regular memvar variable (PUBLIC or PRIVATE)
* In this case we have to do normal item coping.
* hPrevMemvar > 0 is old memvar value which will be hidden by
* new PRIVATE variable
*
* Returns:
* handle to variable memory or fails
*
*/
HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar )
static HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, HB_HANDLE hPrevMemvar )
{
HB_VALUE_PTR pValue;
HB_HANDLE hValue; /* handle 0 is reserved */
/* = 1 removed, since it's initialized in all branches. Caused a warning with Borland C++ */
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueNew(%p, %d)", pSource, (int) bTrueMemvar));
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueNew(%p, %lu)", pSource, hPrevMemvar));
if( s_globalFirstFree )
{
@@ -208,28 +184,104 @@ HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar )
pValue = s_globalTable + hValue;
pValue->pVarItem = ( HB_ITEM_PTR ) hb_xgrab( sizeof( HB_ITEM ) );
pValue->counter = 1;
pValue->pVarItem->type = HB_IT_NIL;
pValue->hPrevMemvar = hPrevMemvar;
pValue->counter = 1;
if( pSource )
{
if( bTrueMemvar )
hb_itemCopy( pValue->pVarItem, pSource );
else
if( hPrevMemvar == ( HB_HANDLE ) -1 ) /* detached local - copy its body only */
memcpy( pValue->pVarItem, pSource, sizeof( HB_ITEM ) );
else
hb_itemCopy( pValue->pVarItem, pSource );
}
if( bTrueMemvar )
pValue->hPrevMemvar = 0;
else
pValue->hPrevMemvar = ( HB_HANDLE ) -1; /* detached variable */
HB_TRACE(HB_TR_INFO, ("hb_memvarValueNew: memvar item created with handle %i", hValue));
return hValue;
}
/* Detach local variable (swap current value with a memvar handle)
*/
static void hb_memvarRecycle( HB_HANDLE hValue )
{
HB_TRACE(HB_TR_DEBUG, ("hb_memvarRecycle(%lu)", hValue));
s_globalTable[ hValue ].hPrevMemvar = s_globalFirstFree;
s_globalFirstFree = hValue;
}
/*
* This function increases the number of references to passed global value
*/
void hb_memvarValueIncRef( HB_HANDLE hValue )
{
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueIncRef(%lu)", hValue));
s_globalTable[ hValue ].counter++;
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) increment refCounter=%li", hValue, s_globalTable[ hValue ].counter));
}
/*
* This function decreases the number of references to passed global value.
* If it is the last reference then this value is deleted.
*/
void hb_memvarValueDecRef( HB_HANDLE hValue )
{
HB_VALUE_PTR pValue;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueDecRef(%lu)", hValue));
pValue = s_globalTable + hValue;
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) decrement refCounter=%li", hValue, pValue->counter-1));
if( --pValue->counter == 0 )
{
if( HB_IS_COMPLEX( pValue->pVarItem ) )
hb_itemClear( pValue->pVarItem );
hb_xfree( pValue->pVarItem );
hb_memvarRecycle( hValue );
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue));
}
}
/*
* Detach local variable (swap current value with a memvar handle)
*/
static void hb_memvarDetachDynSym( PHB_DYNS pDynSym, BOOL fRestore )
{
HB_VALUE_PTR pValue;
HB_HANDLE hValue;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarDetachDynSym(%p, %d)", pDynSym, fRestore));
hValue = pDynSym->hMemvar;
pValue = s_globalTable + hValue;
pDynSym->hMemvar = fRestore ? pValue->hPrevMemvar : 0;
if( --pValue->counter == 0 )
{
if( HB_IS_COMPLEX( pValue->pVarItem ) )
hb_itemClear( pValue->pVarItem );
hb_xfree( pValue->pVarItem );
hb_memvarRecycle( hValue );
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue));
}
else
{
/* memvar is still accessible by active references on HVM stack
* and/or as detached local in codeblocks - so we have to mark it
* as detached or it will be scanned in GC mark pass and if some
* cross references exists it will never be freed.
*/
pValue->hPrevMemvar = ( HB_HANDLE ) -1;
}
}
/*
* Detach local variable (swap current value with a memvar handle)
*/
HB_ITEM_PTR hb_memvarDetachLocal( HB_ITEM_PTR pLocal )
{
HB_TRACE(HB_TR_DEBUG, ("hb_memvarDetachLocal(%p, %d)", pLocal, pLocal->type ));
@@ -250,9 +302,9 @@ HB_ITEM_PTR hb_memvarDetachLocal( HB_ITEM_PTR pLocal )
* In this case we have to copy the current value to a global memory
* pool so it can be shared by codeblocks
*/
if ( ! HB_IS_MEMVAR( pLocal ) )
if( ! HB_IS_MEMVAR( pLocal ) )
{
HB_HANDLE hMemvar = hb_memvarValueNew( pLocal, FALSE );
HB_HANDLE hMemvar = hb_memvarValueNew( pLocal, ( HB_HANDLE ) -1 );
pLocal->type = HB_IT_BYREF | HB_IT_MEMVAR;
pLocal->item.asMemvar.itemsbase = &s_globalTable;
@@ -301,135 +353,34 @@ ULONG hb_memvarGetPrivatesBase( void )
/*
* This function releases PRIVATE variables created after passed base
*
*/
void hb_memvarSetPrivatesBase( ULONG ulBase )
{
HB_HANDLE hVar, hOldValue;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarSetPrivatesBase(%lu)", ulBase));
while( s_privateStackCnt > s_privateStackBase )
{
hVar = s_privateStack[ --s_privateStackCnt ]->hMemvar;
if( hVar )
if( s_privateStack[ --s_privateStackCnt ]->hMemvar )
{
hOldValue = s_globalTable[ hVar ].hPrevMemvar;
hb_memvarValueDecRef( hVar );
/*
* Restore previous value for variables that were overridden
/* Restore previous value for variables that were overridden
*/
s_privateStack[ s_privateStackCnt ]->hMemvar = hOldValue;
hb_memvarDetachDynSym( s_privateStack[ s_privateStackCnt ], TRUE );
}
}
s_privateStackBase = ulBase;
}
/*
* This function increases the number of references to passed global value
*
* Update PRIVATE base ofsset so they will not be removed
* when function return
*/
void hb_memvarValueIncRef( HB_HANDLE hValue )
void hb_memvarUpdatePrivatesBase( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueIncRef(%lu)", hValue));
HB_TRACE(HB_TR_DEBUG, ("hb_memvarUpdatePrivatesBase()"));
s_globalTable[ hValue ].counter++;
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) increment refCounter=%li", hValue, s_globalTable[ hValue ].counter));
s_privateStackBase = s_privateStackCnt;
}
static void hb_memvarRecycle( HB_HANDLE hValue )
{
HB_TRACE(HB_TR_DEBUG, ("hb_memvarRecycle(%lu)", hValue));
if( s_globalFirstFree )
{
s_globalTable[ hValue ].hPrevMemvar = s_globalFirstFree;
s_globalFirstFree = hValue;
}
else
{
/* first free value in the list */
s_globalFirstFree = hValue;
s_globalTable[ hValue ].hPrevMemvar = 0;
}
}
/*
* This function decreases the number of references to passed global value.
* If it is the last reference then this value is deleted.
*
*/
void hb_memvarValueDecRef( HB_HANDLE hValue )
{
HB_VALUE_PTR pValue;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueDecRef(%lu)", hValue));
pValue = s_globalTable + hValue;
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) decrement refCounter=%li", hValue, pValue->counter-1));
if( pValue->counter > 0 )
{
/* Notice that Counter can be equal to 0.
* This can happen if for example PUBLIC variable holds a codeblock
* with detached variable. When hb_memvarsRelease() is called then
* detached variable can be released before the codeblock. So if
* the codeblock will be released later then it will try to release
* again this detached variable.
*/
if( --pValue->counter == 0 )
{
if( HB_IS_COMPLEX( pValue->pVarItem ) )
hb_itemClear( pValue->pVarItem );
hb_xfree( pValue->pVarItem );
hb_memvarRecycle( hValue );
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue));
}
}
}
#if 0
/* This function is called from releasing of detached local variables
* referenced in a codeblock that is wiped out by the Garbage Collector.
* Decrement the reference counter and clear a value stored in the memvar.
* Don't clear arrays or codeblocks to avoid loops - these values will be
* released by the garbage collector.
*/
void hb_memvarValueDecGarbageRef( HB_HANDLE hValue )
{
HB_VALUE_PTR pValue;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueDecRef(%lu)", hValue));
pValue = s_globalTable + hValue;
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) decrement refCounter=%li", hValue, pValue->counter-1));
if( pValue->counter > 0 )
{
/* Notice that Counter can be equal to 0.
* This can happen if for example PUBLIC variable holds a codeblock
* with detached variable. When hb_memvarsRelease() is called then
* detached variable can be released before the codeblock. So if
* the codeblock will be released later then it will try to release
* again this detached variable.
*/
if( --pValue->counter == 0 )
{
if( HB_IS_STRING( pValue->pVarItem ) )
hb_itemClear( pValue->pVarItem );
hb_xfree( pValue->pVarItem );
hb_memvarRecycle( hValue );
HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue));
}
}
}
#endif
/*
* This functions copies passed item value into the memvar pointed
* by symbol
@@ -601,6 +552,50 @@ void hb_memvarNewParameter( PHB_SYMB pSymbol, PHB_ITEM pValue )
hb_memvarCreateFromDynSymbol( pSymbol->pDynSym, HB_MV_PRIVATE, pValue );
}
static HB_DYNS_PTR hb_memvarFindSymbol( char * szArg, ULONG ulLen )
{
HB_DYNS_PTR pDynSym = NULL;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarFindSymbol(%p,%lu)", szArg, ulLen));
if( szArg && *szArg && ulLen )
{
char szUprName[ HB_SYMBOL_NAME_LEN + 1 ];
int iSize = 0;
do
{
char cChar = *szArg++;
if( cChar >= 'a' && cChar <= 'z' )
{
szUprName[ iSize++ ] = cChar - ( 'a' - 'A' );
}
else if( cChar == ' ' || cChar == '\t' || cChar == '\n' )
{
if( iSize )
break;
}
else if( !cChar )
{
break;
}
else
{
szUprName[ iSize++ ] = cChar;
}
}
while( --ulLen && iSize < HB_SYMBOL_NAME_LEN );
if( iSize )
{
szUprName[ iSize ] = '\0';
pDynSym = hb_dynsymFind( szUprName );
}
}
return pDynSym;
}
char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen )
{
HB_DYNS_PTR pDynVar;
@@ -638,7 +633,7 @@ char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen )
*
* pMemvar - an item that stores the name of variable - it can be either
* the HB_IT_SYMBOL (if created by PUBLIC statement) or HB_IT_STRING
* (if created by direct call to __PUBLIC function)
* (if created by direct call to __MVPUBLIC function)
* bScope - the scope of created variable - if a variable with the same name
* exists already then it's value is hidden by new variable with
* passed scope
@@ -676,7 +671,7 @@ static void hb_memvarCreateFromDynSymbol( PHB_DYNS pDynVar, BYTE bScope, PHB_ITE
*/
if( ! pDynVar->hMemvar )
{
pDynVar->hMemvar = hb_memvarValueNew( pValue, TRUE );
pDynVar->hMemvar = hb_memvarValueNew( pValue, 0 );
if( !pValue )
{
/* new PUBLIC variable - initialize it to .F.
@@ -701,10 +696,7 @@ static void hb_memvarCreateFromDynSymbol( PHB_DYNS pDynVar, BYTE bScope, PHB_ITE
* visible at this moment so later we can restore this value when
* the new variable will be released
*/
HB_HANDLE hCurrentValue = pDynVar->hMemvar;
pDynVar->hMemvar = hb_memvarValueNew( pValue, TRUE );
s_globalTable[ pDynVar->hMemvar ].hPrevMemvar = hCurrentValue;
pDynVar->hMemvar = hb_memvarValueNew( pValue, pDynVar->hMemvar );
/* Add this variable to the PRIVATE variables stack
*/
@@ -722,31 +714,32 @@ static void hb_memvarRelease( HB_ITEM_PTR pMemvar )
if( HB_IS_STRING( pMemvar ) )
{
ULONG ulBase = s_privateStackCnt;
PHB_DYNS pDynVar;
PHB_DYNS pDynSymbol = hb_memvarFindSymbol( pMemvar->item.asString.value,
pMemvar->item.asString.length );
/* Find the variable with a requested name that is currently visible
* Start from the top of the stack.
*/
while( ulBase > 0 )
if( pDynSymbol && pDynSymbol->hMemvar )
{
pDynVar = s_privateStack[ --ulBase ];
ULONG ulBase = s_privateStackCnt;
/* reset current value to NIL - the overriden variables will be
* visible after exit from current procedure
/* Find the variable with a requested name that is currently visible
* Start from the top of the stack.
*/
if( pDynVar->hMemvar )
while( ulBase > 0 )
{
if( hb_stricmp( pDynVar->pSymbol->szName, pMemvar->item.asString.value ) == 0 )
if( pDynSymbol == s_privateStack[ --ulBase ] )
{
hb_itemClear( s_globalTable[ pDynVar->hMemvar ].pVarItem );
/* reset current value to NIL - the overriden variables will be
* visible after exit from current procedure
*/
hb_itemClear( s_globalTable[ pDynSymbol->hMemvar ].pVarItem );
return;
}
}
/* No match found for PRIVATEs - it's PUBLIC so let's remove it.
*/
hb_memvarDetachDynSym( pDynSymbol, FALSE );
}
/* No match found for PRIVATEs - try PUBLICs.
*/
hb_memvarReleasePublic( pMemvar );
}
else
hb_errRT_BASE( EG_ARG, 3008, NULL, "RELEASE", HB_ERR_ARGS_BASEPARAMS );
@@ -796,21 +789,18 @@ static int hb_memvarScopeGet( PHB_DYNS pDynVar )
else
{
ULONG ulBase = s_privateStackCnt; /* start from the top of the stack */
int iMemvar = HB_MV_PUBLIC;
while( ulBase )
{
--ulBase;
if( pDynVar == s_privateStack[ ulBase ] )
if( pDynVar == s_privateStack[ --ulBase ] )
{
if( ulBase >= s_privateStackBase )
iMemvar = HB_MV_PRIVATE_LOCAL;
return HB_MV_PRIVATE_LOCAL;
else
iMemvar = HB_MV_PRIVATE_GLOBAL;
ulBase = 0;
return HB_MV_PRIVATE_GLOBAL;
}
}
return iMemvar;
return HB_MV_PUBLIC;
}
}
@@ -818,26 +808,16 @@ static int hb_memvarScopeGet( PHB_DYNS pDynVar )
*/
int hb_memvarScope( char * szVarName, ULONG ulLength )
{
int iMemvar = HB_MV_ERROR;
char * szName;
PHB_DYNS pDynVar;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarScope(%s, %lu)", szVarName, ulLength));
szName = ( char * ) hb_xalloc( ulLength );
if( szName )
{
PHB_DYNS pDynVar;
pDynVar = hb_memvarFindSymbol( szVarName, ulLength );
memcpy( szName, szVarName, ulLength );
pDynVar = hb_dynsymFind( hb_strUpper( szName, ulLength - 1 ) );
if( pDynVar )
iMemvar = hb_memvarScopeGet( pDynVar );
else
iMemvar = HB_MV_NOT_FOUND;
hb_xfree( szName );
}
return iMemvar;
if( pDynVar )
return hb_memvarScopeGet( pDynVar );
else
return HB_MV_NOT_FOUND;
}
/* Releases memory occupied by a variable
@@ -847,15 +827,22 @@ static HB_DYNS_FUNC( hb_memvarClear )
HB_SYMBOL_UNUSED( Cargo );
if( pDynSymbol->hMemvar )
{
s_globalTable[ pDynSymbol->hMemvar ].counter = 1;
hb_memvarValueDecRef( pDynSymbol->hMemvar );
pDynSymbol->hMemvar = 0;
}
hb_memvarDetachDynSym( pDynSymbol, FALSE );
return TRUE;
}
/* Clear all memvar variables */
void hb_memvarsClear( void )
{
HB_TRACE(HB_TR_DEBUG, ("hb_memvarsClear()"));
hb_stackClearMevarsBase();
s_privateStackBase = 0;
hb_memvarSetPrivatesBase( 0 );
hb_dynsymEval( hb_memvarClear, NULL );
}
/* Checks passed dynamic symbol if it is a PUBLIC variable and
* increments the counter eventually
*/
@@ -867,34 +854,6 @@ static HB_DYNS_FUNC( hb_memvarCountPublics )
return TRUE;
}
/* Checks passed dynamic symbol if it is a PUBLIC variable and
* released it eventually stoping the searching
*/
static HB_DYNS_FUNC( hb_memvarClearPublic )
{
if( hb_memvarScopeGet( pDynSymbol ) == HB_MV_PUBLIC &&
hb_stricmp( pDynSymbol->pSymbol->szName, (char *) Cargo ) == 0 )
{
s_globalTable[ pDynSymbol->hMemvar ].counter = 1;
hb_memvarValueDecRef( pDynSymbol->hMemvar );
pDynSymbol->hMemvar = 0;
return FALSE;
}
return TRUE;
}
/* find and release if exists given public variable
*/
static void hb_memvarReleasePublic( PHB_ITEM pMemVar )
{
char *sPublic = pMemVar->item.asString.value;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarReleasePublic(%p)", pMemVar ));
hb_dynsymEval( hb_memvarClearPublic, ( void * ) sPublic );
}
/* Count the number of variables with given scope
*/
static int hb_memvarCount( int iScope )
@@ -979,29 +938,6 @@ static HB_ITEM_PTR hb_memvarDebugVariable( int iScope, int iPos, char * *pszName
return pValue;
}
static HB_DYNS_PTR hb_memvarFindSymbol( char * szArg, ULONG ulLen )
{
HB_DYNS_PTR pDynSym = NULL;
HB_TRACE(HB_TR_DEBUG, ("hb_memvarFindSymbol(%p,%lu)", szArg, ulLen));
if( szArg && *szArg && ulLen )
{
char * szName = ( char * ) hb_xgrab( ulLen + 1 );
szName[ ulLen ] = '\0';
do
{
--ulLen;
szName[ ulLen ] = toupper( szArg[ ulLen ] );
} while( ulLen );
pDynSym = hb_dynsymFind( szName );
hb_xfree( szName );
}
return pDynSym;
}
/* ************************************************************************** */
HB_FUNC( __MVPUBLIC )
@@ -1065,6 +1001,7 @@ HB_FUNC( __MVPRIVATE )
hb_memvarCreateFromItem( pMemvar, VS_PRIVATE, NULL );
}
}
hb_memvarUpdatePrivatesBase();
}
}
@@ -1141,7 +1078,7 @@ HB_FUNC( __MVSCOPE )
HB_FUNC( __MVCLEAR )
{
hb_dynsymEval( hb_memvarClear, NULL );
hb_memvarsClear();
}
HB_FUNC( __MVDBGINFO )
@@ -1277,6 +1214,7 @@ HB_FUNC( __MVPUT )
* create the PRIVATE one
*/
hb_memvarCreateFromDynSymbol( hb_dynsymGet( pName->item.asString.value ), VS_PRIVATE, pValue );
hb_memvarUpdatePrivatesBase();
}
hb_itemReturn( pValue );
}
@@ -1479,7 +1417,7 @@ HB_FUNC( __MVRESTORE )
/* Clear all memory variables if not ADDITIVE */
if( ! bAdditive )
hb_dynsymEval( hb_memvarClear, NULL );
hb_memvarsClear();
/* Generate filename */
@@ -1508,7 +1446,7 @@ HB_FUNC( __MVRESTORE )
if( fhnd != FS_ERROR )
{
char * pszMask = ISCHAR( 3 ) ? hb_parc( 3 ) : ( char * ) "*";
BOOL bIncludeMask = ISCHAR( 4 ) ? hb_parl( 4 ) : TRUE;
BOOL bIncludeMask = ISLOG( 4 ) ? hb_parl( 4 ) : TRUE;
BYTE buffer[ HB_MEM_REC_LEN ];
while( hb_fsRead( fhnd, buffer, HB_MEM_REC_LEN ) == HB_MEM_REC_LEN )
@@ -1594,6 +1532,7 @@ HB_FUNC( __MVRESTORE )
}
hb_fsClose( fhnd );
hb_memvarUpdatePrivatesBase();
}
else
hb_retl( FALSE );

View File

@@ -58,7 +58,7 @@
HB_FUNC( PCOUNT )
{
/* Skip current function */
PHB_ITEM pBase = hb_stackItem( ( hb_stackBaseItem() )->item.asSymbol.stackbase );
PHB_ITEM pBase = hb_stackItem( hb_stackBaseItem()->item.asSymbol.stackstate->lBaseItem );
hb_retni( pBase->item.asSymbol.paramcnt );
}

View File

@@ -167,7 +167,7 @@ char * hb_procname( int iLevel, char * szName, BOOL bSkipBlock )
if( strcmp( szTstName, "__EVAL" ) == 0 )
{
lPrevOffset = lOffset;
lOffset = hb_stackItem( lOffset )->item.asSymbol.stackbase;
lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem;
}
}

View File

@@ -58,7 +58,7 @@
HB_FUNC( HB_PVALUE )
{
USHORT uiParam = hb_parni( 1 );
LONG lOffset = hb_stackBaseItem()->item.asSymbol.stackbase; /* Skip function + self */
LONG lOffset = hb_stackBaseItem()->item.asSymbol.stackstate->lBaseItem; /* Skip function + self */
PHB_ITEM pBase = hb_stackItem( lOffset );
if( uiParam && uiParam <= pBase->item.asSymbol.paramcnt ) /* Valid number */