/* This function releases all memory occupied by a memvar variable and * assigns NIL value - it releases variables created in current * procedure only. * The scope of released variables are specified using passed name's mask */ static void hb_memvarReleaseWithMask( const char * szMask, HB_BOOL bInclude ) { HB_STACK_TLS_PRELOAD HB_SIZE nBase, nCount; PHB_DYNS pDynVar; PHB_ITEM pMemvar; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarReleaseWithMask(%s, %d)", szMask, ( int ) bInclude ) ); nCount = hb_stackGetPrivateStack()->count; nBase = hb_stackBaseItem()->item.asSymbol.stackstate->nPrivateBase; while( nCount-- > nBase ) { pDynVar = hb_stackGetPrivateStack()->stack[ nCount ].pDynSym; /* reset current value to NIL - the overriden variables will be * visible after exit from current procedure */ pMemvar = hb_dynsymGetMemvar( pDynVar ); if( pMemvar ) { HB_BOOL fMatch = hb_strMatchCaseWildExact( pDynVar->pSymbol->szName, szMask ); if( bInclude ? fMatch : ! fMatch ) hb_itemClear( pMemvar ); } } }
/* * Update PRIVATE base ofsset so they will not be removed * when function return */ void hb_memvarUpdatePrivatesBase( void ) { HB_STACK_TLS_PRELOAD HB_TRACE( HB_TR_DEBUG, ( "hb_memvarUpdatePrivatesBase()" ) ); hb_stackGetPrivateStack()->base = hb_stackGetPrivateStack()->count; }
/* * This function returns current PRIVATE variables stack base */ HB_SIZE hb_memvarGetPrivatesBase( void ) { HB_STACK_TLS_PRELOAD HB_SIZE nBase; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarGetPrivatesBase()" ) ); nBase = hb_stackGetPrivateStack()->base; hb_stackGetPrivateStack()->base = hb_stackGetPrivateStack()->count; return nBase; }
/* * Reset PRIVATE base offset to the level of previous function */ static void hb_memvarResetPrivatesBase( void ) { HB_STACK_TLS_PRELOAD HB_TRACE( HB_TR_DEBUG, ( "hb_memvarResetPrivatesBase()" ) ); hb_stackGetPrivateStack()->base = hb_stackBaseItem()->item.asSymbol.stackstate->nPrivateBase; }
/* This function releases all memory occupied by a memvar variable * It also restores the value that was hidden if there is another * PRIVATE variable with the same name. */ static void hb_memvarRelease( PHB_ITEM pMemvar ) { HB_TRACE( HB_TR_DEBUG, ( "hb_memvarRelease(%p)", pMemvar ) ); if( HB_IS_STRING( pMemvar ) ) { PHB_DYNS pDynSymbol = hb_memvarFindSymbol( pMemvar->item.asString.value, pMemvar->item.asString.length ); if( pDynSymbol && hb_dynsymGetMemvar( pDynSymbol ) ) { HB_STACK_TLS_PRELOAD HB_SIZE nBase = hb_stackGetPrivateStack()->count; /* Find the variable with a requested name that is currently visible * Start from the top of the stack. */ while( nBase > 0 ) { if( pDynSymbol == hb_stackGetPrivateStack()->stack[ --nBase ].pDynSym ) { /* reset current value to NIL - the overriden variables will be * visible after exit from current procedure */ pMemvar = hb_dynsymGetMemvar( pDynSymbol ); if( pMemvar ) hb_itemClear( pMemvar ); return; } } /* No match found for PRIVATEs - it's PUBLIC so let's remove it. */ hb_memvarDetachDynSym( pDynSymbol, NULL ); } } else hb_errRT_BASE( EG_ARG, 3008, NULL, "RELEASE", HB_ERR_ARGS_BASEPARAMS ); }
/* Checks if passed dynamic symbol is a variable and returns its scope */ static int hb_memvarScopeGet( PHB_DYNS pDynVar ) { HB_TRACE( HB_TR_DEBUG, ( "hb_memvarScopeGet(%p)", pDynVar ) ); if( hb_dynsymGetMemvar( pDynVar ) == 0 ) return HB_MV_UNKNOWN; else { HB_STACK_TLS_PRELOAD HB_SIZE nBase = hb_stackGetPrivateStack()->count; /* start from the top of the stack */ while( nBase ) { if( pDynVar == hb_stackGetPrivateStack()->stack[ --nBase ].pDynSym ) { if( nBase >= hb_stackGetPrivateStack()->base ) return HB_MV_PRIVATE_LOCAL; else return HB_MV_PRIVATE_GLOBAL; } } return HB_MV_PUBLIC; } }
/* * This function releases PRIVATE variables created after passed base */ void hb_memvarSetPrivatesBase( HB_SIZE nBase ) { HB_STACK_TLS_PRELOAD PHB_PRIVATE_STACK pPrivateStack; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarSetPrivatesBase(%" HB_PFS "u)", nBase ) ); pPrivateStack = hb_stackGetPrivateStack(); while( pPrivateStack->count > pPrivateStack->base ) { PHB_DYNS pDynSym = pPrivateStack->stack[ --pPrivateStack->count ].pDynSym; if( hb_dynsymGetMemvar( pDynSym ) ) { /* Restore previous value for variables that were overridden */ hb_memvarDetachDynSym( pDynSym, pPrivateStack->stack[ pPrivateStack->count ].pPrevMemvar ); } } pPrivateStack->base = nBase; }
/* Clear all memvar variables optionally without GetList PUBLIC variable */ void hb_memvarsClear( HB_BOOL fAll ) { HB_STACK_TLS_PRELOAD PHB_DYNS pGetList; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarsClear(%d)", ( int ) fAll ) ); pGetList = fAll ? NULL : hb_dynsymFind( "GETLIST" ); hb_stackClearMemvarsBase(); hb_stackGetPrivateStack()->base = 0; hb_memvarSetPrivatesBase( 0 ); #if ! defined( HB_MT_VM ) hb_dynsymEval( hb_memvarClear, ( void * ) pGetList ); #else /* this is a little bit hacked but many times faster version * of memvars clearing because it scans only given thread stack * not global dynamic symbol table. It noticeable reduce the cost * of HVM thread releasing. */ hb_stackClearMemvars( pGetList ? ( int ) pGetList->uiSymNum : -1 ); #endif }
/* * This function pushes passed dynamic symbol that belongs to PRIVATE variable * into the stack. The value will be popped from it if the variable falls * outside the scope (either by using RELEASE, CLEAR ALL, CLEAR MEMORY or by * an exit from the function/procedure) * */ static void hb_memvarAddPrivate( PHB_DYNS pDynSym, PHB_ITEM pValue ) { HB_STACK_TLS_PRELOAD PHB_PRIVATE_STACK pPrivateStack; PHB_ITEM pMemvar; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarAddPrivate(%p,%p)", pDynSym, pValue ) ); pPrivateStack = hb_stackGetPrivateStack(); pMemvar = hb_dynsymGetMemvar( pDynSym ); /* If the variable with the same name exists already * and it's PRIVATE variable declared in this function then * do not push new memvar on PRIVATEs stack */ if( pMemvar ) { HB_SIZE nCount = pPrivateStack->count; while( nCount > pPrivateStack->base ) { if( pDynSym == pPrivateStack->stack[ nCount - 1 ].pDynSym ) break; --nCount; } if( nCount <= pPrivateStack->base ) pMemvar = NULL; } if( ! pMemvar ) { /* Allocate the value from the end of table */ if( pPrivateStack->count == pPrivateStack->size ) { /* No more free values in the table - expand the table */ if( pPrivateStack->size == 0 ) { pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) hb_xgrab( sizeof( HB_PRIVATE_ITEM ) * TABLE_INITHB_VALUE ); pPrivateStack->size = TABLE_INITHB_VALUE; pPrivateStack->count = pPrivateStack->base = 0; } else { pPrivateStack->size += TABLE_EXPANDHB_VALUE; pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) hb_xrealloc( pPrivateStack->stack, sizeof( HB_PRIVATE_ITEM ) * pPrivateStack->size ); } } pPrivateStack->stack[ pPrivateStack->count ].pDynSym = pDynSym; pPrivateStack->stack[ pPrivateStack->count++ ].pPrevMemvar = hb_dynsymGetMemvar( pDynSym ); if( pValue && HB_IS_MEMVAR( pValue ) ) { pMemvar = pValue->item.asMemvar.value; hb_xRefInc( pMemvar ); pValue = NULL; } else pMemvar = hb_memvarValueNew(); hb_dynsymSetMemvar( pDynSym, pMemvar ); } if( pValue ) { hb_itemCopy( pMemvar, pValue ); /* Remove MEMOFLAG if exists (assignment from field). */ pMemvar->type &= ~HB_IT_MEMOFLAG; } }