/* * Detach local variable (swap current value with a memvar handle) */ PHB_ITEM hb_memvarDetachLocal( PHB_ITEM pLocal ) { HB_TRACE( HB_TR_DEBUG, ( "hb_memvarDetachLocal(%p)", pLocal ) ); if( HB_IS_BYREF( pLocal ) ) { do { if( HB_IS_MEMVAR( pLocal ) || HB_IS_EXTREF( pLocal ) ) break; else if( HB_IS_ENUM( pLocal ) ) { if( ! pLocal->item.asEnum.valuePtr ) { PHB_ITEM pBase = HB_IS_BYREF( pLocal->item.asEnum.basePtr ) ? hb_itemUnRef( pLocal->item.asEnum.basePtr ) : pLocal->item.asEnum.basePtr; if( HB_IS_ARRAY( pBase ) ) { PHB_ITEM pItem = hb_itemNew( NULL ); hb_arrayGetItemRef( pBase, pLocal->item.asEnum.offset, pItem ); pLocal->item.asEnum.valuePtr = pItem; pLocal = pItem; break; } } } else if( pLocal->item.asRefer.value >= 0 && pLocal->item.asRefer.offset == 0 ) break; pLocal = hb_itemUnRefOnce( pLocal ); } while( HB_IS_BYREF( pLocal ) ); } /* Change the value only if this variable is not referenced * by another codeblock yet. * 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 ) ) { PHB_ITEM pMemvar = hb_memvarValueNew(); hb_itemRawCpy( pMemvar, pLocal ); pMemvar->type &= ~HB_IT_DEFAULT; pLocal->type = HB_IT_BYREF | HB_IT_MEMVAR; pLocal->item.asMemvar.value = pMemvar; } return pLocal; }
static void hb_memvarCreateFromDynSymbol( PHB_DYNS pDynVar, int iScope, PHB_ITEM pValue ) { HB_TRACE( HB_TR_DEBUG, ( "hb_memvarCreateFromDynSymbol(%p, %d, %p)", pDynVar, iScope, pValue ) ); if( iScope & HB_VSCOMP_PUBLIC ) { /* If the variable with the same name exists already * then the current value have to be unchanged */ if( ! hb_dynsymGetMemvar( pDynVar ) ) { PHB_ITEM pMemvar = hb_memvarValueNew(); hb_dynsymSetMemvar( pDynVar, pMemvar ); if( pValue ) { hb_itemCopy( pMemvar, pValue ); /* Remove MEMOFLAG if exists (assignment from field). */ pMemvar->type &= ~HB_IT_MEMOFLAG; } else { /* new PUBLIC variable - initialize it to .F. */ pMemvar->type = HB_IT_LOGICAL; /* NOTE: PUBLIC variables named CLIPPER and HARBOUR are initialized */ /* to .T., this is normal Clipper behaviour. [vszakats] */ pMemvar->item.asLogical.value = ( strcmp( pDynVar->pSymbol->szName, "HARBOUR" ) == 0 || strcmp( pDynVar->pSymbol->szName, "CLIPPER" ) == 0 ); } } } else { /* Create new PRIVATE var and add it to the PRIVATE variables stack */ hb_memvarAddPrivate( pDynVar, pValue ); } }
/* * 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; } }