static void s_sslSocketNew( HB_BOOL fServer ) { HB_SOCKET sd = hb_socketParam( 1 ); if( sd != HB_NO_SOCKET ) { PHB_SOCKEX pSock = NULL; SSL * ssl = hb_SSL_par( 2 ); if( ssl ) pSock = hb_sockexNewSSL( sd, ssl, fServer, hb_parnintdef( 3, - 1 ), hb_param( 2, HB_IT_ANY ) ); else if( HB_ISHASH( 2 ) ) pSock = hb_sockexNew( sd, s_sockFilter.pszName, hb_param( 2, HB_IT_ANY ) ); else hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); if( pSock ) { PHB_ITEM pSockItm = hb_param( 1, HB_IT_POINTER ); if( HB_ISBYREF( 1 ) && hb_sockexItemReplace( pSockItm, pSock ) ) hb_itemReturn( pSockItm ); else { hb_socketItemClear( pSockItm ); hb_sockexItemPut( hb_param( -1, HB_IT_ANY ), pSock ); } } } }
static void hb_PEM_read_bio( PEM_READ_BIO * func ) { BIO * bio; if( hb_BIO_is( 1 ) ) bio = hb_BIO_par( 1 ); else if( HB_ISCHAR( 1 ) ) bio = BIO_new_file( hb_parc( 1 ), "r" ); else if( HB_ISNUM( 1 ) ) bio = BIO_new_fd( hb_parni( 1 ), BIO_NOCLOSE ); else bio = NULL; if( bio ) { PHB_ITEM pPassCallback = hb_param( 2, HB_IT_EVALITEM ); if( pPassCallback ) { hb_retptr( ( *func )( bio, NULL, hb_ssl_pem_password_cb, pPassCallback ) ); } else { /* NOTE: Dropping 'const' qualifier. [vszakats] */ hb_retptr( ( *func )( bio, NULL, NULL, ( void * ) hb_parc( 2 ) ) ); } if( ! hb_BIO_is( 1 ) ) BIO_free( bio ); } else hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); }
static void hb_PEM_read_bio( PEM_READ_BIO * func, HB_PEM_TYPES type ) { BIO * bio; if( hb_BIO_is( 1 ) ) bio = hb_BIO_par( 1 ); else if( HB_ISCHAR( 1 ) ) bio = BIO_new_file( hb_parc( 1 ), "r" ); else if( HB_ISNUM( 1 ) ) bio = BIO_new_fd( hb_parni( 1 ), BIO_NOCLOSE ); else bio = NULL; if( bio ) { PHB_ITEM pPassCallback = hb_param( 2, HB_IT_EVALITEM ); pem_password_cb * cb; void * cargo, * result; if( pPassCallback ) { cb = hb_ssl_pem_password_cb; cargo = pPassCallback; } else { cb = NULL; cargo = ( void * ) hb_parc( 2 ); /* NOTE: Dropping 'const' qualifier. [vszakats] */ } result = ( *func )( bio, NULL, cb, cargo ); if( result ) { switch( type ) { case hb_PEM_X509: hb_X509_ret( ( X509 * ) result, HB_TRUE ); break; case hb_PEM_EVP_PKEY: hb_EVP_PKEY_ret( ( EVP_PKEY * ) result ); break; case hb_PEM_ANY: hb_retptr( NULL ); break; } } else hb_retptr( NULL ); if( ! hb_BIO_is( 1 ) ) BIO_free( bio ); } else hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); }
cairo_t * hb_cairo_param( int iParam ) { cairo_t ** ppCairo = ( cairo_t ** ) hb_parptrGC( hb_cairo_destructor, iParam ); if( ppCairo && *ppCairo ) return *ppCairo; hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); return NULL; }
cairo_surface_t * hb_cairo_surface_param( int iParam ) { cairo_surface_t ** ppSurface = ( cairo_surface_t ** ) hb_parptrGC( hb_cairo_surface_destructor, iParam ); if( ppSurface && *ppSurface ) return *ppSurface; hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); return NULL; }
cairo_pattern_t * hb_cairo_pattern_param( int iParam ) { cairo_pattern_t ** ppPattern = ( cairo_pattern_t ** ) hb_parptrGC( &s_gcPatternFuncs, iParam ); if( ppPattern && *ppPattern ) return *ppPattern; hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); return NULL; }
static void hb_PEM_read_bio( PEM_READ_BIO * func, HB_BOOL fX509 ) { BIO * bio = NULL; HB_BYTE * pBuffer = NULL; HB_SIZE nSize = 0; if( hb_BIO_is( 1 ) ) bio = hb_BIO_par( 1 ); else if( HB_ISCHAR( 1 ) ) { pBuffer = hb_fileLoad( hb_parc( 1 ), 0, &nSize ); if( pBuffer ) bio = BIO_new_mem_buf( ( char * ) pBuffer, ( int ) nSize ); } else if( HB_ISNUM( 1 ) ) bio = BIO_new_fd( hb_parni( 1 ), BIO_NOCLOSE ); if( bio ) { PHB_ITEM pPassCallback = hb_param( 2, HB_IT_EVALITEM ); pem_password_cb * cb; void * cargo, * result; if( pPassCallback ) { cb = hb_ssl_pem_password_cb; cargo = pPassCallback; } else { cb = NULL; cargo = HB_UNCONST( hb_parc( 2 ) ); /* NOTE: Discarding 'const' qualifier, OpenSSL will memcpy() it */ } result = ( *func )( bio, NULL, cb, cargo ); if( fX509 && result ) hb_X509_ret( ( X509 * ) result, HB_TRUE ); else hb_retptr( result ); if( ! hb_BIO_is( 1 ) ) BIO_free( bio ); if( pBuffer ) { OPENSSL_cleanse( pBuffer, ( size_t ) nSize ); hb_xfree( pBuffer ); } } else hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); }
const char * hb_langSelectID( const char * pszID ) { const char * pszIDOld = hb_langID(); PHB_LANG lang; HB_TRACE( HB_TR_DEBUG, ( "hb_langSelectID(%s)", pszID ) ); lang = hb_langFind( pszID ); if( lang ) hb_langSelect( lang ); else hb_errRT_BASE( EG_ARG, 1303, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); return pszIDOld; }
void hb_gcRefFree( void * pBlock ) { if( pBlock ) { PHB_GARBAGE pAlloc = HB_GC_PTR( pBlock ); if( hb_xRefDec( pAlloc ) ) { /* Don't release the block that will be deleted during finalization */ if( ! ( pAlloc->used & HB_GC_DELETE ) ) { pAlloc->used |= HB_GC_DELETE; /* execute clean-up function */ pAlloc->pFuncs->clear( pBlock ); if( hb_xRefCount( pAlloc ) != 0 ) { if( pAlloc->used & HB_GC_DELETE ) { pAlloc->used = s_uUsedFlag; if( hb_vmRequestQuery() == 0 ) hb_errRT_BASE( EG_DESTRUCTOR, 1301, NULL, "Reference to freed block", 0 ); } } else { HB_GC_LOCK(); if( pAlloc->locked ) hb_gcUnlink( &s_pLockedBlock, pAlloc ); else { hb_gcUnlink( &s_pCurrBlock, pAlloc ); HB_GC_AUTO_DEC(); } HB_GC_UNLOCK(); HB_GARBAGE_FREE( pAlloc ); } } } } else { hb_errInternal( HB_EI_XFREENULL, NULL, NULL, NULL ); } }
HB_EXTERN_END HB_FUNC( HB_DBG_VMVARLGET ) { int iLevel = hb_parni( 1 ) + 1; int iLocal = hb_parni( 2 ); PHB_ITEM pLocal = hb_dbg_vmVarLGet( iLevel, iLocal ); if( pLocal ) { hb_itemReturn( pLocal ); } else { hb_errRT_BASE( EG_ARG, 9999, NULL, "HB_DBG_VMVARLGET", 2, hb_paramError( 1 ), hb_paramError( 2 ) ); } }
/* * This function creates a value for memvar variable * * 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 __MVPUBLIC function) * iScope - 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 * pValue - optional item used to initialize the value of created variable * or NULL * */ void hb_memvarCreateFromItem( PHB_ITEM pMemvar, int iScope, PHB_ITEM pValue ) { PHB_DYNS pDynVar = NULL; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarCreateFromItem(%p, %d, %p)", pMemvar, iScope, pValue ) ); /* find dynamic symbol or creeate one */ if( HB_IS_SYMBOL( pMemvar ) ) /* pDynVar = hb_dynsymGet( pMemvar->item.asSymbol.value->szName ); */ pDynVar = pMemvar->item.asSymbol.value->pDynSym; else if( HB_IS_STRING( pMemvar ) ) pDynVar = hb_dynsymGet( pMemvar->item.asString.value ); if( pDynVar ) hb_memvarCreateFromDynSymbol( pDynVar, iScope, pValue ); else hb_errRT_BASE( EG_ARG, 3008, NULL, "&", HB_ERR_ARGS_BASEPARAMS ); }
/* 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 ); }
static void hb_PEM_read_bio( PEM_READ_BIO * func ) { BIO * bio = NULL; HB_BYTE * pBuffer = NULL; HB_SIZE nSize = 0; if( hb_BIO_is( 1 ) ) bio = hb_BIO_par( 1 ); else if( HB_ISCHAR( 1 ) ) { pBuffer = hb_fileLoad( hb_parc( 1 ), 0, &nSize ); if( pBuffer ) bio = BIO_new_mem_buf( ( char * ) pBuffer, ( int ) nSize ); } else if( HB_ISNUM( 1 ) ) bio = BIO_new_fd( hb_parni( 1 ), BIO_NOCLOSE ); if( bio ) { PHB_ITEM pPassCallback = hb_param( 2, HB_IT_EVALITEM ); if( pPassCallback ) hb_retptr( ( *func )( bio, NULL, hb_ssl_pem_password_cb, pPassCallback ) ); else hb_retptr( ( *func )( bio, NULL, NULL, ( void * ) hb_parc( 2 ) ) ); /* NOTE: Dropping 'const' qualifier. [vszakats] */ if( ! hb_BIO_is( 1 ) ) BIO_free( bio ); if( pBuffer ) { OPENSSL_cleanse( pBuffer, ( size_t ) nSize ); hb_xfree( pBuffer ); } } else hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); }
static PHRB_BODY hb_hrbLoad( const char * szHrbBody, HB_SIZE nBodySize, HB_USHORT usMode, const char * szFileName ) { PHRB_BODY pHrbBody = NULL; if( szHrbBody ) { HB_SIZE nBodyOffset = 0; HB_SIZE nSize; /* Size of function */ HB_SIZE nPos; HB_ULONG ul; char * buffer, ch; HB_USHORT usBind = ( usMode & HB_HRB_BIND_MODEMASK ); PHB_SYMB pSymRead; /* Symbols read */ PHB_DYNF pDynFunc; /* Functions read */ PHB_DYNS pDynSym; int iVersion = hb_hrbReadHead( szHrbBody, nBodySize, &nBodyOffset ); if( iVersion == 0 ) { hb_errRT_BASE( EG_CORRUPTION, 9995, NULL, HB_ERR_FUNCNAME, 0 ); return NULL; } pHrbBody = ( PHRB_BODY ) hb_xgrab( sizeof( HRB_BODY ) ); pHrbBody->fInit = HB_FALSE; pHrbBody->fExit = HB_FALSE; pHrbBody->lSymStart = -1; pHrbBody->ulFuncs = 0; pHrbBody->pSymRead = NULL; pHrbBody->pDynFunc = NULL; pHrbBody->pModuleSymbols = NULL; if( ! hb_hrbReadValue( szHrbBody, nBodySize, &nBodyOffset, &pHrbBody->ulSymbols ) || pHrbBody->ulSymbols == 0 ) { hb_hrbUnLoad( pHrbBody ); hb_errRT_BASE( EG_CORRUPTION, 9996, NULL, HB_ERR_FUNCNAME, 0 ); return NULL; } /* calculate the size of dynamic symbol table */ nPos = nBodyOffset; nSize = 0; for( ul = 0; ul < pHrbBody->ulSymbols; ul++ ) /* Read symbols in .hrb */ { while( nBodyOffset < nBodySize ) { ++nSize; if( szHrbBody[ nBodyOffset++ ] == 0 ) break; } nBodyOffset += 2; if( nBodyOffset >= nBodySize ) { hb_hrbUnLoad( pHrbBody ); hb_errRT_BASE( EG_CORRUPTION, 9997, NULL, HB_ERR_FUNCNAME, 0 ); return NULL; } } nBodyOffset = nPos; ul = pHrbBody->ulSymbols * sizeof( HB_SYMB ); pSymRead = ( PHB_SYMB ) hb_xgrab( nSize + ul ); buffer = ( ( char * ) pSymRead ) + ul; for( ul = 0; ul < pHrbBody->ulSymbols; ul++ ) /* Read symbols in .hrb */ { pSymRead[ ul ].szName = buffer; do { ch = *buffer++ = szHrbBody[ nBodyOffset++ ]; } while( ch ); pSymRead[ ul ].scope.value = ( HB_BYTE ) szHrbBody[ nBodyOffset++ ]; pSymRead[ ul ].value.pCodeFunc = ( PHB_PCODEFUNC ) ( HB_PTRDIFF ) szHrbBody[ nBodyOffset++ ]; pSymRead[ ul ].pDynSym = NULL; if( pHrbBody->lSymStart == -1 && ( pSymRead[ ul ].scope.value & HB_FS_FIRST ) != 0 && ( pSymRead[ ul ].scope.value & HB_FS_INITEXIT ) == 0 ) { pHrbBody->lSymStart = ul; } } /* Read number of functions */ if( ! hb_hrbReadValue( szHrbBody, nBodySize, &nBodyOffset, &pHrbBody->ulFuncs ) ) { hb_xfree( pSymRead ); hb_hrbUnLoad( pHrbBody ); hb_errRT_BASE( EG_CORRUPTION, 9997, NULL, HB_ERR_FUNCNAME, 0 ); return NULL; } pHrbBody->pSymRead = pSymRead; if( pHrbBody->ulFuncs ) { pDynFunc = ( PHB_DYNF ) hb_xgrab( pHrbBody->ulFuncs * sizeof( HB_DYNF ) ); memset( pDynFunc, 0, pHrbBody->ulFuncs * sizeof( HB_DYNF ) ); pHrbBody->pDynFunc = pDynFunc; for( ul = 0; ul < pHrbBody->ulFuncs; ul++ ) { HB_ULONG ulValue; /* Read name of function */ pDynFunc[ ul ].szName = hb_hrbReadId( szHrbBody, nBodySize, &nBodyOffset ); if( pDynFunc[ ul ].szName == NULL ) break; /* Read size of function */ if( ! hb_hrbReadValue( szHrbBody, nBodySize, &nBodyOffset, &ulValue ) ) break; nSize = ( HB_SIZE ) ulValue; if( nBodyOffset + nSize > nBodySize ) break; /* Copy function body */ pDynFunc[ ul ].pCode = ( HB_BYTE * ) hb_xgrab( nSize ); memcpy( ( char * ) pDynFunc[ ul ].pCode, szHrbBody + nBodyOffset, nSize ); nBodyOffset += nSize; pDynFunc[ ul ].pCodeFunc = ( PHB_PCODEFUNC ) hb_xgrab( sizeof( HB_PCODEFUNC ) ); pDynFunc[ ul ].pCodeFunc->pCode = pDynFunc[ ul ].pCode; pDynFunc[ ul ].pCodeFunc->pSymbols = pSymRead; } if( ul < pHrbBody->ulFuncs ) { hb_xfree( pSymRead ); hb_hrbUnLoad( pHrbBody ); hb_errRT_BASE( EG_CORRUPTION, 9998, NULL, HB_ERR_FUNCNAME, 0 ); return NULL; } } /* End of PCODE loading, now linking */ for( ul = 0; ul < pHrbBody->ulSymbols; ul++ ) { if( pSymRead[ ul ].value.pCodeFunc == ( PHB_PCODEFUNC ) SYM_FUNC ) { nPos = hb_hrbFindSymbol( pSymRead[ ul ].szName, pHrbBody->pDynFunc, pHrbBody->ulFuncs ); if( nPos == SYM_NOT_FOUND ) { pSymRead[ ul ].value.pCodeFunc = ( PHB_PCODEFUNC ) SYM_EXTERN; } else { pSymRead[ ul ].value.pCodeFunc = ( PHB_PCODEFUNC ) pHrbBody->pDynFunc[ nPos ].pCodeFunc; pSymRead[ ul ].scope.value |= HB_FS_PCODEFUNC | HB_FS_LOCAL | ( usBind == HB_HRB_BIND_FORCELOCAL ? HB_FS_STATIC : 0 ); } } else if( pSymRead[ ul ].value.pCodeFunc == ( PHB_PCODEFUNC ) SYM_DEFERRED ) { pSymRead[ ul ].value.pCodeFunc = ( PHB_PCODEFUNC ) SYM_EXTERN; pSymRead[ ul ].scope.value |= HB_FS_DEFERRED; } /* External function */ if( pSymRead[ ul ].value.pCodeFunc == ( PHB_PCODEFUNC ) SYM_EXTERN ) { pSymRead[ ul ].value.pCodeFunc = NULL; pDynSym = hb_dynsymFind( pSymRead[ ul ].szName ); if( pDynSym ) { pSymRead[ ul ].value.pFunPtr = pDynSym->pSymbol->value.pFunPtr; if( pDynSym->pSymbol->scope.value & HB_FS_PCODEFUNC ) { pSymRead[ ul ].scope.value |= HB_FS_PCODEFUNC; } } else if( ( pSymRead[ ul ].scope.value & HB_FS_DEFERRED ) == 0 ) { if( ( usMode & HB_HRB_BIND_LAZY ) != 0 ) pSymRead[ ul ].scope.value |= HB_FS_DEFERRED; else { char szName[ HB_SYMBOL_NAME_LEN + 1 ]; hb_strncpy( szName, pSymRead[ ul ].szName, sizeof( szName ) - 1 ); hb_xfree( pSymRead ); hb_hrbUnLoad( pHrbBody ); hb_errRT_BASE( EG_ARG, 6101, "Unknown or unregistered symbol", szName, 0 ); return NULL; } } } } if( hb_vmLockModuleSymbols() ) { if( usBind == HB_HRB_BIND_LOCAL ) { for( ul = 0; ul < pHrbBody->ulSymbols; ul++ ) { if( ( pSymRead[ ul ].scope.value & ( HB_FS_LOCAL | HB_FS_STATIC ) ) == HB_FS_LOCAL ) { pDynSym = hb_dynsymFind( pSymRead[ ul ].szName ); if( pDynSym ) { /* convert public function to static one */ pSymRead[ ul ].scope.value |= HB_FS_STATIC; } } } } pHrbBody->pModuleSymbols = hb_vmRegisterSymbols( pHrbBody->pSymRead, ( HB_USHORT ) pHrbBody->ulSymbols, szFileName ? szFileName : "pcode.hrb", 0, HB_TRUE, HB_FALSE, usBind == HB_HRB_BIND_OVERLOAD ); if( pHrbBody->pModuleSymbols->pModuleSymbols != pSymRead ) { /* * Old unused symbol table has been recycled - free the one * we allocated and disactivate static initialization [druzus] */ pHrbBody->pSymRead = pHrbBody->pModuleSymbols->pModuleSymbols; hb_xfree( pSymRead ); pHrbBody->fInit = HB_TRUE; } else { /* mark symbol table as dynamically allocated so HVM will free it on exit */ pHrbBody->pModuleSymbols->fAllocated = HB_TRUE; /* initialize static variables */ hb_hrbInitStatic( pHrbBody ); } hb_vmUnlockModuleSymbols(); } else { hb_xfree( pSymRead ); hb_hrbUnLoad( pHrbBody ); pHrbBody = NULL; } } return pHrbBody; }
/* Check all memory block if they can be released */ void hb_gcCollectAll( HB_BOOL fForce ) { /* MTNOTE: it's not necessary to protect s_bCollecting with mutex * because it can be changed at RT only inside this procedure * when all other threads are stoped by hb_vmSuspendThreads(), * [druzus] */ if( ! s_bCollecting && hb_vmSuspendThreads( fForce ) ) { PHB_GARBAGE pAlloc, pDelete; if( ! s_pCurrBlock || s_bCollecting ) { hb_vmResumeThreads(); return; } s_bCollecting = HB_TRUE; /* Step 1 - mark */ /* All blocks are already marked because we are flipping * the used/unused flag */ /* Step 2 - sweep */ /* check all known places for blocks they are referring */ hb_vmIsStackRef(); hb_vmIsStaticRef(); hb_clsIsClassRef(); /* check list of locked block for blocks referenced from * locked block */ if( s_pLockedBlock ) { pAlloc = s_pLockedBlock; do { pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) ); pAlloc = pAlloc->pNext; } while( s_pLockedBlock != pAlloc ); } /* Step 3 - finalize */ /* Release all blocks that are still marked as unused */ /* * infinite loop can appear when we are executing clean-up functions * scanning s_pCurrBlock. It's possible that one of them will free * the GC block which we are using as stop condition. Only blocks * for which we set HB_GC_DELETE flag are guarded against releasing. * To avoid such situation first we are moving blocks which will be * deleted to separate list. It's additional operation but it can * even increase the speed when we are deleting only few percent * of all allocated blocks because in next passes we will scan only * deleted block list. [druzus] */ pAlloc = NULL; /* for stop condition */ do { if( s_pCurrBlock->used == s_uUsedFlag ) { pDelete = s_pCurrBlock; pDelete->used |= HB_GC_DELETE | HB_GC_DELETELST; hb_gcUnlink( &s_pCurrBlock, pDelete ); hb_gcLink( &s_pDeletedBlock, pDelete ); HB_GC_AUTO_DEC(); } else { /* at least one block will not be deleted, set new stop condition */ if( ! pAlloc ) pAlloc = s_pCurrBlock; s_pCurrBlock = s_pCurrBlock->pNext; } } while( pAlloc != s_pCurrBlock ); /* Step 4 - flip flag */ /* Reverse used/unused flag so we don't have to mark all blocks * during next collecting */ s_uUsedFlag ^= HB_GC_USED_FLAG; #ifdef HB_GC_AUTO /* store number of marked blocks for automatic GC activation */ s_ulBlocksMarked = s_ulBlocks; if( s_ulBlocksAuto == 0 ) s_ulBlocksCheck = HB_GC_AUTO_MAX; else { s_ulBlocksCheck = s_ulBlocksMarked + s_ulBlocksAuto; if( s_ulBlocksCheck <= s_ulBlocksMarked ) s_ulBlocksCheck = HB_GC_AUTO_MAX; } #endif /* call memory manager cleanup function */ hb_xclean(); /* resume suspended threads */ hb_vmResumeThreads(); /* do we have any deleted blocks? */ if( s_pDeletedBlock ) { /* call a cleanup function */ pAlloc = s_pDeletedBlock; do { s_pDeletedBlock->pFuncs->clear( HB_BLOCK_PTR( s_pDeletedBlock ) ); s_pDeletedBlock = s_pDeletedBlock->pNext; } while( pAlloc != s_pDeletedBlock ); /* release all deleted blocks */ do { pDelete = s_pDeletedBlock; hb_gcUnlink( &s_pDeletedBlock, pDelete ); if( hb_xRefCount( pDelete ) != 0 ) { pDelete->used = s_uUsedFlag; pDelete->locked = 0; HB_GC_LOCK(); hb_gcLink( &s_pCurrBlock, pDelete ); HB_GC_AUTO_INC(); HB_GC_UNLOCK(); if( hb_vmRequestQuery() == 0 ) hb_errRT_BASE( EG_DESTRUCTOR, 1302, NULL, "Reference to freed block", 0 ); } else HB_GARBAGE_FREE( pDelete ); } while( s_pDeletedBlock ); } s_bCollecting = HB_FALSE; } }