void hb_memvarGetRefer( PHB_ITEM pItem, PHB_SYMB pMemvarSymb ) { PHB_DYNS pDyn; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarGetRefer(%p, %p)", pItem, pMemvarSymb ) ); pDyn = ( PHB_DYNS ) pMemvarSymb->pDynSym; if( pDyn ) { PHB_ITEM pMemvar; pMemvar = hb_dynsymGetMemvar( pDyn ); HB_TRACE( HB_TR_INFO, ( "Memvar item (%p)(%s) referenced", pMemvar, pMemvarSymb->szName ) ); if( pMemvar ) { if( HB_IS_BYREF( pMemvar ) && ! HB_IS_ENUM( pMemvar ) ) hb_itemCopy( pItem, pMemvar ); else { /* value is already created */ pItem->type = HB_IT_BYREF | HB_IT_MEMVAR; pItem->item.asMemvar.value = pMemvar; hb_xRefInc( pMemvar ); } } else { /* Generate an error with retry possibility * (user created error handler can make this variable accessible) */ PHB_ITEM pError; pError = hb_errRT_New( ES_ERROR, NULL, EG_NOVAR, 1003, NULL, pMemvarSymb->szName, 0, EF_CANRETRY ); while( hb_errLaunch( pError ) == E_RETRY ) { pMemvar = hb_dynsymGetMemvar( pDyn ); if( pMemvar ) { if( HB_IS_BYREF( pMemvar ) && ! HB_IS_ENUM( pMemvar ) ) hb_itemCopy( pItem, pMemvar ); else { /* value is already created */ pItem->type = HB_IT_BYREF | HB_IT_MEMVAR; pItem->item.asMemvar.value = pMemvar; hb_xRefInc( pMemvar ); } break; } } hb_errRelease( pError ); } } else hb_errInternal( HB_EI_MVBADSYMBOL, NULL, pMemvarSymb->szName, NULL ); }
/* * 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; }
char * hb_memvarGetStrValuePtr( char * szVarName, HB_SIZE * pnLen ) { PHB_DYNS pDynVar; char * szValue = NULL; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarGetStrValuePtr(%s, %p)", szVarName, pnLen ) ); pDynVar = hb_memvarFindSymbol( szVarName, *pnLen ); if( pDynVar ) { /* there is dynamic symbol with the requested name - check if it is * a memvar variable */ PHB_ITEM pMemvar = hb_dynsymGetMemvar( pDynVar ); if( pMemvar ) { /* variable contains some data */ if( HB_IS_BYREF( pMemvar ) ) pMemvar = hb_itemUnRef( pMemvar ); if( HB_IS_STRING( pMemvar ) ) { szValue = pMemvar->item.asString.value; *pnLen = pMemvar->item.asString.length; } } } return szValue; }
HB_ERRCODE hb_memvarGet( PHB_ITEM pItem, PHB_SYMB pMemvarSymb ) { PHB_DYNS pDyn; HB_ERRCODE bSuccess = HB_FAILURE; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarGet(%p, %p)", pItem, pMemvarSymb ) ); pDyn = pMemvarSymb->pDynSym; if( pDyn ) { PHB_ITEM pMemvar; pMemvar = hb_dynsymGetMemvar( pDyn ); HB_TRACE( HB_TR_INFO, ( "Memvar item (%p)(%s) queried", pMemvar, pMemvarSymb->szName ) ); if( pMemvar ) { /* value is already created */ if( HB_IS_BYREF( pMemvar ) ) hb_itemCopy( pItem, hb_itemUnRef( pMemvar ) ); else hb_itemCopy( pItem, pMemvar ); bSuccess = HB_SUCCESS; } } else hb_errInternal( HB_EI_MVBADSYMBOL, NULL, pMemvarSymb->szName, NULL ); return bSuccess; }
/* * Altera o valor de uma variavel de memoria em nivel xBase. Retorna 1 se for * bem sucedido ou 0 em caso de erro. * 01/07/2008 - 17:12:17 */ int wxMemvarPut( char * szVarName, PHB_ITEM pValue ) { HB_DYNS_PTR pDyn; int result = 0; #ifdef HB_THREAD_SUPPORT HB_THREAD_STUB pDyn = s_memvarThFindName( szVarName, (HB_STACK *) &HB_VM_STACK ); #else pDyn = hb_dynsymFindName( szVarName ); #endif /* * Se a variavel não existir ... criamos ela aqui como pública! */ if( !pDyn ) { PHB_ITEM pMemvar = hb_itemNew( NULL ); hb_itemPutC( pMemvar, szVarName ); hb_memvarCreateFromItem( pMemvar, VS_PUBLIC, NULL ); hb_itemRelease( pMemvar ); #ifdef HB_THREAD_SUPPORT pDyn = s_memvarThFindName( szVarName, &HB_VM_STACK ); #else pDyn = hb_dynsymFindName( szVarName ); #endif } if( pDyn ) { /* there is dynamic symbol with the requested name - check if it is * a memvar variable */ if( pDyn->hMemvar ) { /* value is already created */ HB_ITEM_PTR pSetItem = hb_memvarGetValueByHandle( pDyn->hMemvar ); // JC1: the variable we have now can't be destroyed in the meanwhile. // It could be changed, but this is a race condition that must be // prevented at prg level. if( HB_IS_BYREF( pSetItem ) ) { pSetItem = hb_itemUnRef( pSetItem ); } hb_itemCopy( pSetItem, pValue ); result = 1; // Count this new value. /* s_globalTable[ pDyn->hMemvar ].counter = 1; */ } } return result; }
PHB_ITEM hb_memvarGetItem( PHB_SYMB pMemvarSymb ) { HB_TRACE( HB_TR_DEBUG, ( "hb_memvarGetItem(%p)", pMemvarSymb ) ); if( pMemvarSymb->pDynSym ) { PHB_ITEM pMemvar = hb_dynsymGetMemvar( pMemvarSymb->pDynSym ); if( pMemvar ) { if( HB_IS_BYREF( pMemvar ) ) return hb_itemUnRef( pMemvar ); else return pMemvar; } } return NULL; }
/* * Retorna uma STRING de uma variavel caracter do xHarbour, criada via .PRG! Ela * retorna em pulLen o tamanho da string encontrada. * 01/07/2008 - 08:40:47 */ char *wxMemvarGetCPtr( char * szVarName, ULONG *pulLen ) { HB_THREAD_STUB HB_DYNS_PTR pDynVar; char *szValue = NULL; HB_TRACE(HB_TR_DEBUG, ("hb_memvarGetStrValuePtr(%s, %p)", szVarName, pulLen)); #ifdef HB_THREAD_SUPPORT pDynVar = s_memvarThFindName( szVarName, &HB_VM_STACK ); #else pDynVar = hb_dynsymFindName( szVarName ); #endif if( pDynVar ) { /* there is dynamic symbol with the requested name - check if it is * a memvar variable */ if( pDynVar->hMemvar ) { /* variable contains some data */ HB_ITEM_PTR pItem = hb_memvarGetValueByHandle( pDynVar->hMemvar ); if( HB_IS_BYREF( pItem ) ) { pItem = hb_itemUnRef( pItem ); /* it is a PARAMETER variable */ } if( HB_IS_STRING( pItem ) ) { szValue = pItem->item.asString.value; *pulLen = pItem->item.asString.length; } } } return szValue; }
/* * Retorna o valor LONG de uma variavel numérica do xHarbour, criada via .PRG * 01/07/2008 - 08:40:47 */ LONG wxMemvarGetNL( char * szVarName ) { HB_THREAD_STUB HB_DYNS_PTR pDynVar; LONG result = 0; HB_TRACE(HB_TR_DEBUG, ("hb_memvarGetStrValuePtr(%s, %p)", szVarName, pulLen)); #ifdef HB_THREAD_SUPPORT pDynVar = s_memvarThFindName( szVarName, &HB_VM_STACK ); #else pDynVar = hb_dynsymFindName( szVarName ); #endif if( pDynVar ) { /* there is dynamic symbol with the requested name - check if it is * a memvar variable */ if( pDynVar->hMemvar ) { /* variable contains some data */ HB_ITEM_PTR pItem = hb_memvarGetValueByHandle( pDynVar->hMemvar ); if( HB_IS_BYREF( pItem ) ) { pItem = hb_itemUnRef( pItem ); /* it is a PARAMETER variable */ } if( HB_IS_NUMERIC( pItem ) ) { result = hb_itemGetNL( pItem ); } } } return result; }
PHB_ITEM hb_dbg_vmVarLGet( int iLevel, int iLocal ) { PHB_ITEM pLocal = NULL; HB_ISIZ nBaseOffset; nBaseOffset = hb_stackBaseOffset(); while( iLevel-- > 0 && nBaseOffset > 1 ) nBaseOffset = hb_stackItem( nBaseOffset - 1 )->item.asSymbol.stackstate->nBaseItem + 1; if( iLevel < 0 ) { if( iLocal > SHRT_MAX ) { iLocal -= USHRT_MAX; iLocal--; } if( iLocal >= 0 ) { PHB_ITEM pBase = hb_stackItem( nBaseOffset - 1 ); if( pBase->item.asSymbol.paramcnt > pBase->item.asSymbol.paramdeclcnt && iLocal > pBase->item.asSymbol.paramdeclcnt ) iLocal += pBase->item.asSymbol.paramcnt - pBase->item.asSymbol.paramdeclcnt; pLocal = hb_stackItem( nBaseOffset + iLocal ); } else pLocal = hb_codeblockGetRef( hb_stackItem( nBaseOffset )->item.asBlock.value, iLocal ); if( HB_IS_BYREF( pLocal ) ) pLocal = hb_itemUnRef( pLocal ); } return pLocal; }
/* Mark a passed item as used so it will be not released by the GC */ void hb_gcItemRef( PHB_ITEM pItem ) { while( HB_IS_BYREF( pItem ) ) { if( HB_IS_ENUM( pItem ) ) return; else if( HB_IS_EXTREF( pItem ) ) { pItem->item.asExtRef.func->mark( pItem->item.asExtRef.value ); return; } else if( ! HB_IS_MEMVAR( pItem ) && pItem->item.asRefer.offset == 0 && pItem->item.asRefer.value >= 0 ) { /* array item reference */ PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asRefer.BasePtr.array ); if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag ) { /* mark this array as used */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark also all array elements */ pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } return; } pItem = hb_itemUnRefOnce( pItem ); } if( HB_IS_ARRAY( pItem ) ) { PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asArray.value ); /* Check this array only if it was not checked yet */ if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag ) { /* mark this array as used so it will be no re-checked from * other references */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark also all array elements */ pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } else if( HB_IS_HASH( pItem ) ) { PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asHash.value ); /* Check this hash table only if it was not checked yet */ if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag ) { /* mark this hash table as used */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark also all hash elements */ pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } else if( HB_IS_BLOCK( pItem ) ) { PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asBlock.value ); if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag ) { /* mark this codeblock as used */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark as used all detached variables in a codeblock */ pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } else if( HB_IS_POINTER( pItem ) ) { if( pItem->item.asPointer.collect ) { PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asPointer.value ); if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag ) { /* mark this memory block as used */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark also all internal user blocks attached to this block */ pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); } } } /* all other data types don't need the GC */ }
/* Mark a passed item as used so it will be not released by the GC */ void hb_gcItemRef( HB_ITEM_PTR pItem ) { HB_THREAD_STUB ULONG ulSize; HB_ITEM FakedItem; PHB_ITEM pKey; PHB_ITEM pValue; HB_CODEBLOCK_PTR pCBlock; USHORT ui; #ifdef SIMULATE_ITEMREF_RECURSION PITEMREF_RESUMEINFO pResumeInfo = (PITEMREF_RESUMEINFO) hb_xgrab( sizeof( ITEMREF_RESUMEINFO ) ); int iResumeCounter = 0; #endif FakedItem.type = HB_IT_ARRAY; ItemRef_Top: while( HB_IS_BYREF( pItem ) ) { if( HB_IS_EXTREF( pItem ) ) { pItem->item.asExtRef.func->mark( pItem->item.asExtRef.value ); RETURN_OR_RESUME_ITEMREF(); } if( HB_IS_MEMVAR( pItem ) == FALSE ) { if( pItem->item.asRefer.offset == 0 ) { FakedItem.item.asArray.value = pItem->item.asRefer.BasePtr.pBaseArray; //hb_gcItemRef( &FakedItem ); NESTED_ITEMREF( &FakedItem, 1 ); ItemRef_ResumePoint_1: // return; RETURN_OR_RESUME_ITEMREF(); } } else { if( HB_VM_STACK.pPos == HB_VM_STACK.pItems ) { //return; RETURN_OR_RESUME_ITEMREF(); } } pItem = hb_itemUnRefOnce( pItem ); } if( HB_IS_ARRAY( pItem ) ) { HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asArray.value; //printf( "Array %p\n", pItem->item.asArray.value ); --pAlloc; /* Check this array only if it was not checked yet */ if( pAlloc->used == s_uUsedFlag ) { ulSize = pItem->item.asArray.value->ulLen; /* mark this block as used so it will be no re-checked from * other references */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark also all array elements */ pItem = pItem->item.asArray.value->pItems; //printf( "Items %p\n", pItem ); while( ulSize ) { //printf( "Item %p\n", pItem ); //hb_gcItemRef( pItem ); NESTED_ITEMREF( pItem, 2 ); ItemRef_ResumePoint_2: ++pItem; --ulSize; } } } else if( HB_IS_HASH( pItem ) ) { HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asHash.value; --pAlloc; /* Check this hash only if it was not checked yet */ if( pAlloc->used == s_uUsedFlag ) { ulSize = pItem->item.asHash.value->ulLen; pKey = pItem->item.asHash.value->pKeys; pValue = pItem->item.asHash.value->pValues; /* mark this block as used so it will be no re-checked from * other references */ pAlloc->used ^= HB_GC_USED_FLAG; /* mark also all hash elements */ while( ulSize ) { //printf( "Kry %p Value: %p\n", pKey, pValue ); //hb_gcItemRef( pKey ); NESTED_ITEMREF( pKey, 3 ); ItemRef_ResumePoint_3: //hb_gcItemRef( pValue ); NESTED_ITEMREF( pValue, 4 ); ItemRef_ResumePoint_4: ++pKey; ++pValue; --ulSize; } } } else if( HB_IS_BLOCK( pItem ) ) { HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asBlock.value; --pAlloc; /* Check this block only if it was not checked yet */ if( pAlloc->used == s_uUsedFlag ) { pCBlock = pItem->item.asBlock.value; ui = 1; pAlloc->used ^= HB_GC_USED_FLAG; /* mark this codeblock as used */ /* mark as used all detached variables in a codeblock */ while( ui <= pCBlock->uiLocals ) { //hb_gcItemRef( &pCBlock->pLocals[ ui ] ); NESTED_ITEMREF( &pCBlock->pLocals[ ui ] , 5 ); ItemRef_ResumePoint_5: ++ui; } } } else if( HB_IS_POINTER( pItem ) ) { /* check if this memory was allocated by a hb_gcAlloc() */ if ( pItem->item.asPointer.collect ) { HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asPointer.value; --pAlloc; /* Check this memory only if it was not checked yet */ if( pAlloc->used == s_uUsedFlag ) { /* mark this memory as used so it will be no re-checked from * other references */ pAlloc->used ^= HB_GC_USED_FLAG; } } } /* all other data types don't need the GC */ RETURN_OR_RESUME_ITEMREF(); }